graphics/RubberBand.py
changeset 1730 64d8f52bc8c8
parent 1571 486f94a8032c
child 1736 7e61baa047f0
equal deleted inserted replaced
1726:d51af006fa6b 1730:64d8f52bc8c8
    33 """
    33 """
    34 Class that implements a rubberband for graphic Viewers
    34 Class that implements a rubberband for graphic Viewers
    35 """
    35 """
    36 
    36 
    37 class RubberBand:
    37 class RubberBand:
    38     
    38 
    39     def __init__(self, viewer):
    39     def __init__(self, viewer):
    40         """
    40         """
    41         Constructor
    41         Constructor
    42         @param viewer: Viewer on which rubberband must be drawn
    42         @param viewer: Viewer on which rubberband must be drawn
    43         """
    43         """
    44         self.Viewer = viewer
    44         self.Viewer = viewer
    45         
    45 
    46         # wx.Panel on which rubberband will be drawn
    46         # wx.Panel on which rubberband will be drawn
    47         self.DrawingSurface = viewer.Editor
    47         self.DrawingSurface = viewer.Editor
    48         
    48 
    49         self.Reset()
    49         self.Reset()
    50     
    50 
    51     def Reset(self):
    51     def Reset(self):
    52         """
    52         """
    53         Initialize internal attributes of rubberband
    53         Initialize internal attributes of rubberband
    54         """
    54         """
    55         self.StartPoint = None
    55         self.StartPoint = None
    56         self.CurrentBBox = None
    56         self.CurrentBBox = None
    57         self.LastBBox = None
    57         self.LastBBox = None
    58     
    58 
    59     def IsShown(self):
    59     def IsShown(self):
    60         """
    60         """
    61         Indicate if rubberband is drawn on viewer
    61         Indicate if rubberband is drawn on viewer
    62         @return: True if rubberband is drawn
    62         @return: True if rubberband is drawn
    63         """
    63         """
    64         return self.CurrentBBox != None
    64         return self.CurrentBBox != None
    65     
    65 
    66     def GetCurrentExtent(self):
    66     def GetCurrentExtent(self):
    67         """
    67         """
    68         Return the rubberband bounding box
    68         Return the rubberband bounding box
    69         @return: Rubberband bounding box (wx.Rect object)
    69         @return: Rubberband bounding box (wx.Rect object)
    70         """
    70         """
    71         # In case of rubberband not shown, return the last rubberband
    71         # In case of rubberband not shown, return the last rubberband
    72         # bounding box
    72         # bounding box
    73         if self.IsShown():
    73         if self.IsShown():
    74             return self.CurrentBBox
    74             return self.CurrentBBox
    75         return self.LastBBox
    75         return self.LastBBox
    76     
    76 
    77     def OnLeftDown(self, event, dc, scaling):
    77     def OnLeftDown(self, event, dc, scaling):
    78         """
    78         """
    79         Called when left mouse is pressed on Viewer. Starts to edit a new
    79         Called when left mouse is pressed on Viewer. Starts to edit a new
    80         rubberband bounding box
    80         rubberband bounding box
    81         @param event: Mouse event
    81         @param event: Mouse event
    83         @param scaling: PLCOpen scaling applied on Viewer
    83         @param scaling: PLCOpen scaling applied on Viewer
    84         """
    84         """
    85         # Save the point where mouse was pressed in Viewer unit, position may
    85         # Save the point where mouse was pressed in Viewer unit, position may
    86         # be modified by scroll and zoom applied on viewer
    86         # be modified by scroll and zoom applied on viewer
    87         self.StartPoint = GetScaledEventPosition(event, dc, scaling)
    87         self.StartPoint = GetScaledEventPosition(event, dc, scaling)
    88         
    88 
    89         # Initialize rubberband bounding box
    89         # Initialize rubberband bounding box
    90         self.CurrentBBox = wx.Rect(self.StartPoint.x, self.StartPoint.y, 0, 0)
    90         self.CurrentBBox = wx.Rect(self.StartPoint.x, self.StartPoint.y, 0, 0)
    91         
    91 
    92         # Change viewer mouse cursor to reflect a rubberband bounding box is
    92         # Change viewer mouse cursor to reflect a rubberband bounding box is
    93         # edited
    93         # edited
    94         self.DrawingSurface.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
    94         self.DrawingSurface.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
    95         
    95 
    96         self.Redraw()
    96         self.Redraw()
    97     
    97 
    98     def OnMotion(self, event, dc, scaling):
    98     def OnMotion(self, event, dc, scaling):
    99         """
    99         """
   100         Called when mouse is dragging over Viewer. Update the current edited
   100         Called when mouse is dragging over Viewer. Update the current edited
   101         rubberband bounding box
   101         rubberband bounding box
   102         @param event: Mouse event
   102         @param event: Mouse event
   104         @param scaling: PLCOpen scaling applied on Viewer
   104         @param scaling: PLCOpen scaling applied on Viewer
   105         """
   105         """
   106         # Get mouse position in Viewer unit, position may be modified by scroll
   106         # Get mouse position in Viewer unit, position may be modified by scroll
   107         # and zoom applied on viewer
   107         # and zoom applied on viewer
   108         pos = GetScaledEventPosition(event, dc, scaling)
   108         pos = GetScaledEventPosition(event, dc, scaling)
   109         
   109 
   110         # Save the last bounding box drawn for erasing it later
   110         # Save the last bounding box drawn for erasing it later
   111         self.LastBBox = wx.Rect(0, 0, 0, 0)
   111         self.LastBBox = wx.Rect(0, 0, 0, 0)
   112         self.LastBBox.Union(self.CurrentBBox)
   112         self.LastBBox.Union(self.CurrentBBox)
   113         
   113 
   114         # Calculate new position and size of the box 
   114         # Calculate new position and size of the box
   115         self.CurrentBBox.x = min(pos.x, self.StartPoint.x)
   115         self.CurrentBBox.x = min(pos.x, self.StartPoint.x)
   116         self.CurrentBBox.y = min(pos.y, self.StartPoint.y)
   116         self.CurrentBBox.y = min(pos.y, self.StartPoint.y)
   117         self.CurrentBBox.width = abs(pos.x - self.StartPoint.x) + 1
   117         self.CurrentBBox.width = abs(pos.x - self.StartPoint.x) + 1
   118         self.CurrentBBox.height = abs(pos.y - self.StartPoint.y) + 1
   118         self.CurrentBBox.height = abs(pos.y - self.StartPoint.y) + 1
   119         
   119 
   120         self.Redraw()
   120         self.Redraw()
   121     
   121 
   122     def OnLeftUp(self, event, dc, scaling):
   122     def OnLeftUp(self, event, dc, scaling):
   123         """
   123         """
   124         Called when mouse is release from Viewer. Erase the current edited
   124         Called when mouse is release from Viewer. Erase the current edited
   125         rubberband bounding box
   125         rubberband bounding box
   126         @param event: Mouse event
   126         @param event: Mouse event
   127         @param dc: Device Context of Viewer
   127         @param dc: Device Context of Viewer
   128         @param scaling: PLCOpen scaling applied on Viewer
   128         @param scaling: PLCOpen scaling applied on Viewer
   129         """
   129         """
   130         # Change viewer mouse cursor to default
   130         # Change viewer mouse cursor to default
   131         self.DrawingSurface.SetCursor(wx.NullCursor)
   131         self.DrawingSurface.SetCursor(wx.NullCursor)
   132         
   132 
   133         # Save the last edited bounding box
   133         # Save the last edited bounding box
   134         self.LastBBox = self.CurrentBBox
   134         self.LastBBox = self.CurrentBBox
   135         self.CurrentBBox = None
   135         self.CurrentBBox = None
   136         
   136 
   137         self.Redraw()
   137         self.Redraw()
   138     
   138 
   139     def DrawBoundingBoxes(self, bboxes, dc=None):
   139     def DrawBoundingBoxes(self, bboxes, dc=None):
   140         """
   140         """
   141         Draw a list of bounding box on Viewer in the order given using XOR 
   141         Draw a list of bounding box on Viewer in the order given using XOR
   142         logical function
   142         logical function
   143         @param bboxes: List of bounding boxes to draw on viewer
   143         @param bboxes: List of bounding boxes to draw on viewer
   144         @param dc: Device Context of Viewer (default None)
   144         @param dc: Device Context of Viewer (default None)
   145         """
   145         """
   146         # Get viewer Device Context if not given
   146         # Get viewer Device Context if not given
   147         if dc is None:
   147         if dc is None:
   148             dc = self.Viewer.GetLogicalDC()
   148             dc = self.Viewer.GetLogicalDC()
   149         
   149 
   150         # Save current viewer scale factors before resetting them in order to
   150         # Save current viewer scale factors before resetting them in order to
   151         # avoid rubberband pen to be scaled
   151         # avoid rubberband pen to be scaled
   152         scalex, scaley = dc.GetUserScale()
   152         scalex, scaley = dc.GetUserScale()
   153         dc.SetUserScale(1, 1)
   153         dc.SetUserScale(1, 1)
   154         
   154 
   155         # Set DC drawing style
   155         # Set DC drawing style
   156         dc.SetPen(wx.Pen(wx.WHITE, style=wx.DOT))
   156         dc.SetPen(wx.Pen(wx.WHITE, style=wx.DOT))
   157         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   157         dc.SetBrush(wx.TRANSPARENT_BRUSH)
   158         dc.SetLogicalFunction(wx.XOR)
   158         dc.SetLogicalFunction(wx.XOR)
   159         
   159 
   160         # Draw the bounding boxes using viewer scale factor
   160         # Draw the bounding boxes using viewer scale factor
   161         for bbox in bboxes:
   161         for bbox in bboxes:
   162             if bbox is not None:
   162             if bbox is not None:
   163                 dc.DrawRectangle(
   163                 dc.DrawRectangle(
   164                     bbox.x * scalex, bbox.y * scaley, 
   164                     bbox.x * scalex, bbox.y * scaley,
   165                     bbox.width * scalex, bbox.height * scaley)
   165                     bbox.width * scalex, bbox.height * scaley)
   166         
   166 
   167         dc.SetLogicalFunction(wx.COPY)
   167         dc.SetLogicalFunction(wx.COPY)
   168         
   168 
   169         # Restore Viewer scale factor
   169         # Restore Viewer scale factor
   170         dc.SetUserScale(scalex, scaley)
   170         dc.SetUserScale(scalex, scaley)
   171     
   171 
   172     def Redraw(self, dc = None):
   172     def Redraw(self, dc = None):
   173         """
   173         """
   174         Redraw rubberband on Viewer
   174         Redraw rubberband on Viewer
   175         @param dc: Device Context of Viewer (default None)
   175         @param dc: Device Context of Viewer (default None)
   176         """
   176         """
   177         # Erase last bbox and draw current bbox
   177         # Erase last bbox and draw current bbox
   178         self.DrawBoundingBoxes([self.LastBBox, self.CurrentBBox], dc)
   178         self.DrawBoundingBoxes([self.LastBBox, self.CurrentBBox], dc)
   179     
   179 
   180     def Erase(self, dc = None):
   180     def Erase(self, dc = None):
   181         """
   181         """
   182         Erase rubberband from Viewer
   182         Erase rubberband from Viewer
   183         @param dc: Device Context of Viewer (default None)
   183         @param dc: Device Context of Viewer (default None)
   184         """
   184         """