57 |
57 |
58 if __name__ == '__main__': |
58 if __name__ == '__main__': |
59 __builtin__.__dict__['_'] = wx.GetTranslation#unicode_translation |
59 __builtin__.__dict__['_'] = wx.GetTranslation#unicode_translation |
60 |
60 |
61 _base_folder = os.path.split(sys.path[0])[0] |
61 _base_folder = os.path.split(sys.path[0])[0] |
62 sys.path.append(os.path.join(base_folder, "beremiz")) |
62 sys.path.append(os.path.join(_base_folder, "beremiz")) |
63 |
63 |
64 _base_path = path.split(__file__)[0] |
64 _base_path = os.path.split(__file__)[0] |
|
65 |
|
66 import connectors |
|
67 from LPCconnector import LPC_connector_factory |
|
68 connectors.connectors["LPC"]=lambda:LPC_connector_factory |
|
69 |
|
70 import targets |
|
71 from LPCtarget import LPC_target |
|
72 targets.targets["LPC"] = {"xsd": os.path.join(_base_path, "LPCtarget", "XSD"), |
|
73 "class": lambda:LPC_target, |
|
74 "code": os.path.join(_base_path,"LPCtarget","plc_LPC_main.c")} |
|
75 targets.toolchains["makefile"] = os.path.join(_base_path, "LPCtarget", "XSD_toolchain_makefile") |
|
76 |
|
77 # helper func to get path to images |
|
78 from util import misc |
|
79 misc.opjimg = lambda imgname: os.path.join(_base_folder, "beremiz", "images", imgname+".png") |
65 |
80 |
66 from Beremiz import * |
81 from Beremiz import * |
67 from ProjectController import ProjectController |
82 from ProjectController import ProjectController |
68 from ConfigTreeNode import ConfigTreeNode |
83 from ConfigTreeNode import ConfigTreeNode |
69 |
84 from ProjectNodeEditor import ProjectNodeEditor |
70 import connectors |
85 |
71 from LPCconnector import LPC_connector_factory |
|
72 connectors.connectors["LPC"]=lambda:LPC_connector_factory |
|
73 |
|
74 import targets |
|
75 from LPCtarget import LPC_target |
|
76 targets.targets["LPC"]={"xsd": path.join(_base_path, "LPCtarget", "XSD"), |
|
77 "class": LPC_target, |
|
78 "code": path.join(_base_path,"LPCtarget","plc_LPC_main.c")} |
|
79 targets.toolchains["makefile"]= path.join(_base_path, "LPCtarget", "XSD_toolchain_makefile"), |
|
80 |
|
81 from util import opjimg |
|
82 from plcopen.structures import LOCATIONDATATYPES |
86 from plcopen.structures import LOCATIONDATATYPES |
83 from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP,\ |
87 from PLCControler import PLCControler, LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP,\ |
84 LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY |
88 LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY |
85 from PLCOpenEditor import IDEFrame, ProjectDialog |
89 from PLCOpenEditor import IDEFrame, ProjectDialog |
86 |
90 |
87 havecanfestival = False |
91 havecanfestival = False |
88 try: |
92 try: |
89 from canfestival import RootClass as CanOpenRootClass |
93 from canfestival import RootClass as CanOpenRootClass |
90 from canfestival.canfestival import _SlaveCTN, _NodeListCTN, NodeManager |
94 from canfestival.canfestival import _SlaveCTN, _NodeListCTN, NodeManager |
|
95 from canfestival.NetworkEditor import NetworkEditor |
|
96 from canfestival.SlaveEditor import SlaveEditor |
91 havecanfestival = True |
97 havecanfestival = True |
92 except: |
98 except: |
93 havecanfestival = False |
99 havecanfestival = False |
94 |
100 |
|
101 SCROLLBAR_UNIT = 10 |
|
102 WINDOW_COLOUR = wx.Colour(240,240,240) |
|
103 TITLE_COLOUR = wx.Colour(200,200,220) |
|
104 CHANGED_TITLE_COLOUR = wx.Colour(220,200,220) |
|
105 CHANGED_WINDOW_COLOUR = wx.Colour(255,240,240) |
|
106 |
|
107 if wx.Platform == '__WXMSW__': |
|
108 faces = { 'times': 'Times New Roman', |
|
109 'mono' : 'Courier New', |
|
110 'helv' : 'Arial', |
|
111 'other': 'Comic Sans MS', |
|
112 'size' : 16, |
|
113 } |
|
114 else: |
|
115 faces = { 'times': 'Times', |
|
116 'mono' : 'Courier', |
|
117 'helv' : 'Helvetica', |
|
118 'other': 'new century schoolbook', |
|
119 'size' : 18, |
|
120 } |
|
121 |
|
122 # Some helpers to tweak GenBitmapTextButtons |
|
123 # TODO: declare customized classes instead. |
|
124 gen_mini_GetBackgroundBrush = lambda obj:lambda dc: wx.Brush(obj.GetParent().GetBackgroundColour(), wx.SOLID) |
|
125 gen_textbutton_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenButton._GetLabelSize(obj)[:-1] + (False,)) |
|
126 |
|
127 def make_genbitmaptogglebutton_flat(button): |
|
128 button.GetBackgroundBrush = gen_mini_GetBackgroundBrush(button) |
|
129 button.labelDelta = 0 |
|
130 button.SetBezelWidth(0) |
|
131 button.SetUseFocusIndicator(False) |
|
132 |
|
133 # Patch wx.lib.imageutils so that gray is supported on alpha images |
|
134 import wx.lib.imageutils |
|
135 from wx.lib.imageutils import grayOut as old_grayOut |
|
136 def grayOut(anImage): |
|
137 if anImage.HasAlpha(): |
|
138 AlphaData = anImage.GetAlphaData() |
|
139 else : |
|
140 AlphaData = None |
|
141 |
|
142 old_grayOut(anImage) |
|
143 |
|
144 if AlphaData is not None: |
|
145 anImage.SetAlphaData(AlphaData) |
|
146 |
|
147 wx.lib.imageutils.grayOut = grayOut |
|
148 |
|
149 class GenBitmapTextButton(wx.lib.buttons.GenBitmapTextButton): |
|
150 def _GetLabelSize(self): |
|
151 """ used internally """ |
|
152 w, h = self.GetTextExtent(self.GetLabel()) |
|
153 if not self.bmpLabel: |
|
154 return w, h, False # if there isn't a bitmap use the size of the text |
|
155 |
|
156 w_bmp = self.bmpLabel.GetWidth()+2 |
|
157 h_bmp = self.bmpLabel.GetHeight()+2 |
|
158 height = h + h_bmp |
|
159 if w_bmp > w: |
|
160 width = w_bmp |
|
161 else: |
|
162 width = w |
|
163 return width, height, False |
|
164 |
|
165 def DrawLabel(self, dc, width, height, dw=0, dy=0): |
|
166 bmp = self.bmpLabel |
|
167 if bmp != None: # if the bitmap is used |
|
168 if self.bmpDisabled and not self.IsEnabled(): |
|
169 bmp = self.bmpDisabled |
|
170 if self.bmpFocus and self.hasFocus: |
|
171 bmp = self.bmpFocus |
|
172 if self.bmpSelected and not self.up: |
|
173 bmp = self.bmpSelected |
|
174 bw,bh = bmp.GetWidth(), bmp.GetHeight() |
|
175 if not self.up: |
|
176 dw = dy = self.labelDelta |
|
177 hasMask = bmp.GetMask() != None |
|
178 else: |
|
179 bw = bh = 0 # no bitmap -> size is zero |
|
180 |
|
181 dc.SetFont(self.GetFont()) |
|
182 if self.IsEnabled(): |
|
183 dc.SetTextForeground(self.GetForegroundColour()) |
|
184 else: |
|
185 dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) |
|
186 |
|
187 label = self.GetLabel() |
|
188 tw, th = dc.GetTextExtent(label) # size of text |
|
189 if not self.up: |
|
190 dw = dy = self.labelDelta |
|
191 |
|
192 pos_x = (width-bw)/2+dw # adjust for bitmap and text to centre |
|
193 pos_y = (height-bh-th)/2+dy |
|
194 if bmp !=None: |
|
195 dc.DrawBitmap(bmp, pos_x, pos_y, hasMask) # draw bitmap if available |
|
196 pos_x = (width-tw)/2+dw # adjust for bitmap and text to centre |
|
197 pos_y += bh + 2 |
|
198 |
|
199 dc.DrawText(label, pos_x, pos_y) # draw the text |
|
200 |
95 |
201 |
96 #------------------------------------------------------------------------------- |
202 #------------------------------------------------------------------------------- |
97 # CANFESTIVAL CONFNODE HACK |
203 # CANFESTIVAL CONFNODE HACK |
98 #------------------------------------------------------------------------------- |
204 #------------------------------------------------------------------------------- |
99 # from canfestival import canfestival |
205 # from canfestival import canfestival |
496 elif os.path.isfile(srcpath): |
614 elif os.path.isfile(srcpath): |
497 shutil.copy2(srcpath, dstpath) |
615 shutil.copy2(srcpath, dstpath) |
498 |
616 |
499 [SIMULATION_MODE, TRANSFER_MODE] = range(2) |
617 [SIMULATION_MODE, TRANSFER_MODE] = range(2) |
500 |
618 |
|
619 class LPCProjectNodeEditor(ProjectNodeEditor): |
|
620 SHOW_PARAMS = False |
|
621 ENABLE_REQUIRED = False |
|
622 |
501 class LPCProjectController(ProjectController): |
623 class LPCProjectController(ProjectController): |
502 |
624 |
503 ConfNodeMethods = [ |
625 StatusMethods = [ |
504 {"bitmap" : opjimg("Debug"), |
626 {"bitmap" : "Debug", |
505 "name" : _("Simulate"), |
627 "name" : _("Simulate"), |
506 "tooltip" : _("Simulate PLC"), |
628 "tooltip" : _("Simulate PLC"), |
507 "method" : "_Simulate"}, |
629 "method" : "_Simulate"}, |
508 {"bitmap" : opjimg("Run"), |
630 {"bitmap" : "Run", |
509 "name" : _("Run"), |
631 "name" : _("Run"), |
510 "shown" : False, |
632 "shown" : False, |
511 "tooltip" : _("Start PLC"), |
633 "tooltip" : _("Start PLC"), |
512 "method" : "_Run"}, |
634 "method" : "_Run"}, |
513 {"bitmap" : opjimg("Stop"), |
635 {"bitmap" : "Stop", |
514 "name" : _("Stop"), |
636 "name" : _("Stop"), |
515 "shown" : False, |
637 "shown" : False, |
516 "tooltip" : _("Stop Running PLC"), |
638 "tooltip" : _("Stop Running PLC"), |
517 "method" : "_Stop"}, |
639 "method" : "_Stop"}, |
518 {"bitmap" : opjimg("Build"), |
640 {"bitmap" : "Build", |
519 "name" : _("Build"), |
641 "name" : _("Build"), |
520 "tooltip" : _("Build project into build folder"), |
642 "tooltip" : _("Build project into build folder"), |
521 "method" : "_Build"}, |
643 "method" : "_Build"}, |
522 {"bitmap" : opjimg("Transfer"), |
644 {"bitmap" : "Transfer", |
523 "name" : _("Transfer"), |
645 "name" : _("Transfer"), |
524 "shown" : False, |
646 "shown" : False, |
525 "tooltip" : _("Transfer PLC"), |
647 "tooltip" : _("Transfer PLC"), |
526 "method" : "_Transfer"}, |
648 "method" : "_Transfer"}, |
527 ] |
649 ] |
528 |
650 |
|
651 ConfNodeMethods = [] |
|
652 |
|
653 EditorType = LPCProjectNodeEditor |
|
654 |
529 def __init__(self, frame, logger, buildpath): |
655 def __init__(self, frame, logger, buildpath): |
530 self.OrigBuildPath = buildpath |
656 self.OrigBuildPath = buildpath |
531 |
657 |
532 ProjectController.__init__(self, frame, logger) |
658 ProjectController.__init__(self, frame, logger) |
533 |
659 |
1082 AppendMenu(parent, help='', id=wx.ID_PREVIEW, |
1222 AppendMenu(parent, help='', id=wx.ID_PREVIEW, |
1083 kind=wx.ITEM_NORMAL, text=_(u'Preview')) |
1223 kind=wx.ITEM_NORMAL, text=_(u'Preview')) |
1084 AppendMenu(parent, help='', id=wx.ID_PRINT, |
1224 AppendMenu(parent, help='', id=wx.ID_PRINT, |
1085 kind=wx.ITEM_NORMAL, text=_(u'Print')) |
1225 kind=wx.ITEM_NORMAL, text=_(u'Print')) |
1086 parent.AppendSeparator() |
1226 parent.AppendSeparator() |
1087 AppendMenu(parent, help='', id=wx.ID_PROPERTIES, |
|
1088 kind=wx.ITEM_NORMAL, text=_(u'Properties')) |
|
1089 parent.AppendSeparator() |
|
1090 AppendMenu(parent, help='', id=wx.ID_EXIT, |
1227 AppendMenu(parent, help='', id=wx.ID_EXIT, |
1091 kind=wx.ITEM_NORMAL, text=_(u'Quit\tCTRL+Q')) |
1228 kind=wx.ITEM_NORMAL, text=_(u'Quit\tCTRL+Q')) |
1092 |
1229 |
1093 self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, id=wx.ID_SAVE) |
1230 self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, id=wx.ID_SAVE) |
1094 self.Bind(wx.EVT_MENU, self.OnCloseTabMenu, id=wx.ID_CLOSE) |
1231 self.Bind(wx.EVT_MENU, self.OnCloseTabMenu, id=wx.ID_CLOSE) |
1095 self.Bind(wx.EVT_MENU, self.OnPageSetupMenu, id=wx.ID_PAGE_SETUP) |
1232 self.Bind(wx.EVT_MENU, self.OnPageSetupMenu, id=wx.ID_PAGE_SETUP) |
1096 self.Bind(wx.EVT_MENU, self.OnPreviewMenu, id=wx.ID_PREVIEW) |
1233 self.Bind(wx.EVT_MENU, self.OnPreviewMenu, id=wx.ID_PREVIEW) |
1097 self.Bind(wx.EVT_MENU, self.OnPrintMenu, id=wx.ID_PRINT) |
1234 self.Bind(wx.EVT_MENU, self.OnPrintMenu, id=wx.ID_PRINT) |
1098 self.Bind(wx.EVT_MENU, self.OnPropertiesMenu, id=wx.ID_PROPERTIES) |
|
1099 self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT) |
1235 self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT) |
1100 |
1236 |
1101 self.AddToMenuToolBar([(wx.ID_SAVE, "save.png", _(u'Save'), None), |
1237 self.AddToMenuToolBar([(wx.ID_SAVE, "save.png", _(u'Save'), None), |
1102 (wx.ID_PRINT, "print.png", _(u'Print'), None)]) |
1238 (wx.ID_PRINT, "print.png", _(u'Print'), None)]) |
1103 |
1239 |
|
1240 def _init_coll_AddMenu_Items(self, parent): |
|
1241 IDEFrame._init_coll_AddMenu_Items(self, parent, False) |
|
1242 new_id = wx.NewId() |
|
1243 AppendMenu(parent, help='', id=new_id, |
|
1244 kind=wx.ITEM_NORMAL, text=_(u'&Resource')) |
|
1245 self.Bind(wx.EVT_MENU, self.AddResourceMenu, id=new_id) |
|
1246 |
1104 def _init_ctrls(self, prnt): |
1247 def _init_ctrls(self, prnt): |
1105 IDEFrame._init_ctrls(self, prnt) |
1248 Beremiz._init_ctrls(self, prnt) |
1106 |
|
1107 self.Bind(wx.EVT_MENU, self.OnOpenWidgetInspector, id=ID_BEREMIZINSPECTOR) |
|
1108 accel = wx.AcceleratorTable([wx.AcceleratorEntry(wx.ACCEL_CTRL|wx.ACCEL_ALT, ord('I'), ID_BEREMIZINSPECTOR)]) |
|
1109 self.SetAcceleratorTable(accel) |
|
1110 |
1249 |
1111 self.PLCConfig = wx.ScrolledWindow(id=ID_BEREMIZPLCCONFIG, |
1250 self.PLCConfig = wx.ScrolledWindow(id=ID_BEREMIZPLCCONFIG, |
1112 name='PLCConfig', parent=self.LeftNoteBook, pos=wx.Point(0, 0), |
1251 name='PLCConfig', parent=self.LeftNoteBook, pos=wx.Point(0, 0), |
1113 size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL) |
1252 size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL) |
1114 self.PLCConfig.SetBackgroundColour(wx.WHITE) |
1253 self.PLCConfig.SetBackgroundColour(wx.WHITE) |
1115 self.PLCConfig.Bind(wx.EVT_LEFT_DOWN, self.OnPanelLeftDown) |
1254 self.PLCConfig.Bind(wx.EVT_LEFT_DOWN, self.OnPanelLeftDown) |
1116 self.PLCConfig.Bind(wx.EVT_SIZE, self.OnMoveWindow) |
1255 self.PLCConfig.Bind(wx.EVT_SIZE, self.OnMoveWindow) |
|
1256 self.MainTabs["PLCConfig"] = (self.PLCConfig, _("Topology")) |
1117 self.LeftNoteBook.InsertPage(0, self.PLCConfig, _("Topology"), True) |
1257 self.LeftNoteBook.InsertPage(0, self.PLCConfig, _("Topology"), True) |
1118 |
1258 |
1119 self.LogConsole = wx.TextCtrl(id=ID_BEREMIZLOGCONSOLE, value='', |
1259 self.PLCConfigMainSizer = wx.FlexGridSizer(cols=1, hgap=2, rows=2, vgap=2) |
1120 name='LogConsole', parent=self.BottomNoteBook, pos=wx.Point(0, 0), |
1260 self.PLCParamsSizer = wx.BoxSizer(wx.VERTICAL) |
1121 size=wx.Size(0, 0), style=wx.TE_MULTILINE|wx.TE_RICH2) |
1261 self.ConfNodeTreeSizer = wx.FlexGridSizer(cols=2, hgap=0, rows=0, vgap=2) |
1122 self.LogConsole.Bind(wx.EVT_LEFT_DCLICK, self.OnLogConsoleDClick) |
1262 self.ConfNodeTreeSizer.AddGrowableCol(0) |
1123 self.BottomNoteBook.AddPage(self.LogConsole, _("Log Console")) |
1263 self.ConfNodeTreeSizer.AddGrowableCol(1) |
1124 |
1264 |
1125 self._init_beremiz_sizers() |
1265 self.PLCConfigMainSizer.AddSizer(self.PLCParamsSizer, 0, border=10, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) |
1126 |
1266 self.PLCConfigMainSizer.AddSizer(self.ConfNodeTreeSizer, 0, border=10, flag=wx.BOTTOM|wx.LEFT|wx.RIGHT) |
|
1267 self.PLCConfigMainSizer.AddGrowableCol(0) |
|
1268 self.PLCConfigMainSizer.AddGrowableRow(1) |
|
1269 |
|
1270 self.PLCConfig.SetSizer(self.PLCConfigMainSizer) |
|
1271 |
|
1272 self.AUIManager.Update() |
|
1273 |
|
1274 def __init__(self, parent, projectOpen=None, buildpath=None, ctr=None, debug=True): |
|
1275 self.ConfNodeInfos = {} |
|
1276 |
|
1277 Beremiz.__init__(self, parent, projectOpen, buildpath, ctr, debug) |
|
1278 |
1127 def OnCloseFrame(self, event): |
1279 def OnCloseFrame(self, event): |
1128 global frame |
1280 global frame |
1129 |
1281 |
1130 if self.CheckSaveBeforeClosing(_("Close Application")): |
1282 if self.CheckSaveBeforeClosing(_("Close Application")): |
1131 |
1283 |
1182 MenuToolBar.EnableTool(wx.ID_PRINT, False) |
1332 MenuToolBar.EnableTool(wx.ID_PRINT, False) |
1183 self.FileMenu.Enable(wx.ID_PAGE_SETUP, True) |
1333 self.FileMenu.Enable(wx.ID_PAGE_SETUP, True) |
1184 project_modified = self.CTR.ProjectTestModified() |
1334 project_modified = self.CTR.ProjectTestModified() |
1185 self.FileMenu.Enable(wx.ID_SAVE, project_modified) |
1335 self.FileMenu.Enable(wx.ID_SAVE, project_modified) |
1186 MenuToolBar.EnableTool(wx.ID_SAVE, project_modified) |
1336 MenuToolBar.EnableTool(wx.ID_SAVE, project_modified) |
1187 self.FileMenu.Enable(wx.ID_PROPERTIES, True) |
|
1188 else: |
1337 else: |
1189 self.FileMenu.Enable(wx.ID_CLOSE, False) |
1338 self.FileMenu.Enable(wx.ID_CLOSE, False) |
1190 self.FileMenu.Enable(wx.ID_PAGE_SETUP, False) |
1339 self.FileMenu.Enable(wx.ID_PAGE_SETUP, False) |
1191 self.FileMenu.Enable(wx.ID_PREVIEW, False) |
1340 self.FileMenu.Enable(wx.ID_PREVIEW, False) |
1192 self.FileMenu.Enable(wx.ID_PRINT, False) |
1341 self.FileMenu.Enable(wx.ID_PRINT, False) |
1193 MenuToolBar.EnableTool(wx.ID_PRINT, False) |
1342 MenuToolBar.EnableTool(wx.ID_PRINT, False) |
1194 self.FileMenu.Enable(wx.ID_SAVE, False) |
1343 self.FileMenu.Enable(wx.ID_SAVE, False) |
1195 MenuToolBar.EnableTool(wx.ID_SAVE, False) |
1344 MenuToolBar.EnableTool(wx.ID_SAVE, False) |
1196 self.FileMenu.Enable(wx.ID_PROPERTIES, False) |
1345 |
1197 |
1346 def RefreshScrollBars(self): |
|
1347 xstart, ystart = self.PLCConfig.GetViewStart() |
|
1348 window_size = self.PLCConfig.GetClientSize() |
|
1349 sizer = self.PLCConfig.GetSizer() |
|
1350 if sizer: |
|
1351 maxx, maxy = sizer.GetMinSize() |
|
1352 posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT)) |
|
1353 posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT)) |
|
1354 self.PLCConfig.Scroll(posx, posy) |
|
1355 self.PLCConfig.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, |
|
1356 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy) |
|
1357 |
1198 def RefreshPLCParams(self): |
1358 def RefreshPLCParams(self): |
1199 self.Freeze() |
1359 self.Freeze() |
1200 self.ClearSizer(self.PLCParamsSizer) |
1360 self.ClearSizer(self.PLCParamsSizer) |
1201 |
1361 |
1202 if self.CTR is not None: |
1362 if self.CTR is not None: |
1228 plcwindowmainsizer.AddSizer(plcwindowbuttonsizer, 0, border=0, flag=wx.ALIGN_CENTER) |
1388 plcwindowmainsizer.AddSizer(plcwindowbuttonsizer, 0, border=0, flag=wx.ALIGN_CENTER) |
1229 |
1389 |
1230 msizer = self.GenerateMethodButtonSizer(self.CTR, plcwindow, not self.ConfNodeInfos[self.CTR]["right_visible"]) |
1390 msizer = self.GenerateMethodButtonSizer(self.CTR, plcwindow, not self.ConfNodeInfos[self.CTR]["right_visible"]) |
1231 plcwindowbuttonsizer.AddSizer(msizer, 0, border=0, flag=wx.GROW) |
1391 plcwindowbuttonsizer.AddSizer(msizer, 0, border=0, flag=wx.GROW) |
1232 |
1392 |
|
1393 self.PLCConfigMainSizer.Layout() |
|
1394 self.RefreshScrollBars() |
|
1395 self.Thaw() |
|
1396 |
|
1397 def GenerateMethodButtonSizer(self, confnode, parent, horizontal = True): |
|
1398 normal_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = faces["helv"]) |
|
1399 mouseover_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, underline=True, faceName = faces["helv"]) |
|
1400 if horizontal: |
|
1401 msizer = wx.FlexGridSizer(cols=len(confnode.ConfNodeMethods)) |
|
1402 else: |
|
1403 msizer = wx.FlexGridSizer(cols=1) |
|
1404 for confnode_method in confnode.ConfNodeMethods: |
|
1405 if "method" in confnode_method and confnode_method.get("shown",True): |
|
1406 id = wx.NewId() |
|
1407 label = confnode_method["name"] |
|
1408 button = GenBitmapTextButton(id=id, parent=parent, |
|
1409 bitmap=wx.Bitmap(Bpath("images", "%s.png"%confnode_method.get("bitmap", "Unknown"))), label=label, |
|
1410 name=label, pos=wx.DefaultPosition, style=wx.NO_BORDER) |
|
1411 button.SetFont(normal_bt_font) |
|
1412 button.SetToolTipString(confnode_method["tooltip"]) |
|
1413 button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(confnode, confnode_method["method"]), id=id) |
|
1414 # a fancy underline on mouseover |
|
1415 def setFontStyle(b, s): |
|
1416 def fn(event): |
|
1417 b.SetFont(s) |
|
1418 b.Refresh() |
|
1419 event.Skip() |
|
1420 return fn |
|
1421 button.Bind(wx.EVT_ENTER_WINDOW, setFontStyle(button, mouseover_bt_font)) |
|
1422 button.Bind(wx.EVT_LEAVE_WINDOW, setFontStyle(button, normal_bt_font)) |
|
1423 #hack to force size to mini |
|
1424 if not confnode_method.get("enabled",True): |
|
1425 button.Disable() |
|
1426 msizer.AddWindow(button, 0, border=0, flag=wx.ALIGN_CENTER) |
|
1427 return msizer |
|
1428 |
|
1429 def GenerateEnableButton(self, parent, sizer, confnode): |
|
1430 enabled = confnode.CTNEnabled() |
|
1431 if enabled is not None: |
|
1432 enablebutton_id = wx.NewId() |
|
1433 enablebutton = wx.lib.buttons.GenBitmapToggleButton(id=enablebutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'Disabled.png')), |
|
1434 name='EnableButton', parent=parent, size=wx.Size(16, 16), pos=wx.Point(0, 0), style=0)#wx.NO_BORDER) |
|
1435 enablebutton.SetToolTipString(_("Enable/Disable this confnode")) |
|
1436 make_genbitmaptogglebutton_flat(enablebutton) |
|
1437 enablebutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'Enabled.png'))) |
|
1438 enablebutton.SetToggle(enabled) |
|
1439 def toggleenablebutton(event): |
|
1440 res = self.SetConfNodeParamsAttribute(confnode, "BaseParams.Enabled", enablebutton.GetToggle()) |
|
1441 enablebutton.SetToggle(res) |
|
1442 event.Skip() |
|
1443 enablebutton.Bind(wx.EVT_BUTTON, toggleenablebutton, id=enablebutton_id) |
|
1444 sizer.AddWindow(enablebutton, 0, border=0, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) |
|
1445 else: |
|
1446 sizer.AddSpacer(wx.Size(16, 16)) |
|
1447 |
|
1448 def RefreshConfNodeTree(self): |
|
1449 self.Freeze() |
|
1450 self.ClearSizer(self.ConfNodeTreeSizer) |
|
1451 if self.CTR is not None: |
|
1452 for child in self.CTR.IECSortedChildren(): |
|
1453 self.GenerateTreeBranch(child) |
|
1454 if not self.ConfNodeInfos[child]["expanded"]: |
|
1455 self.CollapseConfNode(child) |
1233 self.PLCConfigMainSizer.Layout() |
1456 self.PLCConfigMainSizer.Layout() |
1234 self.RefreshScrollBars() |
1457 self.RefreshScrollBars() |
1235 self.Thaw() |
1458 self.Thaw() |
1236 |
1459 |
1237 def GenerateTreeBranch(self, confnode): |
1460 def GenerateTreeBranch(self, confnode): |
1358 for location in confnode_locations: |
1584 for location in confnode_locations: |
1359 locations_infos["root"]["children"].append("root.%s" % location["name"]) |
1585 locations_infos["root"]["children"].append("root.%s" % location["name"]) |
1360 self.GenerateLocationTreeBranch(treectrl, treectrl.GetRootItem(), locations_infos, "root", location) |
1586 self.GenerateLocationTreeBranch(treectrl, treectrl.GetRootItem(), locations_infos, "root", location) |
1361 if locations_infos["root"]["expanded"]: |
1587 if locations_infos["root"]["expanded"]: |
1362 self.ExpandLocation(locations_infos, "root") |
1588 self.ExpandLocation(locations_infos, "root") |
|
1589 |
|
1590 def ExpandConfNode(self, confnode, force = False): |
|
1591 for child in self.ConfNodeInfos[confnode]["children"]: |
|
1592 self.ConfNodeInfos[child]["left"].Show() |
|
1593 self.ConfNodeInfos[child]["right"].Show() |
|
1594 if force or self.ConfNodeInfos[child]["expanded"]: |
|
1595 self.ExpandConfNode(child, force) |
|
1596 if force: |
|
1597 self.ConfNodeInfos[child]["expanded"] = True |
|
1598 locations_infos = self.ConfNodeInfos[confnode].get("locations_infos", None) |
|
1599 if locations_infos is not None: |
|
1600 if force or locations_infos["root"]["expanded"]: |
|
1601 self.ExpandLocation(locations_infos, "root", force) |
|
1602 if force: |
|
1603 locations_infos["root"]["expanded"] = True |
|
1604 |
|
1605 def CollapseConfNode(self, confnode, force = False): |
|
1606 for child in self.ConfNodeInfos[confnode]["children"]: |
|
1607 self.ConfNodeInfos[child]["left"].Hide() |
|
1608 self.ConfNodeInfos[child]["right"].Hide() |
|
1609 self.CollapseConfNode(child, force) |
|
1610 if force: |
|
1611 self.ConfNodeInfos[child]["expanded"] = False |
|
1612 locations_infos = self.ConfNodeInfos[confnode].get("locations_infos", None) |
|
1613 if locations_infos is not None: |
|
1614 self.CollapseLocation(locations_infos, "root", force) |
|
1615 if force: |
|
1616 locations_infos["root"]["expanded"] = False |
|
1617 |
|
1618 def ExpandLocation(self, locations_infos, group, force = False, refresh_size=True): |
|
1619 locations_infos[group]["expanded"] = True |
|
1620 if group == "root": |
|
1621 if locations_infos[group]["left"] is not None: |
|
1622 locations_infos[group]["left"].Show() |
|
1623 if locations_infos[group]["right"] is not None: |
|
1624 locations_infos[group]["right"].Show() |
|
1625 elif locations_infos["root"]["left"] is not None: |
|
1626 locations_infos["root"]["left"].Expand(locations_infos[group]["item"]) |
|
1627 if force: |
|
1628 for child in locations_infos[group]["children"]: |
|
1629 self.ExpandLocation(locations_infos, child, force, False) |
|
1630 if locations_infos["root"]["left"] is not None and refresh_size: |
|
1631 self.RefreshTreeCtrlSize(locations_infos["root"]["left"]) |
|
1632 |
|
1633 def CollapseLocation(self, locations_infos, group, force = False, refresh_size=True): |
|
1634 locations_infos[group]["expanded"] = False |
|
1635 if group == "root": |
|
1636 if locations_infos[group]["left"] is not None: |
|
1637 locations_infos[group]["left"].Hide() |
|
1638 if locations_infos[group]["right"] is not None: |
|
1639 locations_infos[group]["right"].Hide() |
|
1640 elif locations_infos["root"]["left"] is not None: |
|
1641 locations_infos["root"]["left"].Collapse(locations_infos[group]["item"]) |
|
1642 if force: |
|
1643 for child in locations_infos[group]["children"]: |
|
1644 self.CollapseLocation(locations_infos, child, force, False) |
|
1645 if locations_infos["root"]["left"] is not None and refresh_size: |
|
1646 self.RefreshTreeCtrlSize(locations_infos["root"]["left"]) |
|
1647 |
|
1648 def GenerateLocationTreeBranch(self, treectrl, root, locations_infos, parent, location): |
|
1649 location_name = "%s.%s" % (parent, location["name"]) |
|
1650 if not locations_infos.has_key(location_name): |
|
1651 locations_infos[location_name] = {"expanded" : False} |
|
1652 |
|
1653 if location["type"] in [LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY]: |
|
1654 label = "%(name)s (%(location)s)" % location |
|
1655 elif location["location"] != "": |
|
1656 label = "%(location)s: %(name)s" % location |
|
1657 else: |
|
1658 label = location["name"] |
|
1659 item = treectrl.AppendItem(root, label) |
|
1660 treectrl.SetPyData(item, location_name) |
|
1661 treectrl.SetItemImage(item, self.LocationImageDict[location["type"]]) |
|
1662 |
|
1663 locations_infos[location_name]["item"] = item |
|
1664 locations_infos[location_name]["children"] = [] |
|
1665 infos = location.copy() |
|
1666 infos.pop("children") |
|
1667 locations_infos[location_name]["infos"] = infos |
|
1668 for child in location["children"]: |
|
1669 child_name = "%s.%s" % (location_name, child["name"]) |
|
1670 locations_infos[location_name]["children"].append(child_name) |
|
1671 self.GenerateLocationTreeBranch(treectrl, item, locations_infos, location_name, child) |
|
1672 if locations_infos[location_name]["expanded"]: |
|
1673 self.ExpandLocation(locations_infos, location_name) |
|
1674 |
|
1675 def GenerateLocationBeginDragFunction(self, locations_infos): |
|
1676 def OnLocationBeginDragFunction(event): |
|
1677 item = event.GetItem() |
|
1678 location_name = locations_infos["root"]["left"].GetPyData(item) |
|
1679 if location_name is not None: |
|
1680 infos = locations_infos[location_name]["infos"] |
|
1681 if infos["type"] in [LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY]: |
|
1682 data = wx.TextDataObject(str((infos["location"], "location", infos["IEC_type"], infos["var_name"], infos["description"]))) |
|
1683 dragSource = wx.DropSource(self) |
|
1684 dragSource.SetData(data) |
|
1685 dragSource.DoDragDrop() |
|
1686 return OnLocationBeginDragFunction |
|
1687 |
|
1688 def RefreshTreeCtrlSize(self, treectrl): |
|
1689 rect = self.GetTreeCtrlItemRect(treectrl, treectrl.GetRootItem()) |
|
1690 treectrl.SetMinSize(wx.Size(max(rect.width, rect.x + rect.width) + 20, max(rect.height, rect.y + rect.height))) |
|
1691 self.PLCConfigMainSizer.Layout() |
|
1692 self.PLCConfig.Refresh() |
|
1693 wx.CallAfter(self.RefreshScrollBars) |
|
1694 |
|
1695 def GetTreeCtrlItemRect(self, treectrl, item): |
|
1696 item_rect = treectrl.GetBoundingRect(item, True) |
|
1697 if item_rect is not None: |
|
1698 minx, miny = item_rect.x, item_rect.y |
|
1699 maxx, maxy = item_rect.x + item_rect.width, item_rect.y + item_rect.height |
|
1700 else: |
|
1701 minx = miny = maxx = maxy = 0 |
|
1702 |
|
1703 if treectrl.ItemHasChildren(item) and (item == treectrl.GetRootItem() or treectrl.IsExpanded(item)): |
|
1704 if wx.VERSION >= (2, 6, 0): |
|
1705 child, item_cookie = treectrl.GetFirstChild(item) |
|
1706 else: |
|
1707 child, item_cookie = treectrl.GetFirstChild(item, 0) |
|
1708 while child.IsOk(): |
|
1709 child_rect = self.GetTreeCtrlItemRect(treectrl, child) |
|
1710 minx = min(minx, child_rect.x) |
|
1711 miny = min(miny, child_rect.y) |
|
1712 maxx = max(maxx, child_rect.x + child_rect.width) |
|
1713 maxy = max(maxy, child_rect.y + child_rect.height) |
|
1714 child, item_cookie = treectrl.GetNextChild(item, item_cookie) |
|
1715 |
|
1716 return wx.Rect(minx, miny, maxx - minx, maxy - miny) |
|
1717 |
|
1718 def GenerateLocationExpandCollapseFunction(self, locations_infos, expand): |
|
1719 def OnLocationExpandedFunction(event): |
|
1720 item = event.GetItem() |
|
1721 location_name = locations_infos["root"]["left"].GetPyData(item) |
|
1722 if location_name is not None: |
|
1723 locations_infos[location_name]["expanded"] = expand |
|
1724 self.RefreshTreeCtrlSize(locations_infos["root"]["left"]) |
|
1725 event.Skip() |
|
1726 return OnLocationExpandedFunction |
|
1727 |
|
1728 def GetButtonCallBackFunction(self, confnode, method): |
|
1729 """ Generate the callbackfunc for a given confnode method""" |
|
1730 def OnButtonClick(event): |
|
1731 # Disable button to prevent re-entrant call |
|
1732 event.GetEventObject().Disable() |
|
1733 # Call |
|
1734 getattr(confnode,method)() |
|
1735 # Re-enable button |
|
1736 event.GetEventObject().Enable() |
|
1737 # Trigger refresh on Idle |
|
1738 wx.CallAfter(self.RefreshAll) |
|
1739 event.Skip() |
|
1740 return OnButtonClick |
|
1741 |
|
1742 def ClearSizer(self, sizer): |
|
1743 staticboxes = [] |
|
1744 for item in sizer.GetChildren(): |
|
1745 if item.IsSizer(): |
|
1746 item_sizer = item.GetSizer() |
|
1747 self.ClearSizer(item_sizer) |
|
1748 if isinstance(item_sizer, wx.StaticBoxSizer): |
|
1749 staticboxes.append(item_sizer.GetStaticBox()) |
|
1750 sizer.Clear(True) |
|
1751 for staticbox in staticboxes: |
|
1752 staticbox.Destroy() |
|
1753 |
|
1754 def RefreshAll(self): |
|
1755 Beremiz.RefreshAll(self) |
|
1756 self.RefreshPLCParams() |
|
1757 self.RefreshConfNodeTree() |
1363 |
1758 |
1364 class StdoutPseudoFile: |
1759 class StdoutPseudoFile: |
1365 |
1760 |
1366 def __init__(self, port): |
1761 def __init__(self, port): |
1367 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
1762 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |