Move RubberBand from GraphicCommons to individual file
authorLaurent Bessard
Fri, 24 May 2013 16:29:57 +0200
changeset 1173 ad09b4a755ce
parent 1172 dff0a4e40808
child 1174 9cc1a3fa9619
Move RubberBand from GraphicCommons to individual file
graphics/GraphicCommons.py
graphics/RubberBand.py
graphics/__init__.py
--- a/graphics/GraphicCommons.py	Fri May 24 11:17:35 2013 +0200
+++ b/graphics/GraphicCommons.py	Fri May 24 16:29:57 2013 +0200
@@ -437,123 +437,6 @@
         self.AccessLock.release()
 
 #-------------------------------------------------------------------------------
-#                               Viewer Rubberband
-#-------------------------------------------------------------------------------
-
-"""
-Class that implements a rubberband
-"""
-
-class RubberBand:
-    
-    # Create a rubberband by indicated on which window it must be drawn
-    def __init__(self, viewer):
-        self.Viewer = viewer
-        self.drawingSurface = viewer.Editor
-        self.Reset()
-    
-    # Method that initializes the internal attributes of the rubberband
-    def Reset(self):
-        self.startPoint = None
-        self.currentBox = None
-        self.lastBox = None
-    
-    # Method that return if a box is currently edited
-    def IsShown(self):
-        return self.currentBox != None
-    
-    # Method that returns the currently edited box
-    def GetCurrentExtent(self):
-        if self.currentBox is None:
-            return self.lastBox
-        return self.currentBox
-    
-    # Method called when a new box starts to be edited
-    def OnLeftDown(self, event, dc, scaling):
-        pos = GetScaledEventPosition(event, dc, scaling)
-        # Save the point for calculate the box position and size
-        self.startPoint = pos
-        self.currentBox = wx.Rect(pos.x, pos.y, 0, 0)
-        self.drawingSurface.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
-        self.Redraw()
-    
-    # Method called when dragging with a box edited
-    def OnMotion(self, event, dc, scaling):
-        pos = GetScaledEventPosition(event, dc, scaling)
-        # Save the last position and size of the box for erasing it
-        self.lastBox = wx.Rect(self.currentBox.x, self.currentBox.y, self.currentBox.width,
-            self.currentBox.height)
-        # Calculate new position and size of the box 
-        if pos.x >= self.startPoint.x:
-            self.currentBox.x = self.startPoint.x
-            self.currentBox.width = pos.x - self.startPoint.x + 1
-        else:
-            self.currentBox.x = pos.x
-            self.currentBox.width = self.startPoint.x - pos.x + 1
-        if pos.y >= self.startPoint.y:
-            self.currentBox.y = self.startPoint.y
-            self.currentBox.height = pos.y - self.startPoint.y + 1
-        else:
-            self.currentBox.y = pos.y
-            self.currentBox.height = self.startPoint.y - pos.y + 1
-        self.Redraw()
-    
-    # Method called when dragging is stopped
-    def OnLeftUp(self, event, dc, scaling):
-        self.drawingSurface.SetCursor(wx.NullCursor)
-        self.lastBox = self.currentBox
-        self.currentBox = None
-        self.Redraw()
-
-    # Method that erase the last box and draw the new box
-    def Redraw(self, dc = None):
-        if dc is None:
-            dc = self.Viewer.GetLogicalDC()
-        scalex, scaley = dc.GetUserScale()
-        dc.SetUserScale(1, 1)
-        dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
-        dc.SetBrush(wx.TRANSPARENT_BRUSH)
-        dc.SetLogicalFunction(wx.XOR)
-        if self.lastBox:
-            # Erase last box
-            dc.DrawRectangle(self.lastBox.x * scalex, self.lastBox.y * scaley, 
-                             self.lastBox.width * scalex, self.lastBox.height * scaley)
-        if self.currentBox:
-            # Draw current box
-            dc.DrawRectangle(self.currentBox.x * scalex, self.currentBox.y * scaley, 
-                             self.currentBox.width * scalex, self.currentBox.height * scaley)
-        dc.SetUserScale(scalex, scaley)
-    
-    # Erase last box
-    def Erase(self, dc = None):
-        if dc is None:
-            dc = self.Viewer.GetLogicalDC()
-        scalex, scaley = dc.GetUserScale()
-        dc.SetUserScale(1, 1)
-        dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
-        dc.SetBrush(wx.TRANSPARENT_BRUSH)
-        dc.SetLogicalFunction(wx.XOR)
-        if self.lastBox:
-            dc.DrawRectangle(self.lastBox.x * scalex, self.lastBox.y * scaley, 
-                             self.lastBox.width * scalex, self.lastBox.height * scalex)
-        dc.SetUserScale(scalex, scaley)
-
-    # Draw current box
-    def Draw(self, dc = None):
-        if dc is None:
-            dc = self.Viewer.GetLogicalDC()
-        scalex, scaley = dc.GetUserScale()
-        dc.SetUserScale(1, 1)
-        dc.SetPen(wx.Pen(wx.WHITE, 1, wx.DOT))
-        dc.SetBrush(wx.TRANSPARENT_BRUSH)
-        dc.SetLogicalFunction(wx.XOR)
-        if self.currentBox:
-            # Draw current box
-            dc.DrawRectangle(self.currentBox.x * scalex, self.currentBox.y * scaley, 
-                             self.currentBox.width * scalex, self.currentBox.height * scaley)
-        dc.SetUserScale(scalex, scaley)
-
-#-------------------------------------------------------------------------------
 #                    Helpers for highlighting text
 #-------------------------------------------------------------------------------
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphics/RubberBand.py	Fri May 24 16:29:57 2013 +0200
@@ -0,0 +1,192 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard. 
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import wx
+
+from graphics.GraphicCommons import GetScaledEventPosition
+
+#-------------------------------------------------------------------------------
+#                               Viewer RubberBand
+#-------------------------------------------------------------------------------
+
+"""
+Class that implements a rubberband for graphic Viewers
+"""
+
+class RubberBand:
+    
+    def __init__(self, viewer):
+        """
+        Constructor
+        @param viewer: Viewer on which rubberband must be drawn
+        """
+        self.Viewer = viewer
+        
+        # wx.Panel on which rubberband will be drawn
+        self.DrawingSurface = viewer.Editor
+        
+        self.Reset()
+    
+    def Reset(self):
+        """
+        Initialize internal attributes of rubberband
+        """
+        self.StartPoint = None
+        self.CurrentBBox = None
+        self.LastBBox = None
+    
+    def IsShown(self):
+        """
+        Indicate if rubberband is drawn on viewer
+        @return: True if rubberband is drawn
+        """
+        return self.CurrentBBox != None
+    
+    def GetCurrentExtent(self):
+        """
+        Return the rubberband bounding box
+        @return: Rubberband bounding box (wx.Rect object)
+        """
+        # In case of rubberband not shown, return the last rubberband
+        # bounding box
+        if self.IsShown():
+            return self.CurrentBBox
+        return self.LastBBox
+    
+    def OnLeftDown(self, event, dc, scaling):
+        """
+        Called when left mouse is pressed on Viewer. Starts to edit a new
+        rubberband bounding box
+        @param event: Mouse event
+        @param dc: Device Context of Viewer
+        @param scaling: PLCOpen scaling applied on Viewer
+        """
+        # Save the point where mouse was pressed in Viewer unit, position may
+        # be modified by scroll and zoom applied on viewer
+        self.StartPoint = GetScaledEventPosition(event, dc, scaling)
+        
+        # Initialize rubberband bounding box
+        self.CurrentBBox = wx.Rect(self.StartPoint.x, self.StartPoint.y, 0, 0)
+        
+        # Change viewer mouse cursor to reflect a rubberband bounding box is
+        # edited
+        self.DrawingSurface.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
+        
+        self.Redraw()
+    
+    def OnMotion(self, event, dc, scaling):
+        """
+        Called when mouse is dragging over Viewer. Update the current edited
+        rubberband bounding box
+        @param event: Mouse event
+        @param dc: Device Context of Viewer
+        @param scaling: PLCOpen scaling applied on Viewer
+        """
+        # Get mouse position in Viewer unit, position may be modified by scroll
+        # and zoom applied on viewer
+        pos = GetScaledEventPosition(event, dc, scaling)
+        
+        # Save the last bounding box drawn for erasing it later
+        self.LastBBox = wx.Rect(0, 0, 0, 0)
+        self.LastBBox.Union(self.CurrentBBox)
+        
+        # Calculate new position and size of the box 
+        self.CurrentBBox.x = min(pos.x, self.StartPoint.x)
+        self.CurrentBBox.y = min(pos.y, self.StartPoint.y)
+        self.CurrentBBox.width = abs(pos.x - self.StartPoint.x) + 1
+        self.CurrentBBox.height = abs(pos.y - self.StartPoint.y) + 1
+        
+        self.Redraw()
+    
+    def OnLeftUp(self, event, dc, scaling):
+        """
+        Called when mouse is release from Viewer. Erase the current edited
+        rubberband bounding box
+        @param event: Mouse event
+        @param dc: Device Context of Viewer
+        @param scaling: PLCOpen scaling applied on Viewer
+        """
+        # Change viewer mouse cursor to default
+        self.DrawingSurface.SetCursor(wx.NullCursor)
+        
+        # Save the last edited bounding box
+        self.LastBBox = self.CurrentBBox
+        self.CurrentBBox = None
+        
+        self.Redraw()
+    
+    def DrawBoundingBoxes(self, bboxes, dc=None):
+        """
+        Draw a list of bounding box on Viewer in the order given using XOR 
+        logical function
+        @param bboxes: List of bounding boxes to draw on viewer
+        @param dc: Device Context of Viewer (default None)
+        """
+        # Get viewer Device Context if not given
+        if dc is None:
+            dc = self.Viewer.GetLogicalDC()
+        
+        # Save current viewer scale factors before resetting them in order to
+        # avoid rubberband pen to be scaled
+        scalex, scaley = dc.GetUserScale()
+        dc.SetUserScale(1, 1)
+        
+        # Set DC drawing style
+        dc.SetPen(wx.Pen(wx.WHITE, style=wx.DOT))
+        dc.SetBrush(wx.TRANSPARENT_BRUSH)
+        dc.SetLogicalFunction(wx.XOR)
+        
+        # Draw the bounding boxes using viewer scale factor
+        for bbox in bboxes:
+            if bbox is not None:
+                dc.DrawRectangle(
+                    bbox.x * scalex, bbox.y * scaley, 
+                    bbox.width * scalex, bbox.height * scaley)
+        
+        # Restore Viewer scale factor
+        dc.SetUserScale(scalex, scaley)
+    
+    def Redraw(self, dc = None):
+        """
+        Redraw rubberband on Viewer
+        @param dc: Device Context of Viewer (default None)
+        """
+        # Erase last bbox and draw current bbox
+        self.DrawBoundingBoxes([self.LastBBox, self.CurrentBBox], dc)
+    
+    def Erase(self, dc = None):
+        """
+        Erase rubberband from Viewer
+        @param dc: Device Context of Viewer (default None)
+        """
+        # Erase last bbox
+        self.DrawBoundingBoxes([self.LastBBox], dc)
+
+    def Draw(self, dc = None):
+        """
+        Draw rubberband on Viewer
+        @param dc: Device Context of Viewer (default None)
+        """
+        # Erase last bbox and draw current bbox
+        self.DrawBoundingBoxes([self.CurrentBBox], dc)
--- a/graphics/__init__.py	Fri May 24 11:17:35 2013 +0200
+++ b/graphics/__init__.py	Fri May 24 16:29:57 2013 +0200
@@ -27,4 +27,5 @@
 from GraphicCommons import *
 from FBD_Objects import *
 from LD_Objects import *
-from SFC_Objects import *
\ No newline at end of file
+from SFC_Objects import *
+from RubberBand import RubberBand
\ No newline at end of file