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 |
25 import wx |
25 import wx |
|
26 import time |
26 from math import * |
27 from math import * |
27 from types import * |
28 from types import * |
28 |
29 |
29 #------------------------------------------------------------------------------- |
30 #------------------------------------------------------------------------------- |
30 # Common constants |
31 # Common constants |
186 return dir_target |
187 return dir_target |
187 return v_base |
188 return v_base |
188 |
189 |
189 |
190 |
190 #------------------------------------------------------------------------------- |
191 #------------------------------------------------------------------------------- |
|
192 # Debug Data Consumer Class |
|
193 #------------------------------------------------------------------------------- |
|
194 |
|
195 class DebugDataConsumer: |
|
196 |
|
197 def __init__(self): |
|
198 self.LastValue = None |
|
199 self.Value = None |
|
200 self.Inhibited = False |
|
201 |
|
202 def Inhibit(self, inhibit): |
|
203 self.Inhibited = inhibit |
|
204 if inhibit and self.LastValue is not None: |
|
205 self.SetValue(self.LastValue) |
|
206 self.LastValue = None |
|
207 |
|
208 def NewValue(self, tick, value): |
|
209 if self.Inhibited: |
|
210 self.LastValue = value |
|
211 else: |
|
212 self.SetValue(value) |
|
213 |
|
214 def SetValue(self, value): |
|
215 self.Value = value |
|
216 |
|
217 #------------------------------------------------------------------------------- |
|
218 # Debug Viewer Class |
|
219 #------------------------------------------------------------------------------- |
|
220 |
|
221 REFRESH_PERIOD = 0.1 |
|
222 |
|
223 class DebugViewer: |
|
224 |
|
225 def __init__(self, producer, debug, register_tick=True): |
|
226 self.DataProducer = producer |
|
227 self.Debug = debug |
|
228 |
|
229 self.DataConsumers = {} |
|
230 |
|
231 self.LastRefreshTime = time.time() |
|
232 |
|
233 if register_tick: |
|
234 self.DataProducer.SubscribeDebugIECVariable("__tick__", self) |
|
235 |
|
236 self.RefreshTimer = wx.Timer(self, -1) |
|
237 self.Bind(wx.EVT_TIMER, self.OnRefreshTimer, self.RefreshTimer) |
|
238 |
|
239 def __del__(self): |
|
240 self.DataProducer.UnsubscribeDebugIECVariable("__tick__", self) |
|
241 self.DeleteDataConsumers() |
|
242 self.RefreshTimer.Stop() |
|
243 |
|
244 def Inhibit(self, inhibit): |
|
245 for consumer, iec_path in self.DataConsumers.iteritems(): |
|
246 consumer.Inhibit(inhibit) |
|
247 |
|
248 def AddDataConsumer(self, iec_path, consumer): |
|
249 result = self.DataProducer.SubscribeDebugIECVariable(iec_path, consumer) is not None |
|
250 if result is not None and consumer != self: |
|
251 self.DataConsumers[consumer] = iec_path |
|
252 return result |
|
253 |
|
254 def RemoveDataConsumer(self, consumer): |
|
255 iec_path = self.DataConsumers.pop(consumer, None) |
|
256 if iec_path is not None: |
|
257 self.DataProducer.UnsubscribeDebugIECVariable(iec_path, consumer) |
|
258 |
|
259 def DeleteDataConsumers(self): |
|
260 for consumer, iec_path in self.DataConsumers.iteritems(): |
|
261 self.DataProducer.UnsubscribeDebugIECVariable(iec_path, consumer) |
|
262 self.DataConsumers = {} |
|
263 |
|
264 def OnRefreshTimer(self, event): |
|
265 self.RefreshNewData() |
|
266 event.Skip() |
|
267 |
|
268 def NewDataAvailable(self): |
|
269 self.Inhibit(True) |
|
270 current_time = time.time() |
|
271 if current_time - self.LastRefreshTime > REFRESH_PERIOD: |
|
272 self.LastRefreshTime = current_time |
|
273 wx.CallAfter(self.RefreshViewOnNewData) |
|
274 |
|
275 def RefreshViewOnNewData(self): |
|
276 if self: |
|
277 self.RefreshNewData() |
|
278 self.RefreshTimer.Start(int(REFRESH_PERIOD * 1000), oneShot=True) |
|
279 |
|
280 def RefreshNewData(self): |
|
281 self.Inhibit(False) |
|
282 |
|
283 #------------------------------------------------------------------------------- |
191 # Viewer Rubberband |
284 # Viewer Rubberband |
192 #------------------------------------------------------------------------------- |
285 #------------------------------------------------------------------------------- |
193 |
286 |
194 """ |
287 """ |
195 Class that implements a rubberband |
288 Class that implements a rubberband |
310 |
403 |
311 self.Bind(wx.EVT_PAINT, self.OnPaint) |
404 self.Bind(wx.EVT_PAINT, self.OnPaint) |
312 |
405 |
313 def SetTip(self, tip): |
406 def SetTip(self, tip): |
314 self.Tip = tip |
407 self.Tip = tip |
315 dc = wx.ClientDC(self) |
408 wx.CallAfter(self.RefreshTip) |
316 w, h = dc.GetTextExtent(tip) |
409 |
317 self.SetSize(wx.Size(w + 4, h + 4)) |
410 def RefreshTip(self): |
318 self.Refresh() |
411 if self: |
|
412 dc = wx.ClientDC(self) |
|
413 w, h = dc.GetTextExtent(self.Tip) |
|
414 self.SetSize(wx.Size(w + 4, h + 4)) |
|
415 self.Refresh() |
319 |
416 |
320 def OnPaint(self, event): |
417 def OnPaint(self, event): |
321 dc = wx.AutoBufferedPaintDC(self) |
418 dc = wx.AutoBufferedPaintDC(self) |
322 dc.Clear() |
419 dc.Clear() |
323 dc.SetPen(wx.BLACK_PEN) |
420 dc.SetPen(wx.BLACK_PEN) |
1431 |
1528 |
1432 """ |
1529 """ |
1433 Class that implements a wire for connecting two blocks |
1530 Class that implements a wire for connecting two blocks |
1434 """ |
1531 """ |
1435 |
1532 |
1436 class Wire(Graphic_Element): |
1533 class Wire(Graphic_Element, DebugDataConsumer): |
1437 |
1534 |
1438 # Create a new wire |
1535 # Create a new wire |
1439 def __init__(self, parent, start = None, end = None): |
1536 def __init__(self, parent, start = None, end = None): |
1440 Graphic_Element.__init__(self, parent) |
1537 Graphic_Element.__init__(self, parent) |
|
1538 DebugDataConsumer.__init__(self) |
1441 self.StartPoint = start |
1539 self.StartPoint = start |
1442 self.EndPoint = end |
1540 self.EndPoint = end |
1443 self.StartConnected = None |
1541 self.StartConnected = None |
1444 self.EndConnected = None |
1542 self.EndConnected = None |
1445 # If the start and end points are defined, calculate the wire |
1543 # If the start and end points are defined, calculate the wire |
1449 else: |
1547 else: |
1450 self.Points = [] |
1548 self.Points = [] |
1451 self.Segments = [] |
1549 self.Segments = [] |
1452 self.SelectedSegment = None |
1550 self.SelectedSegment = None |
1453 self.Valid = True |
1551 self.Valid = True |
1454 self.Value = None |
|
1455 self.ValueSize = None |
1552 self.ValueSize = None |
1456 self.ComputedValue = None |
1553 self.ComputedValue = None |
1457 self.OverStart = False |
1554 self.OverStart = False |
1458 self.OverEnd = False |
1555 self.OverEnd = False |
1459 self.ComputingType = False |
1556 self.ComputingType = False |
1460 self.ToolTip = None |
1557 self.ToolTip = None |
1461 self.Font = parent.GetMiniFont() |
|
1462 |
1558 |
1463 def Flush(self): |
1559 def Flush(self): |
1464 self.StartConnected = None |
1560 self.StartConnected = None |
1465 self.EndConnected = None |
1561 self.EndConnected = None |
1466 |
1562 |
1489 if self.StartConnected: |
1585 if self.StartConnected: |
1490 rect = rect.Union(self.StartConnected.GetRedrawRect(movex, movey)) |
1586 rect = rect.Union(self.StartConnected.GetRedrawRect(movex, movey)) |
1491 if self.EndConnected: |
1587 if self.EndConnected: |
1492 rect = rect.Union(self.EndConnected.GetRedrawRect(movex, movey)) |
1588 rect = rect.Union(self.EndConnected.GetRedrawRect(movex, movey)) |
1493 if self.ValueSize is not None: |
1589 if self.ValueSize is not None: |
1494 width, height = self.ValueSize |
|
1495 width, height = self.ValueSize |
1590 width, height = self.ValueSize |
1496 if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4: |
1591 if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4: |
1497 x = self.Points[0].x + width * self.StartPoint[1][0] / 2 |
1592 x = self.Points[0].x + width * self.StartPoint[1][0] / 2 |
1498 y = self.Points[0].y + (height * self.StartPoint[1][1] - 1) / 2 |
1593 y = self.Points[0].y + (height * self.StartPoint[1][1] - 1) / 2 |
1499 rect = rect.Union(wx.Rect(x, y, width, height)) |
1594 rect = rect.Union(wx.Rect(x, y, width, height)) |
1634 if self.ToolTip is not None: |
1729 if self.ToolTip is not None: |
1635 self.ToolTip.SetTip(self.ComputedValue) |
1730 self.ToolTip.SetTip(self.ComputedValue) |
1636 if len(self.ComputedValue) > 4: |
1731 if len(self.ComputedValue) > 4: |
1637 self.ComputedValue = self.ComputedValue[:4] + "..." |
1732 self.ComputedValue = self.ComputedValue[:4] + "..." |
1638 if isinstance(self.ComputedValue, StringType): |
1733 if isinstance(self.ComputedValue, StringType): |
1639 dc = wx.ClientDC(self.Parent) |
1734 self.ValueSize = self.Parent.GetMiniTextExtent(self.ComputedValue) |
1640 dc.SetFont(self.Font) |
|
1641 self.ValueSize = dc.GetTextExtent(self.ComputedValue) |
|
1642 else: |
1735 else: |
1643 self.ValueSize = None |
1736 self.ValueSize = None |
1644 if self.StartConnected: |
1737 if self.StartConnected: |
1645 self.StartConnected.RefreshValue() |
1738 self.StartConnected.RefreshValue() |
1646 if self.EndConnected: |
1739 if self.EndConnected: |
1647 self.EndConnected.RefreshValue() |
1740 self.EndConnected.RefreshValue() |
1648 self.Refresh() |
1741 self.Parent.UpdateRefreshRect(self.GetRedrawRect()) |
1649 if isinstance(value, BooleanType) and self.StartConnected is not None: |
1742 if isinstance(value, BooleanType) and self.StartConnected is not None: |
1650 block = self.StartConnected.GetParentBlock() |
1743 block = self.StartConnected.GetParentBlock() |
1651 block.SpreadCurrent() |
1744 block.SpreadCurrent() |
1652 |
1745 |
1653 def GetValue(self): |
1746 def GetValue(self): |
2512 dc.DrawLine(self.Points[self.SelectedSegment].x, self.Points[self.SelectedSegment].y, |
2605 dc.DrawLine(self.Points[self.SelectedSegment].x, self.Points[self.SelectedSegment].y, |
2513 self.Points[self.SelectedSegment + 1].x, self.Points[self.SelectedSegment + 1].y) |
2606 self.Points[self.SelectedSegment + 1].x, self.Points[self.SelectedSegment + 1].y) |
2514 if self.SelectedSegment == len(self.Segments) - 1: |
2607 if self.SelectedSegment == len(self.Segments) - 1: |
2515 dc.DrawPoint(self.Points[-1].x, self.Points[-1].y) |
2608 dc.DrawPoint(self.Points[-1].x, self.Points[-1].y) |
2516 if self.Value is not None and not isinstance(self.Value, BooleanType) and self.Value != "undefined": |
2609 if self.Value is not None and not isinstance(self.Value, BooleanType) and self.Value != "undefined": |
2517 dc.SetFont(self.Font) |
2610 dc.SetFont(self.Parent.GetMiniFont()) |
2518 dc.SetTextForeground(wx.NamedColour("purple")) |
2611 dc.SetTextForeground(wx.NamedColour("purple")) |
2519 width, height = self.ValueSize |
2612 width, height = self.ValueSize |
2520 if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4: |
2613 if self.BoundingBox[2] > width * 4 or self.BoundingBox[3] > height * 4: |
2521 x = self.Points[0].x + width * (self.StartPoint[1][0] - 1) / 2 |
2614 x = self.Points[0].x + width * (self.StartPoint[1][0] - 1) / 2 |
2522 y = self.Points[0].y + height * (self.StartPoint[1][1] - 1) / 2 |
2615 y = self.Points[0].y + height * (self.StartPoint[1][1] - 1) / 2 |