]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/ogl/_canvas.py
   1 # -*- coding: iso-8859-1 -*- 
   2 #---------------------------------------------------------------------------- 
   4 # Purpose:      The canvas class 
   6 # Author:       Pierre Hjälm (from C++ original by Julian Smart) 
  10 # Copyright:    (c) 2004 Pierre Hjälm - 1998 Julian Smart 
  11 # Licence:      wxWindows license 
  12 #---------------------------------------------------------------------------- 
  15 from _lines 
import LineShape
 
  16 from _composit 
import * 
  18 NoDragging
, StartDraggingLeft
, ContinueDraggingLeft
, StartDraggingRight
, ContinueDraggingRight 
= 0, 1, 2, 3, 4 
  20 KEY_SHIFT
, KEY_CTRL 
= 1, 2 
  24 # Helper function: True if 'contains' wholly contains 'contained'. 
  25 def WhollyContains(contains
, contained
): 
  26     xp1
, yp1 
= contains
.GetX(), contains
.GetY() 
  27     xp2
, yp2 
= contained
.GetX(), contained
.GetY() 
  29     w1
, h1 
= contains
.GetBoundingBoxMax() 
  30     w2
, h2 
= contained
.GetBoundingBoxMax() 
  32     left1 
= xp1 
- w1 
/ 2.0 
  34     right1 
= xp1 
+ w1 
/ 2.0 
  35     bottom1 
= yp1 
+ h1 
/ 2.0 
  37     left2 
= xp2 
- w2 
/ 2.0 
  39     right2 
= xp2 
+ w2 
/ 2.0 
  40     bottom2 
= yp2 
+ h2 
/ 2.0 
  42     return ((left1 
<= left2
) and (top1 
<= top2
) and (right1 
>= right2
) and (bottom1 
>= bottom2
)) 
  46 class ShapeCanvas(wx
.ScrolledWindow
): 
  47     def __init__(self
, parent 
= None, id = -1, pos 
= wx
.DefaultPosition
, size 
= wx
.DefaultSize
, style 
= wx
.BORDER
, name 
= "ShapeCanvas"): 
  48         wx
.ScrolledWindow
.__init
__(self
, parent
, id, pos
, size
, style
, name
) 
  50         self
._shapeDiagram 
= None 
  51         self
._dragState 
= NoDragging
 
  52         self
._draggedShape 
= None 
  57         self
._checkTolerance 
= True 
  59         wx
.EVT_PAINT(self
, self
.OnPaint
) 
  60         wx
.EVT_MOUSE_EVENTS(self
, self
.OnMouseEvent
) 
  62     def SetDiagram(self
, diag
): 
  63         self
._shapeDiagram 
= diag
 
  66         return self
._shapeDiagram
 
  68     def OnPaint(self
, evt
): 
  72         dc
.SetBackground(wx
.Brush(self
.GetBackgroundColour(), wx
.SOLID
)) 
  76             self
.GetDiagram().Redraw(dc
) 
  78     def OnMouseEvent(self
, evt
): 
  79         dc 
= wx
.ClientDC(self
) 
  82         x
, y 
= evt
.GetLogicalPosition(dc
) 
  90         dragging 
= evt
.Dragging() 
  92         # Check if we're within the tolerance for mouse movements. 
  93         # If we're very close to the position we started dragging 
  94         # from, this may not be an intentional drag at all. 
  96             if self
._checkTolerance
: 
  97                 # the difference between two logical coordinates is a logical coordinate 
  98                 dx 
= abs(x 
- self
._firstDragX
)  
  99                 dy 
= abs(y 
- self
._firstDragY
) 
 100                 toler 
= self
.GetDiagram().GetMouseTolerance() 
 101                 if (dx 
<= toler
) and (dy 
<= toler
): 
 103             # If we've ignored the tolerance once, then ALWAYS ignore 
 104             # tolerance in this drag, even if we come back within 
 105             # the tolerance range. 
 106             self
._checkTolerance 
= False 
 108         # Dragging - note that the effect of dragging is left entirely up 
 109         # to the object, so no movement is done unless explicitly done by 
 111         if dragging 
and self
._draggedShape 
and self
._dragState 
== StartDraggingLeft
: 
 112             self
._dragState 
= ContinueDraggingLeft
 
 114             # If the object isn't m_draggable, transfer message to canvas 
 115             if self
._draggedShape
.Draggable(): 
 116                 self
._draggedShape
.GetEventHandler().OnBeginDragLeft(x
, y
, keys
, self
._draggedAttachment
) 
 118                 self
._draggedShape 
= None 
 119                 self
.OnBeginDragLeft(x
, y
, keys
) 
 121             self
._oldDragX
, self
._oldDragY 
= x
, y
 
 123         elif dragging 
and self
._draggedShape 
and self
._dragState 
== ContinueDraggingLeft
: 
 125             self
._draggedShape
.GetEventHandler().OnDragLeft(False, self
._oldDragX
, self
._oldDragY
, keys
, self
._draggedAttachment
) 
 126             self
._draggedShape
.GetEventHandler().OnDragLeft(True, x
, y
, keys
, self
._draggedAttachment
) 
 127             self
._oldDragX
, self
._oldDragY 
= x
, y
 
 129         elif evt
.LeftUp() and self
._draggedShape 
and self
._dragState 
== ContinueDraggingLeft
: 
 130             self
._dragState 
= NoDragging
 
 131             self
._checkTolerance 
= True 
 133             self
._draggedShape
.GetEventHandler().OnDragLeft(False, self
._oldDragX
, self
._oldDragY
, keys
, self
._draggedAttachment
) 
 134             self
._draggedShape
.GetEventHandler().OnEndDragLeft(x
, y
, keys
, self
._draggedAttachment
) 
 135             self
._draggedShape 
= None 
 137         elif dragging 
and self
._draggedShape 
and self
._dragState 
== StartDraggingRight
: 
 138             self
._dragState 
= ContinueDraggingRight
 
 139             if self
._draggedShape
.Draggable
: 
 140                 self
._draggedShape
.GetEventHandler().OnBeginDragRight(x
, y
, keys
, self
._draggedAttachment
) 
 142                 self
._draggedShape 
= None 
 143                 self
.OnBeginDragRight(x
, y
, keys
) 
 144             self
._oldDragX
, self
._oldDragY 
= x
, y
 
 146         elif dragging 
and self
._draggedShape 
and self
._dragState 
== ContinueDraggingRight
: 
 148             self
._draggedShape
.GetEventHandler().OnDragRight(False, self
._oldDragX
, self
._oldDragY
, keys
, self
._draggedAttachment
) 
 149             self
._draggedShape
.GetEventHandler().OnDragRight(True, x
, y
, keys
, self
._draggedAttachment
) 
 150             self
._oldDragX
, self
._oldDragY 
= x
, y
 
 152         elif evt
.RightUp() and self
._draggedShape 
and self
._dragState 
== ContinueDraggingRight
: 
 153             self
._dragState 
= NoDragging
 
 154             self
._checkTolerance 
= True 
 156             self
._draggedShape
.GetEventHandler().OnDragRight(False, self
._oldDragX
, self
._oldDragY
, keys
, self
._draggedAttachment
) 
 157             self
._draggedShape
.GetEventHandler().OnEndDragRight(x
, y
, keys
, self
._draggedAttachment
) 
 158             self
._draggedShape 
= None 
 160         # All following events sent to canvas, not object 
 161         elif dragging 
and not self
._draggedShape 
and self
._dragState 
== StartDraggingLeft
: 
 162             self
._dragState 
= ContinueDraggingLeft
 
 163             self
.OnBeginDragLeft(x
, y
, keys
) 
 164             self
._oldDragX
, self
._oldDragY 
= x
, y
 
 166         elif dragging 
and not self
._draggedShape 
and self
._dragState 
== ContinueDraggingLeft
: 
 168             self
.OnDragLeft(False, self
._oldDragX
, self
._oldDragY
, keys
) 
 169             self
.OnDragLeft(True, x
, y
, keys
) 
 170             self
._oldDragX
, self
._oldDragY 
= x
, y                
 
 172         elif evt
.LeftUp() and not self
._draggedShape 
and self
._dragState 
== ContinueDraggingLeft
: 
 173             self
._dragState 
= NoDragging
 
 174             self
._checkTolerance 
= True 
 176             self
.OnDragLeft(False, self
._oldDragX
, self
._oldDragY
, keys
) 
 177             self
.OnEndDragLeft(x
, y
, keys
) 
 178             self
._draggedShape 
= None 
 180         elif dragging 
and not self
._draggedShape 
and self
._dragState 
== StartDraggingRight
: 
 181             self
._dragState 
= ContinueDraggingRight
 
 182             self
.OnBeginDragRight(x
, y
, keys
) 
 183             self
._oldDragX
, self
._oldDragY 
= x
, y
 
 185         elif dragging 
and not self
._draggedShape 
and self
._dragState 
== ContinueDraggingRight
: 
 187             self
.OnDragRight(False, self
._oldDragX
, self
._oldDragY
, keys
) 
 188             self
.OnDragRight(True, x
, y
, keys
) 
 189             self
._oldDragX
, self
._oldDragY 
= x
, y
 
 191         elif evt
.RightUp() and not self
._draggedShape 
and self
._dragState 
== ContinueDraggingRight
: 
 192             self
._dragState 
= NoDragging
 
 193             self
._checkTolerance 
= True 
 195             self
.OnDragRight(False, self
._oldDragX
, self
._oldDragY
, keys
) 
 196             self
.OnEndDragRight(x
, y
, keys
) 
 197             self
._draggedShape 
= None 
 199         # Non-dragging events 
 201             self
._checkTolerance 
= True 
 203             # Find the nearest object 
 206             nearest_object
, attachment 
= self
.FindShape(x
, y
) 
 207             if nearest_object
: # Object event 
 209                     self
._draggedShape 
= nearest_object
 
 210                     self
._draggedAttachment 
= attachment
 
 211                     self
._dragState 
= StartDraggingLeft
 
 216                     # N.B. Only register a click if the same object was 
 217                     # identified for down *and* up. 
 218                     if nearest_object 
== self
._draggedShape
: 
 219                         nearest_object
.GetEventHandler().OnLeftClick(x
, y
, keys
, attachment
) 
 220                     self
._draggedShape 
= None 
 221                     self
._dragState 
= NoDragging
 
 223                 elif evt
.LeftDClick(): 
 224                     nearest_object
.GetEventHandler().OnLeftDoubleClick(x
, y
, keys
, attachment
) 
 225                     self
._draggedShape 
= None 
 226                     self
._dragState 
= NoDragging
 
 228                 elif evt
.RightDown(): 
 229                     self
._draggedShape 
= nearest_object
 
 230                     self
._draggedAttachment 
= attachment
 
 231                     self
._dragState 
= StartDraggingRight
 
 236                     if nearest_object 
== self
._draggedShape
: 
 237                         nearest_object
.GetEventHandler().OnRightClick(x
, y
, keys
, attachment
) 
 238                     self
._draggedShape 
= None 
 239                     self
._dragState 
= NoDragging
 
 243                     self
._draggedShape 
= None 
 244                     self
._dragState 
= StartDraggingLeft
 
 249                     self
.OnLeftClick(x
, y
, keys
) 
 250                     self
._draggedShape 
= None 
 251                     self
._dragState 
= NoDragging
 
 253                 elif evt
.RightDown(): 
 254                     self
._draggedShape 
= None 
 255                     self
._dragState 
= StartDraggingRight
 
 260                     self
.OnRightClick(x
, y
, keys
) 
 261                     self
._draggedShape 
= None 
 262                     self
._dragState 
= NoDragging
 
 264     def FindShape(self
, x
, y
, info 
= None, notObject 
= None): 
 266         nearest_attachment 
= 0 
 267         nearest_object 
= None 
 269         # Go backward through the object list, since we want: 
 270         # (a) to have the control points drawn LAST to overlay 
 272         # (b) to find the control points FIRST if they exist 
 274         rl 
= self
.GetDiagram().GetShapeList()[:] 
 277             # First pass for lines, which might be inside a container, so we 
 278             # want lines to take priority over containers. This first loop 
 279             # could fail if we clickout side a line, so then we'll 
 281             if object.IsShown() and \
 
 282                isinstance(object, LineShape
) and \
 
 283                object.HitTest(x
, y
) and \
 
 284                ((info 
== None) or isinstance(object, info
)) and \
 
 285                (not notObject 
or not notObject
.HasDescendant(object)): 
 286                 temp_attachment
, dist 
= object.HitTest(x
, y
) 
 287                 # A line is trickier to spot than a normal object. 
 288                 # For a line, since it's the diagonal of the box 
 289                 # we use for the hit test, we may have several 
 290                 # lines in the box and therefore we need to be able 
 291                 # to specify the nearest point to the centre of the line 
 292                 # as our hit criterion, to give the user some room for 
 296                     nearest_object 
= object 
 297                     nearest_attachment 
= temp_attachment
 
 300             # On second pass, only ever consider non-composites or 
 301             # divisions. If children want to pass up control to 
 302             # the composite, that's up to them. 
 303             if (object.IsShown() and  
 304                    (isinstance(object, DivisionShape
) or  
 305                     not isinstance(object, CompositeShape
)) and  
 306                     object.HitTest(x
, y
) and  
 307                     (info 
== None or isinstance(object, info
)) and  
 308                     (not notObject 
or not notObject
.HasDescendant(object))): 
 309                 temp_attachment
, dist 
= object.HitTest(x
, y
) 
 310                 if not isinstance(object, LineShape
): 
 311                     # If we've hit a container, and we have already 
 312                     # found a line in the first pass, then ignore 
 313                     # the container in case the line is in the container. 
 314                     # Check for division in case line straddles divisions 
 315                     # (i.e. is not wholly contained). 
 316                     if not nearest_object 
or not (isinstance(object, DivisionShape
) or WhollyContains(object, nearest_object
)): 
 317                         nearest_object 
= object 
 318                         nearest_attachment 
= temp_attachment
 
 321         return nearest_object
, nearest_attachment
 
 323     def AddShape(self
, object, addAfter 
= None): 
 324         self
.GetDiagram().AddShape(object, addAfter
) 
 326     def InsertShape(self
, object): 
 327         self
.GetDiagram().InsertShape(object) 
 329     def RemoveShape(self
, object): 
 330         self
.GetDiagram().RemoveShape(object) 
 332     def GetQuickEditMode(self
): 
 333         return self
.GetDiagram().GetQuickEditMode() 
 335     def Redraw(self
, dc
): 
 336         self
.GetDiagram().Redraw(dc
) 
 338     def Snap(self
, x
, y
): 
 339         return self
.GetDiagram().Snap(x
, y
) 
 341     def OnLeftClick(self
, x
, y
, keys 
= 0): 
 344     def OnRightClick(self
, x
, y
, keys 
= 0): 
 347     def OnDragLeft(self
, draw
, x
, y
, keys 
= 0): 
 350     def OnBeginDragLeft(self
, x
, y
, keys 
= 0): 
 353     def OnEndDragLeft(self
, x
, y
, keys 
= 0): 
 356     def OnDragRight(self
, draw
, x
, y
, keys 
= 0): 
 359     def OnBeginDragRight(self
, x
, y
, keys 
= 0): 
 362     def OnEndDragRight(self
, x
, y
, keys 
= 0):