Fix support for adjusting block size to block minimum size and to Viewer scaling
authorLaurent Bessard
Tue, 16 Oct 2012 11:34:24 +0200
changeset 852 1009f956d2ee
parent 851 666f5bdad301
child 853 0f97bddb5a30
Fix support for adjusting block size to block minimum size and to Viewer scaling
editors/Viewer.py
graphics/FBD_Objects.py
graphics/GraphicCommons.py
--- a/editors/Viewer.py	Mon Oct 15 17:05:19 2012 +0200
+++ b/editors/Viewer.py	Tue Oct 16 11:34:24 2012 +0200
@@ -501,11 +501,12 @@
     # Add Default Menu items to the given menu
     def AddDefaultMenuItems(self, menu, edit=False, block=False):
         if block:
-            [ID_EDIT_BLOCK, ID_DELETE] = [wx.NewId() for i in xrange(2)]
+            [ID_EDIT_BLOCK, ID_DELETE, ID_ADJUST_BLOCK_SIZE] = [wx.NewId() for i in xrange(3)]
         
             # Create menu items
             self.AddMenuItems(menu, [
                  (ID_EDIT_BLOCK, wx.ITEM_NORMAL, _(u'Edit Block'), '', self.OnEditBlockMenu),
+                 (ID_ADJUST_BLOCK_SIZE, wx.ITEM_NORMAL, _(u'Adjust Block Size'), '', self.OnAdjustBlockSizeMenu),
                  (ID_DELETE, wx.ITEM_NORMAL, _(u'Delete'), '', self.OnDeleteMenu)])
         
             menu.Enable(ID_EDIT_BLOCK, edit)
@@ -790,13 +791,17 @@
         self.Comments[comment.GetId()] = comment
 
     def IsBlock(self, block):
-        return self.Blocks.get(block.GetId(), False)
+        if block is not None:
+            return self.Blocks.get(block.GetId(), False)
+        return False
         
     def IsWire(self, wire):
         return self.Wires.get(wire, False)
         
     def IsComment(self, comment):
-        return self.Comments.get(comment.GetId(), False)
+        if comment is not None:
+            return self.Comments.get(comment.GetId(), False)
+        return False
 
     def RemoveBlock(self, block):
         self.Blocks.pop(block.GetId())
@@ -1237,8 +1242,7 @@
             self.AddBlock(element)
             connectors = element.GetConnectors()
         element.SetPosition(instance["x"], instance["y"])
-        if isinstance(element, SFC_Divergence):
-            element.SetSize(instance["width"], instance["height"])
+        element.SetSize(instance["width"], instance["height"])
         for i, output_connector in enumerate(instance["outputs"]):
             if i < len(connectors["outputs"]):
                 connector = connectors["outputs"][i]
@@ -1256,8 +1260,6 @@
                 if input_connector.get("edge", "none") != "none":
                     connector.SetEdge(input_connector["edge"])
                 self.CreateWires(connector, instance["id"], input_connector["links"], ids, selection)
-        if not isinstance(element, SFC_Divergence):
-            element.SetSize(instance["width"], instance["height"])
         if selection is not None and selection[0].get(instance["id"], False):
             self.SelectInGroup(element)
 
@@ -1521,6 +1523,14 @@
         if self.SelectedElement is not None:
             self.ParentWindow.EditProjectElement(ITEM_POU, "P::%s"%self.SelectedElement.GetType())
 
+    def OnAdjustBlockSizeMenu(self, event):
+        if self.SelectedElement is not None:
+            movex, movey = self.SelectedElement.SetBestSize(self.Scaling)
+            self.SelectedElement.RefreshModel()
+            self.RefreshBuffer()
+            if movex != 0 or movey != 0:
+                self.RefreshRect(self.GetScrolledRect(self.SelectedElement.GetRedrawRect(movex, movey)), False)
+
     def OnDeleteMenu(self, event):
         if self.SelectedElement is not None:
             self.SelectedElement.Delete()
@@ -1836,14 +1846,15 @@
                         else:
                             self.ParentWindow.OpenGraphicViewer(iec_path)
             elif event.ControlDown() and not event.ShiftDown():
-                instance_type = self.SelectedElement.GetType()
-                if self.IsBlock(self.SelectedElement) and instance_type in self.Controler.GetProjectPouNames(self.Debug):
-                    self.ParentWindow.EditProjectElement(ITEM_POU, 
-                        self.Controler.ComputePouName(instance_type))
-                else:
-                    self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling)
+                if not isinstance(self.SelectedElement, Group_Element):
+                    instance_type = self.SelectedElement.GetType()
+                    if self.IsBlock(self.SelectedElement) and instance_type in self.Controler.GetProjectPouNames(self.Debug):
+                        self.ParentWindow.EditProjectElement(ITEM_POU, 
+                            self.Controler.ComputePouName(instance_type))
+                    else:
+                        self.SelectedElement.OnLeftDClick(event, self.GetLogicalDC(), self.Scaling)
             elif event.ControlDown() and event.ShiftDown():
-                movex, movey = self.SelectedElement.AdjustToScaling(self.Scaling)
+                movex, movey = self.SelectedElement.SetBestSize(self.Scaling)
                 self.SelectedElement.RefreshModel()
                 self.RefreshBuffer()
                 if movex != 0 or movey != 0:
@@ -2468,6 +2479,7 @@
             self.RefreshBuffer()
             if old_name != values["name"]:
                 self.Controler.UpdateEditedElementUsedVariable(self.TagName, old_name, values["name"])
+                self.RefreshBuffer()
                 self.RefreshView(selection=({connection.GetId(): True}, {}))
             else:
                 self.RefreshScrollBars()
--- a/graphics/FBD_Objects.py	Mon Oct 15 17:05:19 2012 +0200
+++ b/graphics/FBD_Objects.py	Tue Oct 16 11:34:24 2012 +0200
@@ -690,38 +690,19 @@
     def GetExecutionOrder(self):
         return self.ExecutionOrder
     
-    # Changes the element size
-    def SetSize(self, width, height):
-        scaling = self.Parent.GetScaling()
-        min_width, min_height = self.GetMinSize()
-        if width < min_width:
-            if self.Type == INPUT:
-                posx = max(0, self.Pos.x + width - min_width)
-                if scaling is not None:
-                    posx = round_scaling(posx, scaling[0])
-                self.Pos.x = posx
-            elif self.Type == OUTPUT:
-                posx = max(0, self.Pos.x + (width - min_width) / 2)
-                if scaling is not None:
-                    posx = round_scaling(posx, scaling[0])
-                self.Pos.x = posx
-            width = min_width
-            if scaling is not None:
-                width = round_scaling(width, scaling[0], 1)
-        if height < min_height:
-            posy = max(0, self.Pos.y + (height - min_height) / 2)
-            if scaling is not None:
-                posy = round_scaling(posy, scaling[1])
-            self.Pos.y = posy
-            height = min_height
-            if scaling is not None:
-                height = round_scaling(height, scaling[1], 1)
-        Graphic_Element.SetSize(self, width, height)
-    
     # Returns the variable minimum size
     def GetMinSize(self):
         return self.NameSize[0] + 10, self.NameSize[1] + 10
     
+    # Set size of the variable to the minimum size
+    def SetBestSize(self, scaling):
+        if self.Type == INPUT:
+            return Graphic_Element.SetBestSize(self, scaling, x_factor=1.)
+        elif self.Type == OUTPUT:
+            return Graphic_Element.SetBestSize(self, scaling, x_factor=0.)
+        else:
+            return Graphic_Element.SetBestSize(self, scaling)
+    
     # Method called when a LeftDClick event have been generated
     def OnLeftDClick(self, event, dc, scaling):
         # Edit the variable properties
@@ -930,28 +911,12 @@
     def GetName(self):
         return self.Name
     
-    # Changes the element size
-    def SetSize(self, width, height):
-        scaling = self.Parent.GetScaling()
-        min_width, min_height = self.GetMinSize()
-        if width < min_width:
-            if self.Type == CONTINUATION:
-                posx = max(0, self.Pos.x + width - min_width)
-                if scaling is not None:
-                    posx = round_scaling(posx, scaling[0])
-                self.Pos.x = posx
-            width = min_width
-            if scaling is not None:
-                width = round_scaling(width, scaling[0], 1)
-        if height < min_height:
-            posy = max(0, self.Pos.y + (height - min_height) / 2)
-            if scaling is not None:
-                posy = round_scaling(posy, scaling[1])
-            self.Pos.y = posy
-            height = min_height
-            if scaling is not None:
-                height = round_scaling(height, scaling[1], 1)
-        Graphic_Element.SetSize(self, width, height)
+    # Set size of the variable to the minimum size
+    def SetBestSize(self, scaling):
+        if self.Type == CONTINUATION:
+            return Graphic_Element.SetBestSize(self, scaling, x_factor=1.)
+        else:
+            return Graphic_Element.SetBestSize(self, scaling, x_factor=0.)
     
     # Returns the connection minimum size
     def GetMinSize(self):
--- a/graphics/GraphicCommons.py	Mon Oct 15 17:05:19 2012 +0200
+++ b/graphics/GraphicCommons.py	Tue Oct 16 11:34:24 2012 +0200
@@ -118,13 +118,13 @@
 
 def round_scaling(x, n, constraint=0):
     fraction = float(x) / float(n)
-    if constraint == - 1:
+    if constraint == -1:
         xround = int(fraction)
     else:
         xround = round(fraction)
-        if constraint == 1 and int(fraction) == xround:
-            xround += 1
-    return xround * n
+        if constraint == 1 and xround < fraction:
+            xround += 1 
+    return int(xround * n)
 
 """
 Basic vector operations for calculate wire points
@@ -675,7 +675,7 @@
         return [self.Id], []
     
     def TestVisible(self, screen):
-        self.Visible = self.GetRedrawRect().Intersects(screen)
+        self.Visible = self.Selected or self.GetRedrawRect().Intersects(screen)
     
     def IsVisible(self):
         return self.Visible
@@ -737,6 +737,25 @@
     def GetMinSize(self):
         return 0, 0
     
+    # Set size of the element to the minimum size
+    def SetBestSize(self, scaling, x_factor=0.5, y_factor=0.5):
+        width, height = self.GetSize()
+        posx, posy = self.GetPosition()
+        min_width, min_height = self.GetMinSize()
+        if width < min_width:
+            self.Pos.x = max(0, self.Pos.x - (width - min_width) * x_factor)
+            width = min_width
+        if height < min_height:
+            self.Pos.y = max(0, self.Pos.y - (height - min_height) * y_factor)
+            height = min_height
+        if scaling is not None:
+            self.Pos.x = round_scaling(self.Pos.x, scaling[0])
+            self.Pos.y = round_scaling(self.Pos.y, scaling[1])
+            width = round_scaling(width, scaling[0], 1)
+            height = round_scaling(height, scaling[1], 1)
+        self.SetSize(width, height)
+        return self.Pos.x - posx, self.Pos.y - posy
+    
     # Refresh the element Bounding Box
     def RefreshBoundingBox(self):
         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
@@ -943,20 +962,6 @@
         self.Move(x, y)
         self.SetSize(width, height)
     
-    # Moves and Resizes the element for fitting scaling
-    def AdjustToScaling(self, scaling):
-        if scaling is not None:
-            movex = round_scaling(self.Pos.x, scaling[0]) - self.Pos.x
-            movey = round_scaling(self.Pos.y, scaling[1]) - self.Pos.y
-            min_width, min_height = self.GetMinSize()
-            width = max(round_scaling(min_width, scaling[0], 1),
-                        round_scaling(self.Size.width, scaling[0]))
-            height = max(round_scaling(min_height, scaling[1], 1),
-                         round_scaling(self.Size.height, scaling[1]))
-            self.Resize(movex, movey, width, height)
-            return movex, movey
-        return 0, 0
-    
     # Refreshes the element state according to move defined and handle selected
     def ProcessDragging(self, movex, movey, event, scaling, width_fac = 1, height_fac = 1):
         handle_type, handle = self.Handle
@@ -1176,7 +1181,7 @@
                         new_element = element.Clone(parent, newid, name, pos = new_pos)
                     else:
                         new_element = element.Clone(parent, newid, pos = new_pos)
-                    new_element.AdjustToScaling(parent.Scaling)
+                    new_element.SetBestSize(parent.Scaling)
                 else:
                     new_element = element.Clone(parent)
                 connectors.update(element.GetConnectorTranslation(new_element))
@@ -1368,15 +1373,15 @@
     # Returns the size of this group
     def GetSize(self):
         return self.BoundingBox.width, self.BoundingBox.height
-
-    # Moves and Resizes the group elements for fitting scaling
-    def AdjustToScaling(self, scaling):
-        movex_max = movey_max = 0
+    
+    # Set size of the group elements to their minimum size
+    def SetBestSize(self, scaling):
+        max_movex = max_movey = 0
         for element in self.Elements:
-            movex, movey = element.AdjustToScaling(scaling)
-            movex_max = max(movex_max, abs(movex))
-            movey_max = max(movey_max, abs(movey))
-        return movex_max, movey_max
+            movex, movey = element.SetBestSize(scaling)
+            max_movex = max(max_movex, movex)
+            max_movey = max(max_movey, movey)
+        return max_movex, max_movey
     
     # Refreshes the group elements to move defined and handle selected
     def ProcessDragging(self, movex, movey, event, scaling):
@@ -1986,8 +1991,11 @@
     def SetSize(width, height):
         pass
     
+    # Forbids to et size of the group elements to their minimum size
+        pass
+    
     # Moves and Resizes the element for fitting scaling
-    def AdjustToScaling(self, scaling):
+    def SetBestSize(self, scaling):
         if scaling is not None:
             movex_max = movey_max = 0
             for idx, point in enumerate(self.Points):