|
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) 2012: 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 from types import TupleType |
|
26 |
|
27 import wx |
|
28 |
|
29 from DebugVariableItem import DebugVariableItem |
|
30 from DebugVariableViewer import DebugVariableViewer |
|
31 from GraphButton import GraphButton |
|
32 |
|
33 #------------------------------------------------------------------------------- |
|
34 # Debug Variable Text Viewer Drop Target |
|
35 #------------------------------------------------------------------------------- |
|
36 |
|
37 """ |
|
38 Class that implements a custom drop target class for Debug Variable Text Viewer |
|
39 """ |
|
40 |
|
41 class DebugVariableTextDropTarget(wx.TextDropTarget): |
|
42 |
|
43 def __init__(self, parent, window): |
|
44 """ |
|
45 Constructor |
|
46 @param parent: Reference to Debug Variable Text Viewer |
|
47 @param window: Reference to the Debug Variable Panel |
|
48 """ |
|
49 wx.TextDropTarget.__init__(self) |
|
50 self.ParentControl = parent |
|
51 self.ParentWindow = window |
|
52 |
|
53 def __del__(self): |
|
54 """ |
|
55 Destructor |
|
56 """ |
|
57 # Remove reference to Debug Variable Text Viewer and Debug Variable |
|
58 # Panel |
|
59 self.ParentControl = None |
|
60 self.ParentWindow = None |
|
61 |
|
62 def OnDragOver(self, x, y, d): |
|
63 """ |
|
64 Function called when mouse is dragged over Drop Target |
|
65 @param x: X coordinate of mouse pointer |
|
66 @param y: Y coordinate of mouse pointer |
|
67 @param d: Suggested default for return value |
|
68 """ |
|
69 # Signal parent that mouse is dragged over |
|
70 self.ParentControl.OnMouseDragging(x, y) |
|
71 |
|
72 return wx.TextDropTarget.OnDragOver(self, x, y, d) |
|
73 |
|
74 def OnDropText(self, x, y, data): |
|
75 """ |
|
76 Function called when mouse is dragged over Drop Target |
|
77 @param x: X coordinate of mouse pointer |
|
78 @param y: Y coordinate of mouse pointer |
|
79 @param data: Text associated to drag'n drop |
|
80 """ |
|
81 message = None |
|
82 |
|
83 # Check that data is valid regarding DebugVariablePanel |
|
84 try: |
|
85 values = eval(data) |
|
86 if not isinstance(values, TupleType): |
|
87 raise |
|
88 except: |
|
89 message = _("Invalid value \"%s\" for debug variable") % data |
|
90 values = None |
|
91 |
|
92 # Display message if data is invalid |
|
93 if message is not None: |
|
94 wx.CallAfter(self.ShowMessage, message) |
|
95 |
|
96 # Data contain a reference to a variable to debug |
|
97 elif values[1] == "debug": |
|
98 |
|
99 # Get Before which Viewer the variable has to be moved or added |
|
100 # according to the position of mouse in Viewer. |
|
101 width, height = self.ParentControl.GetSize() |
|
102 target_idx = self.ParentControl.GetIndex() |
|
103 if y > height / 2: |
|
104 target_idx += 1 |
|
105 |
|
106 # Drag'n Drop is an internal is an internal move inside Debug |
|
107 # Variable Panel |
|
108 if len(values) > 2 and values[2] == "move": |
|
109 self.ParentWindow.MoveValue(values[0], |
|
110 target_idx) |
|
111 |
|
112 # Drag'n Drop was initiated by another control of Beremiz |
|
113 else: |
|
114 self.ParentWindow.InsertValue(values[0], |
|
115 target_idx, |
|
116 force=True) |
|
117 |
|
118 def OnLeave(self): |
|
119 """ |
|
120 Function called when mouse is leave Drop Target |
|
121 """ |
|
122 # Signal Debug Variable Panel to reset highlight |
|
123 self.ParentWindow.ResetHighlight() |
|
124 |
|
125 return wx.TextDropTarget.OnLeave(self) |
|
126 |
|
127 def ShowMessage(self, message): |
|
128 """ |
|
129 Show error message in Error Dialog |
|
130 @param message: Error message to display |
|
131 """ |
|
132 dialog = wx.MessageDialog(self.ParentWindow, |
|
133 message, |
|
134 _("Error"), |
|
135 wx.OK|wx.ICON_ERROR) |
|
136 dialog.ShowModal() |
|
137 dialog.Destroy() |
|
138 |
|
139 |
|
140 #------------------------------------------------------------------------------- |
|
141 # Debug Variable Text Viewer Class |
|
142 #------------------------------------------------------------------------------- |
|
143 |
|
144 """ |
|
145 Class that implements a Viewer that display variable values as a text |
|
146 """ |
|
147 |
|
148 class DebugVariableTextViewer(DebugVariableViewer, wx.Panel): |
|
149 |
|
150 def __init__(self, parent, window, items=[]): |
|
151 """ |
|
152 Constructor |
|
153 @param parent: Parent wx.Window of DebugVariableText |
|
154 @param window: Reference to the Debug Variable Panel |
|
155 @param items: List of DebugVariableItem displayed by Viewer |
|
156 """ |
|
157 DebugVariableViewer.__init__(self, window, items) |
|
158 |
|
159 wx.Panel.__init__(self, parent) |
|
160 # Set panel background colour |
|
161 self.SetBackgroundColour(wx.WHITE) |
|
162 # Define panel drop target |
|
163 self.SetDropTarget(DebugVariableTextDropTarget(self, window)) |
|
164 |
|
165 # Bind events |
|
166 self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) |
|
167 self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) |
|
168 self.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter) |
|
169 self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave) |
|
170 self.Bind(wx.EVT_SIZE, self.OnResize) |
|
171 self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) |
|
172 self.Bind(wx.EVT_PAINT, self.OnPaint) |
|
173 |
|
174 # Define panel min size for parent sizer layout |
|
175 self.SetMinSize(wx.Size(0, 25)) |
|
176 |
|
177 # Add buttons to Viewer |
|
178 for bitmap, callback in [("force", self.OnForceButton), |
|
179 ("release", self.OnReleaseButton), |
|
180 ("delete_graph", self.OnCloseButton)]: |
|
181 self.Buttons.append(GraphButton(0, 0, bitmap, callback)) |
|
182 |
|
183 # Hide buttons until mouse enter Viewer |
|
184 self.ShowButtons(False) |
|
185 |
|
186 def RefreshViewer(self): |
|
187 """ |
|
188 Method that refresh the content displayed by Viewer |
|
189 """ |
|
190 # Create buffered DC for drawing in panel |
|
191 width, height = self.GetSize() |
|
192 bitmap = wx.EmptyBitmap(width, height) |
|
193 dc = wx.BufferedDC(wx.ClientDC(self), bitmap) |
|
194 dc.Clear() |
|
195 dc.BeginDrawing() |
|
196 |
|
197 # Get Graphics Context for DC, for anti-aliased and transparent |
|
198 # rendering |
|
199 gc = wx.GCDC(dc) |
|
200 |
|
201 # Get first item |
|
202 item = self.ItemsDict.values()[0] |
|
203 |
|
204 # Get item variable path masked according Debug Variable Panel mask |
|
205 item_path = item.GetVariable( |
|
206 self.ParentWindow.GetVariableNameMask()) |
|
207 |
|
208 # Draw item variable path at Viewer left side |
|
209 w, h = gc.GetTextExtent(item_path) |
|
210 gc.DrawText(item_path, 20, (height - h) / 2) |
|
211 |
|
212 # Update 'Release' button state and text color according to item forced |
|
213 # flag value |
|
214 item_forced = item.IsForced() |
|
215 self.Buttons[1].Enable(item_forced) |
|
216 self.RefreshButtonsPosition() |
|
217 if item_forced: |
|
218 gc.SetTextForeground(wx.BLUE) |
|
219 |
|
220 # Draw item current value at right side of Viewer |
|
221 item_value = item.GetValue() |
|
222 w, h = gc.GetTextExtent(item_value) |
|
223 gc.DrawText(item_value, width - 40 - w, (height - h) / 2) |
|
224 |
|
225 # Draw other Viewer common elements |
|
226 self.DrawCommonElements(gc) |
|
227 |
|
228 gc.EndDrawing() |
|
229 |
|
230 def OnLeftDown(self, event): |
|
231 """ |
|
232 Function called when mouse left button is pressed |
|
233 @param event: wx.MouseEvent |
|
234 """ |
|
235 # Get first item |
|
236 item = self.ItemsDict.values()[0] |
|
237 |
|
238 # Calculate item path bounding box |
|
239 width, height = self.GetSize() |
|
240 item_path = item.GetVariable( |
|
241 self.ParentWindow.GetVariableNameMask()) |
|
242 w, h = self.GetTextExtent(item_path) |
|
243 |
|
244 # Test if mouse has been pressed in this bounding box. In that case |
|
245 # start a move drag'n drop of item variable |
|
246 x, y = event.GetPosition() |
|
247 item_path_bbox = wx.Rect(20, (height - h) / 2, w, h) |
|
248 if item_path_bbox.InsideXY(x, y): |
|
249 data = wx.TextDataObject(str((item.GetVariable(), "debug", "move"))) |
|
250 dragSource = wx.DropSource(self) |
|
251 dragSource.SetData(data) |
|
252 dragSource.DoDragDrop() |
|
253 |
|
254 # In other case handle event normally |
|
255 else: |
|
256 event.Skip() |
|
257 |
|
258 def OnLeftUp(self, event): |
|
259 """ |
|
260 Function called when mouse left button is released |
|
261 @param event: wx.MouseEvent |
|
262 """ |
|
263 # Execute callback on button under mouse pointer if it exists |
|
264 x, y = event.GetPosition() |
|
265 wx.CallAfter(self.HandleButton, x, y) |
|
266 event.Skip() |
|
267 |
|
268 def OnPaint(self, event): |
|
269 """ |
|
270 Function called when redrawing Viewer content is needed |
|
271 @param event: wx.PaintEvent |
|
272 """ |
|
273 self.RefreshViewer() |
|
274 event.Skip() |