30 |
30 |
31 import wx |
31 import wx |
32 |
32 |
33 from plcopen.structures import * |
33 from plcopen.structures import * |
34 from PLCControler import ITEM_VAR_LOCAL, ITEM_POU, ITEM_PROGRAM, ITEM_FUNCTIONBLOCK |
34 from PLCControler import ITEM_VAR_LOCAL, ITEM_POU, ITEM_PROGRAM, ITEM_FUNCTIONBLOCK |
|
35 from graphics.DebugDataConsumer import DebugDataConsumer |
35 |
36 |
36 from dialogs import * |
37 from dialogs import * |
37 from graphics import * |
38 from graphics import * |
38 from editors.DebugViewer import DebugViewer, REFRESH_PERIOD |
39 from editors.DebugViewer import DebugViewer, REFRESH_PERIOD |
39 from EditorPanel import EditorPanel |
40 from EditorPanel import EditorPanel |
422 def ShowMessage(self, message): |
423 def ShowMessage(self, message): |
423 message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR) |
424 message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR) |
424 message.ShowModal() |
425 message.ShowModal() |
425 message.Destroy() |
426 message.Destroy() |
426 |
427 |
|
428 |
|
429 |
|
430 class DebugInstanceName(DebugDataConsumer): |
|
431 VALUE_TRANSLATION = {True: _("Active"), False: _("Inactive")} |
|
432 |
|
433 def __init__(self, parent): |
|
434 DebugDataConsumer.__init__(self) |
|
435 self.Parent = parent |
|
436 self.ActionLastState = None |
|
437 self.ActionState = None |
|
438 self.x_offset = 2 |
|
439 self.y_offset = 2 |
|
440 |
|
441 def SetValue(self, value): |
|
442 self.ActionState = value |
|
443 if self.ActionState != self.ActionLastState: |
|
444 self.ActionLastState = self.ActionState |
|
445 wx.CallAfter(self.Parent.ElementNeedRefresh, self) |
|
446 |
|
447 def GetInstanceName(self): |
|
448 return _("Debug: %s") % self.Parent.InstancePath |
|
449 |
|
450 def GetRedrawRect(self): |
|
451 x, y = self.Parent.CalcUnscrolledPosition(self.x_offset, self.y_offset) |
|
452 dc = self.Parent.GetLogicalDC() |
|
453 ipw, iph = dc.GetTextExtent(self.GetInstanceName()) |
|
454 vw, vh = 0, 0 |
|
455 for value in self.VALUE_TRANSLATION.itervalues(): |
|
456 w, h = dc.GetTextExtent(" (%s)" % value) |
|
457 vw = max(vw, w) |
|
458 vh = max(vh, h) |
|
459 return wx.Rect(ipw + x, y, vw, vh) |
|
460 |
|
461 def Draw(self, dc): |
|
462 scalex, scaley = dc.GetUserScale() |
|
463 dc.SetUserScale(1, 1) |
|
464 x, y = self.Parent.CalcUnscrolledPosition(self.x_offset, self.y_offset) |
|
465 |
|
466 text = self.GetInstanceName() |
|
467 if self.ActionState is not None: |
|
468 text += " (" |
|
469 |
|
470 dc.DrawText(text, x, y) |
|
471 tw, th = dc.GetTextExtent(text) |
|
472 if self.ActionState is not None: |
|
473 |
|
474 text = self.VALUE_TRANSLATION[self.ActionState] |
|
475 if self.ActionState: |
|
476 dc.SetTextForeground(wx.GREEN) |
|
477 dc.DrawText(text, x + tw, y) |
|
478 if self.ActionState: |
|
479 dc.SetTextForeground(wx.BLACK) |
|
480 tw = tw + dc.GetTextExtent(text)[0] |
|
481 |
|
482 text = ")" |
|
483 dc.DrawText(text, x + tw, y) |
|
484 dc.SetUserScale(scalex, scaley) |
|
485 |
427 """ |
486 """ |
428 Class that implements a Viewer based on a wx.ScrolledWindow for drawing and |
487 Class that implements a Viewer based on a wx.ScrolledWindow for drawing and |
429 manipulating graphic elements |
488 manipulating graphic elements |
430 """ |
489 """ |
431 |
490 |
633 self.SearchResults = None |
692 self.SearchResults = None |
634 self.CurrentFindHighlight = None |
693 self.CurrentFindHighlight = None |
635 self.InstancePath = instancepath |
694 self.InstancePath = instancepath |
636 self.StartMousePos = None |
695 self.StartMousePos = None |
637 self.StartScreenPos = None |
696 self.StartScreenPos = None |
|
697 self.InstanceName = DebugInstanceName(self) |
638 |
698 |
639 # Prevent search for highlighted element to be called too often |
699 # Prevent search for highlighted element to be called too often |
640 self.LastHighlightCheckTime = gettime() |
700 self.LastHighlightCheckTime = gettime() |
641 # Prevent search for element producing tooltip to be called too often |
701 # Prevent search for element producing tooltip to be called too often |
642 self.LastToolTipCheckTime = gettime() |
702 self.LastToolTipCheckTime = gettime() |
1105 |
1165 |
1106 #------------------------------------------------------------------------------- |
1166 #------------------------------------------------------------------------------- |
1107 # Refresh functions |
1167 # Refresh functions |
1108 #------------------------------------------------------------------------------- |
1168 #------------------------------------------------------------------------------- |
1109 |
1169 |
1110 VALUE_TRANSLATION = {True: _("Active"), False: _("Inactive")} |
|
1111 |
|
1112 def SetValue(self, value): |
|
1113 if self.Value != value: |
|
1114 self.Value = value |
|
1115 |
|
1116 xstart, ystart = self.GetViewStart() |
|
1117 window_size = self.Editor.GetClientSize() |
|
1118 refresh_rect = self.GetRedrawRect() |
|
1119 if (xstart * SCROLLBAR_UNIT <= refresh_rect.x + refresh_rect.width and |
|
1120 xstart * SCROLLBAR_UNIT + window_size[0] >= refresh_rect.x and |
|
1121 ystart * SCROLLBAR_UNIT <= refresh_rect.y + refresh_rect.height and |
|
1122 ystart * SCROLLBAR_UNIT + window_size[1] >= refresh_rect.y): |
|
1123 self.ElementNeedRefresh(self) |
|
1124 |
|
1125 def GetRedrawRect(self): |
|
1126 dc = self.GetLogicalDC() |
|
1127 ipw, iph = dc.GetTextExtent(_("Debug: %s") % self.InstancePath) |
|
1128 vw, vh = 0, 0 |
|
1129 for value in self.VALUE_TRANSLATION.itervalues(): |
|
1130 w, h = dc.GetTextExtent("(%s)" % value) |
|
1131 vw = max(vw, w) |
|
1132 vh = max(vh, h) |
|
1133 return wx.Rect(ipw + 4, 2, vw, vh) |
|
1134 |
1170 |
1135 def ElementNeedRefresh(self, element): |
1171 def ElementNeedRefresh(self, element): |
1136 self.ElementRefreshList_lock.acquire() |
1172 self.ElementRefreshList_lock.acquire() |
1137 self.ElementRefreshList.append(element) |
1173 self.ElementRefreshList.append(element) |
1138 self.ElementRefreshList_lock.release() |
1174 self.ElementRefreshList_lock.release() |
1157 DebugViewer.SubscribeAllDataConsumers(self) |
1193 DebugViewer.SubscribeAllDataConsumers(self) |
1158 |
1194 |
1159 # Refresh Viewer elements |
1195 # Refresh Viewer elements |
1160 def RefreshView(self, variablepanel=True, selection=None): |
1196 def RefreshView(self, variablepanel=True, selection=None): |
1161 EditorPanel.RefreshView(self, variablepanel) |
1197 EditorPanel.RefreshView(self, variablepanel) |
1162 |
|
1163 if self.TagName.split("::")[0] == "A" and self.Debug: |
|
1164 self.AddDataConsumer("%s.Q" % self.InstancePath.upper(), self) |
|
1165 |
1198 |
1166 if self.ToolTipElement is not None: |
1199 if self.ToolTipElement is not None: |
1167 self.ToolTipElement.DestroyToolTip() |
1200 self.ToolTipElement.DestroyToolTip() |
1168 self.ToolTipElement = None |
1201 self.ToolTipElement = None |
1169 |
1202 |
1185 self.SelectedElement.RefreshWireExclusion() |
1218 self.SelectedElement.RefreshWireExclusion() |
1186 self.SelectedElement.RefreshBoundingBox() |
1219 self.SelectedElement.RefreshBoundingBox() |
1187 |
1220 |
1188 self.RefreshScrollBars() |
1221 self.RefreshScrollBars() |
1189 |
1222 |
|
1223 if self.TagName.split("::")[0] == "A" and self.Debug: |
|
1224 self.AddDataConsumer("%s.Q" % self.InstancePath.upper(), self.InstanceName) |
|
1225 |
1190 for wire in self.Wires: |
1226 for wire in self.Wires: |
1191 if not wire.IsConnectedCompatible(): |
1227 if not wire.IsConnectedCompatible(): |
1192 wire.SetValid(False) |
1228 wire.SetValid(False) |
1193 if self.Debug: |
1229 if self.Debug: |
1194 iec_path = self.GetElementIECPath(wire) |
1230 iec_path = self.GetElementIECPath(wire) |
3659 if self.SelectedElement is not None and (self.SelectedElement.IsVisible() or printing): |
3695 if self.SelectedElement is not None and (self.SelectedElement.IsVisible() or printing): |
3660 self.SelectedElement.Draw(dc) |
3696 self.SelectedElement.Draw(dc) |
3661 |
3697 |
3662 if not printing: |
3698 if not printing: |
3663 if self.Debug: |
3699 if self.Debug: |
3664 scalex, scaley = dc.GetUserScale() |
3700 self.InstanceName.Draw(dc) |
3665 dc.SetUserScale(1, 1) |
|
3666 |
|
3667 # is_action = self.TagName.split("::")[0] == "A" |
|
3668 text = _("Debug: %s") % self.InstancePath |
|
3669 '''if is_action and self.Value is not None: |
|
3670 text += " ("''' |
|
3671 text_offset_x, text_offset_y = self.CalcUnscrolledPosition(2, 2) |
|
3672 dc.DrawText(text, text_offset_x, text_offset_y) |
|
3673 # TODO Fix self.Value in LD_Viewer instance. |
|
3674 # This code used to highlight with green color text in upper-left corner |
|
3675 # (path to current instance) in debug mode, if current instance active. Only SFC actions are affected. |
|
3676 '''if is_action and self.Value is not None: |
|
3677 value_text = self.VALUE_TRANSLATION[self.Value] |
|
3678 tw, th = dc.GetTextExtent(text) |
|
3679 if self.Value: |
|
3680 dc.SetTextForeground(wx.GREEN) |
|
3681 dc.DrawText(value_text, text_offset_x + tw, text_offset_y) |
|
3682 if self.Value: |
|
3683 dc.SetTextForeground(wx.BLACK) |
|
3684 vw, vh = dc.GetTextExtent(value_text) |
|
3685 dc.DrawText(")", text_offset_x + tw + vw + 2, text_offset_y)''' |
|
3686 |
|
3687 dc.SetUserScale(scalex, scaley) |
|
3688 |
|
3689 if self.rubberBand.IsShown(): |
3701 if self.rubberBand.IsShown(): |
3690 self.rubberBand.Draw(dc) |
3702 self.rubberBand.Draw(dc) |
3691 dc.EndDrawing() |
3703 dc.EndDrawing() |
3692 |
3704 |
3693 def OnPaint(self, event): |
3705 def OnPaint(self, event): |