]> git.saurik.com Git - wxWidgets.git/blame - wxPython/samples/ide/activegrid/tool/AbstractEditor.py
Only freeze the splitter, the children will be automatically frozen too.
[wxWidgets.git] / wxPython / samples / ide / activegrid / tool / AbstractEditor.py
CommitLineData
1f780e48
RD
1#----------------------------------------------------------------------------
2# Name: AbstractEditor.py
3# Purpose: Non-text editor for DataModel and Process
4#
5# Author: Peter Yared, Morgan Hua
6#
7# Created: 7/28/04
8# CVS-ID: $Id$
9# Copyright: (c) 2004-2005 ActiveGrid, Inc.
10# License: wxWindows License
11#----------------------------------------------------------------------------
12
13
14import wx
15import wx.lib.docview
16import wx.lib.ogl as ogl
17import PropertyService
18_ = wx.GetTranslation
19
20
21SELECT_BRUSH = wx.Brush("BLUE", wx.SOLID)
22SHAPE_BRUSH = wx.Brush("WHEAT", wx.SOLID)
23LINE_BRUSH = wx.BLACK_BRUSH
b792147d 24INACTIVE_SELECT_BRUSH = wx.Brush("LIGHT BLUE", wx.SOLID)
1f780e48
RD
25
26
27def GetRawModel(model):
28 if hasattr(model, "GetRawModel"):
29 rawModel = model.GetRawModel()
30 else:
31 rawModel = model
32 return rawModel
33
34
35class CanvasView(wx.lib.docview.View):
36
37
38 #----------------------------------------------------------------------------
39 # Overridden methods
40 #----------------------------------------------------------------------------
41
42
43 def __init__(self, brush = SHAPE_BRUSH):
44 wx.lib.docview.View.__init__(self)
45 self._brush = brush
46 self._canvas = None
47 self._pt1 = None
48 self._pt2 = None
49 self._needEraseLasso = False
50 self._propShape = None
26ee3a06
RD
51 self._maxWidth = 2000
52 self._maxHeight = 16000
1f780e48
RD
53
54
26ee3a06
RD
55 def OnDraw(self, dc):
56 """ for Print Preview and Print """
57 dc.BeginDrawing()
58 self._canvas.Redraw(dc)
59 dc.EndDrawing()
60
61
1f780e48
RD
62 def OnCreate(self, doc, flags):
63 frame = wx.GetApp().CreateDocumentFrame(self, doc, flags)
64 frame.Show()
65 sizer = wx.BoxSizer()
66 self._CreateCanvas(frame)
67 sizer.Add(self._canvas, 1, wx.EXPAND, 0)
68 frame.SetSizer(sizer)
69 frame.Layout()
70 self.Activate()
71 return True
b792147d 72
1f780e48
RD
73
74 def OnActivateView(self, activate, activeView, deactiveView):
75 if activate and self._canvas:
76 # In MDI mode just calling set focus doesn't work and in SDI mode using CallAfter causes an endless loop
77 if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
6f1a3f9c 78 self.SetFocus()
1f780e48 79 else:
6f1a3f9c
RD
80 wx.CallAfter(self.SetFocus)
81
82
83 def SetFocus(self):
84 if self._canvas:
85 self._canvas.SetFocus()
1f780e48
RD
86
87
b792147d 88 def OnFocus(self, event):
6f1a3f9c 89 self.SetFocus()
b792147d
RD
90 self.FocusColorPropertyShape(True)
91 event.Skip()
92
93
94 def OnKillFocus(self, event):
95 self.FocusColorPropertyShape(False)
96 event.Skip()
97
98
6f1a3f9c
RD
99 def HasFocus(self):
100 winWithFocus = wx.Window.FindFocus()
101 if not winWithFocus:
102 return False
103 while winWithFocus:
104 if winWithFocus == self._canvas:
105 return True
106 winWithFocus = winWithFocus.GetParent()
107 return False
108
109
1f780e48
RD
110 def OnClose(self, deleteWindow = True):
111 statusC = wx.GetApp().CloseChildDocuments(self.GetDocument())
112 statusP = wx.lib.docview.View.OnClose(self, deleteWindow = deleteWindow)
113 if hasattr(self, "ClearOutline"):
114 wx.CallAfter(self.ClearOutline) # need CallAfter because when closing the document, it is Activated and then Close, so need to match OnActivateView's CallAfter
115 if not (statusC and statusP):
116 return False
117 self.Activate(False)
118 if deleteWindow and self.GetFrame():
119 self.GetFrame().Destroy()
120 return True
121
122
123 def _CreateCanvas(self, parent):
124 self._canvas = ogl.ShapeCanvas(parent)
125 wx.EVT_LEFT_DOWN(self._canvas, self.OnLeftClick)
126 wx.EVT_LEFT_UP(self._canvas, self.OnLeftUp)
127 wx.EVT_MOTION(self._canvas, self.OnLeftDrag)
128 wx.EVT_LEFT_DCLICK(self._canvas, self.OnLeftDoubleClick)
129 wx.EVT_KEY_DOWN(self._canvas, self.OnKeyPressed)
b792147d
RD
130
131 # need this otherwise mouse clicks don't set focus to this view
132 wx.EVT_LEFT_DOWN(self._canvas, self.OnFocus)
133 wx.EVT_LEFT_DCLICK(self._canvas, self.OnFocus)
134 wx.EVT_RIGHT_DOWN(self._canvas, self.OnFocus)
135 wx.EVT_RIGHT_DCLICK(self._canvas, self.OnFocus)
136 wx.EVT_MIDDLE_DOWN(self._canvas, self.OnFocus)
137 wx.EVT_MIDDLE_DCLICK(self._canvas, self.OnFocus)
138
139 wx.EVT_KILL_FOCUS(self._canvas, self.OnKillFocus)
140 wx.EVT_SET_FOCUS(self._canvas, self.OnFocus)
1f780e48 141
26ee3a06 142 self._canvas.SetScrollbars(20, 20, self._maxWidth / 20, self._maxHeight / 20)
1f780e48
RD
143
144 self._canvas.SetBackgroundColour(wx.WHITE)
145 self._diagram = ogl.Diagram()
146 self._canvas.SetDiagram(self._diagram)
147 self._diagram.SetCanvas(self._canvas)
148
149
150 def OnKeyPressed(self, event):
151 key = event.KeyCode()
152 if key == wx.WXK_DELETE:
153 self.OnClear(event)
154 else:
155 event.Skip()
156
157
158 def OnLeftClick(self, event):
159 self.EraseRubberBand()
160
161 dc = wx.ClientDC(self._canvas)
162 self._canvas.PrepareDC(dc)
163
164 # keep track of mouse down for group select
165 self._pt1 = event.GetLogicalPosition(dc) # this takes into account scrollbar offset
166 self._pt2 = None
167
168 shape = self._canvas.FindShape(self._pt1[0], self._pt1[1])[0]
169 if shape:
170 self.BringToFront(shape)
171
172 self._pt1 = None
173 event.Skip() # pass on event to shape handler to take care of selection
174
175 return
176 elif event.ControlDown() or event.ShiftDown(): # extend select, don't deselect
177 pass
178 else:
179 # click on empty part of canvas, deselect everything
180 needRefresh = False
181 for shape in self._diagram.GetShapeList():
182 if hasattr(shape, "GetModel"):
183 if shape.Selected():
184 needRefresh = True
185 shape.Select(False, dc)
186 if needRefresh:
187 self._canvas.Redraw(dc)
188
189 self.SetPropertyModel(None)
190
191 if len(self.GetSelection()) == 0:
192 self.SetPropertyShape(None)
193
194
195
196 def OnLeftDoubleClick(self, event):
197 propertyService = wx.GetApp().GetService(PropertyService.PropertyService)
198 if propertyService:
199 propertyService.ShowWindow()
200
201
202 def OnLeftDrag(self, event):
203 # draw lasso for group select
204 if self._pt1 and event.LeftIsDown(): # we are in middle of lasso selection
205 self.EraseRubberBand()
206
207 dc = wx.ClientDC(self._canvas)
208 self._canvas.PrepareDC(dc)
209 self._pt2 = event.GetLogicalPosition(dc) # this takes into account scrollbar offset
210 self.DrawRubberBand()
211 else:
212 event.Skip()
213
214
215 def OnLeftUp(self, event):
216 # do group select
217 if self._needEraseLasso:
218 self.EraseRubberBand()
219
220 dc = wx.ClientDC(self._canvas)
221 self._canvas.PrepareDC(dc)
222 x1, y1 = self._pt1
223 x2, y2 = event.GetLogicalPosition(dc) # this takes into account scrollbar offset
224
225 tol = self._diagram.GetMouseTolerance()
226 if abs(x1 - x2) > tol or abs(y1 - y2) > tol:
227 # make sure x1 < x2 and y1 < y2 to make comparison test easier
228 if x1 > x2:
229 temp = x1
230 x1 = x2
231 x2 = temp
232 if y1 > y2:
233 temp = y1
234 y1 = y2
235 y2 = temp
236
237 for shape in self._diagram.GetShapeList():
238 if not shape.GetParent() and hasattr(shape, "GetModel"): # if part of a composite, don't select it
239 x, y = shape.GetX(), shape.GetY()
240 width, height = shape.GetBoundingBoxMax()
241 selected = x1 < x - width/2 and x2 > x + width/2 and y1 < y - height/2 and y2 > y + height/2
242 if event.ControlDown() or event.ShiftDown(): # extend select, don't deselect
243 if selected:
244 shape.Select(selected, dc)
245 else: # select items in lasso and deselect items out of lasso
246 shape.Select(selected, dc)
247 self._canvas.Redraw(dc)
248 else:
249 event.Skip()
250 else:
251 event.Skip()
252
253
254 def EraseRubberBand(self):
255 if self._needEraseLasso:
256 self._needEraseLasso = False
257
258 dc = wx.ClientDC(self._canvas)
259 self._canvas.PrepareDC(dc)
260 dc.SetLogicalFunction(wx.XOR)
261 pen = wx.Pen(wx.Colour(200, 200, 200), 1, wx.SHORT_DASH)
262 dc.SetPen(pen)
263 brush = wx.Brush(wx.Colour(255, 255, 255), wx.TRANSPARENT)
264 dc.SetBrush(brush)
265 dc.ResetBoundingBox()
266 dc.BeginDrawing()
267
268 x1, y1 = self._pt1
269 x2, y2 = self._pt2
270
271 # make sure x1 < x2 and y1 < y2
272 # this will make (x1, y1) = upper left corner
273 if x1 > x2:
274 temp = x1
275 x1 = x2
276 x2 = temp
277 if y1 > y2:
278 temp = y1
279 y1 = y2
280 y2 = temp
281
282 # erase previous outline
283 dc.SetClippingRegion(x1, y1, x2 - x1, y2 - y1)
284 dc.DrawRectangle(x1, y1, x2 - x1, y2 - y1)
285 dc.EndDrawing()
286
287
288 def DrawRubberBand(self):
289 self._needEraseLasso = True
290
291 dc = wx.ClientDC(self._canvas)
292 self._canvas.PrepareDC(dc)
293 dc.SetLogicalFunction(wx.XOR)
294 pen = wx.Pen(wx.Colour(200, 200, 200), 1, wx.SHORT_DASH)
295 dc.SetPen(pen)
296 brush = wx.Brush(wx.Colour(255, 255, 255), wx.TRANSPARENT)
297 dc.SetBrush(brush)
298 dc.ResetBoundingBox()
299 dc.BeginDrawing()
300
301 x1, y1 = self._pt1
302 x2, y2 = self._pt2
303
304 # make sure x1 < x2 and y1 < y2
305 # this will make (x1, y1) = upper left corner
306 if x1 > x2:
307 temp = x1
308 x1 = x2
309 x2 = temp
310 if y1 > y2:
311 temp = y1
312 y1 = y2
313 y2 = temp
314
315 # draw outline
316 dc.SetClippingRegion(x1, y1, x2 - x1, y2 - y1)
317 dc.DrawRectangle(x1, y1, x2 - x1, y2 - y1)
318 dc.EndDrawing()
319
320
321 def FindParkingSpot(self, width, height):
322 """ given a width and height, find a upper left corner where shape can be parked without overlapping other shape """
323 offset = 30 # space between shapes
324 x = offset
325 y = offset
326 maxX = 700 # max distance to the right where we'll place tables
327 noParkingSpot = True
328
329 while noParkingSpot:
330 point = self.isSpotOccupied(x, y, width, height)
331 if point:
332 x = point[0] + offset
333 if x > maxX:
334 x = offset
335 y = point[1] + offset
336 else:
337 noParkingSpot = False
338
339 return x, y
340
341
342 def isSpotOccupied(self, x, y, width, height):
343 """ returns None if at x,y,width,height no object occupies that rectangle,
344 otherwise returns lower right corner of object that occupies given x,y position
345 """
346 x2 = x + width
347 y2 = y + height
348
349 for shape in self._diagram.GetShapeList():
350 if isinstance(shape, ogl.RectangleShape) or isinstance(shape, ogl.EllipseShape):
351 if shape.GetParent() and isinstance(shape.GetParent(), ogl.CompositeShape):
352 # skip, part of a composite shape
353 continue
354
355 if hasattr(shape, "GetModel"):
356 other_x, other_y, other_width, other_height = shape.GetModel().getEditorBounds()
357 other_x2 = other_x + other_width
358 other_y2 = other_y + other_height
359 else:
360 # shapes x,y are at the center of the shape, need to transform to upper left coordinate
361 other_width, other_height = shape.GetBoundingBoxMax()
362 other_x = shape.GetX() - other_width/2
363 other_y = shape.GetY() - other_height/2
364
365 other_x2 = other_x + other_width
366 other_y2 = other_y + other_height
367 # intersection check
368 if ((other_x2 < other_x or other_x2 > x) and
369 (other_y2 < other_y or other_y2 > y) and
370 (x2 < x or x2 > other_x) and
371 (y2 < y or y2 > other_y)):
372 return (other_x2, other_y2)
373 return None
374
375
376 #----------------------------------------------------------------------------
377 # Canvas methods
378 #----------------------------------------------------------------------------
379
380 def AddShape(self, shape, x = None, y = None, pen = None, brush = None, text = None, eventHandler = None):
381 if isinstance(shape, ogl.CompositeShape):
382 dc = wx.ClientDC(self._canvas)
383 self._canvas.PrepareDC(dc)
384 shape.Move(dc, x, y)
385 else:
386 shape.SetDraggable(True, True)
387 shape.SetCanvas(self._canvas)
388
389 if x:
390 shape.SetX(x)
391 if y:
392 shape.SetY(y)
393 shape.SetCentreResize(False)
394 if pen:
395 shape.SetPen(pen)
396 if brush:
397 shape.SetBrush(brush)
398 if text:
399 shape.AddText(text)
400 shape.SetShadowMode(ogl.SHADOW_RIGHT)
401 self._diagram.AddShape(shape)
402 shape.Show(True)
403 if not eventHandler:
404 eventHandler = EditorCanvasShapeEvtHandler(self)
405 eventHandler.SetShape(shape)
406 eventHandler.SetPreviousHandler(shape.GetEventHandler())
407 shape.SetEventHandler(eventHandler)
408 return shape
409
410
411 def RemoveShape(self, model = None, shape = None):
412 if not model and not shape:
413 return
414
415 if not shape:
416 shape = self.GetShape(model)
417
418 if shape:
419 shape.Select(False)
420 self._diagram.RemoveShape(shape)
421 if isinstance(shape, ogl.CompositeShape):
422 shape.RemoveFromCanvas(self._canvas)
423
424
425 def UpdateShape(self, model):
426 for shape in self._diagram.GetShapeList():
427 if hasattr(shape, "GetModel") and shape.GetModel() == model:
428 x, y, w, h = model.getEditorBounds()
429 newX = x + w / 2
430 newY = y + h / 2
431 changed = False
432 if isinstance(shape, ogl.CompositeShape):
433 if shape.GetX() != newX or shape.GetY() != newY:
434 dc = wx.ClientDC(self._canvas)
435 self._canvas.PrepareDC(dc)
436 shape.SetSize(w, h, True) # wxBug: SetSize must be before Move because links won't go to the right place
437 shape.Move(dc, newX, newY) # wxBug: Move must be before SetSize because links won't go to the right place
438 changed = True
439 else:
440 oldw, oldh = shape.GetBoundingBoxMax()
441 oldx = shape.GetX()
442 oldy = shape.GetY()
443 if oldw != w or oldh != h or oldx != newX or oldy != newY:
444 shape.SetSize(w, h)
445 shape.SetX(newX)
446 shape.SetY(newY)
447 changed = True
448 if changed:
449 shape.ResetControlPoints()
450 self._canvas.Refresh()
451 break
452
453
454 def GetShape(self, model):
455 for shape in self._diagram.GetShapeList():
456 if hasattr(shape, "GetModel") and shape.GetModel() == model:
457 return shape
458 return None
459
460
461 def GetSelection(self):
462 return filter(lambda shape: shape.Selected(), self._diagram.GetShapeList())
463
464
465 def SetSelection(self, models, extendSelect = False):
466 dc = wx.ClientDC(self._canvas)
467 self._canvas.PrepareDC(dc)
468 update = False
469 if not isinstance(models, type([])) and not isinstance(models, type(())):
470 models = [models]
471 for shape in self._diagram.GetShapeList():
472 if hasattr(shape, "GetModel"):
473 if shape.Selected() and not shape.GetModel() in models: # was selected, but not in new list, so deselect, unless extend select
474 if not extendSelect:
475 shape.Select(False, dc)
476 update = True
477 elif not shape.Selected() and shape.GetModel() in models: # was not selected and in new list, so select
478 shape.Select(True, dc)
479 update = True
480 elif extendSelect and shape.Selected() and shape.GetModel() in models: # was selected, but extend select means to deselect
481 shape.Select(False, dc)
482 update = True
483 if update:
484 self._canvas.Redraw(dc)
485
486
487 def BringToFront(self, shape):
488 if shape.GetParent() and isinstance(shape.GetParent(), ogl.CompositeShape):
489 self._diagram.RemoveShape(shape.GetParent())
490 self._diagram.AddShape(shape.GetParent())
491 else:
492 self._diagram.RemoveShape(shape)
493 self._diagram.AddShape(shape)
494
495
496 def SendToBack(self, shape):
497 if shape.GetParent() and isinstance(shape.GetParent(), ogl.CompositeShape):
498 self._diagram.RemoveShape(shape.GetParent())
499 self._diagram.InsertShape(shape.GetParent())
500 else:
501 self._diagram.RemoveShape(shape)
502 self._diagram.InsertShape(shape)
503
504
505 def ScrollVisible(self, shape):
506 xUnit, yUnit = shape._canvas.GetScrollPixelsPerUnit()
507 scrollX, scrollY = self._canvas.GetViewStart() # in scroll units
508 scrollW, scrollH = self._canvas.GetSize() # in pixels
509 w, h = shape.GetBoundingBoxMax() # in pixels
510 x = shape.GetX() - w/2 # convert to upper left coordinate from center
511 y = shape.GetY() - h/2 # convert to upper left coordinate from center
512
513 if x >= scrollX*xUnit and x <= scrollX*xUnit + scrollW: # don't scroll if already visible
514 x = -1
515 else:
516 x = x/xUnit
517
518 if y >= scrollY*yUnit and y <= scrollY*yUnit + scrollH: # don't scroll if already visible
519 y = -1
520 else:
521 y = y/yUnit
522
523 self._canvas.Scroll(x, y) # in scroll units
524
525
526 def SetPropertyShape(self, shape):
527 # no need to highlight if no PropertyService is running
528 propertyService = wx.GetApp().GetService(PropertyService.PropertyService)
529 if not propertyService:
530 return
531
532 if shape == self._propShape:
533 return
534
535 if hasattr(shape, "GetPropertyShape"):
536 shape = shape.GetPropertyShape()
537
538 dc = wx.ClientDC(self._canvas)
539 self._canvas.PrepareDC(dc)
540 dc.BeginDrawing()
541
542 # erase old selection if it still exists
543 if self._propShape and self._propShape in self._diagram.GetShapeList():
544 self._propShape.SetBrush(self._brush)
545 if (self._propShape._textColourName in ["BLACK", "WHITE"]): # Would use GetTextColour() but it is broken
546 self._propShape.SetTextColour("BLACK", 0)
547 self._propShape.Draw(dc)
548
549 # set new selection
550 self._propShape = shape
551
552 # draw new selection
553 if self._propShape and self._propShape in self._diagram.GetShapeList():
6f1a3f9c
RD
554 if self.HasFocus():
555 self._propShape.SetBrush(SELECT_BRUSH)
556 else:
557 self._propShape.SetBrush(INACTIVE_SELECT_BRUSH)
1f780e48
RD
558 if (self._propShape._textColourName in ["BLACK", "WHITE"]): # Would use GetTextColour() but it is broken
559 self._propShape.SetTextColour("WHITE", 0)
560 self._propShape.Draw(dc)
561
562 dc.EndDrawing()
563
564
b792147d
RD
565 def FocusColorPropertyShape(self, gotFocus=False):
566 # no need to change highlight if no PropertyService is running
567 propertyService = wx.GetApp().GetService(PropertyService.PropertyService)
568 if not propertyService:
569 return
570
571 if not self._propShape:
572 return
573
574 dc = wx.ClientDC(self._canvas)
575 self._canvas.PrepareDC(dc)
576 dc.BeginDrawing()
577
578 # draw deactivated selection
579 if self._propShape and self._propShape in self._diagram.GetShapeList():
580 if gotFocus:
581 self._propShape.SetBrush(SELECT_BRUSH)
582 else:
583 self._propShape.SetBrush(INACTIVE_SELECT_BRUSH)
584 if (self._propShape._textColourName in ["BLACK", "WHITE"]): # Would use GetTextColour() but it is broken
585 self._propShape.SetTextColour("WHITE", 0)
586 self._propShape.Draw(dc)
587
588 dc.EndDrawing()
589
590
1f780e48
RD
591 #----------------------------------------------------------------------------
592 # Property Service methods
593 #----------------------------------------------------------------------------
594
595 def GetPropertyModel(self):
596 if hasattr(self, "_propModel"):
597 return self._propModel
598 return None
599
600
601 def SetPropertyModel(self, model):
602 # no need to set the model if no PropertyService is running
603 propertyService = wx.GetApp().GetService(PropertyService.PropertyService)
604 if not propertyService:
605 return
606
607 if hasattr(self, "_propModel") and model == self._propModel:
608 return
609
610 self._propModel = model
611 propertyService.LoadProperties(self._propModel, self.GetDocument())
612
613
614class EditorCanvasShapeMixin:
615
616 def GetModel(self):
617 return self._model
618
619
620 def SetModel(self, model):
621 self._model = model
622
623
624class EditorCanvasShapeEvtHandler(ogl.ShapeEvtHandler):
625
626 """ wxBug: Bug in OLG package. With wxShape.SetShadowMode() turned on, when we set the size,
627 the width/height is larger by 6 pixels. Need to subtract this value from width and height when we
628 resize the object.
629 """
630 SHIFT_KEY = 1
631 CONTROL_KEY = 2
632
633 def __init__(self, view):
634 ogl.ShapeEvtHandler.__init__(self)
635 self._view = view
636
637
638 def OnLeftClick(self, x, y, keys = 0, attachment = 0):
639 shape = self.GetShape()
640 if hasattr(shape, "GetModel"): # Workaround, on drag, we should deselect all other objects and select the clicked on object
641 model = shape.GetModel()
642 else:
643 shape = shape.GetParent()
644 if shape:
645 model = shape.GetModel()
646
647 self._view.SetSelection(model, keys == self.SHIFT_KEY or keys == self.CONTROL_KEY)
648 self._view.SetPropertyShape(shape)
649 self._view.SetPropertyModel(model)
650
651
652 def OnEndDragLeft(self, x, y, keys = 0, attachment = 0):
653 ogl.ShapeEvtHandler.OnEndDragLeft(self, x, y, keys, attachment)
654 shape = self.GetShape()
655 if hasattr(shape, "GetModel"): # Workaround, on drag, we should deselect all other objects and select the clicked on object
656 model = shape.GetModel()
657 else:
658 parentShape = shape.GetParent()
659 if parentShape:
660 model = parentShape.GetModel()
661 self._view.SetSelection(model, keys == self.SHIFT_KEY or keys == self.CONTROL_KEY)
662
663
26ee3a06
RD
664 def OnMovePre(self, dc, x, y, oldX, oldY, display):
665 """ Prevent objects from being dragged outside of viewable area """
666 if (x > self._view._maxWidth) or (y > self._view._maxHeight):
667 return False
668
669 return ogl.ShapeEvtHandler.OnMovePre(self, dc, x, y, oldX, oldY, display)
670
671
1f780e48 672 def OnMovePost(self, dc, x, y, oldX, oldY, display):
26ee3a06 673 """ Update the model's record of where the shape should be. Also enable redo/undo. """
1f780e48
RD
674 if x == oldX and y == oldY:
675 return
676 if not self._view.GetDocument():
677 return
678 shape = self.GetShape()
679 if isinstance(shape, EditorCanvasShapeMixin) and shape.Draggable():
680 model = shape.GetModel()
681 if hasattr(model, "getEditorBounds") and model.getEditorBounds():
682 x, y, w, h = model.getEditorBounds()
683 newX = shape.GetX() - shape.GetBoundingBoxMax()[0] / 2
684 newY = shape.GetY() - shape.GetBoundingBoxMax()[1] / 2
685 newWidth = shape.GetBoundingBoxMax()[0]
686 newHeight = shape.GetBoundingBoxMax()[1]
687 if shape._shadowMode != ogl.SHADOW_NONE:
688 newWidth -= shape._shadowOffsetX
689 newHeight -= shape._shadowOffsetY
690 newbounds = (newX, newY, newWidth, newHeight)
691
692 if x != newX or y != newY or w != newWidth or h != newHeight:
693 self._view.GetDocument().GetCommandProcessor().Submit(EditorCanvasUpdateShapeBoundariesCommand(self._view.GetDocument(), model, newbounds))
694
695
696 def Draw(self, dc):
697 pass
698
699
700class EditorCanvasUpdateShapeBoundariesCommand(wx.lib.docview.Command):
701
702
703 def __init__(self, canvasDocument, model, newbounds):
704 wx.lib.docview.Command.__init__(self, canUndo = True)
705 self._canvasDocument = canvasDocument
706 self._model = model
707 self._oldbounds = model.getEditorBounds()
708 self._newbounds = newbounds
709
710
711 def GetName(self):
712 name = self._canvasDocument.GetNameForObject(self._model)
713 if not name:
714 name = ""
715 print "ERROR: AbstractEditor.EditorCanvasUpdateShapeBoundariesCommand.GetName: unable to get name for ", self._model
716 return _("Move/Resize %s") % name
717
718
719 def Do(self):
720 return self._canvasDocument.UpdateEditorBoundaries(self._model, self._newbounds)
721
722
723 def Undo(self):
724 return self._canvasDocument.UpdateEditorBoundaries(self._model, self._oldbounds)
725