2 # -*- coding: utf-8 -*- |
2 # -*- coding: utf-8 -*- |
3 |
3 |
4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor |
4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor |
5 #based on the plcopen standard. |
5 #based on the plcopen standard. |
6 # |
6 # |
7 #Copyright (C): Edouard TISSERANT and Laurent BESSARD |
7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD |
8 # |
8 # |
9 #See COPYING file for copyrights details. |
9 #See COPYING file for copyrights details. |
10 # |
10 # |
11 #This library is free software; you can redistribute it and/or |
11 #This library is free software; you can redistribute it and/or |
12 #modify it under the terms of the GNU General Public |
12 #modify it under the terms of the GNU General Public |
14 #version 2.1 of the License, or (at your option) any later version. |
14 #version 2.1 of the License, or (at your option) any later version. |
15 # |
15 # |
16 #This library is distributed in the hope that it will be useful, |
16 #This library is distributed in the hope that it will be useful, |
17 #but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 #but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
19 #Lesser General Public License for more details. |
19 #General Public License for more details. |
20 # |
20 # |
21 #You should have received a copy of the GNU General Public |
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 |
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 |
23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
24 |
24 |
84 MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION] = range(15) |
84 MODE_DIVERGENCE, MODE_JUMP, MODE_ACTION] = range(15) |
85 |
85 |
86 # Contants for defining which drawing mode is selected for app |
86 # Contants for defining which drawing mode is selected for app |
87 [FREEDRAWING_MODE, DRIVENDRAWING_MODE] = [1, 2] |
87 [FREEDRAWING_MODE, DRIVENDRAWING_MODE] = [1, 2] |
88 |
88 |
|
89 CURSORS = None |
|
90 |
|
91 def ResetCursors(): |
|
92 global CURSORS |
|
93 if CURSORS == None: |
|
94 CURSORS = [wxNullCursor, |
|
95 wxStockCursor(wxCURSOR_HAND), |
|
96 wxStockCursor(wxCURSOR_SIZENWSE), |
|
97 wxStockCursor(wxCURSOR_SIZENESW), |
|
98 wxStockCursor(wxCURSOR_SIZEWE), |
|
99 wxStockCursor(wxCURSOR_SIZENS)] |
|
100 |
|
101 HANDLE_CURSORS = { |
|
102 (1, 1) : 2, |
|
103 (3, 3) : 2, |
|
104 (1, 3) : 3, |
|
105 (3, 1) : 3, |
|
106 (1, 2) : 4, |
|
107 (3, 2) : 4, |
|
108 (2, 1) : 5, |
|
109 (2, 3) : 5 |
|
110 } |
89 |
111 |
90 """ |
112 """ |
91 Basic vector operations for calculate wire points |
113 Basic vector operations for calculate wire points |
92 """ |
114 """ |
93 |
115 |
263 self.Dragging = False |
285 self.Dragging = False |
264 self.Selected = False |
286 self.Selected = False |
265 self.Pos = wxPoint(0, 0) |
287 self.Pos = wxPoint(0, 0) |
266 self.Size = wxSize(0, 0) |
288 self.Size = wxSize(0, 0) |
267 self.BoundingBox = wxRect(0, 0, 0, 0) |
289 self.BoundingBox = wxRect(0, 0, 0, 0) |
|
290 self.CurrentCursor = 0 |
|
291 ResetCursors() |
268 |
292 |
269 # Make a clone of this element |
293 # Make a clone of this element |
270 def Clone(self): |
294 def Clone(self): |
271 return Graphic_Element(self.Parent, self.Id) |
295 return Graphic_Element(self.Parent, self.Id) |
272 |
296 |
337 def SetSelected(self, selected): |
361 def SetSelected(self, selected): |
338 self.Selected = selected |
362 self.Selected = selected |
339 |
363 |
340 # Test if the point is on a handle of this element |
364 # Test if the point is on a handle of this element |
341 def TestHandle(self, pt): |
365 def TestHandle(self, pt): |
|
366 extern_rect = wxRect(self.BoundingBox.x - HANDLE_SIZE - 2, self.BoundingBox.y - HANDLE_SIZE - 2, |
|
367 self.BoundingBox.width + 2 * HANDLE_SIZE + 4, self.BoundingBox.height + 2 * HANDLE_SIZE + 4) |
|
368 intern_rect = wxRect(self.BoundingBox.x - 2, self.BoundingBox.y - 2, |
|
369 self.BoundingBox.width + 4, self.BoundingBox.height + 4) |
342 # Verify that this element is selected |
370 # Verify that this element is selected |
343 if self.Selected: |
371 if self.Selected and extern_rect.InsideXY(pt.x, pt.y) and not intern_rect.InsideXY(pt.x, pt.y): |
344 # Find if point is on a handle horizontally |
372 # Find if point is on a handle horizontally |
345 if self.BoundingBox.x - HANDLE_SIZE - 2 <= pt.x < self.BoundingBox.x - 2: |
373 if self.BoundingBox.x - HANDLE_SIZE - 2 <= pt.x < self.BoundingBox.x - 2: |
346 handle_x = 1 |
374 handle_x = 1 |
347 elif self.BoundingBox.x + (self.BoundingBox.width - HANDLE_SIZE) / 2 <= pt.x < self.BoundingBox.x + (self.BoundingBox.width + HANDLE_SIZE) / 2: |
375 elif self.BoundingBox.x + (self.BoundingBox.width - HANDLE_SIZE) / 2 <= pt.x < self.BoundingBox.x + (self.BoundingBox.width + HANDLE_SIZE) / 2: |
348 handle_x = 2 |
376 handle_x = 2 |
366 |
394 |
367 # Method called when a LeftDown event have been generated |
395 # Method called when a LeftDown event have been generated |
368 def OnLeftDown(self, event, dc, scaling): |
396 def OnLeftDown(self, event, dc, scaling): |
369 pos = event.GetLogicalPosition(dc) |
397 pos = event.GetLogicalPosition(dc) |
370 # Test if an handle have been clicked |
398 # Test if an handle have been clicked |
371 result = self.TestHandle(pos) |
399 handle = self.TestHandle(pos) |
372 # Find which type of handle have been clicked, |
400 # Find which type of handle have been clicked, |
373 # Save a resize event and change the cursor |
401 # Save a resize event and change the cursor |
374 if result == (1, 1) or result == (3, 3): |
402 cursor = HANDLE_CURSORS.get(handle, 1) |
375 self.Handle = (HANDLE_RESIZE, result) |
403 if cursor != self.CurrentCursor: |
376 self.Parent.SetCursor(wxStockCursor(wxCURSOR_SIZENWSE)) |
404 self.Parent.SetCursor(CURSORS[cursor]) |
377 elif result == (1, 3) or result == (3, 1): |
405 self.CurrentCursor = cursor |
378 self.Handle = (HANDLE_RESIZE, result) |
406 if cursor > 1: |
379 self.Parent.SetCursor(wxStockCursor(wxCURSOR_SIZENESW)) |
407 self.Handle = (HANDLE_RESIZE, handle) |
380 elif result == (1, 2) or result == (3, 2): |
|
381 self.Handle = (HANDLE_RESIZE, result) |
|
382 self.Parent.SetCursor(wxStockCursor(wxCURSOR_SIZEWE)) |
|
383 elif result == (2, 1) or result == (2, 3): |
|
384 self.Handle = (HANDLE_RESIZE, result) |
|
385 self.Parent.SetCursor(wxStockCursor(wxCURSOR_SIZENS)) |
|
386 # If no handle have been clicked, save a move event, and change the cursor |
|
387 else: |
408 else: |
388 self.Handle = (HANDLE_MOVE, None) |
409 self.Handle = (HANDLE_MOVE, None) |
389 self.Parent.SetCursor(wxStockCursor(wxCURSOR_HAND)) |
|
390 self.SetSelected(False) |
410 self.SetSelected(False) |
391 # Initializes the last position |
411 # Initializes the last position |
392 self.oldPos = GetScaledEventPosition(event, dc, scaling) |
412 self.oldPos = GetScaledEventPosition(event, dc, scaling) |
393 |
413 |
394 # Method called when a LeftUp event have been generated |
414 # Method called when a LeftUp event have been generated |
400 movex = pos.x - self.oldPos.x |
420 movex = pos.x - self.oldPos.x |
401 movey = pos.y - self.oldPos.y |
421 movey = pos.y - self.oldPos.y |
402 self.ProcessDragging(movex, movey) |
422 self.ProcessDragging(movex, movey) |
403 self.RefreshModel() |
423 self.RefreshModel() |
404 self.Parent.RefreshBuffer() |
424 self.Parent.RefreshBuffer() |
|
425 if self.CurrentCursor != 0: |
|
426 self.Parent.SetCursor(CURSORS[0]) |
|
427 self.CurrentCursor = 0 |
405 self.SetSelected(True) |
428 self.SetSelected(True) |
406 self.oldPos = None |
429 self.oldPos = None |
407 |
430 |
408 # Method called when a RightUp event have been generated |
431 # Method called when a RightUp event have been generated |
409 def OnRightUp(self, event, dc, scaling): |
432 def OnRightUp(self, event, dc, scaling): |
431 self.ProcessDragging(movex, movey) |
454 self.ProcessDragging(movex, movey) |
432 # If cursor just pass over the element, changes the cursor if it is on a handle |
455 # If cursor just pass over the element, changes the cursor if it is on a handle |
433 else: |
456 else: |
434 pos = event.GetLogicalPosition(dc) |
457 pos = event.GetLogicalPosition(dc) |
435 handle = self.TestHandle(pos) |
458 handle = self.TestHandle(pos) |
436 if handle == (1, 1) or handle == (3, 3): |
459 # Find which type of handle have been clicked, |
437 wxCallAfter(self.Parent.SetCursor, wxStockCursor(wxCURSOR_SIZENWSE)) |
460 # Save a resize event and change the cursor |
438 elif handle == (1, 3) or handle == (3, 1): |
461 cursor = HANDLE_CURSORS.get(handle, 0) |
439 wxCallAfter(self.Parent.SetCursor, wxStockCursor(wxCURSOR_SIZENESW)) |
462 if cursor != self.CurrentCursor: |
440 elif handle == (1, 2) or handle == (3, 2): |
463 self.Parent.SetCursor(CURSORS[cursor]) |
441 wxCallAfter(self.Parent.SetCursor, wxStockCursor(wxCURSOR_SIZEWE)) |
464 self.CurrentCursor = cursor |
442 elif handle == (2, 1) or handle == (2, 3): |
465 |
443 wxCallAfter(self.Parent.SetCursor, wxStockCursor(wxCURSOR_SIZENS)) |
|
444 else: |
|
445 wxCallAfter(self.Parent.SetCursor, wxNullCursor) |
|
446 |
|
447 # Moves the element |
466 # Moves the element |
448 def Move(self, dx, dy, exclude = []): |
467 def Move(self, dx, dy, exclude = []): |
449 self.Pos.x += dx |
468 self.Pos.x += dx |
450 self.Pos.y += dy |
469 self.Pos.y += dy |
451 self.RefreshConnected(exclude) |
470 self.RefreshConnected(exclude) |