Path: blob/main/tools/contributed/sumopy/agilepy/lib_wx/processdialog.py
169689 views
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo1# Copyright (C) 2016-2025 German Aerospace Center (DLR) and others.2# SUMOPy module3# Copyright (C) 2012-2021 University of Bologna - DICAM4# This program and the accompanying materials are made available under the5# terms of the Eclipse Public License 2.0 which is available at6# https://www.eclipse.org/legal/epl-2.0/7# This Source Code may also be made available under the following Secondary8# Licenses when the conditions for such availability set forth in the Eclipse9# Public License 2.0 are satisfied: GNU General Public License, version 210# or later which is available at11# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html12# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later1314# @file processdialog.py15# @author Joerg Schweizer16# @date 2012171819import wx20import os21import objpanel22from wxmisc import AgileStatusbar232425class ProcessDialogMixin:2627def get_status(self):28return self.process.status2930def clear_log(self):31self.get_logger().w('', 'message')32self.get_logger().w('', 'action')3334def copy_options_to_results(self, results):35# TODO36pass3738def on_save_options(self, event):39"""40Save current options to file.41"""42dlg = wx.FileDialog(43self, message="Save Options as ...",44# defaultDir=os.getcwd(),45# defaultFile="",46wildcard='Python obj files (*.obj)|*.obj|All files (*.*)|*.*',47style=wx.SAVE | wx.CHANGE_DIR48)4950# This sets the default filter that the user will initially see. Otherwise,51# the first filter in the list will be used by default.52dlg.SetFilterIndex(0)5354# Show the dialog and retrieve the user response. If it is the OK response,55# process the data.56if dlg.ShowModal() == wx.ID_OK:57filepath = dlg.GetPath()58self.process.save_options(filepath)5960def on_load_options(self, event):61"""62Load previously saved options from file.63"""6465dlg = wx.FileDialog(self, message="Open object",66# defaultDir=os.getcwd(),67# defaultFile="",68wildcard='Python obj files (*.obj)|*.obj|All files (*.*)|*.*',69style=wx.OPEN | wx.CHANGE_DIR70)7172# Show the dialog and retrieve the user response. If it is the OK response,73# process the data.74if dlg.ShowModal() == wx.ID_OK:75# This returns a Python list of files that were selected.76filepath = dlg.GetPath()77self.process.load_options(filepath)7879self.restore()808182class ProcessDialog(ProcessDialogMixin, objpanel.ObjPanelDialog):83def __init__(self, parent,84process,85attrconfigs=None,86tables=None,87table=None, id=None, ids=None,88groupnames=None, show_groupnames=False,89title=None, size=wx.DefaultSize, pos=wx.DefaultPosition,90style=wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER,91choose_id=False, choose_attr=False,92func_choose_id=None, func_change_obj=None, panelstyle='default',93immediate_apply=True):9495self.process = process96if title is None:97title = process.get_name()9899buttons, defaultbutton, standartbuttons = self._get_buttons()100101objpanel.ObjPanelDialog.__init__(self, parent, process,102attrconfigs=None,103id=None, ids=None,104groupnames=['options', 'inputparameters'],105show_groupnames=False,106title=title, size=(800, 400), pos=wx.DefaultPosition,107style=wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER,108choose_id=False, choose_attr=False,109func_choose_id=None,110func_change_obj=None,111panelstyle='default',112immediate_apply=immediate_apply,113buttons=buttons,114standartbuttons=standartbuttons,115defaultbutton=defaultbutton,116)117118def _get_buttons(self):119buttons = [('Run', self.on_run, 'Start the process!'),120#('Kill', self.on_kill, 'Kill process in background.'),121('Apply', self.on_apply, 'Apply current options, complete them and make them consistent, but do not run.'),122('Save Options...', self.on_save_options, self.on_save_options.__doc__),123('Load Options...', self.on_load_options, self.on_load_options.__doc__),124]125defaultbutton = 'Run'126standartbuttons = ['cancel', ]127128return buttons, defaultbutton, standartbuttons129130def get_process(self):131return self.process132133def on_run(self, event=None):134self.on_apply()135self.process.run()136if self.process.status == 'success':137self.Destroy()138139def on_kill(self, event=None):140self.process.kill()141142def on_apply(self, event=None):143self.process.update_params()144self.restore()145146def recreate_panel_proc(self, obj=None,147attrconfigs=None,148tables=None,149table=None, id=None, ids=None,150groupnames=None, show_groupnames=False,151show_title=True,152is_modal=False,153immediate_apply=False,154panelstyle='default',155func_change_obj=None,156func_choose_id=None,157func_choose_attr=None,158**buttonargs):159"""160Recreates panel and destroys previous contents:161attr = a list ith attribute names to be shown162groups = list with group names to be shown163show_groupnames = the group names are shown164together with the respective attributes165is_modal = if true the panel will be optimized for dialog window166immediate_apply = changes to widgets will be immediately applied to167obj attribute without pressing apply168buttonargs = a dictionary with arguments for botton creation169obj = the object to be displayed170id = used if there is only one single id to be displayed171ids = used if a selection of ids need to be displayed172func_change_obj = function to be called if user clicks on on object173with obj as argument174func_choose_id = function to be called when user clicks on id(table row)175with id as argument176func_choose_attr = function to be called when user clicks on attribute177with attr as argument. In this case the attribute178names of scalars turn into buttons. Array attributes179are selected by clicking on the column name.180"""181# print 'ProcessDialog.recreate_panel',groupnames182# for attrconfig in obj.get_attrman().get_configs():183# print ' attrconfig.attrname',attrconfig.attrname184#self.id = id185#self.ids = ids186self.obj = obj187self.func_change_obj = func_change_obj188self.func_choose_id = func_choose_id189self.func_choose_attr = func_choose_attr190self._show_title = show_title191192if (attrconfigs is None) & (tables in (None, [])) & (table is None):193attrconfigs = obj.get_attrman().get_configs()194if not self._show_title:195# titels of groupname are not shown so just196# select attributes at this stage197attrconfig_new = []198for attrconfig in attrconfigs:199# print ' attrconfig.attrname',attrconfig.attrname200is_shown = False201for groupname in attrconfig.groupnames:202# print ' comp:',attrconfig.attrname,groupname,groupname in groupnames203if groupname in groupnames:204is_shown = True205break206207if is_shown:208attrconfig_new.append(attrconfig)209attrconfigs = attrconfig_new210211tables = None # obj.get_tablemans()212213# print 'is_scalar_panel & is_multitab'214215sizer = self.init_notebook()216self.add_scalarpage(attrconfigs=attrconfigs, groupnames=groupnames,217id=id, immediate_apply=immediate_apply, panelstyle=panelstyle,218is_modal=is_modal, show_title=show_title,219show_buttons=False, **buttonargs)220221for table in tables:222self.add_tablepage(table, groupnames=groupnames)223224self.show_notebook()225sizer = self.GetSizer()226self.add_buttons(self, sizer,227is_modal=is_modal,228**buttonargs)229# some widgets like color need this to expand into their maximum space230self.restore()231return True232233234class ProcessDialogInteractive(ProcessDialogMixin, wx.Frame):235236"""237A frame used for the ObjBrowser Demo238239"""240241def __init__(self, parent,242process,243title=None,244func_close=None,245is_close_after_completion=True,246):247248if title is None:249title = process.get_name()250wx.Frame.__init__(self, parent, -1, title=title, pos=wx.DefaultPosition, size=wx.DefaultSize)251252self.parent = parent253self.process = process254255self.func_close = func_close256# if self.func_close is None:257self.is_close_after_completion = is_close_after_completion258# else:259# self.is_close_after_completion = False260#self._is_run = False261262self.Bind(wx.EVT_TIMER, self.on_step)263self.timer = wx.Timer(self)264# Set up the MenuBar265#MenuBar = wx.MenuBar()266#file_menu = wx.Menu()267#item = file_menu.Append(-1, "&Import CSV...","Import OD data from a CSV text file with format <zonename orig>, <zonename dest>,<number of trips>")268#self.Bind(wx.EVT_MENU, self.on_import_csv, item)269#item = file_menu.Append(-1, "&Import Exel...","Import OD data from an Exel file.")270#self.Bind(wx.EVT_MENU, self.on_import_exel, item)271#help_menu = wx.Menu()272# item = help_menu.Append(-1, "&About",273# "More information About this program")274#self.Bind(wx.EVT_MENU, self.on_menu, item)275#MenuBar.Append(help_menu, "&Help")276# self.SetMenuBar(MenuBar)277278#################################################################279# create statusbar280#self.statusbar = AgileStatusbar(self)281self.statusbar = AgileStatusbar(self, fields=[ # ('action',-4),282('message', -10),283# ('coords',-1),284# ('zoom',-1),285('progress', -3),286('status', -1),287# ('coords',-1),288])289self.SetStatusBar(self.statusbar)290# self.count=0.0291292logger = process.get_logger()293self.oldprogressfunc = logger.get_clallbackfunc('progress')294logger.add_callback(self.show_progress, 'progress')295296self.oldmessagefunc = logger.get_clallbackfunc('message')297logger.add_callback(self.write_message, 'message')298299#################################################################300# create toolbar301302# self.init_toolbar(size=size_toolbaricons)303304self.browser = self.make_browser()305306# Create a sizer to manage the Canvas and message window307MainSizer = wx.BoxSizer(wx.VERTICAL)308MainSizer.Add(self.browser, 4, wx.EXPAND)309310self.SetSizer(MainSizer)311self.Bind(wx.EVT_CLOSE, self.on_close)312#self.Bind(wx.EVT_IDLE, self.on_idle)313314self.EventsAreBound = False315316# getting all the colors for random objects317# wxlib.colourdb.updateColourDB()318#self.colors = wxlib.colourdb.getColourList()319320return None321322def _get_buttons(self):323if hasattr(self.process, 'step'):324buttons = [('Start', self.on_start, 'Start the process!'),325('Stop', self.on_stop, 'Stop process.'),326('Step', self.on_singlestep, 'Make a single step.'),327('Done', self.on_done, 'Stop process and close window.'),328]329defaultbutton = 'Start'330331else:332if self.is_close_after_completion:333buttons = [('Run', self.on_start, 'Start the process!'),334]335else:336buttons = [('Run', self.on_start, 'Start the process!'),337('Done', self.on_done, 'Finish with process and close window.'),338]339defaultbutton = 'Run'340341buttons.append(('Cancel', self.on_close, 'Close window, without running the process.'))342# standartbuttons=['cancel'] # uses also standard on_cancel :(343standartbuttons = []344return buttons, defaultbutton, standartbuttons345346# def on_idle(self,event):347# print 'on_idle'348#349# if self._is_run:350# self.process.step()351# if self.process.status=='success':352# self._is_run = False353# self.Destroy()354355def on_start(self, event=None):356self.browser.apply()357if self.process.status != 'running':358self.process.update_params()359# self.refresh_browser()360361# TODO: check whether to use ALWAYS run to put process in running mode362if hasattr(self.process, 'step'):363self.process.do()364else:365self.process.run()366367# no closing function defined368if self.is_close_after_completion:369self.on_close(event)370371# print 'on_start: after preparation self.process.status=',self.process.status372373if hasattr(self.process, 'step'):374self.timer.Start(1)375376# while self.process.status=='running':377# print 'call step'378# self.process.step()379380# if self.process.status=='running':381# # this will call step method in on_idle382# self._is_run = True383#384# elif self.process.status=='preparation':385# self.process.update_params()386# self.refresh_browser()387# self.process.run()388389def on_step(self, event=None):390if self.process.status == 'running':391# print 'call step'392self.process.step()393else:394print ' Simulation finished'395self.timer.Stop()396397def on_stop(self, event=None):398self.timer.Stop()399400def on_singlestep(self, event=None):401if self.process.status == 'running':402if hasattr(self.process, 'step'):403wx.FutureCall(1, self.process.step)404405def on_close(self, event=None):406# print 'on_close',self.process.status407if self.process.status == 'running':408self.process.aboard()409# print ' aboarded.'410411self.MakeModal(False)412# print ' call func_close',self.func_close413if self.func_close is not None:414self.func_close(self)415416# print ' reput callbacks to main'417if self.oldprogressfunc is not None:418self.process.get_logger().add_callback(self.oldprogressfunc, 'progress')419420if self.oldmessagefunc is not None:421self.process.get_logger().add_callback(self.oldmessagefunc, 'message')422423# print ' call destroy'424self.Destroy()425# self.Close() # no effect426427def on_done(self, event=None):428# print 'on_done',self.process.status429self.on_close(event)430431def on_cancel(self, event):432"""433Apply values, destroy itself and parent434"""435# print 'on_cancel'436self.on_close(event)437438def on_kill(self, event=None):439# self.process.kill()440pass441442def show_progress(self, percent, **kwargs):443"""444Shows progress on progress bar. Plug-in funcion for logger.445"""446# print 'show_progress',percent447self.statusbar.set_progress(percent)448# self.Refresh()449# wx.Yield()450# self.Update()451452def write_message(self, text, **kwargs):453print 'write_message', text454self.statusbar.write_message(text)455456def make_browser(self):457458buttons, defaultbutton, standartbuttons = self._get_buttons()459browser = objpanel.ObjPanel(self, self.process,460attrconfigs=None,461id=None, ids=None,462groupnames=['options', 'inputparameters'],463func_change_obj=None,464show_groupnames=False, show_title=False,465is_modal=True,466mainframe=None,467pos=wx.DefaultPosition,468size=wx.DefaultSize,469style=wx.MAXIMIZE_BOX | wx.RESIZE_BORDER,470immediate_apply=False, # True,471panelstyle='default',472buttons=buttons,473standartbuttons=standartbuttons,474defaultbutton=defaultbutton,475)476return browser477478def refresh_browser(self):479"""480Deletes previous conents481Builds panel for obj482Updates path window and history483"""484# print 'Wizzard.refresh_panel with',obj.ident485# remove previous obj panel486sizer = self.GetSizer()487sizer.Remove(0)488self.browser.Destroy()489#del self.browser490self.browser = self.make_browser()491492sizer.Add(self.browser, 1, wx.GROW)493494self.Refresh()495# sizer.Fit(self)496sizer.Layout()497# add to history498499500