diff --git a/Components.py b/Components.py index ed53b7ca..ce7427c7 100644 --- a/Components.py +++ b/Components.py @@ -68,9 +68,9 @@ def getClassMember(python_file = ''): if inspect.ismodule(module): ## classes composing the imported module return dict(inspect.getmembers(module, inspect.isclass)) + ### exception in module - else: - return module + return module def GetClass(elem): """ Get python class from filename. @@ -124,9 +124,9 @@ def GetArgs(cls = None): if inspect.isclass(cls): constructor = inspect.getargspec(cls.__init__) return dict(list(zip(constructor[0][1:], constructor[3]))) if constructor[3] != None else {} - else: - #sys.stderr.write(_("Error in GetArgs: First parameter is not a class\n")) - return None + + #sys.stderr.write(_("Error in GetArgs: First parameter is not a class\n")) + return None ########################################################### ### @@ -726,8 +726,7 @@ def updateDEVSPriorityList(self): ### if devs instance is not none and priority_list has been invoked (else componentSet order is considered) if self.priority_list != []: - shape_list = self.GetShapeList() - block_list = [c for c in shape_list if isinstance(c, Block)] + block_list = [c for c in self.GetShapeList() if isinstance(c, Block)] label_list = [m.label for m in block_list] diff --git a/Container.py b/Container.py index 684d2878..74f87973 100644 --- a/Container.py +++ b/Container.py @@ -242,13 +242,12 @@ def CheckClass(m): ### check cls error if isinstance(cls, tuple): return cls - else: - ### check devs instance - devs = getInstance(cls, args) + ### check devs instance + devs = getInstance(cls, args) - ### check instance error - return devs if isinstance(devs, tuple) or isinstance(devs, Exception) else None + ### check instance error + return devs if isinstance(devs, (tuple, Exception)) else None ################################################################ # # @@ -392,7 +391,7 @@ def makeDEVSInstance(diagram = None): ### shape list of diagram shape_list = diagram.GetShapeList() - block_list = (c for c in shape_list if isinstance(c, Block)) + block_list = {c for c in shape_list if isinstance(c, Block)} ### for all codeBlock shape, we make the devs instance for m in block_list: @@ -742,7 +741,7 @@ def checkDEVSInstance(self, diagram=None, D={}): """ ### shape list of diagram - shape_list = diagram.GetShapeList() + shape_list = set(diagram.GetShapeList()) #### for all codeBlock and containerBlock shapes, we make the devs instance for m in [s for s in shape_list if isinstance(s, (CodeBlock, ContainerBlock))]: @@ -787,7 +786,8 @@ def OnCheck(self, event): ### no models in diagram else: wx.MessageBox(_("Diagram is empty.\n\nPlease, drag-and-drop model from libraries control panel to build a diagram or load an existing diagram."),_('Error Manager')) - + + @BuzyCursorNotification def OnSimulation(self, event): """ Method calling the simulationGUI """ @@ -806,7 +806,7 @@ def OnSimulation(self, event): diagram = self ### Check if all models doesn't contain errors - D = self.DoCheck() + D = None #self.DoCheck() ### if there is no error in models if D is not None: @@ -818,7 +818,7 @@ def OnSimulation(self, event): playSound(SIMULATION_ERROR_SOUND_PATH) if dial.ShowModal() == wx.ID_YES: - frame = CheckerGUI.CheckerGUI(win, self.DoCheck()) + frame = CheckerGUI.CheckerGUI(win, D) frame.SetDiagram(self) frame.Show() @@ -1006,29 +1006,24 @@ def update(self, concret_subject = None): def PopShape(self,index=-1): """ Function that pop the shape at the index position """ - return self.shapes.pop(index) def DeleteAllShapes(self): """ Method that delete all shapes """ - del self.shapes[:] - self.modify = True self.parent.DiagramModified() def ChangeShapeOrder(self, shape, pos=0): """ """ - self.shapes.remove(shape) self.shapes.insert(pos,shape) def GetCount(self): """ Function that return the number of shapes that composed the diagram """ - return len(self.shapes) def GetFlatBlockShapeList(self, l=[]): @@ -1067,7 +1062,6 @@ def GetShapeByLabel(self, label=''): def GetShapeList(self): """ Function that return the shapes list """ - return self.shapes def GetConnectionShapeGenerator(self): @@ -1078,56 +1072,52 @@ def GetConnectionShapeGenerator(self): def GetBlockCount(self): """ Function that return the number of Block shape """ - return self.GetCodeBlockCount()+self.GetContainerBlockCount() def GetCodeBlockCount(self): """ Function that return the number of codeBlock shape """ - return self.deletedCodeBlockId.pop() if self.deletedCodeBlockId else self.nbCodeBlock def GetContainerBlockCount(self): """ Function that return the number of containerBlock shape """ - return self.deletedContainerBlockId.pop() if self.deletedContainerBlockId else self.nbContainerBlock def GetiPortCount(self): """ Function that return the number of iPort shape """ - return self.deletediPortId.pop() if self.deletediPortId else self.nbiPort def GetoPortCount(self): """ Function that return the number of oPort shape """ - return self.deletedoPortId.pop() if self.deletedoPortId else self.nboPort def Clean(self): """ Clean DEVS instances attached to all block model in the diagram. """ + if not self.devsModel: + return - if self.devsModel: - for devs in [a for a in list(self.devsModel.getFlatComponentSet().values()) if hasattr(a, 'finish')]: - try: - Publisher.unsubscribe(devs.finish, "%d.finished"%(id(devs))) - except: - sys.stdout.write(_("Impossible to execute the finish method for the model %s!\n")%devs) - devs.finish(None) - - self.devsModel.setComponentSet([]) + for devs in [a for a in list(self.devsModel.getFlatComponentSet().values()) if hasattr(a, 'finish')]: + try: + Publisher.unsubscribe(devs.finish, "%d.finished"%(id(devs))) + except: + sys.stdout.write(_("Impossible to execute the finish method for the model %s!\n")%devs) + devs.finish(None) - for m in self.GetShapeList(): - m.setDEVSModel(None) + self.devsModel.setComponentSet([]) - if isinstance(m, ConnectionShape): - m.input[0].setDEVSModel(None) - m.output[0].setDEVSModel(None) + for m in self.GetShapeList(): + m.setDEVSModel(None) - if isinstance(m, ContainerBlock): - m.Clean() + if isinstance(m, ConnectionShape): + m.input[0].setDEVSModel(None) + m.output[0].setDEVSModel(None) + + if isinstance(m, ContainerBlock): + m.Clean() def GetStat(self, d): """ Get information about diagram like the numbe rof atomic model or the number of link between models. @@ -1272,7 +1262,7 @@ def move(self,x,y): if not self.lock_flag: self.x = array.array('d', [v+x for v in self.x]) self.y = array.array('d', [v+y for v in self.y]) - + #def OnResize(self): # """ Resize method controled by ResizeNode move method # """ @@ -2577,6 +2567,48 @@ def DiagramModified(self): tb = win.GetToolBar() tb.EnableTool(Menu.ID_SAVE, self.diagram.modify) + def ShowQuickAttributeEditor(self): + """ + """ + # mouse positions + xwindow, ywindow = wx.GetMousePosition() + + xm,ym = self.ScreenToClient(wx.Point(xwindow, ywindow)) + + mainW = self.GetTopLevelParent() + + flag = True + ### find if window exists on the top of model, then inactive the QuickAttributeEditor + for win in [w for w in mainW.GetChildren() if w.IsTopLevel()]: + if win.IsActive(): + flag = False + + if self.f: + self.f.Close() + self.f = None + + if flag: + for s in {m for m in self.diagram.GetShapeList() if isinstance(m, Block) and self.isSelected(m)}: + x = s.x[0]*self.scalex + y = s.y[0]*self.scaley + w = (s.x[1]-s.x[0])*self.scalex + h = (s.y[1]-s.y[0])*self.scaley + + # if mousse over hight the shape + try: + + if (x<=xm and xm < x+w) and (y<=ym and ym < y+h): + #if self.isSelected(s) and flag: + self.f = QuickAttributeEditor(self, wx.NewIdRef(), s) + self.timer.Start(1000) + break + else: + if self.timer.IsRunning(): + self.timer.Stop() + + except AttributeError as info: + raise AttributeError(_("use >= wx-2.8-gtk-unicode library: %s")%info) + ### def OnMotion(self, event): """ Motion manager. @@ -2586,65 +2618,9 @@ def OnMotion(self, event): self.diagram.modify = False - point = self.getEventCoordinates(event) - x = point[0] - self.currentPoint[0] - y = point[1] - self.currentPoint[1] - - for s in self.getSelectedShapes(): - s.move(x,y) - - ### change cursor when resizing model - if isinstance(s, ResizeableNode): - self.SetCursor(wx.StockCursor(wx.CURSOR_SIZING)) - - ### change cursor when connectionShape hit a node - elif isinstance(s, ConnectionShape): - ### dot trace to prepare connection - if len(s.pen)>2: - s.pen[2]= wx.PENSTYLE_DOT - - self.SetCursor(wx.StockCursor(wx.CURSOR_HAND)) - - for node in [n for n in self.nodes if isinstance(n, ConnectableNode)]: - if node.HitTest(point[0], point[1]): - self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS)) - #else: - #self.SetCursor(wx.StockCursor(wx.CURSOR_HAND)) - - ## list of shape connected to the connectionShape (for exclude these of the catching engine) - #L = s.input or () - #L += s.output or () - - #### try to catch connectionShape with block - #for ss in filter(lambda n: (isinstance(n, Block) or isinstance(n, Port) ) and n not in L, self.diagram.shapes): - #touch = False - #for line in range(len(s.x)-1): - #try: - #### get a and b coeff for linear equation - #a = (s.y[line]-s.y[line+1])/(s.x[line]-s.x[line+1]) - #b = s.y[line] -a*s.x[line] - #### X and Y points of linear equation - #X = range(int(s.x[line]), int(s.x[line+1])) - #Y = map(lambda x: a*x+b,X) - ## if one point of the connectionShape hit the shape, we chage its geometry - #for px,py in zip(X, Y): - #if ss.HitTest(px,py): - #touch=True - #except ZeroDivisionError: - #pass - ## if ss is crossed, we add it on the containerShape touch_list - #if touch: - #if ss not in s.touch_list: - #s.touch_list.append(ss) - else: - self.SetCursor(wx.StockCursor(wx.CURSOR_HAND)) - pass - - self.diagram.modify = True - - self.currentPoint = point - - if self.getSelectedShapes() == []: + sc = self.getSelectedShapes() + + if len(sc) == 0: # User is dragging the mouse, check if # left button is down if self.HasCapture(): @@ -2654,73 +2630,56 @@ def OnMotion(self, event): dc = wx.ClientDC(self) odc = wx.DCOverlay(self.overlay, dc) odc.Clear() - if wx.VERSION_STRING < '4.0': - ctx = wx.GraphicsContext_Create(dc) - else: - ctx = wx.GraphicsContext.Create(dc) + ctx = wx.GraphicsContext.Create(dc) ctx.SetPen(wx.GREY_PEN) ctx.SetBrush(wx.Brush(wx.Colour(229,229,229,80))) - if wx.VERSION_STRING < '4.0': - ctx.DrawRectangle(*wx.RectPP(self.selectionStart, event.Position)) - else: - try: - ctx.DrawRectangle(*wx.Rect(self.selectionStart, event.Position)) - except TypeError: - pass + + try: + ctx.DrawRectangle(*wx.Rect(self.selectionStart, event.Position)) + except TypeError: + pass del odc else: self.Refresh() else: - ### refresh all canvas with Flicker effect corrected in OnPaint and OnEraseBackground - self.Refresh() - - # gestion du pop up pour la modification du nombre de port - else: - - # mouse postions - xwindow, ywindow = wx.GetMousePosition() + point = self.getEventCoordinates(event) + x = point[0] - self.currentPoint[0] + y = point[1] - self.currentPoint[1] - if wx.VERSION_STRING < '4.0': - xm,ym = self.ScreenToClientXY(xwindow, ywindow) - else: - xm,ym = self.ScreenToClient(wx.Point(xwindow, ywindow)) + for s in sc: + s.move(x,y) - mainW = self.GetTopLevelParent() + ### change cursor when resizing model + if isinstance(s, ResizeableNode): + self.SetCursor(wx.StockCursor(wx.CURSOR_SIZING)) - flag = True - ### find if window exists on the top of model, then inactive the QuickAttributeEditor - for win in [w for w in mainW.GetChildren() if w.IsTopLevel()]: - if win.IsActive(): - flag = False + ### change cursor when connectionShape hit a node + elif isinstance(s, ConnectionShape): + ### dot trace to prepare connection + if len(s.pen)>2: + s.pen[2]= wx.PENSTYLE_DOT - if self.f: - self.f.Close() - self.f = None + self.SetCursor(wx.StockCursor(wx.CURSOR_HAND)) - for s in [m for m in self.diagram.GetShapeList() if isinstance(m, Block)]: - x = s.x[0]*self.scalex - y = s.y[0]*self.scaley - w = (s.x[1]-s.x[0])*self.scalex - h = (s.y[1]-s.y[0])*self.scaley + for node in [n for n in self.nodes if isinstance(n, ConnectableNode)]: + if node.HitTest(point[0], point[1]): + self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS)) + else: + self.SetCursor(wx.StockCursor(wx.CURSOR_HAND)) - # if mousse over hight the shape - try: + self.diagram.modify = True + self.currentPoint = point - if (x<=xm and xm < x+w) and (y<=ym and ym < y+h): - if self.isSelected(s) and flag: - self.f = QuickAttributeEditor(self, wx.NewIdRef(), s) - self.timer.Start(1200) - break - else: - if self.timer.IsRunning(): - self.timer.Stop() + ### refresh all canvas with Flicker effect corrected in OnPaint and OnEraseBackground + self.Refresh() - except AttributeError as info: - raise AttributeError(_("use >= wx-2.8-gtk-unicode library: %s")%info) + # pop-up to change the number of ports + else: + self.ShowQuickAttributeEditor() - self.DiagramModified() + #self.DiagramModified() # def SetDiagram(self, diagram): # """ Setter for diagram attribute. @@ -4141,6 +4100,25 @@ 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. """ @@ -4165,13 +4143,7 @@ def __init__(self, item, index, cf): """ ConnectableNode.__init__(self, item, index, cf) - self.label = "in%d"%self.index - - def OnRightDown(self, event): - """ Right Down event has been received. - """ - pass - #event.Skip() + self.label = f"in{self.index}" def move(self, x, y): """ Move method. diff --git a/DropTarget.py b/DropTarget.py index ddb1f1c9..994dc740 100644 --- a/DropTarget.py +++ b/DropTarget.py @@ -68,7 +68,7 @@ def OnDragOver(self,x,y,d): """ ### list of ContainerBlock shape in canvas - L = [s for s in self.canvas.diagram.GetShapeList() if isinstance(s, Container.ContainerBlock)] + L = {s for s in self.canvas.diagram.GetShapeList() if isinstance(s, Container.ContainerBlock)} ### for all ContainerBlock we make a rect and test if the point x,y is in this rect to instance the DetachedFrame for shape in L: @@ -154,7 +154,7 @@ def OnData(self, x, y, d): block_list.append(m) ### list of ContainerBlock shape in canvas - L = [s for s in self.canvas.diagram.GetShapeList() if isinstance(s, Container.ContainerBlock)] + L = {s for s in self.canvas.diagram.GetShapeList() if isinstance(s, Container.ContainerBlock)} ### for all ContainerBlock we make a rect and test if the point x,y is in this rect to instance the DetachedFrame for shape in L: diff --git a/Editor.py b/Editor.py index 3a8c1780..ec1107b0 100644 --- a/Editor.py +++ b/Editor.py @@ -879,9 +879,9 @@ def __PageChanged(self, evt): try: canvas = self.GetPage(self.GetSelection()) - ### permet d'activer les redo et undo pour chaque page - self.parent.tb.EnableTool(wx.ID_UNDO, not len(canvas.stockUndo) == 0) - self.parent.tb.EnableTool(wx.ID_REDO, not len(canvas.stockRedo) == 0) + ### allows to activate redo and undo for each page + self.parent.tb.EnableTool(wx.ID_UNDO, len(canvas.stockUndo) != 0) + self.parent.tb.EnableTool(wx.ID_REDO, len(canvas.stockRedo) != 0) canvas.deselect() canvas.Refresh() @@ -2082,7 +2082,7 @@ def UpdateModule(self): info = ReloadModule.recompile(module_name) cp = self.nb.GetCurrentPage() - cp.error_flag = isinstance(info, Exception) or isinstance(info, str) + cp.error_flag = isinstance(info, (Exception, str)) if cp.error_flag: wx.MessageBox(_('Error saving file:\n%s')%str(info), \