1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo 2# Copyright (C) 2016-2019 German Aerospace Center (DLR) and others. 3# SUMOPy module 4# Copyright (C) 2012-2017 University of Bologna - DICAM 5# This program and the accompanying materials 6# are made available under the terms of the Eclipse Public License v2.0 7# which accompanies this distribution, and is available at 8# http://www.eclipse.org/legal/epl-v20.html 9# SPDX-License-Identifier: EPL-2.0 10 11# @file origin_to_destination_wxgui.py 12# @author Joerg Schweizer 13# @date 14# @version $Id$ 15 16import wx 17 18 19import agilepy.lib_base.classman as cm 20import agilepy.lib_base.arrayman as am 21from agilepy.lib_base.misc import get_inversemap 22from agilepy.lib_wx.ogleditor import * 23from agilepy.lib_wx.objpanel import ObjPanel 24from coremodules.network.network import SumoIdsConf, MODES 25 26 27class OdCommonMixin: 28 def add_odoptions_common(self, modes=None, activitytypes=None): 29 # print 'add_odoptions_common',modes 30 self.add(am.AttrConf('t_start', 0, 31 groupnames=['options'], 32 perm='rw', 33 name='Start time', 34 unit='s', 35 info='Start time of interval', 36 )) 37 38 self.add(am.AttrConf('t_end', 3600, 39 groupnames=['options'], 40 perm='rw', 41 name='End time', 42 unit='s', 43 info='End time of interval', 44 )) 45 46 # here we ged classes not vehicle type 47 # specific vehicle type within a class will be generated later 48 if modes is None: 49 modechoices = {'': -1} 50 else: 51 modechoices = modes.names.get_indexmap() 52 # print ' modechoices',modechoices 53 self.add(am.AttrConf('id_mode', -1, 54 groupnames=['options'], 55 choices=modechoices, 56 name='Mode', 57 info='Transport mode.', 58 )) 59 60 self.add(cm.AttrConf('scale', 1.0, 61 groupnames=['options'], 62 perm='rw', 63 name='Scale', 64 info='Scale demand by this factor before adding. Value od 1.0 means no scaling.' 65 )) 66 67 if activitytypes is None: 68 activitytypechoices = {'': -1} 69 id_act_orig = -1 70 id_act_dest = -1 71 else: 72 activitytypechoices = activitytypes.names.get_indexmap() 73 id_act_orig = activitytypes.names.get_id_from_index('home') 74 id_act_dest = activitytypes.names.get_id_from_index('work') 75 76 self.add(cm.AttrConf('id_activitytype_orig', id_act_orig, 77 groupnames=['options'], 78 choices=activitytypechoices, 79 perm='rw', 80 name='Activity at orig.', 81 info='Activity type at origin.', 82 )) 83 84 self.add(cm.AttrConf('id_activitytype_dest', id_act_dest, 85 groupnames=['options'], 86 choices=activitytypechoices, 87 perm='rw', 88 name='Activity at dest.', 89 info='Activity type at destination.', 90 )) 91 92 93class OdFlowsWxGuiMixin: 94 """Contains OdFlow spacific functions that communicate between the widgets of the main wx gui 95 and the functions of the plugin. 96 """ 97 98 def refresh_odflow(self, is_refresh): 99 if is_refresh: 100 neteditor = self.get_neteditor() 101 #neteditor.add_tool(AddODflowTool(self, odintervals)) 102 neteditor.add_toolclass(AddODflowTool) 103 104 def add_menu_odflows(self, menubar): 105 menubar.append_menu('demand/Zone-to-zone demand', 106 bitmap=self.get_icon("fig_od_24px.png"), 107 ) 108 menubar.append_item('demand/Zone-to-zone demand/add zone-to-zone flows...', 109 self.on_add_odtrips, 110 info='Add or import trips between origin and destination zones, with a certain mode during a certain time interval.', 111 bitmap=self.get_agileicon("Document_Import_24px.png"), 112 ) 113 114 menubar.append_item('demand/Zone-to-zone demand/generate trips from flows', 115 self.on_generate_odtrips, 116 # info=self.on_generate_odtrips.__doc__.strip(), 117 #bitmap = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE_AS,wx.ART_MENU), 118 ) 119 120 menubar.append_item('demand/Zone-to-zone demand/generate routes from flows, if connected', 121 self.on_generate_odroutes, 122 # info=self.on_generate_odtrips.__doc__.strip(), 123 #bitmap = wx.ArtProvider.GetBitmap(wx.ART_FILE_SAVE_AS,wx.ART_MENU), 124 ) 125 126 menubar.append_item('demand/Zone-to-zone demand/clear zone-to-zone flows', 127 self.on_clear_odtrips, 128 info='Clear all zone to zone trips.', 129 bitmap=wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_MENU), 130 ) 131 132 def on_add_odtrips(self, event=None): 133 """ 134 Opend odm wizzard 135 """ 136 dlg = AddOdDialog(self._mainframe, self._demand.odintervals) 137 dlg.Show() 138 dlg.MakeModal(True) 139 self._mainframe.browse_obj(self._demand.odintervals) 140 # self.scenariopanel.refresh_panel(self.scenario) 141 142 def on_generate_odtrips(self, event=None): 143 """ 144 Generates trips from origin to destination zone from current OD matrices. 145 """ 146 self._demand.odintervals.generate_trips(n_trials_connect=-1, 147 is_make_route=False,) 148 self._mainframe.browse_obj(self._demand.trips) 149 150 def on_generate_odroutes(self, event=None): 151 """ 152 Generates routes from origin to destination zone from current OD matrices, if connected. 153 """ 154 self._demand.odintervals.generate_trips(n_trials_connect=5, 155 is_make_route=True,) 156 self._mainframe.browse_obj(self._demand.trips) 157 158 def on_clear_odtrips(self, event=None): 159 """ 160 Generates trips from origin to destination zone from current OD matrices. 161 """ 162 self._demand.odintervals.clear_od_trips() 163 self._mainframe.browse_obj(self._demand.odintervals) 164 165 166class AddODflowTool(OdCommonMixin, SelectTool): 167 """ 168 OD flow toolfor OGL canvas. 169 """ 170 171 def __init__(self, parent, mainframe=None): 172 """ 173 To be overridden by specific tool. 174 """ 175 self.init_common('odflow', parent, 'Add OD flow', 176 info="""Tool to add a flow between a zone of origin and a zone of destination: 177 <LEFT MOUSE> on the respective borderlines of zone of origin, and zone of destination. 178 Enter time interval and transport mode. 179 Enter number of trips and press "add flows". 180 <LEFT MOUSE> on border of a new zone of destination to add flows to other zones of destination. 181 Or press button "Reset zones" to start with a new assignment. 182 """, 183 is_textbutton=False, 184 ) 185 186 self._init_select(is_show_selected=False) 187 188 #self.drawobj_zone_orig = None 189 #self.drawobj_zone_dest = None 190 self.add_odoptions_common() 191 # make options 192 self.add(cm.AttrConf('id_orig', -1, 193 groupnames=['options'], 194 choices={'': -1}, 195 perm='r', 196 name='Orig zone', 197 info='Name of traffic assignment zone of origin of trip. Click on zone border to specify.', 198 )) 199 200 self.add(cm.AttrConf('id_dest', -1, 201 dtype='object', 202 groupnames=['options'], 203 choices={'': -1}, 204 perm='r', 205 name='Dest zone', 206 info='Name of traffic assignment zone of destination of trip.Click on zone border to specify.', 207 )) 208 209 self.add(cm.AttrConf('tripnumber', 0, 210 groupnames=['options'], 211 perm='rw', 212 name='Trips', 213 info='Number of trips from zone of origin to zone of destination.', 214 )) 215 216 def set_button_info(self, bsize=(32, 32)): 217 # print 'set_button_info select tool' self.get_icon("icon_sumo_24px.png") 218 iconpath = os.path.join(os.path.dirname(__file__), 'images') 219 self._bitmap = wx.Bitmap(os.path.join(iconpath, 'fig_od_32px.png'), wx.BITMAP_TYPE_PNG) 220 self._bitmap_sel = self._bitmap 221 222 def set_cursor(self): 223 # http://www.wxpython.org/docs/api/wx.Cursor-class.html 224 if self._canvas is not None: 225 self._canvas.SetCursor(wx.StockCursor(wx.CURSOR_RIGHT_ARROW)) 226 227 def activate(self, canvas=None): 228 """ 229 This call by metacanvas??TooldsPallet signals that the tool has been 230 activated and can now interact with metacanvas. 231 """ 232 # print 'activate' 233 SelectTool.activate(self, canvas) 234 235 zones = self.get_zones() 236 zonenames = zones.ids_sumo.get_indexmap() 237 zonenames[''] = -1 238 self.id_orig.choices = zonenames 239 self.id_dest.choices = zonenames 240 241 modechoices = self.get_scenario().demand.vtypes.get_modechoices() 242 self.id_mode.set_value(modechoices['passenger']) 243 self.id_mode.choices = modechoices 244 245 activitytypes = self.get_scenario().demand.activitytypes 246 self.id_activitytype_orig.choices = activitytypes.names.get_indexmap() 247 self.id_activitytype_dest.choices = activitytypes.names.get_indexmap() 248 self.id_activitytype_orig.set_value(activitytypes.names.get_id_from_index('home')) 249 self.id_activitytype_dest.set_value(activitytypes.names.get_id_from_index('work')) 250 251 self.highlight_zones() 252 canvas.draw() 253 254 def deactivate(self): 255 """ 256 This call by metacanvas signals that the tool has been 257 deactivated and can now interact with metacanvas. 258 """ 259 260 self._is_active = False 261 self.unhighlight_zones() 262 self._canvas.draw() 263 self.deactivate_select() 264 265 def on_execute_selection(self, event): 266 """ 267 Definively execute operation on currently selected drawobjects. 268 """ 269 # print 'AddODflowTool.on_execute_selection',self.get_netelement_current() 270 # self.set_objbrowser() 271 # self.highlight_current() 272 self.unhighlight_current() 273 self.unhighlight_zones() 274 netelement_current = self.get_netelement_current() 275 if netelement_current is not None: 276 (zones, id_zone) = netelement_current 277 if zones.get_ident() == 'zones': 278 # print ' check',self.name_orig.get_value(),'*',self.name_orig.get_value() is '' 279 if self.id_orig.get_value() < 0: 280 # print ' set name_orig',zones.ids_sumo[id_zone] 281 self.id_orig.set_value(id_zone) 282 283 else: 284 # print ' set name_dest',zones.ids_sumo[id_zone] 285 self.id_dest.set_value(id_zone) 286 287 self.unselect_all() # includes unhighlight 288 self.highlight_zones() 289 self.parent.refresh_optionspanel(self) 290 return True 291 292 def highlight_zones(self): 293 # print 'highlight_zones',self.id_orig.value,self.id_dest.value 294 zones = self.get_zones() 295 drawing = self.get_drawing() 296 if self.id_orig.value >= 0: 297 drawing.highlight_element(zones, [self.id_orig.value], is_update=True) 298 if self.id_dest.value >= 0: 299 drawing.highlight_element(zones, [self.id_dest.value], is_update=True) 300 301 def unhighlight_zones(self): 302 zones = self.get_zones() 303 drawing = self.get_drawing() 304 if self.id_orig.value >= 0: 305 drawing.unhighlight_element(zones, self.id_orig.value, is_update=True) 306 if self.id_dest.value >= 0: 307 drawing.unhighlight_element(zones, self.id_dest.value, is_update=True) 308 309 def on_change_selection(self, event): 310 """ 311 Called after selection has been changed with SHIFT-click 312 Do operation on currently selected drawobjects. 313 """ 314 # self.set_objbrowser() 315 return False 316 317 def get_netelement_current(self): 318 mainframe = self.parent.get_mainframe() 319 if mainframe is not None: 320 drawobj, _id = self.get_current_selection() 321 if drawobj is not None: 322 obj = drawobj.get_netelement() 323 return obj, _id 324 else: 325 return None 326 else: 327 return None 328 329 def get_scenario(self): 330 # get net and scenario via netdrawing 331 return self.get_drawing().get_net().parent 332 333 def get_odintervals(self): 334 return self.get_scenario().demand.odintervals 335 336 def get_zones(self): 337 return self.get_scenario().landuse.zones 338 339 def on_add_new(self, event=None): 340 self._optionspanel.apply() 341 zonenames = self.get_zones().ids_sumo 342 # print 'on_add_new', 343 # print ' odintervals',self.get_odintervals(),dir(self.get_odintervals()) 344 odtrips = self.get_odintervals().add_od_flow(self.t_start.value, self.t_end.value, 345 self.id_mode.value, 346 self.id_activitytype_orig.value, 347 self.id_activitytype_dest.value, 348 self.scale.value, 349 zonenames[self.id_orig.value], 350 zonenames[self.id_dest.value], 351 self.tripnumber.value, 352 ) 353 self.unselect_all() 354 self.unhighlight_zones() 355 mainframe = self.parent.get_mainframe() 356 if mainframe is not None: 357 mainframe.browse_obj(odtrips) 358 359 self.id_dest.set_value(-1) # set empty zone 360 self.highlight_zones() 361 self.parent.refresh_optionspanel(self) 362 self._canvas.draw() 363 364 def on_clear_zones(self, event=None): 365 self.unhighlight_zones() 366 self.id_orig.set_value(-1) # set empty zone 367 self.id_dest.set_value(-1) # set empty zone 368 self.unselect_all() 369 370 self.parent.refresh_optionspanel(self) 371 self._canvas.draw() 372 373 def get_optionspanel(self, parent, size=wx.DefaultSize): 374 """ 375 Return tool option widgets on given parent 376 """ 377 size = (200, -1) 378 buttons = [('Add flow', self.on_add_new, 'Add a new OD flow to demand.'), 379 ('Rest Zones', self.on_clear_zones, 'Clear the fields with zones of origin and destination.'), 380 #('Save flows', self.on_add, 'Save OD flows to current demand.'), 381 #('Cancel', self.on_close, 'Close wizzard without adding flows.'), 382 ] 383 defaultbuttontext = 'Add flow' 384 self._optionspanel = ObjPanel(parent, obj=self, 385 attrconfigs=None, 386 groupnames=['options'], 387 func_change_obj=None, 388 show_groupnames=False, show_title=True, is_modal=False, 389 mainframe=self.parent.get_mainframe(), 390 pos=wx.DefaultPosition, size=size, style=wx.MAXIMIZE_BOX | wx.RESIZE_BORDER, 391 immediate_apply=True, panelstyle='default', # 'instrumental' 392 buttons=buttons, defaultbutton=defaultbuttontext, 393 standartbuttons=[], # standartbuttons=['restore'] 394 ) 395 396 return self._optionspanel 397 398 399class AddOdWizzard(OdCommonMixin, am.ArrayObjman): 400 """Contains information and methods to add an od matrix for 401 a certain mode and for a certain time interval to the scenario. 402 """ 403 404 def __init__(self, odintervals): 405 # print 'AddOdWizzard',odintervals#,odintervals.times_start 406 # print ' dir(odintervals)',dir(odintervals) 407 zones = odintervals.get_zones() 408 409 self._init_objman('odm_adder', parent=odintervals, 410 name='ODM Wizzard', 411 info='Wizzard to add origin zone to destination zone demand informations.', 412 ) 413 414 self.add_odoptions_common(odintervals.parent.get_scenario().net.modes, odintervals.parent.activitytypes) 415 416 self.add_col(am.ArrayConf('names_orig', '', 417 dtype='object', 418 groupnames=['state'], 419 choices=list(zones.ids_sumo.get_value()), 420 name='Orig zone', 421 info='Name of traffic assignment zone of origin of trip.', 422 )) 423 424 self.add_col(am.ArrayConf('names_dest', '', 425 dtype='object', 426 groupnames=['state'], 427 choices=list(zones.ids_sumo.get_value()), 428 name='Dest zone', 429 info='Name of traffic assignment zone of destination of trip.', 430 )) 431 432 self.add_col(am.ArrayConf('tripnumbers', 0, 433 groupnames=['state'], 434 perm='rw', 435 name='Trips', 436 info='Number of trips from zone of origin to zone of destination.', 437 xmltag='tripnumber', 438 )) 439 440 self.add(cm.FuncConf('func_make_row', 'on_add_row', None, 441 groupnames=['rowfunctions', '_private'], 442 name='New OD flow.', 443 info='Add a new OD flow.', 444 )) 445 446 self.add(cm.FuncConf('func_delete_row', 'on_del_row', None, 447 groupnames=['rowfunctions', '_private'], 448 name='Del OD flow', 449 info='Delete OD flow.', 450 )) 451 452 # self.attrs.print_attrs() 453 454 def on_del_row(self, id_row): 455 # print 'on_del_row', id_row 456 if id_row is not None: 457 self.del_row(id_row) 458 459 def on_add_row(self, id=None): 460 if len(self) > 0: 461 # copy previous 462 od_last = self.get_row(self.get_ids()[-1]) 463 #id_orig = self.odtab.ids_orig.get(id_last) 464 #id_dest = self.odtab.ids_dest.get(id_last) 465 #id = self.suggest_id() 466 self.add_row(**od_last) 467 else: 468 # create empty 469 self.add_row() 470 471 def add_demand(self): 472 """ 473 Add demand to scenario. 474 """ 475 # print 'AddOdm.add_demand' 476 odintervals = self.parent 477 #demand = self._scenario.demand 478 # odm={} # create a temporary dict with (o,d) as key and trips as value 479 ids = self.get_ids() 480 odintervals.add_od_flows(self.t_start.value, self.t_end.value, 481 self.id_mode.value, 482 self.id_activitytype_orig.value, self.id_activitytype_dest.value, 483 self.scale.value, 484 self.names_orig[ids], self.names_dest[ids], 485 self.tripnumbers[ids] 486 ) 487 488 #t_start, t_end, id_mode, 489 # id_activitytype_orig, id_activitytype_dest, 490 # scale, names_orig,names_dest,tripnumbers): 491 492 def import_csv(self, filepath, sep=",", n_firstline=1): 493 names_zone = self.parent.get_zones().ids_sumo 494 # make shure that index table is updated 495 names_zone.rebuild_indices() 496 f = open(filepath, 'r') 497 # print ' open',filepath 498 i_line = n_firstline 499 for line in f.readlines(): 500 # print ' ',line, 501 cols = line.split(sep) 502 if len(cols) == 3: 503 name_orig, name_dest, tripnumbers_str = cols 504 505 name_orig = name_orig.strip() 506 name_dest = name_dest.strip() 507 if names_zone.has_index(name_orig) & names_zone.has_index(name_dest): 508 id_new = self.suggest_id() 509 self.add_row(id_new, 510 names_orig=name_orig, 511 names_dest=name_dest, 512 tripnumbers=int(tripnumbers_str) 513 ) 514 else: 515 print 'WARNING: unknown zonename in line %d of file %s' % (i_line, filepath) 516 517 else: 518 if len(cols) != 0: 519 print 'WARNING: inconsistent o,d,trips info in line %d of file %s' % (i_line, filepath) 520 i_line += 1 521 # self.odtab.print_rows() 522 f.close() 523 524 525class AddOdDialog(wx.Frame): 526 527 """ 528 A frame used for the ObjBrowser Demo 529 530 """ 531 532 def __init__(self, parent, odintervals): 533 wx.Frame.__init__(self, parent, -1, title='Add OD flow Wizzard', pos=wx.DefaultPosition, size=wx.DefaultSize) 534 self.wizzard = AddOdWizzard(odintervals) 535 self.parent = parent 536 # Set up the MenuBar 537 MenuBar = wx.MenuBar() 538 539 file_menu = wx.Menu() 540 item = file_menu.Append(-1, "&Import CSV...", 541 "Import OD data from a CSV text file with format <zonename orig>, <zonename dest>,<number of trips>") 542 self.Bind(wx.EVT_MENU, self.on_import_csv, item) 543 #item = file_menu.Append(-1, "&Import Exel...","Import OD data from an Exel file.") 544 #self.Bind(wx.EVT_MENU, self.on_import_exel, item) 545 546 item = file_menu.Append(-1, "&Save flows and close", "Add OD flows to scenario and close wizzard") 547 self.Bind(wx.EVT_MENU, self.on_add, item) 548 549 item = file_menu.Append(-1, "&Close", "Close wizzard withot saving") 550 self.Bind(wx.EVT_MENU, self.on_close, item) 551 552 MenuBar.Append(file_menu, "&File") 553 554 edit_menu = wx.Menu() 555 item = edit_menu.Append(-1, "&Add OD flow to table", 556 "Add a new flow by defining zones of origin, destination and number of trips in table") 557 self.Bind(wx.EVT_MENU, self.on_add_new, item) 558 MenuBar.Append(edit_menu, "&Edit") 559 560 if odintervals.get_net().parent is not None: 561 self.dirpath = odintervals.get_net().parent.get_workdirpath() 562 else: 563 self.dirpath = os.getcwd() 564 565 #help_menu = wx.Menu() 566 # item = help_menu.Append(-1, "&About", 567 # "More information About this program") 568 #self.Bind(wx.EVT_MENU, self.on_menu, item) 569 #MenuBar.Append(help_menu, "&Help") 570 571 self.SetMenuBar(MenuBar) 572 573 self.CreateStatusBar() 574 575 self.browser = self.make_browser() 576 577 # Create a sizer to manage the Canvas and message window 578 MainSizer = wx.BoxSizer(wx.VERTICAL) 579 MainSizer.Add(self.browser, 4, wx.EXPAND) 580 581 self.SetSizer(MainSizer) 582 self.Bind(wx.EVT_CLOSE, self.on_close) 583 584 self.EventsAreBound = False 585 586 # getting all the colors for random objects 587 # wxlib.colourdb.updateColourDB() 588 #self.colors = wxlib.colourdb.getColourList() 589 590 return None 591 592 def make_browser(self): 593 # Create Browser widget here 594 buttons = [ # ('Add new OD flow', self.on_add_new, 'Add a new flow by defining zones of origin, destination and number of trips in table.'), 595 ('Save flows', self.on_add, 'Save OD flows to current demand.'), 596 ('Cancel', self.on_close, 'Close wizzard without adding flows.'), 597 ] 598 defaultbuttontext = 'Save flows' 599 # standartbuttons=['cancel','apply','ok']# apply does not show 600 standartbuttons = ['apply'] 601 602 browser = ObjPanel(self, self.wizzard, 603 attrconfigs=None, 604 id=None, ids=None, 605 groupnames=None, 606 func_change_obj=None, 607 show_groupnames=False, show_title=False, 608 is_modal=True, 609 mainframe=None, 610 pos=wx.DefaultPosition, 611 size=wx.DefaultSize, 612 style=wx.MAXIMIZE_BOX | wx.RESIZE_BORDER, 613 immediate_apply=False, # True, 614 panelstyle='default', 615 buttons=buttons, 616 standartbuttons=standartbuttons, 617 defaultbutton=defaultbuttontext, 618 ) 619 return browser 620 621 def on_import_csv(self, event=None): 622 # print 'on_import_csv' 623 self.browser.apply() 624 wizzard = self.browser.obj 625 626 wildcards_all = "CSV files (*.csv)|*.csv|CSV files (*.txt)|*.txt|All files (*.*)|*.*" # +"|"+otherwildcards 627 dlg = wx.FileDialog(self.parent, message="Import CSV file", 628 defaultDir=self.dirpath, 629 defaultFile="", 630 wildcard=wildcards_all, 631 style=wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR 632 ) 633 634 # Show the dialog and retrieve the user response. If it is the OK response, 635 # process the data. 636 if dlg.ShowModal() == wx.ID_OK: 637 # This returns a Python list of files that were selected. 638 paths = dlg.GetPaths() 639 # print 'You selected %d files:' % len(paths) 640 if len(paths) > 0: 641 filepath = paths[0] 642 else: 643 filepath = '' 644 dlg.Destroy() 645 else: 646 return 647 ### 648 wizzard.import_csv(filepath) 649 ## 650 651 self.refresh_browser() 652 # 653 self.Raise() 654 # self.SetFocus() 655 # self.MakeModal(False) 656 # self.MakeModal(True) 657 # self.browser.restore() 658 659 def on_add_new(self, event=None): 660 # print 'on_add,AddOdm',self.browser.obj 661 self.browser.apply() # important to transfer widget values to obj! 662 wizzard = self.browser.obj 663 wizzard.on_add_row() 664 self.refresh_browser() 665 666 def on_add(self, event=None): 667 # print 'on_add,AddOdm',self.browser.obj 668 self.browser.apply() # important to transfer widget values to obj! 669 wizzard = self.browser.obj 670 wizzard.add_demand() 671 672 self.on_close(event) 673 674 def on_close(self, event=None): 675 self.MakeModal(False) 676 self.Destroy() 677 pass 678 679 def on_add_close(self, event=None): 680 self.on_add() 681 self.on_close() 682 683 def refresh_browser(self): 684 """ 685 Deletes previous conents 686 Builds panel for obj 687 Updates path window and history 688 """ 689 # print 'Wizzard.refresh_panel with',obj.ident 690 # remove previous obj panel 691 sizer = self.GetSizer() 692 sizer.Remove(0) 693 self.browser.Destroy() 694 #del self.browser 695 self.browser = self.make_browser() 696 697 sizer.Add(self.browser, 1, wx.GROW) 698 699 self.Refresh() 700 # sizer.Fit(self) 701 sizer.Layout() 702 # add to history 703