diff --git a/AttributeEditor.py b/AttributeEditor.py index cf00f330..8eadb310 100644 --- a/AttributeEditor.py +++ b/AttributeEditor.py @@ -243,6 +243,8 @@ def __init__(self, parent, id, model): ### def __do_layout(self): + """ + """ sizer_1 = wx.BoxSizer(wx.HORIZONTAL) sizer_1.Add(self._sb_input, 0, wx.ADJUST_MINSIZE, 0) sizer_1.Add(self._sb_output, 0, wx.ADJUST_MINSIZE, 0) @@ -252,30 +254,42 @@ def __do_layout(self): ### def __set_binding(self): + """ + """ self._sb_input.Bind(wx.EVT_TEXT, self.OnInput) self._sb_output.Bind(wx.EVT_TEXT, self.OnOuput) self.Bind(wx.EVT_CLOSE, self.OnClose) @Post_Undo def OnInput(self, event): + """ + """ self.__state['input'] = self._sb_input.GetValue() self.notify() @Post_Undo def OnOuput(self, event): + """ + """ self.__state['output'] = self._sb_output.GetValue() self.notify() ### def GetState(self): + """ + """ return self.__state ### def Undo(self): + """ + """ self.canvas.Undo() ### def OnClose(self, event): + """ + """ self.Destroy() event.Skip() diff --git a/Components.py b/Components.py index ce7427c7..dc541fca 100644 --- a/Components.py +++ b/Components.py @@ -507,7 +507,7 @@ def Load(filename, label): else: ### mandatory due to the LoadFile call before m.label = label - + print(filename,m) return AMDComponent.ChekFilename(filename, m) @staticmethod diff --git a/Container.py b/Container.py index 74f87973..fbfcf42e 100644 --- a/Container.py +++ b/Container.py @@ -2780,8 +2780,20 @@ def select(self, item=None): item.OnSelect(None) if isinstance(item, Connectable): - self.nodes.extend([INode(item, n, self) for n in range(item.input)]) - self.nodes.extend([ONode(item, n, self) for n in range(item.output)]) + for n in range(item.input): + if n in item.getInputLabels(): + self.nodes.append(INode(item, n, self, item.getInputLabel(n))) + else: + self.nodes.append(INode(item, n, self)) + + for n in range(item.output): + if n in item.getOutputLabels(): + self.nodes.append(ONode(item, n, self, item.getOutputLabel(n))) + else: + self.nodes.append(ONode(item, n, self)) + + # self.nodes.extend([INode(item, n, self) for n in range(item.input)]) + # self.nodes.extend([ONode(item, n, self) for n in range(item.output)]) if isinstance(item, Resizeable): self.nodes.extend([ResizeableNode(item, n, self) for n in range(len(item.x))]) @@ -3203,7 +3215,6 @@ class ConnectionShape(LinesShape, Resizeable, Selectable, Structurable): """ ConnectionShape class """ - def __init__(self): """ Constructor """ @@ -3221,8 +3232,6 @@ def __init__(self): def __setstate__(self, state): """ Restore state from the unpickled state values. """ - - ####################################" Just for old model if 'touch_list' not in state: state['touch_list'] = [] if 'font' not in state: state['font'] = [FONT_SIZE, 74, 93, 700, u'Arial'] @@ -3231,19 +3240,28 @@ def __setstate__(self, state): self.__dict__.update(state) def setInput(self, item, index): + """ + """ self.input = (item, index) def setOutput(self, item, index): + """ + """ self.output = (item, index) def getInput(self): + """ + """ return self.input def getOutput(self): + """ + """ return self.output def draw(self, dc): - + """ + """ if self.input: self.x[0], self.y[0] = self.input[0].getPortXY('output', self.input[1]) @@ -3431,6 +3449,8 @@ def OnProperties(self, event): f.Show() def OnPluginsManager(self, event): + """ + """ canvas = event.GetEventObject() f = PluginsGUI.ModelPluginsManager( parent=canvas.GetParent(), id=wx.NewIdRef(), @@ -3534,6 +3554,12 @@ def update(self, concret_subject = None): i = diagram.priority_list.index(old_label) diagram.priority_list[i] = new_label + ### clear custom port labels if their number change + # if prop == 'input': + # self.setInputLabels({}) + # if prop == 'output': + # self.setOutputLabels({}) + ### clear manager : direct update only for image_path propertie if val not in ('',[],{}) or (prop == 'image_path' and val == ""): canvas = concret_subject.canvas @@ -3790,15 +3816,16 @@ def __setstate__(self, state): if 'label_pos' not in state: state['label_pos'] = 'center' if 'input_direction' not in state: state['input_direction'] = 'ouest' if 'output_direction' not in state: state['output_direction'] = 'est' - ############################################## + if '_input_labels' not in state: state['_input_labels'] = {} + if '_output_labels' not in state: state['_output_labels'] = {} + ############################################## self.__dict__.update(state) if new_class: self.__class__ = new_class + ### def __getstate__(self): - """ - """ """Return state values to be pickled.""" return Achievable.__getstate__(self) @@ -3808,7 +3835,7 @@ def __getattr__(self, name): """ if name == 'dump_attributes': #return ['model_path', 'python_path', 'args'] + self.GetAttributes() - return ['args'] + self.GetAttributes() + return ['args'] + Connectable.DUMP_ATTR + self.GetAttributes() #======================================================================= elif name == 'dump_abstr_attributes': ### Atomic model has no abstract attributes @@ -3817,9 +3844,9 @@ def __getattr__(self, name): else: raise AttributeError(name) - def draw(self, dc): - + """ + """ if self.selected: ### inform about the nature of the block using icon name = 'atomic3.png' if self.model_path != "" else 'pythonFile.png' if self.python_path.endswith('.py') else 'pyc.png' @@ -3832,7 +3859,6 @@ def draw(self, dc): def OnLeftDClick(self, event): """ On left double click event has been invoked. """ - self.OnProperties(event) event.Skip() @@ -3994,6 +4020,8 @@ def __setstate__(self, state): if 'label_pos' not in state:state['label_pos'] = 'center' if 'input_direction' not in state: state['input_direction'] = 'ouest' if 'output_direction' not in state: state['output_direction'] = 'est' + if '_input_labels' not in state: state['_intput_labels'] = {} + if '_output_labels' not in state: state['_output_labels'] = {} ##################################### self.__dict__.update(state) @@ -4009,7 +4037,7 @@ def __getattr__(self, name): if name == 'dump_attributes': #return ['shapes', 'priority_list', 'constants_dico', 'model_path', 'python_path','args'] + self.GetAttributes() - return ['shapes', 'priority_list', 'constants_dico','args'] + self.GetAttributes() + return ['shapes', 'priority_list', 'constants_dico','args'] + Connectable.DUMP_ATTR +self.GetAttributes() #======================================================================= elif name == 'dump_abstr_attributes': return Abstractable.DUMP_ATTR if hasattr(self, 'layers') and hasattr(self, 'current_level') else [] @@ -4017,9 +4045,9 @@ def __getattr__(self, name): else: raise AttributeError(name) - def draw(self, dc): - + """ + """ if self.selected: ### inform about the nature of the block using icon img = wx.Bitmap(os.path.join(ICON_PATH_16_16, 'coupled3.png'), wx.BITMAP_TYPE_ANY) @@ -4100,25 +4128,6 @@ def OnLeftDown(self, event): self.cf.deselect(self.item) event.Skip() - def OnRightDown(self, event): - """ Left Down click has been invoked - """ - ### dialog to ask new port label - - old_label = self.label - - d = wx.TextEntryDialog(None, _('New Label'), value = old_label, style=wx.OK) - d.ShowModal() - - ### new label - new_label = d.GetValue() - - ### only if new and old label are different - if new_label != old_label: - self.label = new_label - - event.Skip() - def HitTest(self,x,y): """ Collision detection method. """ @@ -4138,12 +4147,12 @@ class INode(ConnectableNode): """ INode(item, index, cf) """ - def __init__(self, item, index, cf): + def __init__(self, item, index, cf, label=None): """ Constructor. """ ConnectableNode.__init__(self, item, index, cf) - self.label = f"in{self.index}" + self.label = f"in{self.index}" if not label else label def move(self, x, y): """ Move method. @@ -4156,6 +4165,38 @@ def move(self, x, y): self.cf.showOutputs() self.cf.select(ci) + def OnRightDown(self, event): + """ Left Down click has been invoked + """ + ### dialog to ask new port label + + menu = Menu.NodePopupMenu(self) + ### Show popup_menu + canvas = event.GetEventObject() + canvas.PopupMenu(menu, event.GetPosition()) + ### destroy menu local variable + menu.Destroy() + + event.Skip() + + def OnEditLabel(self, event): + """ Function called by the OnRightDown call event function + """ + ### old label + old_label = self.label + + ### ask tne new label + d = wx.TextEntryDialog(None, _('New Input Label'), value = old_label, style=wx.OK) + d.ShowModal() + + ### new label + new_label = d.GetValue() + + ### only if new and old label are different + if new_label != old_label: + self.label = new_label + self.item.addInputLabels(self.index, self.label) + def leftUp(self, items): """ Left up action has been invocked. """ @@ -4211,12 +4252,12 @@ class ONode(ConnectableNode): """ ONode(item, index, cf) """ - def __init__(self, item, index, cf): + def __init__(self, item, index, cf, label=None): """ Constructor. """ ConnectableNode.__init__(self, item, index, cf) - self.label = "out%d"%self.index + self.label = "out%d"%self.index if not label else label def move(self, x, y): """ Moving method. @@ -4229,6 +4270,26 @@ def move(self, x, y): self.cf.showInputs() self.cf.select(ci) + def OnRightDown(self, event): + """ Left Down click has been invoked + """ + ### dialog to ask new port label + + old_label = self.label + + d = wx.TextEntryDialog(None, _('New Output Label'), value = old_label, style=wx.OK) + d.ShowModal() + + ### new label + new_label = d.GetValue() + + ### only if new and old label are different + if new_label != old_label: + self.label = new_label + self.item.addOutputLabels(self.index, self.label) + + event.Skip() + def leftUp(self, items): """ Left up action has been invocked """ @@ -4379,6 +4440,8 @@ def __setstate__(self, state): state['attributes'].insert(1,'label_pos') if 'output_direction' not in state: state['output_direction'] ="est" if 'input_direction' not in state: state['input_direction'] = "ouest" + if '_input_labels' not in state: state['_input_labels'] = {} + if '_output_labels' not in state: state['_output_labels'] = {} ############################################## self.__dict__.update(state) diff --git a/Menu.py b/Menu.py index 11b5c624..a0b5c9ca 100644 --- a/Menu.py +++ b/Menu.py @@ -699,6 +699,25 @@ def __init__(self, parent): ### Bind is not necessary because ID_EXIT_DAIGRAM and ID_DETACH_DIAGRAM are already binded +class NodePopupMenu(wx.Menu): + """ Node popup menu + """ + + def __init__(self, parent): + """ Constructor. + """ + wx.Menu.__init__(self) + + edit = wx.MenuItem(self, -1, _('Edit'), _('Edit label')) + + edit.SetBitmap(wx.Bitmap(os.path.join(ICON_PATH_16_16,'edit.png'))) + + AppendItem = self.AppendItem if wx.VERSION_STRING < '4.0' else self.Append + + AppendItem(edit) + + ### bind event with new OnDeletePage + self.Bind(wx.EVT_MENU, parent.OnEditLabel, edit) class PropertiesCtrlPopupMenu(wx.Menu): """ PropertiesCtrl popup menu. """ diff --git a/Mixins/Connectable.py b/Mixins/Connectable.py index dae1954c..1d002f26 100644 --- a/Mixins/Connectable.py +++ b/Mixins/Connectable.py @@ -23,16 +23,60 @@ class Connectable: """ Mixin to create connectable nodes or ports. """ + DUMP_ATTR = ['_input_labels','_output_labels'] ### - def __init__(self, nb_in = 1, nb_out = 3): + def __init__(self, nb_in:int=1, nb_out:int=3)->None: """ Constructor. """ self.input = nb_in self.output = nb_out + ### to store label of ports + self._input_labels = {} + self._output_labels = {} + + def getInputLabel(self, port:int)->str: + """ return the label of the input port n + """ + return self._input_labels[port] + + def getOutputLabel(self, port:int)->str: + """ return the label of the output port n + """ + return self._output_labels[port] + + def getInputLabels(self)->dict: + """ return the input label dict + """ + return self._input_labels + + def getOutputLabels(self)->dict: + """ return the output label dict + """ + return self._output_labels + + def setInputLabels(self,v:dict)->None: + """ set the input label dict + """ + self._input_labels = v + + def setOutputLabels(self, v:dict)->None: + """ set the output label dict + """ + self._output_labels = v + + def addInputLabels(self, port:int, label:str)->None: + """ add a label to the input port + """ + self._input_labels[port] = label + + def addOutputLabels(self, port:int, label:str): + """ add a label to the output port + """ + self._output_labels[port] = label ### - def getPortXY(self, type, num): + def getPortXY(self, type:str, num)->tuple: """ Return the tuple (x,y). """ diff --git a/PropertiesGridCtrl.py b/PropertiesGridCtrl.py index 6df6b9b9..3ea3b9c9 100644 --- a/PropertiesGridCtrl.py +++ b/PropertiesGridCtrl.py @@ -778,8 +778,10 @@ def OnRightClick(self, event): def OnGridColSort(self, event): """ """ - self.SetSortingColumn(event.Getcol()) - + try: + self.SetSortingColumn(event.Getcol()) + except AttributeError: + pass ### def OnEditCell(self, evt): """ diff --git a/ZipManager.py b/ZipManager.py index 8bc64776..2350620d 100644 --- a/ZipManager.py +++ b/ZipManager.py @@ -153,7 +153,7 @@ def Update(self, replace_files:[str]=[])->None: ### delete empty fileName replace_files = [f for f in replace_files if f!=''] - # call this function because : http://www.digi.com/wiki/developer/index.php/Error_messages + # call this function because: http://www.digi.com/wiki/developer/index.php/Error_messages Zip.ClearCache(self.fn) zin = zipfile.ZipFile(self.fn, 'r') @@ -176,6 +176,7 @@ def Update(self, replace_files:[str]=[])->None: except UnicodeDecodeError as info: zout.writestr(base_name, data) else: + exclude_file.append(replace_files.index(fn)) sys.stdout.write("%s not rewrite\n"%(fn)) #sys.stdout.write("update %s from compressed %s\n"%(base_name, fn))