graphics/RubberBand.py
changeset 1173 ad09b4a755ce
parent 1170 074e46cdedbc
child 1273 921858d68a13
equal deleted inserted replaced
1172:dff0a4e40808 1173:ad09b4a755ce
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
       
     5 #based on the plcopen standard. 
       
     6 #
       
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
       
     8 #
       
     9 #See COPYING file for copyrights details.
       
    10 #
       
    11 #This library is free software; you can redistribute it and/or
       
    12 #modify it under the terms of the GNU General Public
       
    13 #License as published by the Free Software Foundation; either
       
    14 #version 2.1 of the License, or (at your option) any later version.
       
    15 #
       
    16 #This library is distributed in the hope that it will be useful,
       
    17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    19 #General Public License for more details.
       
    20 #
       
    21 #You should have received a copy of the GNU General Public
       
    22 #License along with this library; if not, write to the Free Software
       
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    24 
       
    25 import wx
       
    26 
       
    27 from graphics.GraphicCommons import GetScaledEventPosition
       
    28 
       
    29 #-------------------------------------------------------------------------------
       
    30 #                               Viewer RubberBand
       
    31 #-------------------------------------------------------------------------------
       
    32 
       
    33 """
       
    34 Class that implements a rubberband for graphic Viewers
       
    35 """
       
    36 
       
    37 class RubberBand:
       
    38     
       
    39     def __init__(self, viewer):
       
    40         """
       
    41         Constructor
       
    42         @param viewer: Viewer on which rubberband must be drawn
       
    43         """
       
    44         self.Viewer = viewer
       
    45         
       
    46         # wx.Panel on which rubberband will be drawn
       
    47         self.DrawingSurface = viewer.Editor
       
    48         
       
    49         self.Reset()
       
    50     
       
    51     def Reset(self):
       
    52         """
       
    53         Initialize internal attributes of rubberband
       
    54         """
       
    55         self.StartPoint = None
       
    56         self.CurrentBBox = None
       
    57         self.LastBBox = None
       
    58     
       
    59     def IsShown(self):
       
    60         """
       
    61         Indicate if rubberband is drawn on viewer
       
    62         @return: True if rubberband is drawn
       
    63         """
       
    64         return self.CurrentBBox != None
       
    65     
       
    66     def GetCurrentExtent(self):
       
    67         """
       
    68         Return the rubberband bounding box
       
    69         @return: Rubberband bounding box (wx.Rect object)
       
    70         """
       
    71         # In case of rubberband not shown, return the last rubberband
       
    72         # bounding box
       
    73         if self.IsShown():
       
    74             return self.CurrentBBox
       
    75         return self.LastBBox
       
    76     
       
    77     def OnLeftDown(self, event, dc, scaling):
       
    78         """
       
    79         Called when left mouse is pressed on Viewer. Starts to edit a new
       
    80         rubberband bounding box
       
    81         @param event: Mouse event
       
    82         @param dc: Device Context of Viewer
       
    83         @param scaling: PLCOpen scaling applied on Viewer
       
    84         """
       
    85         # Save the point where mouse was pressed in Viewer unit, position may
       
    86         # be modified by scroll and zoom applied on viewer
       
    87         self.StartPoint = GetScaledEventPosition(event, dc, scaling)
       
    88         
       
    89         # Initialize rubberband bounding box
       
    90         self.CurrentBBox = wx.Rect(self.StartPoint.x, self.StartPoint.y, 0, 0)
       
    91         
       
    92         # Change viewer mouse cursor to reflect a rubberband bounding box is
       
    93         # edited
       
    94         self.DrawingSurface.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
       
    95         
       
    96         self.Redraw()
       
    97     
       
    98     def OnMotion(self, event, dc, scaling):
       
    99         """
       
   100         Called when mouse is dragging over Viewer. Update the current edited
       
   101         rubberband bounding box
       
   102         @param event: Mouse event
       
   103         @param dc: Device Context of Viewer
       
   104         @param scaling: PLCOpen scaling applied on Viewer
       
   105         """
       
   106         # Get mouse position in Viewer unit, position may be modified by scroll
       
   107         # and zoom applied on viewer
       
   108         pos = GetScaledEventPosition(event, dc, scaling)
       
   109         
       
   110         # Save the last bounding box drawn for erasing it later
       
   111         self.LastBBox = wx.Rect(0, 0, 0, 0)
       
   112         self.LastBBox.Union(self.CurrentBBox)
       
   113         
       
   114         # Calculate new position and size of the box 
       
   115         self.CurrentBBox.x = min(pos.x, self.StartPoint.x)
       
   116         self.CurrentBBox.y = min(pos.y, self.StartPoint.y)
       
   117         self.CurrentBBox.width = abs(pos.x - self.StartPoint.x) + 1
       
   118         self.CurrentBBox.height = abs(pos.y - self.StartPoint.y) + 1
       
   119         
       
   120         self.Redraw()
       
   121     
       
   122     def OnLeftUp(self, event, dc, scaling):
       
   123         """
       
   124         Called when mouse is release from Viewer. Erase the current edited
       
   125         rubberband bounding box
       
   126         @param event: Mouse event
       
   127         @param dc: Device Context of Viewer
       
   128         @param scaling: PLCOpen scaling applied on Viewer
       
   129         """
       
   130         # Change viewer mouse cursor to default
       
   131         self.DrawingSurface.SetCursor(wx.NullCursor)
       
   132         
       
   133         # Save the last edited bounding box
       
   134         self.LastBBox = self.CurrentBBox
       
   135         self.CurrentBBox = None
       
   136         
       
   137         self.Redraw()
       
   138     
       
   139     def DrawBoundingBoxes(self, bboxes, dc=None):
       
   140         """
       
   141         Draw a list of bounding box on Viewer in the order given using XOR 
       
   142         logical function
       
   143         @param bboxes: List of bounding boxes to draw on viewer
       
   144         @param dc: Device Context of Viewer (default None)
       
   145         """
       
   146         # Get viewer Device Context if not given
       
   147         if dc is None:
       
   148             dc = self.Viewer.GetLogicalDC()
       
   149         
       
   150         # Save current viewer scale factors before resetting them in order to
       
   151         # avoid rubberband pen to be scaled
       
   152         scalex, scaley = dc.GetUserScale()
       
   153         dc.SetUserScale(1, 1)
       
   154         
       
   155         # Set DC drawing style
       
   156         dc.SetPen(wx.Pen(wx.WHITE, style=wx.DOT))
       
   157         dc.SetBrush(wx.TRANSPARENT_BRUSH)
       
   158         dc.SetLogicalFunction(wx.XOR)
       
   159         
       
   160         # Draw the bounding boxes using viewer scale factor
       
   161         for bbox in bboxes:
       
   162             if bbox is not None:
       
   163                 dc.DrawRectangle(
       
   164                     bbox.x * scalex, bbox.y * scaley, 
       
   165                     bbox.width * scalex, bbox.height * scaley)
       
   166         
       
   167         # Restore Viewer scale factor
       
   168         dc.SetUserScale(scalex, scaley)
       
   169     
       
   170     def Redraw(self, dc = None):
       
   171         """
       
   172         Redraw rubberband on Viewer
       
   173         @param dc: Device Context of Viewer (default None)
       
   174         """
       
   175         # Erase last bbox and draw current bbox
       
   176         self.DrawBoundingBoxes([self.LastBBox, self.CurrentBBox], dc)
       
   177     
       
   178     def Erase(self, dc = None):
       
   179         """
       
   180         Erase rubberband from Viewer
       
   181         @param dc: Device Context of Viewer (default None)
       
   182         """
       
   183         # Erase last bbox
       
   184         self.DrawBoundingBoxes([self.LastBBox], dc)
       
   185 
       
   186     def Draw(self, dc = None):
       
   187         """
       
   188         Draw rubberband on Viewer
       
   189         @param dc: Device Context of Viewer (default None)
       
   190         """
       
   191         # Erase last bbox and draw current bbox
       
   192         self.DrawBoundingBoxes([self.CurrentBBox], dc)