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