1 #!/usr/bin/env python |
1 (binary file text/x-python, hash: b44c0975cfce47c7a2c8339d9d185fc586dc4e31) |
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) 2007: 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 datetime import datetime |
|
26 import wx, wx.grid |
|
27 |
|
28 if wx.VERSION >= (2, 8, 0): |
|
29 import wx.aui |
|
30 USE_AUI = True |
|
31 else: |
|
32 USE_AUI = False |
|
33 |
|
34 import os, re, platform, sys, time, traceback, getopt |
|
35 import cPickle |
|
36 |
|
37 CWD = os.path.split(os.path.realpath(__file__))[0] |
|
38 base_folder = os.path.split(CWD)[0] |
|
39 sys.path.append(base_folder) |
|
40 from docutils import * |
|
41 |
|
42 from types import TupleType |
|
43 |
|
44 __version__ = "$Revision: 1.130 $" |
|
45 |
|
46 if __name__ == '__main__': |
|
47 # Usage message displayed when help request or when error detected in |
|
48 # command line |
|
49 def usage(): |
|
50 print "\nUsage of PLCOpenEditor.py :" |
|
51 print "\n %s [Filepath]\n"%sys.argv[0] |
|
52 |
|
53 # Parse options given to PLCOpenEditor in command line |
|
54 try: |
|
55 opts, args = getopt.getopt(sys.argv[1:], "h", ["help"]) |
|
56 except getopt.GetoptError: |
|
57 # print help information and exit: |
|
58 usage() |
|
59 sys.exit(2) |
|
60 |
|
61 # Extract if help has been requested |
|
62 for o, a in opts: |
|
63 if o in ("-h", "--help"): |
|
64 usage() |
|
65 sys.exit() |
|
66 |
|
67 # Extract the optional filename to open |
|
68 fileOpen = None |
|
69 if len(args) > 1: |
|
70 usage() |
|
71 sys.exit() |
|
72 elif len(args) == 1: |
|
73 fileOpen = args[0] |
|
74 |
|
75 # Create wxApp (Need to create App before internationalization because of |
|
76 # Windows) |
|
77 app = wx.PySimpleApp() |
|
78 |
|
79 # Import module for internationalization |
|
80 import gettext |
|
81 import __builtin__ |
|
82 |
|
83 # Get folder containing translation files |
|
84 localedir = os.path.join(CWD,"locale") |
|
85 # Get the default language |
|
86 langid = wx.LANGUAGE_DEFAULT |
|
87 # Define translation domain (name of translation files) |
|
88 domain = "PLCOpenEditor" |
|
89 |
|
90 # Define locale for wx |
|
91 loc = __builtin__.__dict__.get('loc', None) |
|
92 if loc is None: |
|
93 loc = wx.Locale(langid) |
|
94 __builtin__.__dict__['loc'] = loc |
|
95 # Define location for searching translation files |
|
96 loc.AddCatalogLookupPathPrefix(localedir) |
|
97 # Define locale domain |
|
98 loc.AddCatalog(domain) |
|
99 |
|
100 if __name__ == '__main__': |
|
101 __builtin__.__dict__['_'] = wx.GetTranslation |
|
102 |
|
103 from SFCViewer import * |
|
104 from LDViewer import * |
|
105 from Viewer import * |
|
106 from TextViewer import * |
|
107 from GraphicViewer import * |
|
108 from RessourceEditor import * |
|
109 from DataTypeEditor import * |
|
110 from PLCControler import * |
|
111 from VariablePanel import VariablePanel |
|
112 |
|
113 # Define PLCOpenEditor controls id |
|
114 [ID_PLCOPENEDITOR, ID_PLCOPENEDITORLEFTNOTEBOOK, |
|
115 ID_PLCOPENEDITORBOTTOMNOTEBOOK, ID_PLCOPENEDITORRIGHTNOTEBOOK, |
|
116 ID_PLCOPENEDITORTYPESTREE, ID_PLCOPENEDITORINSTANCESTREE, |
|
117 ID_PLCOPENEDITORMAINSPLITTER, ID_PLCOPENEDITORSECONDSPLITTER, |
|
118 ID_PLCOPENEDITORTHIRDSPLITTER, ID_PLCOPENEDITORLIBRARYPANEL, |
|
119 ID_PLCOPENEDITORLIBRARYTREE, ID_PLCOPENEDITORLIBRARYCOMMENT, |
|
120 ID_PLCOPENEDITORTABSOPENED, ID_PLCOPENEDITORTABSOPENED, |
|
121 ID_PLCOPENEDITORTOOLBAR, ID_PLCOPENEDITORDEFAULTTOOLBAR, |
|
122 ID_PLCOPENEDITORSFCTOOLBAR, ID_PLCOPENEDITORFBDTOOLBAR, |
|
123 ID_PLCOPENEDITORLDTOOLBAR, |
|
124 ] = [wx.NewId() for _init_ctrls in range(19)] |
|
125 |
|
126 # Define PLCOpenEditor FileMenu extra items id |
|
127 [ID_PLCOPENEDITORFILEMENUGENERATE, |
|
128 ] = [wx.NewId() for _init_coll_FileMenu_Items in range(1)] |
|
129 |
|
130 # Define PLCOpenEditor EditMenu extra items id |
|
131 [ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, ID_PLCOPENEDITOREDITMENUADDDATATYPE, |
|
132 ID_PLCOPENEDITOREDITMENUADDFUNCTION, ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK, |
|
133 ID_PLCOPENEDITOREDITMENUADDPROGRAM, ID_PLCOPENEDITOREDITMENUADDCONFIGURATION, |
|
134 ] = [wx.NewId() for _init_coll_EditMenu_Items in range(6)] |
|
135 |
|
136 |
|
137 #------------------------------------------------------------------------------- |
|
138 # ToolBars definitions |
|
139 #------------------------------------------------------------------------------- |
|
140 |
|
141 # Define PLCOpenEditor Toolbar items id |
|
142 [ID_PLCOPENEDITORTOOLBARSELECTION, ID_PLCOPENEDITORTOOLBARCOMMENT, |
|
143 ID_PLCOPENEDITORTOOLBARVARIABLE, ID_PLCOPENEDITORTOOLBARBLOCK, |
|
144 ID_PLCOPENEDITORTOOLBARCONNECTION, ID_PLCOPENEDITORTOOLBARWIRE, |
|
145 ID_PLCOPENEDITORTOOLBARPOWERRAIL, ID_PLCOPENEDITORTOOLBARRUNG, |
|
146 ID_PLCOPENEDITORTOOLBARCOIL, ID_PLCOPENEDITORTOOLBARCONTACT, |
|
147 ID_PLCOPENEDITORTOOLBARBRANCH, ID_PLCOPENEDITORTOOLBARINITIALSTEP, |
|
148 ID_PLCOPENEDITORTOOLBARSTEP, ID_PLCOPENEDITORTOOLBARTRANSITION, |
|
149 ID_PLCOPENEDITORTOOLBARACTIONBLOCK, ID_PLCOPENEDITORTOOLBARDIVERGENCE, |
|
150 ID_PLCOPENEDITORTOOLBARJUMP, |
|
151 ] = [wx.NewId() for _init_coll_DefaultToolBar_Items in range(17)] |
|
152 |
|
153 # Define behaviour of each Toolbar item according to current POU body type |
|
154 # Informations meaning are in this order: |
|
155 # - Item is toggled |
|
156 # - PLCOpenEditor mode where item is displayed (could be more then one) |
|
157 # - Item id |
|
158 # - Item callback function name |
|
159 # - Item icon filename |
|
160 # - Item tooltip text |
|
161 ToolBarItems = { |
|
162 "FBD" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
163 ID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", |
|
164 "add_comment.png", _("Create a new comment")), |
|
165 (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
166 ID_PLCOPENEDITORTOOLBARVARIABLE, "OnVariableTool", |
|
167 "add_variable.png", _("Create a new variable")), |
|
168 (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
169 ID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", |
|
170 "add_block.png", _("Create a new block")), |
|
171 (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
172 ID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", |
|
173 "add_connection.png", _("Create a new connection"))], |
|
174 "LD" : [(True, FREEDRAWING_MODE, |
|
175 ID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", |
|
176 "add_comment.png", _("Create a new comment")), |
|
177 (True, FREEDRAWING_MODE, |
|
178 ID_PLCOPENEDITORTOOLBARPOWERRAIL, "OnPowerRailTool", |
|
179 "add_powerrail.png", _("Create a new power rail")), |
|
180 (False, DRIVENDRAWING_MODE, |
|
181 ID_PLCOPENEDITORTOOLBARRUNG, "OnRungTool", |
|
182 "add_rung.png", _("Create a new rung")), |
|
183 (True, FREEDRAWING_MODE, |
|
184 ID_PLCOPENEDITORTOOLBARCOIL, "OnCoilTool", |
|
185 "add_coil.png", _("Create a new coil")), |
|
186 (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
187 ID_PLCOPENEDITORTOOLBARCONTACT, "OnContactTool", |
|
188 "add_contact.png", _("Create a new contact")), |
|
189 (False, DRIVENDRAWING_MODE, |
|
190 ID_PLCOPENEDITORTOOLBARBRANCH, "OnBranchTool", |
|
191 "add_branch.png", _("Create a new branch")), |
|
192 (True, FREEDRAWING_MODE, |
|
193 ID_PLCOPENEDITORTOOLBARVARIABLE, "OnVariableTool", |
|
194 "add_variable.png", _("Create a new variable")), |
|
195 (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
196 ID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", |
|
197 "add_block.png", _("Create a new block")), |
|
198 (True, FREEDRAWING_MODE, |
|
199 ID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", |
|
200 "add_connection.png", _("Create a new connection"))], |
|
201 "SFC" : [(True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
202 ID_PLCOPENEDITORTOOLBARCOMMENT, "OnCommentTool", |
|
203 "add_comment.png", _("Create a new comment")), |
|
204 (True, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
205 ID_PLCOPENEDITORTOOLBARINITIALSTEP, "OnInitialStepTool", |
|
206 "add_initial_step.png", _("Create a new initial step")), |
|
207 (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
208 ID_PLCOPENEDITORTOOLBARSTEP, "OnStepTool", |
|
209 "add_step.png", _("Create a new step")), |
|
210 (True, FREEDRAWING_MODE, |
|
211 ID_PLCOPENEDITORTOOLBARTRANSITION, "OnTransitionTool", |
|
212 "add_transition.png", _("Create a new transition")), |
|
213 (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
214 ID_PLCOPENEDITORTOOLBARACTIONBLOCK, "OnActionBlockTool", |
|
215 "add_action.png", _("Create a new action block")), |
|
216 (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
217 ID_PLCOPENEDITORTOOLBARDIVERGENCE, "OnDivergenceTool", |
|
218 "add_divergence.png", _("Create a new divergence")), |
|
219 (False, FREEDRAWING_MODE|DRIVENDRAWING_MODE, |
|
220 ID_PLCOPENEDITORTOOLBARJUMP, "OnJumpTool", |
|
221 "add_jump.png", _("Create a new jump")), |
|
222 (True, FREEDRAWING_MODE, |
|
223 ID_PLCOPENEDITORTOOLBARVARIABLE, "OnVariableTool", |
|
224 "add_variable.png", _("Create a new variable")), |
|
225 (True, FREEDRAWING_MODE, |
|
226 ID_PLCOPENEDITORTOOLBARBLOCK, "OnBlockTool", |
|
227 "add_block.png", _("Create a new block")), |
|
228 (True, FREEDRAWING_MODE, |
|
229 ID_PLCOPENEDITORTOOLBARCONNECTION, "OnConnectionTool", |
|
230 "add_connection.png", _("Create a new connection")), |
|
231 (True, FREEDRAWING_MODE, |
|
232 ID_PLCOPENEDITORTOOLBARPOWERRAIL, "OnPowerRailTool", |
|
233 "add_powerrail.png", _("Create a new power rail")), |
|
234 (True, FREEDRAWING_MODE, |
|
235 ID_PLCOPENEDITORTOOLBARCONTACT, "OnContactTool", |
|
236 "add_contact.png", _("Create a new contact"))], |
|
237 "ST" : [], |
|
238 "IL" : [] |
|
239 } |
|
240 |
|
241 #------------------------------------------------------------------------------- |
|
242 # Helper Functions |
|
243 #------------------------------------------------------------------------------- |
|
244 |
|
245 # Compatibility function for wx versions < 2.6 |
|
246 def AppendMenu(parent, help, id, kind, text): |
|
247 if wx.VERSION >= (2, 6, 0): |
|
248 parent.Append(help=help, id=id, kind=kind, text=text) |
|
249 else: |
|
250 parent.Append(helpString=help, id=id, kind=kind, item=text) |
|
251 |
|
252 [TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, |
|
253 INSTANCESTREE, LIBRARYTREE, SCALING |
|
254 ] = range(9) |
|
255 |
|
256 def GetShortcutKeyCallbackFunction(viewer_function): |
|
257 def ShortcutKeyFunction(self, event): |
|
258 control = self.FindFocus() |
|
259 if isinstance(control, (Viewer, TextViewer)): |
|
260 getattr(control, viewer_function)() |
|
261 elif isinstance(control, wx.TextCtrl): |
|
262 control.ProcessEvent(event) |
|
263 return ShortcutKeyFunction |
|
264 |
|
265 def GetParentName(tree, item, parent_type): |
|
266 parent_item = tree.GetItemParent(item) |
|
267 parent_item_type = tree.GetPyData(parent_item) |
|
268 while parent_item_type != parent_type: |
|
269 parent_item = tree.GetItemParent(parent_item) |
|
270 parent_item_type = tree.GetPyData(parent_item) |
|
271 return tree.GetItemText(parent_item) |
|
272 |
|
273 def GetDeleteElementFunction(remove_function, parent_type=None, check_function=None): |
|
274 def DeleteElementFunction(self, selected): |
|
275 name = self.TypesTree.GetItemText(selected) |
|
276 if check_function is None or not check_function(self.Controler, name): |
|
277 if parent_type is not None: |
|
278 parent_name = GetParentName(self.TypesTree, selected, parent_type) |
|
279 remove_function(self.Controler, parent_name, name) |
|
280 else: |
|
281 remove_function(self.Controler, name) |
|
282 else: |
|
283 self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!")%name) |
|
284 return DeleteElementFunction |
|
285 |
|
286 |
|
287 #------------------------------------------------------------------------------- |
|
288 # IDEFrame Base Class |
|
289 #------------------------------------------------------------------------------- |
|
290 |
|
291 UNEDITABLE_NAMES_DICT = dict([(_(name), name) for name in UNEDITABLE_NAMES]) |
|
292 |
|
293 class IDEFrame(wx.Frame): |
|
294 |
|
295 # Compatibility function for wx versions < 2.6 |
|
296 if wx.VERSION < (2, 6, 0): |
|
297 def Bind(self, event, function, id = None): |
|
298 if id is not None: |
|
299 event(self, id, function) |
|
300 else: |
|
301 event(self, function) |
|
302 |
|
303 def _init_coll_MenuBar_Menus(self, parent): |
|
304 parent.Append(menu=self.FileMenu, title=_(u'File')) |
|
305 parent.Append(menu=self.EditMenu, title=_(u'Edit')) |
|
306 parent.Append(menu=self.DisplayMenu, title=_(u'Display')) |
|
307 parent.Append(menu=self.HelpMenu, title=_(u'Help')) |
|
308 |
|
309 def _init_coll_FileMenu_Items(self, parent): |
|
310 pass |
|
311 |
|
312 def _init_coll_EditMenu_Items(self, parent): |
|
313 AppendMenu(parent, help='', id=wx.ID_UNDO, |
|
314 kind=wx.ITEM_NORMAL, text=_(u'Undo\tCTRL+Z')) |
|
315 AppendMenu(parent, help='', id=wx.ID_REDO, |
|
316 kind=wx.ITEM_NORMAL, text=_(u'Redo\tCTRL+Y')) |
|
317 AppendMenu(parent, help='', id=ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, |
|
318 kind=wx.ITEM_CHECK, text=_(u'Enable Undo/Redo')) |
|
319 parent.AppendSeparator() |
|
320 AppendMenu(parent, help='', id=wx.ID_CUT, |
|
321 kind=wx.ITEM_NORMAL, text=_(u'Cut\tCTRL+X')) |
|
322 AppendMenu(parent, help='', id=wx.ID_COPY, |
|
323 kind=wx.ITEM_NORMAL, text=_(u'Copy\tCTRL+C')) |
|
324 AppendMenu(parent, help='', id=wx.ID_PASTE, |
|
325 kind=wx.ITEM_NORMAL, text=_(u'Paste\tCTRL+V')) |
|
326 parent.AppendSeparator() |
|
327 addmenu = wx.Menu(title='') |
|
328 parent.AppendMenu(wx.ID_ADD, _("Add Element"), addmenu) |
|
329 AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDDATATYPE, |
|
330 kind=wx.ITEM_NORMAL, text=_(u'Data Type')) |
|
331 AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTION, |
|
332 kind=wx.ITEM_NORMAL, text=_(u'Function')) |
|
333 AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK, |
|
334 kind=wx.ITEM_NORMAL, text=_(u'Function Block')) |
|
335 AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDPROGRAM, |
|
336 kind=wx.ITEM_NORMAL, text=_(u'Program')) |
|
337 AppendMenu(addmenu, help='', id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION, |
|
338 kind=wx.ITEM_NORMAL, text=_(u'Configuration')) |
|
339 AppendMenu(parent, help='', id=wx.ID_SELECTALL, |
|
340 kind=wx.ITEM_NORMAL, text=_(u'Select All\tCTRL+A')) |
|
341 AppendMenu(parent, help='', id=wx.ID_DELETE, |
|
342 kind=wx.ITEM_NORMAL, text=_(u'Delete')) |
|
343 self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO) |
|
344 self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO) |
|
345 self.Bind(wx.EVT_MENU, self.OnEnableUndoRedoMenu, id=ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO) |
|
346 self.Bind(wx.EVT_MENU, self.OnCutMenu, id=wx.ID_CUT) |
|
347 self.Bind(wx.EVT_MENU, self.OnCopyMenu, id=wx.ID_COPY) |
|
348 self.Bind(wx.EVT_MENU, self.OnPasteMenu, id=wx.ID_PASTE) |
|
349 self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu, |
|
350 id=ID_PLCOPENEDITOREDITMENUADDDATATYPE) |
|
351 self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("function"), |
|
352 id=ID_PLCOPENEDITOREDITMENUADDFUNCTION) |
|
353 self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("functionBlock"), |
|
354 id=ID_PLCOPENEDITOREDITMENUADDFUNCTIONBLOCK) |
|
355 self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction("program"), |
|
356 id=ID_PLCOPENEDITOREDITMENUADDPROGRAM) |
|
357 self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu, |
|
358 id=ID_PLCOPENEDITOREDITMENUADDCONFIGURATION) |
|
359 self.Bind(wx.EVT_MENU, self.OnSelectAllMenu, id=wx.ID_SELECTALL) |
|
360 self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=wx.ID_DELETE) |
|
361 |
|
362 def _init_coll_DisplayMenu_Items(self, parent): |
|
363 AppendMenu(parent, help='', id=wx.ID_REFRESH, |
|
364 kind=wx.ITEM_NORMAL, text=_(u'Refresh\tF5')) |
|
365 if self.EnableDebug: |
|
366 AppendMenu(parent, help='', id=wx.ID_CLEAR, |
|
367 kind=wx.ITEM_NORMAL, text=_(u'Clear Errors\tCTRL+K')) |
|
368 parent.AppendSeparator() |
|
369 zoommenu = wx.Menu(title='') |
|
370 parent.AppendMenu(wx.ID_ZOOM_FIT, _("Zoom"), zoommenu) |
|
371 for idx, value in enumerate(ZOOM_FACTORS): |
|
372 new_id = wx.NewId() |
|
373 AppendMenu(zoommenu, help='', id=new_id, |
|
374 kind=wx.ITEM_RADIO, text=str(int(round(value * 100))) + "%") |
|
375 self.Bind(wx.EVT_MENU, self.GenerateZoomFunction(idx), id=new_id) |
|
376 self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH) |
|
377 if self.EnableDebug: |
|
378 self.Bind(wx.EVT_MENU, self.OnClearErrorsMenu, id=wx.ID_CLEAR) |
|
379 |
|
380 def _init_coll_HelpMenu_Items(self, parent): |
|
381 pass |
|
382 |
|
383 def _init_utils(self): |
|
384 self.MenuBar = wx.MenuBar() |
|
385 |
|
386 self.FileMenu = wx.Menu(title='') |
|
387 self.EditMenu = wx.Menu(title='') |
|
388 self.DisplayMenu = wx.Menu(title='') |
|
389 self.HelpMenu = wx.Menu(title='') |
|
390 |
|
391 self._init_coll_MenuBar_Menus(self.MenuBar) |
|
392 self._init_coll_FileMenu_Items(self.FileMenu) |
|
393 self._init_coll_EditMenu_Items(self.EditMenu) |
|
394 self._init_coll_DisplayMenu_Items(self.DisplayMenu) |
|
395 self._init_coll_HelpMenu_Items(self.HelpMenu) |
|
396 |
|
397 def _init_coll_MainLibrarySizer_Items(self, parent): |
|
398 parent.AddWindow(self.LibraryTree, 0, border=0, flag=wx.GROW) |
|
399 parent.AddSizer(self.LibraryComment, 0, border=0, flag=wx.GROW) |
|
400 |
|
401 def _init_coll_MainLibrarySizer_Growables(self, parent): |
|
402 parent.AddGrowableCol(0) |
|
403 parent.AddGrowableRow(0) |
|
404 |
|
405 def _init_sizers(self): |
|
406 self.MainLibrarySizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=0) |
|
407 |
|
408 self._init_coll_MainLibrarySizer_Growables(self.MainLibrarySizer) |
|
409 self._init_coll_MainLibrarySizer_Items(self.MainLibrarySizer) |
|
410 |
|
411 self.LibraryPanel.SetSizer(self.MainLibrarySizer) |
|
412 |
|
413 def _init_ctrls(self, prnt): |
|
414 wx.Frame.__init__(self, id=ID_PLCOPENEDITOR, name='IDEFrame', |
|
415 parent=prnt, pos=wx.DefaultPosition, size=wx.Size(1000, 600), |
|
416 style=wx.DEFAULT_FRAME_STYLE) |
|
417 self._init_utils() |
|
418 self.SetClientSize(wx.Size(1000, 600)) |
|
419 self.SetMenuBar(self.MenuBar) |
|
420 |
|
421 self.TabsImageList = wx.ImageList(31, 16) |
|
422 self.TabsImageListIndexes = {} |
|
423 |
|
424 #----------------------------------------------------------------------- |
|
425 # Creating main structure |
|
426 #----------------------------------------------------------------------- |
|
427 |
|
428 if USE_AUI: |
|
429 self.AUIManager = wx.aui.AuiManager(self) |
|
430 self.AUIManager.SetDockSizeConstraint(0.5, 0.5) |
|
431 self.Panes = {} |
|
432 |
|
433 self.LeftNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORLEFTNOTEBOOK, |
|
434 style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE| |
|
435 wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE) |
|
436 self.AUIManager.AddPane(self.LeftNoteBook, |
|
437 wx.aui.AuiPaneInfo().Caption(_("Project")).Left().Layer(1). |
|
438 BestSize(wx.Size(300, 500)).CloseButton(False)) |
|
439 |
|
440 self.BottomNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORBOTTOMNOTEBOOK, |
|
441 style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE| |
|
442 wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE) |
|
443 self.AUIManager.AddPane(self.BottomNoteBook, |
|
444 wx.aui.AuiPaneInfo().Bottom().Layer(0). |
|
445 BestSize(wx.Size(800, 300)).CloseButton(False)) |
|
446 |
|
447 self.RightNoteBook = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORRIGHTNOTEBOOK, |
|
448 style=wx.aui.AUI_NB_TOP|wx.aui.AUI_NB_TAB_SPLIT|wx.aui.AUI_NB_TAB_MOVE| |
|
449 wx.aui.AUI_NB_SCROLL_BUTTONS|wx.aui.AUI_NB_TAB_EXTERNAL_MOVE) |
|
450 self.AUIManager.AddPane(self.RightNoteBook, |
|
451 wx.aui.AuiPaneInfo().Right().Layer(0). |
|
452 BestSize(wx.Size(250, 400)).CloseButton(False)) |
|
453 |
|
454 self.TabsOpened = wx.aui.AuiNotebook(self, ID_PLCOPENEDITORTABSOPENED, |
|
455 style=wx.aui.AUI_NB_DEFAULT_STYLE|wx.aui.AUI_NB_WINDOWLIST_BUTTON) |
|
456 self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGED, |
|
457 self.OnPouSelectedChanged) |
|
458 self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, |
|
459 self.OnPageClose) |
|
460 self.TabsOpened.Bind(wx.aui.EVT_AUINOTEBOOK_END_DRAG, |
|
461 self.OnPageDragged) |
|
462 self.AUIManager.AddPane(self.TabsOpened, wx.aui.AuiPaneInfo().CentrePane()) |
|
463 |
|
464 else: |
|
465 self.MainSplitter = wx.SplitterWindow(id=ID_PLCOPENEDITORMAINSPLITTER, |
|
466 name='MainSplitter', parent=self, point=wx.Point(0, 0), |
|
467 size=wx.Size(0, 0), style=wx.SP_3D) |
|
468 self.MainSplitter.SetNeedUpdating(True) |
|
469 self.MainSplitter.SetMinimumPaneSize(1) |
|
470 |
|
471 self.LeftNoteBook = wx.Notebook(id=ID_PLCOPENEDITORLEFTNOTEBOOK, |
|
472 name='LeftNoteBook', parent=self.MainSplitter, pos=wx.Point(0, |
|
473 0), size=wx.Size(0, 0), style=0) |
|
474 |
|
475 self.SecondSplitter = wx.SplitterWindow(id=ID_PLCOPENEDITORSECONDSPLITTER, |
|
476 name='SecondSplitter', parent=self.MainSplitter, point=wx.Point(0, 0), |
|
477 size=wx.Size(0, 0), style=wx.SP_3D) |
|
478 self.SecondSplitter.SetMinimumPaneSize(1) |
|
479 |
|
480 self.MainSplitter.SplitVertically(self.LeftNoteBook, self.SecondSplitter, 200) |
|
481 |
|
482 self.ThirdSplitter = wx.SplitterWindow(id=ID_PLCOPENEDITORTHIRDSPLITTER, |
|
483 name='ThirdSplitter', parent=self.SecondSplitter, point=wx.Point(0, 0), |
|
484 size=wx.Size(0, 0), style=wx.SP_3D) |
|
485 self.ThirdSplitter.SetMinimumPaneSize(1) |
|
486 |
|
487 self.BottomNoteBook = wx.Notebook(id=ID_PLCOPENEDITORBOTTOMNOTEBOOK, |
|
488 name='BottomNoteBook', parent=self.SecondSplitter, pos=wx.Point(0, |
|
489 0), size=wx.Size(0, 0), style=0) |
|
490 |
|
491 self.SecondSplitter.SplitHorizontally(self.ThirdSplitter, self.BottomNoteBook, -200) |
|
492 |
|
493 self.TabsOpened = wx.Notebook(id=ID_PLCOPENEDITORTABSOPENED, |
|
494 name='TabsOpened', parent=self.ThirdSplitter, pos=wx.Point(0, |
|
495 0), size=wx.Size(0, 0), style=0) |
|
496 self.TabsOpened.SetImageList(self.TabsImageList) |
|
497 if wx.VERSION >= (2, 6, 0): |
|
498 self.TabsOpened.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, |
|
499 self.OnPouSelectedChanged, id=ID_PLCOPENEDITORTABSOPENED) |
|
500 else: |
|
501 wx.EVT_NOTEBOOK_PAGE_CHANGED(self.TabsOpened, ID_PLCOPENEDITORTABSOPENED, |
|
502 self.OnPouSelectedChanged) |
|
503 |
|
504 self.RightNoteBook = wx.Notebook(id=ID_PLCOPENEDITORRIGHTNOTEBOOK, |
|
505 name='RightNoteBook', parent=self.ThirdSplitter, pos=wx.Point(0, |
|
506 0), size=wx.Size(0, 0), style=0) |
|
507 |
|
508 self.ThirdSplitter.SplitVertically(self.TabsOpened, self.RightNoteBook, -250) |
|
509 |
|
510 #----------------------------------------------------------------------- |
|
511 # Creating PLCopen Project tree |
|
512 #----------------------------------------------------------------------- |
|
513 |
|
514 self.TypesTree = wx.TreeCtrl(id=ID_PLCOPENEDITORTYPESTREE, |
|
515 name='TypesTree', parent=self.LeftNoteBook, |
|
516 pos=wx.Point(0, 0), size=wx.Size(0, 0), |
|
517 style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER|wx.TR_EDIT_LABELS) |
|
518 if wx.Platform == '__WXMSW__': |
|
519 self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnTypesTreeRightUp, |
|
520 id=ID_PLCOPENEDITORTYPESTREE) |
|
521 self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnTypesTreeItemSelected, |
|
522 id=ID_PLCOPENEDITORTYPESTREE) |
|
523 else: |
|
524 if wx.VERSION >= (2, 6, 0): |
|
525 self.TypesTree.Bind(wx.EVT_RIGHT_UP, self.OnTypesTreeRightUp) |
|
526 self.TypesTree.Bind(wx.EVT_LEFT_UP, self.OnTypesTreeLeftUp) |
|
527 else: |
|
528 wx.EVT_RIGHT_UP(self.TypesTree, self.OnTypesTreeRightUp) |
|
529 wx.EVT_LEFT_UP(self.TypesTree, self.OnTypesTreeLeftUp) |
|
530 self.Bind(wx.EVT_TREE_SEL_CHANGING, self.OnTypesTreeItemChanging, |
|
531 id=ID_PLCOPENEDITORTYPESTREE) |
|
532 self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnTypesTreeBeginDrag, |
|
533 id=ID_PLCOPENEDITORTYPESTREE) |
|
534 self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnTypesTreeItemBeginEdit, |
|
535 id=ID_PLCOPENEDITORTYPESTREE) |
|
536 self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnTypesTreeItemEndEdit, |
|
537 id=ID_PLCOPENEDITORTYPESTREE) |
|
538 self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnTypesTreeItemActivated, |
|
539 id=ID_PLCOPENEDITORTYPESTREE) |
|
540 self.LeftNoteBook.AddPage(self.TypesTree, _("Types")) |
|
541 |
|
542 #----------------------------------------------------------------------- |
|
543 # Creating PLCopen Project tree |
|
544 #----------------------------------------------------------------------- |
|
545 |
|
546 self.InstancesTree = wx.TreeCtrl(id=ID_PLCOPENEDITORINSTANCESTREE, |
|
547 name='InstancesTree', parent=self.LeftNoteBook, |
|
548 pos=wx.Point(0, 0), size=wx.Size(0, 0), |
|
549 style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER) |
|
550 if self.EnableDebug: |
|
551 if wx.VERSION >= (2, 6, 0): |
|
552 self.InstancesTree.Bind(wx.EVT_RIGHT_UP, self.OnInstancesTreeRightUp) |
|
553 else: |
|
554 wx.EVT_RIGHT_UP(self.InstancesTree, self.OnInstancesTreeRightUp) |
|
555 self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnInstancesTreeBeginDrag, |
|
556 id=ID_PLCOPENEDITORINSTANCESTREE) |
|
557 self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnInstancesTreeItemActivated, |
|
558 id=ID_PLCOPENEDITORINSTANCESTREE) |
|
559 self.LeftNoteBook.AddPage(self.InstancesTree, _("Instances")) |
|
560 |
|
561 #----------------------------------------------------------------------- |
|
562 # Creating Tool Bar |
|
563 #----------------------------------------------------------------------- |
|
564 |
|
565 if USE_AUI: |
|
566 ToolBar = wx.ToolBar(self, ID_PLCOPENEDITORTOOLBAR, wx.DefaultPosition, wx.DefaultSize, |
|
567 wx.TB_FLAT | wx.TB_NODIVIDER | wx.NO_BORDER) |
|
568 ToolBar.SetToolBitmapSize(wx.Size(25, 25)) |
|
569 ToolBar.AddRadioTool(ID_PLCOPENEDITORTOOLBARSELECTION, |
|
570 wx.Bitmap(os.path.join(CWD, 'Images', 'select.png')), wx.NullBitmap, _("Select an object")) |
|
571 ToolBar.Realize() |
|
572 self.Panes["ToolBar"] = ToolBar |
|
573 self.AUIManager.AddPane(ToolBar, wx.aui.AuiPaneInfo(). |
|
574 Name("ToolBar").Caption(_("Toolbar")). |
|
575 ToolbarPane().Top(). |
|
576 LeftDockable(False).RightDockable(False)) |
|
577 else: |
|
578 self.ToolBar = self.CreateToolBar(wx.TB_HORIZONTAL|wx.TB_FLAT|wx.NO_BORDER, |
|
579 ID_PLCOPENEDITORTOOLBAR, 'ToolBar') |
|
580 self.ToolBar.SetToolBitmapSize(wx.Size(25, 25)) |
|
581 self.ToolBar.AddRadioTool(ID_PLCOPENEDITORTOOLBARSELECTION, |
|
582 wx.Bitmap(os.path.join(CWD, 'Images', 'select.png')), wx.NullBitmap, _("Select an object")) |
|
583 self.ToolBar.Realize() |
|
584 |
|
585 self.Bind(wx.EVT_TOOL, self.OnSelectionTool, |
|
586 id=ID_PLCOPENEDITORTOOLBARSELECTION) |
|
587 |
|
588 self.VariablePanelIndexer = VariablePanelIndexer(self.BottomNoteBook, self) |
|
589 self.BottomNoteBook.AddPage(self.VariablePanelIndexer, _("Variables")) |
|
590 |
|
591 self.LibraryPanel = wx.Panel(id=ID_PLCOPENEDITORLIBRARYPANEL, |
|
592 name='LibraryPanel', parent=self.RightNoteBook, pos=wx.Point(0, |
|
593 0), size=wx.Size(0, 0), style=0) |
|
594 self.RightNoteBook.AddPage(self.LibraryPanel, _("Library")) |
|
595 |
|
596 if wx.Platform == '__WXMSW__': |
|
597 librarytreestyle = wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.SUNKEN_BORDER |
|
598 else: |
|
599 librarytreestyle = wx.TR_HAS_BUTTONS|wx.TR_HIDE_ROOT|wx.TR_SINGLE|wx.SUNKEN_BORDER |
|
600 self.LibraryTree = wx.TreeCtrl(id=ID_PLCOPENEDITORLIBRARYTREE, |
|
601 name='LibraryTree', parent=self.LibraryPanel, |
|
602 pos=wx.Point(0, 0), size=wx.Size(0, 0), |
|
603 style=librarytreestyle) |
|
604 self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnLibraryTreeItemSelected, |
|
605 id=ID_PLCOPENEDITORLIBRARYTREE) |
|
606 self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnLibraryTreeBeginDrag, |
|
607 id=ID_PLCOPENEDITORLIBRARYTREE) |
|
608 |
|
609 self.LibraryComment = wx.TextCtrl(id=ID_PLCOPENEDITORLIBRARYCOMMENT, |
|
610 name='LibraryComment', parent=self.LibraryPanel, |
|
611 pos=wx.Point(0, 0), size=wx.Size(0, 60), |
|
612 style=wx.TE_READONLY|wx.TE_MULTILINE) |
|
613 |
|
614 self._init_sizers() |
|
615 |
|
616 if self.EnableDebug: |
|
617 self.DebugVariablePanel = DebugVariablePanel(self.RightNoteBook, self.Controler) |
|
618 self.RightNoteBook.AddPage(self.DebugVariablePanel, _("Debugger")) |
|
619 |
|
620 if USE_AUI: |
|
621 self.AUIManager.Update() |
|
622 |
|
623 ## Constructor of the PLCOpenEditor class. |
|
624 # @param parent The parent window. |
|
625 # @param controler The controler been used by PLCOpenEditor (default: None). |
|
626 # @param fileOpen The filepath to open if no controler defined (default: None). |
|
627 # @param debug The filepath to open if no controler defined (default: False). |
|
628 def __init__(self, parent, enable_debug = False): |
|
629 self.Controler = None |
|
630 self.EnableDebug = enable_debug |
|
631 |
|
632 self._init_ctrls(parent) |
|
633 |
|
634 # Define Tree item icon list |
|
635 self.TreeImageList = wx.ImageList(16, 16) |
|
636 self.TreeImageDict = {} |
|
637 |
|
638 # Icons for languages |
|
639 for language in LANGUAGES: |
|
640 self.TreeImageDict[language]=self.TreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%language))) |
|
641 |
|
642 # Icons for other items |
|
643 for imgname, itemtype in [ |
|
644 #editables |
|
645 ("PROJECT", ITEM_PROJECT), |
|
646 #("POU", ITEM_POU), |
|
647 #("VARIABLE", ITEM_VARIABLE), |
|
648 ("TRANSITION", ITEM_TRANSITION), |
|
649 ("ACTION", ITEM_ACTION), |
|
650 ("CONFIGURATION", ITEM_CONFIGURATION), |
|
651 ("RESOURCE", ITEM_RESOURCE), |
|
652 ("DATATYPE", ITEM_DATATYPE), |
|
653 # uneditables |
|
654 ("DATATYPES", ITEM_DATATYPES), |
|
655 ("FUNCTION", ITEM_FUNCTION), |
|
656 ("FUNCTIONBLOCK", ITEM_FUNCTIONBLOCK), |
|
657 ("PROGRAM", ITEM_PROGRAM), |
|
658 ("VAR_LOCAL", ITEM_VAR_LOCAL), |
|
659 ("VAR_LOCAL", ITEM_VAR_GLOBAL), |
|
660 ("VAR_LOCAL", ITEM_VAR_EXTERNAL), |
|
661 ("VAR_LOCAL", ITEM_VAR_TEMP), |
|
662 ("VAR_INPUT", ITEM_VAR_INPUT), |
|
663 ("VAR_OUTPUT", ITEM_VAR_OUTPUT), |
|
664 ("VAR_INOUT", ITEM_VAR_INOUT), |
|
665 ("TRANSITIONS", ITEM_TRANSITIONS), |
|
666 ("ACTIONS", ITEM_ACTIONS), |
|
667 ("CONFIGURATIONS", ITEM_CONFIGURATIONS), |
|
668 ("RESOURCES", ITEM_RESOURCES), |
|
669 ("PROPERTIES", ITEM_PROPERTIES)]: |
|
670 self.TreeImageDict[itemtype]=self.TreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%imgname))) |
|
671 |
|
672 # Assign icon list to TreeCtrls |
|
673 self.TypesTree.SetImageList(self.TreeImageList) |
|
674 self.InstancesTree.SetImageList(self.TreeImageList) |
|
675 |
|
676 self.CurrentToolBar = [] |
|
677 self.CurrentLanguage = "" |
|
678 self.SelectedItem = None |
|
679 self.Errors = [] |
|
680 self.DrawingMode = FREEDRAWING_MODE |
|
681 #self.DrawingMode = DRIVENDRAWING_MODE |
|
682 if USE_AUI: |
|
683 self.AuiTabCtrl = [] |
|
684 |
|
685 # Initialize Printing configuring elements |
|
686 self.PrintData = wx.PrintData() |
|
687 self.PrintData.SetPaperId(wx.PAPER_A4) |
|
688 self.PrintData.SetPrintMode(wx.PRINT_MODE_PRINTER) |
|
689 self.PageSetupData = wx.PageSetupDialogData(self.PrintData) |
|
690 self.PageSetupData.SetMarginTopLeft(wx.Point(10, 15)) |
|
691 self.PageSetupData.SetMarginBottomRight(wx.Point(10, 20)) |
|
692 |
|
693 self.SetRefreshFunctions() |
|
694 |
|
695 self.Maximize() |
|
696 |
|
697 |
|
698 #------------------------------------------------------------------------------- |
|
699 # General Functions |
|
700 #------------------------------------------------------------------------------- |
|
701 |
|
702 def SetRefreshFunctions(self): |
|
703 self.RefreshFunctions = { |
|
704 TITLE : self.RefreshTitle, |
|
705 TOOLBAR : self.RefreshToolBar, |
|
706 FILEMENU : self.RefreshFileMenu, |
|
707 EDITMENU : self.RefreshEditMenu, |
|
708 DISPLAYMENU : self.RefreshDisplayMenu, |
|
709 TYPESTREE : self.RefreshTypesTree, |
|
710 INSTANCESTREE : self.RefreshInstancesTree, |
|
711 LIBRARYTREE : self.RefreshLibraryTree, |
|
712 SCALING : self.RefreshScaling} |
|
713 |
|
714 ## Call PLCOpenEditor refresh functions. |
|
715 # @param elements List of elements to refresh. |
|
716 def _Refresh(self, *elements): |
|
717 for element in elements: |
|
718 self.RefreshFunctions[element]() |
|
719 |
|
720 ## Callback function when AUINotebook Page closed with CloseButton |
|
721 # @param event AUINotebook Event. |
|
722 def OnPageClose(self, event): |
|
723 # Get Selected Tab |
|
724 selected = event.GetSelection() |
|
725 if selected >= 0: |
|
726 # Remove corresponding VariablePanel |
|
727 window = self.TabsOpened.GetPage(selected) |
|
728 if not window.IsDebugging(): |
|
729 self.VariablePanelIndexer.RemoveVariablePanel(window.GetTagName()) |
|
730 # Refresh Tab selection |
|
731 if self.TabsOpened.GetPageCount() > 0: |
|
732 new_index = min(selected, self.TabsOpened.GetPageCount() - 1) |
|
733 self.TabsOpened.SetSelection(new_index) |
|
734 window = self.TabsOpened.GetPage(selected) |
|
735 if not window.IsDebugging(): |
|
736 self.VariablePanelIndexer.ChangeVariablePanel(window.GetTagName()) |
|
737 # Refresh all window elements that have changed |
|
738 self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU) |
|
739 wx.CallAfter(self.RefreshTabCtrlEvent) |
|
740 event.Skip() |
|
741 |
|
742 def GetCopyBuffer(self): |
|
743 data = None |
|
744 if wx.TheClipboard.IsOpened() or wx.TheClipboard.Open(): |
|
745 dataobj = wx.TextDataObject() |
|
746 if wx.TheClipboard.GetData(dataobj): |
|
747 data = dataobj.GetText() |
|
748 if wx.TheClipboard.IsOpened(): |
|
749 wx.TheClipboard.Close() |
|
750 return data |
|
751 |
|
752 def SetCopyBuffer(self, text): |
|
753 if wx.TheClipboard.IsOpened() or wx.TheClipboard.Open(): |
|
754 data = wx.TextDataObject() |
|
755 data.SetText(text) |
|
756 wx.TheClipboard.SetData(data) |
|
757 wx.TheClipboard.Flush() |
|
758 if wx.TheClipboard.IsOpened(): |
|
759 wx.TheClipboard.Close() |
|
760 self.RefreshEditMenu() |
|
761 |
|
762 def GetDrawingMode(self): |
|
763 return self.DrawingMode |
|
764 |
|
765 def RefreshScaling(self): |
|
766 for i in xrange(self.TabsOpened.GetPageCount()): |
|
767 editor = self.TabsOpened.GetPage(i) |
|
768 editor.RefreshScaling() |
|
769 |
|
770 def ShowProperties(self): |
|
771 old_values = self.Controler.GetProjectProperties() |
|
772 dialog = ProjectDialog(self) |
|
773 dialog.SetValues(old_values) |
|
774 if dialog.ShowModal() == wx.ID_OK: |
|
775 new_values = dialog.GetValues() |
|
776 new_values["creationDateTime"] = old_values["creationDateTime"] |
|
777 if new_values != old_values: |
|
778 self.Controler.SetProjectProperties(None, new_values) |
|
779 self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, |
|
780 TYPESTREE, INSTANCESTREE, SCALING) |
|
781 dialog.Destroy() |
|
782 |
|
783 #------------------------------------------------------------------------------- |
|
784 # Notebook Unified Functions |
|
785 #------------------------------------------------------------------------------- |
|
786 |
|
787 ## Function that generate bitmap for |
|
788 # for wx.aui.AUINotebook. |
|
789 # @param window Panel to display in tab. |
|
790 # @param text title for the tab ctrl. |
|
791 def GenerateBitmap(self, icon1_name, icon2_name = None): |
|
792 # Find index of bitmap if already created |
|
793 index = self.TabsImageListIndexes.get((icon1_name, icon2_name), None) |
|
794 # Return index or bitmap if found |
|
795 if index is not None: |
|
796 if USE_AUI: |
|
797 return self.TabsImageList.GetBitmap(index) |
|
798 else: |
|
799 return index |
|
800 if icon2_name is None: |
|
801 # Bitmap with only one icon |
|
802 bitmap = wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%icon1_name)) |
|
803 else: |
|
804 # Bitmap with two icon |
|
805 icon1 = wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%icon1_name)) |
|
806 icon2 = wx.Bitmap(os.path.join(CWD, 'Images', '%s.png'%icon2_name)) |
|
807 |
|
808 # Calculate bitmap size |
|
809 width = icon1.GetWidth() + icon2.GetWidth() - 1 |
|
810 height = max(icon1.GetHeight(), icon2.GetHeight()) |
|
811 # Create bitmap with both icons |
|
812 bitmap = wx.EmptyBitmap(width, height) |
|
813 dc = wx.MemoryDC() |
|
814 dc.SelectObject(bitmap) |
|
815 dc.Clear() |
|
816 dc.DrawBitmap(icon1, 0, 0) |
|
817 dc.DrawBitmap(icon2, icon1.GetWidth() - 1, 0) |
|
818 dc.Destroy() |
|
819 |
|
820 # Store bitmap in ImageList |
|
821 index = self.TabsImageList.Add(bitmap) |
|
822 # Save bitmap index in ImageList in dictionary |
|
823 self.TabsImageListIndexes[(icon1_name, icon2_name)] = index |
|
824 if USE_AUI: |
|
825 return bitmap |
|
826 else: |
|
827 return index |
|
828 |
|
829 ## Function that add a tab in Notebook, calling refresh for tab DClick event |
|
830 # for wx.aui.AUINotebook. |
|
831 # @param window Panel to display in tab. |
|
832 # @param text title for the tab ctrl. |
|
833 def AddPage(self, window, text): |
|
834 self.TabsOpened.AddPage(window, text) |
|
835 self.RefreshTabCtrlEvent() |
|
836 |
|
837 ## Function that fix difference in deleting all tabs between |
|
838 # wx.Notebook and wx.aui.AUINotebook. |
|
839 def DeleteAllPages(self): |
|
840 if USE_AUI: |
|
841 for idx in xrange(self.TabsOpened.GetPageCount()): |
|
842 self.TabsOpened.DeletePage(0) |
|
843 else: |
|
844 self.TabsOpened.DeleteAllPages() |
|
845 self.RefreshTabCtrlEvent() |
|
846 |
|
847 ## Function that fix difference in setting picture on tab between |
|
848 # wx.Notebook and wx.aui.AUINotebook. |
|
849 # @param idx Tab index. |
|
850 # @param bitmap wx.Bitmap to define on tab. |
|
851 # @return True if operation succeeded |
|
852 def SetPageBitmap(self, idx, bitmap): |
|
853 if USE_AUI: |
|
854 return self.TabsOpened.SetPageBitmap(idx, bitmap) |
|
855 else: |
|
856 return self.TabsOpened.SetPageImage(idx, bitmap) |
|
857 |
|
858 #------------------------------------------------------------------------------- |
|
859 # Dialog Message Functions |
|
860 #------------------------------------------------------------------------------- |
|
861 |
|
862 ## Function displaying an Error dialog in PLCOpenEditor. |
|
863 # @param message The message to display. |
|
864 def ShowErrorMessage(self, message): |
|
865 dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR) |
|
866 dialog.ShowModal() |
|
867 dialog.Destroy() |
|
868 |
|
869 ## Function displaying an Error dialog in PLCOpenEditor. |
|
870 # @return False if closing cancelled. |
|
871 def CheckSaveBeforeClosing(self): |
|
872 if not self.Controler.ProjectIsSaved(): |
|
873 dialog = wx.MessageDialog(self, _("There are changes, do you want to save?"), _("Close Application"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) |
|
874 answer = dialog.ShowModal() |
|
875 dialog.Destroy() |
|
876 if answer == wx.ID_YES: |
|
877 self.SaveProject() |
|
878 elif answer == wx.ID_CANCEL: |
|
879 return False |
|
880 return True |
|
881 |
|
882 #------------------------------------------------------------------------------- |
|
883 # File Menu Functions |
|
884 #------------------------------------------------------------------------------- |
|
885 |
|
886 def RefreshFileMenu(self): |
|
887 pass |
|
888 |
|
889 def ResetView(self): |
|
890 self.DeleteAllPages() |
|
891 self.VariablePanelIndexer.RemoveAllPanels() |
|
892 self.TypesTree.DeleteAllItems() |
|
893 self.InstancesTree.DeleteAllItems() |
|
894 self.LibraryTree.DeleteAllItems() |
|
895 self.Controler = None |
|
896 |
|
897 def OnCloseTabMenu(self, event): |
|
898 selected = self.TabsOpened.GetSelection() |
|
899 if selected >= 0: |
|
900 window = self.TabsOpened.GetPage(selected) |
|
901 if not window.IsDebugging(): |
|
902 self.VariablePanelIndexer.RemoveVariablePanel(window.GetTagName()) |
|
903 self.TabsOpened.DeletePage(selected) |
|
904 if self.TabsOpened.GetPageCount() > 0: |
|
905 new_index = min(selected, self.TabsOpened.GetPageCount() - 1) |
|
906 self.TabsOpened.SetSelection(new_index) |
|
907 window = self.TabsOpened.GetPage(new_index) |
|
908 if not window.IsDebugging(): |
|
909 self.VariablePanelIndexer.ChangeVariablePanel(window.GetTagName()) |
|
910 self._Refresh(TOOLBAR, FILEMENU, EDITMENU) |
|
911 event.Skip() |
|
912 |
|
913 def OnPageSetupMenu(self, event): |
|
914 dialog = wx.PageSetupDialog(self, self.PageSetupData) |
|
915 if dialog.ShowModal() == wx.ID_OK: |
|
916 self.PageSetupData = wx.PageSetupDialogData(dialog.GetPageSetupData()) |
|
917 self.PrintData = wx.PrintData(self.PageSetupData.GetPrintData()) |
|
918 dialog.Destroy() |
|
919 event.Skip() |
|
920 |
|
921 def OnPreviewMenu(self, event): |
|
922 selected = self.TabsOpened.GetSelection() |
|
923 if selected != -1: |
|
924 window = self.TabsOpened.GetPage(selected) |
|
925 data = wx.PrintDialogData(self.PrintData) |
|
926 properties = self.Controler.GetProjectProperties(window.IsDebugging()) |
|
927 page_size = map(int, properties["pageSize"]) |
|
928 margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight()) |
|
929 printout = GraphicPrintout(window, page_size, margins, True) |
|
930 printout2 = GraphicPrintout(window, page_size, margins, True) |
|
931 preview = wx.PrintPreview(printout, printout2, data) |
|
932 |
|
933 if preview.Ok(): |
|
934 preview_frame = wx.PreviewFrame(preview, self, _("Print preview")) |
|
935 |
|
936 preview_frame.Initialize() |
|
937 |
|
938 preview_frame.Show(True) |
|
939 event.Skip() |
|
940 |
|
941 def OnPrintMenu(self, event): |
|
942 selected = self.TabsOpened.GetSelection() |
|
943 if selected != -1: |
|
944 window = self.TabsOpened.GetPage(selected) |
|
945 dialog_data = wx.PrintDialogData(self.PrintData) |
|
946 dialog_data.SetToPage(1) |
|
947 properties = self.Controler.GetProjectProperties(window.IsDebugging()) |
|
948 page_size = map(int, properties["pageSize"]) |
|
949 margins = (self.PageSetupData.GetMarginTopLeft(), self.PageSetupData.GetMarginBottomRight()) |
|
950 printer = wx.Printer(dialog_data) |
|
951 printout = GraphicPrintout(window, page_size, margins) |
|
952 |
|
953 if not printer.Print(self, printout, True): |
|
954 self.ShowErrorMessage(_("There was a problem printing.\nPerhaps your current printer is not set correctly?")) |
|
955 printout.Destroy() |
|
956 event.Skip() |
|
957 |
|
958 def OnPropertiesMenu(self, event): |
|
959 self.ShowProperties() |
|
960 event.Skip() |
|
961 |
|
962 def OnQuitMenu(self, event): |
|
963 self.Close() |
|
964 # don't call event.Skip() here or it will attempt to close the |
|
965 # frame twice for some reason |
|
966 |
|
967 #------------------------------------------------------------------------------- |
|
968 # Edit Menu Functions |
|
969 #------------------------------------------------------------------------------- |
|
970 |
|
971 def RefreshEditMenu(self): |
|
972 if self.Controler is not None: |
|
973 undo, redo = self.Controler.GetBufferState() |
|
974 self.EditMenu.Enable(wx.ID_UNDO, undo) |
|
975 self.EditMenu.Enable(wx.ID_REDO, redo) |
|
976 self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, True) |
|
977 self.EditMenu.Check(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, |
|
978 self.Controler.IsProjectBufferEnabled()) |
|
979 self.EditMenu.Enable(wx.ID_ADD, True) |
|
980 self.EditMenu.Enable(wx.ID_DELETE, True) |
|
981 if self.TabsOpened.GetPageCount() > 0: |
|
982 self.EditMenu.Enable(wx.ID_CUT, True) |
|
983 self.EditMenu.Enable(wx.ID_COPY, True) |
|
984 if self.GetCopyBuffer() is not None: |
|
985 self.EditMenu.Enable(wx.ID_PASTE, True) |
|
986 else: |
|
987 self.EditMenu.Enable(wx.ID_PASTE, False) |
|
988 self.EditMenu.Enable(wx.ID_SELECTALL, True) |
|
989 else: |
|
990 self.EditMenu.Enable(wx.ID_CUT, False) |
|
991 self.EditMenu.Enable(wx.ID_COPY, False) |
|
992 self.EditMenu.Enable(wx.ID_PASTE, False) |
|
993 self.EditMenu.Enable(wx.ID_SELECTALL, False) |
|
994 else: |
|
995 self.EditMenu.Enable(wx.ID_UNDO, False) |
|
996 self.EditMenu.Enable(wx.ID_REDO, False) |
|
997 self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, False) |
|
998 self.EditMenu.Enable(ID_PLCOPENEDITOREDITMENUENABLEUNDOREDO, False) |
|
999 self.EditMenu.Enable(wx.ID_CUT, False) |
|
1000 self.EditMenu.Enable(wx.ID_COPY, False) |
|
1001 self.EditMenu.Enable(wx.ID_PASTE, False) |
|
1002 self.EditMenu.Enable(wx.ID_SELECTALL, False) |
|
1003 self.EditMenu.Enable(wx.ID_ADD, False) |
|
1004 self.EditMenu.Enable(wx.ID_DELETE, False) |
|
1005 |
|
1006 def CloseTabsWithoutModel(self): |
|
1007 idxs = range(self.TabsOpened.GetPageCount()) |
|
1008 idxs.reverse() |
|
1009 for idx in idxs: |
|
1010 window = self.TabsOpened.GetPage(idx) |
|
1011 if not window.IsDebugging(): |
|
1012 tagname = window.GetTagName() |
|
1013 if self.Controler.GetEditedElement(tagname) is None: |
|
1014 self.VariablePanelIndexer.RemoveVariablePanel(tagname) |
|
1015 self.TabsOpened.DeletePage(idx) |
|
1016 |
|
1017 def CloseDebugTabs(self): |
|
1018 if self.EnableDebug: |
|
1019 idxs = range(self.TabsOpened.GetPageCount()) |
|
1020 idxs.reverse() |
|
1021 for idx in idxs: |
|
1022 window = self.TabsOpened.GetPage(idx) |
|
1023 if window.IsDebugging(): |
|
1024 self.TabsOpened.DeletePage(idx) |
|
1025 self.DebugVariablePanel.ResetGrid() |
|
1026 |
|
1027 def OnUndoMenu(self, event): |
|
1028 self.Controler.LoadPrevious() |
|
1029 self.CloseTabsWithoutModel() |
|
1030 self.RefreshEditor() |
|
1031 self._Refresh(TITLE, EDITMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE, |
|
1032 SCALING) |
|
1033 event.Skip() |
|
1034 |
|
1035 def OnRedoMenu(self, event): |
|
1036 self.Controler.LoadNext() |
|
1037 self.CloseTabsWithoutModel() |
|
1038 self.RefreshEditor() |
|
1039 self._Refresh(TITLE, EDITMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE, |
|
1040 SCALING) |
|
1041 event.Skip() |
|
1042 |
|
1043 def OnEnableUndoRedoMenu(self, event): |
|
1044 self.Controler.EnableProjectBuffer(event.IsChecked()) |
|
1045 self.RefreshEditMenu() |
|
1046 event.Skip() |
|
1047 |
|
1048 OnCutMenu = GetShortcutKeyCallbackFunction("Cut") |
|
1049 OnCopyMenu = GetShortcutKeyCallbackFunction("Copy") |
|
1050 OnPasteMenu = GetShortcutKeyCallbackFunction("Paste") |
|
1051 |
|
1052 def OnSelectAllMenu(self, event): |
|
1053 control = self.FindFocus() |
|
1054 if isinstance(control, (Viewer, TextViewer)): |
|
1055 control.SelectAll() |
|
1056 elif isinstance(control, wx.TextCtrl): |
|
1057 control.SetSelection(0, control.GetLastPosition()) |
|
1058 elif isinstance(control, wx.ComboBox): |
|
1059 control.SetMark(0, control.GetLastPosition() + 1) |
|
1060 event.Skip() |
|
1061 |
|
1062 DeleteFunctions = { |
|
1063 ITEM_DATATYPE: GetDeleteElementFunction(PLCControler.ProjectRemoveDataType, check_function=PLCControler.DataTypeIsUsed), |
|
1064 ITEM_POU: GetDeleteElementFunction(PLCControler.ProjectRemovePou, check_function=PLCControler.PouIsUsed), |
|
1065 ITEM_TRANSITION: GetDeleteElementFunction(PLCControler.ProjectRemovePouTransition, ITEM_POU), |
|
1066 ITEM_ACTION: GetDeleteElementFunction(PLCControler.ProjectRemovePouAction, ITEM_POU), |
|
1067 ITEM_CONFIGURATION: GetDeleteElementFunction(PLCControler.ProjectRemoveConfiguration), |
|
1068 ITEM_RESOURCE: GetDeleteElementFunction(PLCControler.ProjectRemoveConfigurationResource, ITEM_CONFIGURATION) |
|
1069 } |
|
1070 |
|
1071 def OnDeleteMenu(self, event): |
|
1072 window = self.FindFocus() |
|
1073 if window == self.TypesTree or window is None: |
|
1074 selected = self.TypesTree.GetSelection() |
|
1075 if selected.IsOk(): |
|
1076 type = self.TypesTree.GetPyData(selected) |
|
1077 function = self.DeleteFunctions.get(type, None) |
|
1078 if function is not None: |
|
1079 function(self, selected) |
|
1080 self.CloseTabsWithoutModel() |
|
1081 self._Refresh(TITLE, TOOLBAR, EDITMENU, TYPESTREE, |
|
1082 INSTANCESTREE, LIBRARYTREE) |
|
1083 elif isinstance(window, (Viewer, TextViewer)): |
|
1084 event = wx.KeyEvent(wx.EVT_CHAR._getEvtType()) |
|
1085 event.m_keyCode = wx.WXK_DELETE |
|
1086 window.ProcessEvent(event) |
|
1087 event.Skip() |
|
1088 |
|
1089 |
|
1090 #------------------------------------------------------------------------------- |
|
1091 # Display Menu Functions |
|
1092 #------------------------------------------------------------------------------- |
|
1093 |
|
1094 def RefreshDisplayMenu(self): |
|
1095 if self.Controler is not None: |
|
1096 if self.TabsOpened.GetPageCount() > 0: |
|
1097 self.DisplayMenu.Enable(wx.ID_REFRESH, True) |
|
1098 selected = self.TabsOpened.GetSelection() |
|
1099 if selected != -1: |
|
1100 window = self.TabsOpened.GetPage(selected) |
|
1101 if isinstance(window, Viewer): |
|
1102 self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, True) |
|
1103 zoommenu = self.DisplayMenu.FindItemById(wx.ID_ZOOM_FIT).GetSubMenu() |
|
1104 zoomitem = zoommenu.FindItemByPosition(window.GetScale()) |
|
1105 zoomitem.Check(True) |
|
1106 else: |
|
1107 self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False) |
|
1108 else: |
|
1109 self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False) |
|
1110 else: |
|
1111 self.DisplayMenu.Enable(wx.ID_REFRESH, False) |
|
1112 self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False) |
|
1113 if self.EnableDebug: |
|
1114 self.DisplayMenu.Enable(wx.ID_CLEAR, True) |
|
1115 else: |
|
1116 self.DisplayMenu.Enable(wx.ID_REFRESH, False) |
|
1117 if self.EnableDebug: |
|
1118 self.DisplayMenu.Enable(wx.ID_CLEAR, False) |
|
1119 self.DisplayMenu.Enable(wx.ID_ZOOM_FIT, False) |
|
1120 |
|
1121 def OnRefreshMenu(self, event): |
|
1122 self.RefreshEditor() |
|
1123 event.Skip() |
|
1124 |
|
1125 def OnClearErrorsMenu(self, event): |
|
1126 self.ClearErrors() |
|
1127 event.Skip() |
|
1128 |
|
1129 def GenerateZoomFunction(self, idx): |
|
1130 def ZoomFunction(event): |
|
1131 selected = self.TabsOpened.GetSelection() |
|
1132 if selected != -1: |
|
1133 window = self.TabsOpened.GetPage(selected) |
|
1134 window.SetScale(idx) |
|
1135 window.RefreshVisibleElements() |
|
1136 window.RefreshScrollBars() |
|
1137 event.Skip() |
|
1138 return ZoomFunction |
|
1139 |
|
1140 |
|
1141 #------------------------------------------------------------------------------- |
|
1142 # Project Editor Panels Management Functions |
|
1143 #------------------------------------------------------------------------------- |
|
1144 |
|
1145 def OnPageDragged(self, event): |
|
1146 wx.CallAfter(self.RefreshTabCtrlEvent) |
|
1147 event.Skip() |
|
1148 |
|
1149 def RefreshTabCtrlEvent(self): |
|
1150 if USE_AUI: |
|
1151 auitabctrl = [] |
|
1152 for child in self.TabsOpened.GetChildren(): |
|
1153 if isinstance(child, wx.aui.AuiTabCtrl): |
|
1154 auitabctrl.append(child) |
|
1155 if child not in self.AuiTabCtrl: |
|
1156 child.Bind(wx.EVT_LEFT_DCLICK, self.GetTabsOpenedDClickFunction(child)) |
|
1157 self.AuiTabCtrl = auitabctrl |
|
1158 if self.TabsOpened.GetPageCount() == 0: |
|
1159 pane = self.AUIManager.GetPane(self.TabsOpened) |
|
1160 if pane.IsMaximized(): |
|
1161 self.AUIManager.RestorePane(pane) |
|
1162 self.AUIManager.Update() |
|
1163 |
|
1164 def OnPouSelectedChanged(self, event): |
|
1165 old_selected = self.TabsOpened.GetSelection() |
|
1166 if old_selected >= 0: |
|
1167 window = self.TabsOpened.GetPage(old_selected) |
|
1168 if not window.IsDebugging(): |
|
1169 window.ResetBuffer() |
|
1170 selected = event.GetSelection() |
|
1171 if selected >= 0: |
|
1172 window = self.TabsOpened.GetPage(selected) |
|
1173 if not window.IsDebugging(): |
|
1174 self.SelectTypesTreeItem(window.GetTagName()) |
|
1175 else: |
|
1176 self.SelectInstancesTreeItem(self.InstancesTree.GetRootItem(), window.GetInstancePath()) |
|
1177 window.RefreshView() |
|
1178 if not window.IsDebugging(): |
|
1179 self.VariablePanelIndexer.ChangeVariablePanel(window.GetTagName()) |
|
1180 self._Refresh(FILEMENU, EDITMENU, DISPLAYMENU, TOOLBAR) |
|
1181 event.Skip() |
|
1182 |
|
1183 def RefreshEditor(self, variablepanel = True): |
|
1184 selected = self.TabsOpened.GetSelection() |
|
1185 if selected != -1: |
|
1186 window = self.TabsOpened.GetPage(selected) |
|
1187 window.RefreshView() |
|
1188 if not window.IsDebugging() and variablepanel: |
|
1189 self.RefreshVariablePanel(window.GetTagName()) |
|
1190 |
|
1191 def RefreshVariablePanel(self, tagname): |
|
1192 self.VariablePanelIndexer.RefreshVariablePanel(tagname) |
|
1193 |
|
1194 def RefreshEditorNames(self, old_tagname, new_tagname): |
|
1195 for i in xrange(self.TabsOpened.GetPageCount()): |
|
1196 editor = self.TabsOpened.GetPage(i) |
|
1197 if editor.GetTagName() == old_tagname: |
|
1198 editor.SetTagName(new_tagname) |
|
1199 self.VariablePanelIndexer.UpdateVariablePanelTagName(old_tagname, new_tagname) |
|
1200 |
|
1201 def IsOpened(self, tagname): |
|
1202 for idx in xrange(self.TabsOpened.GetPageCount()): |
|
1203 if self.TabsOpened.GetPage(idx).IsViewing(tagname): |
|
1204 return idx |
|
1205 return None |
|
1206 |
|
1207 def RefreshPageTitles(self): |
|
1208 for idx in xrange(self.TabsOpened.GetPageCount()): |
|
1209 window = self.TabsOpened.GetPage(idx) |
|
1210 debug = window.IsDebugging() |
|
1211 words = window.GetTagName().split("::") |
|
1212 if words[0] == "P": |
|
1213 pou_type = self.Controler.GetEditedElementType(window.GetTagName(), debug)[1].upper() |
|
1214 pou_body_type = self.Controler.GetEditedElementBodyType(window.GetTagName(), debug) |
|
1215 self.SetPageBitmap(idx, self.GenerateBitmap(pou_type, pou_body_type)) |
|
1216 elif words[0] == "T": |
|
1217 pou_body_type = self.Controler.GetEditedElementBodyType(window.GetTagName(), debug) |
|
1218 self.SetPageBitmap(idx, self.GenerateBitmap("TRANSITION", pou_body_type)) |
|
1219 elif words[0] == "A": |
|
1220 pou_body_type = self.Controler.GetEditedElementBodyType(window.GetTagName(), debug) |
|
1221 self.SetPageBitmap(idx, self.GenerateBitmap("ACTION", pou_body_type)) |
|
1222 elif words[0] == "C": |
|
1223 self.SetPageBitmap(idx, self.GenerateBitmap("CONFIGURATION")) |
|
1224 elif words[0] == "R": |
|
1225 self.SetPageBitmap(idx, self.GenerateBitmap("RESOURCE")) |
|
1226 elif words[0] == "D": |
|
1227 self.SetPageBitmap(idx, self.GenerateBitmap("DATATYPE")) |
|
1228 if debug: |
|
1229 text = window.GetInstancePath() |
|
1230 if len(text) > 15: |
|
1231 text = "..." + text[-12:] |
|
1232 self.TabsOpened.SetPageText(idx, text) |
|
1233 else: |
|
1234 self.TabsOpened.SetPageText(idx, "-".join(words[1:])) |
|
1235 |
|
1236 def GetTabsOpenedDClickFunction(self, tabctrl): |
|
1237 def OnTabsOpenedDClick(event): |
|
1238 pos = event.GetPosition() |
|
1239 if tabctrl.TabHitTest(pos.x, pos.y, None): |
|
1240 pane = self.AUIManager.GetPane(self.TabsOpened) |
|
1241 if pane.IsMaximized(): |
|
1242 self.AUIManager.RestorePane(pane) |
|
1243 else: |
|
1244 self.AUIManager.MaximizePane(pane) |
|
1245 self.AUIManager.Update() |
|
1246 event.Skip() |
|
1247 return OnTabsOpenedDClick |
|
1248 |
|
1249 #------------------------------------------------------------------------------- |
|
1250 # Types Tree Management Functions |
|
1251 #------------------------------------------------------------------------------- |
|
1252 |
|
1253 def RefreshTypesTree(self): |
|
1254 infos = self.Controler.GetProjectInfos() |
|
1255 root = self.TypesTree.GetRootItem() |
|
1256 if not root.IsOk(): |
|
1257 root = self.TypesTree.AddRoot(infos["name"]) |
|
1258 self.GenerateTypesTreeBranch(root, infos) |
|
1259 self.TypesTree.Expand(root) |
|
1260 |
|
1261 def ResetSelectedItem(self): |
|
1262 self.SelectedItem = None |
|
1263 |
|
1264 def GenerateTypesTreeBranch(self, root, infos, topology=False): |
|
1265 to_delete = [] |
|
1266 item_name = infos["name"] |
|
1267 self.TypesTree.SetItemText(root, _(item_name)) |
|
1268 self.TypesTree.SetPyData(root, infos["type"]) |
|
1269 if infos.get("tagname", None) in self.Errors: |
|
1270 self.TypesTree.SetItemBackgroundColour(root, wx.Colour(255, 255, 0)) |
|
1271 self.TypesTree.SetItemTextColour(root, wx.RED) |
|
1272 else: |
|
1273 self.TypesTree.SetItemBackgroundColour(root, wx.WHITE) |
|
1274 self.TypesTree.SetItemTextColour(root, wx.BLACK) |
|
1275 if infos["type"] == ITEM_POU: |
|
1276 self.TypesTree.SetItemImage(root, self.TreeImageDict[self.Controler.GetPouBodyType(infos["name"])]) |
|
1277 else: |
|
1278 self.TypesTree.SetItemImage(root, self.TreeImageDict[infos["type"]]) |
|
1279 |
|
1280 if wx.VERSION >= (2, 6, 0): |
|
1281 item, root_cookie = self.TypesTree.GetFirstChild(root) |
|
1282 else: |
|
1283 item, root_cookie = self.TypesTree.GetFirstChild(root, 0) |
|
1284 for values in infos["values"]: |
|
1285 if not item.IsOk(): |
|
1286 item = self.TypesTree.AppendItem(root, "") |
|
1287 if wx.Platform != '__WXMSW__': |
|
1288 item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) |
|
1289 self.GenerateTypesTreeBranch(item, values) |
|
1290 item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) |
|
1291 while item.IsOk(): |
|
1292 to_delete.append(item) |
|
1293 item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) |
|
1294 for item in to_delete: |
|
1295 self.TypesTree.Delete(item) |
|
1296 |
|
1297 def SelectTypesTreeItem(self, tagname): |
|
1298 if self.TypesTree is not None: |
|
1299 root = self.TypesTree.GetRootItem() |
|
1300 words = tagname.split("::") |
|
1301 if words[0] == "D": |
|
1302 return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_DATATYPE)]) |
|
1303 elif words[0] == "P": |
|
1304 return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_POU)]) |
|
1305 elif words[0] == "T": |
|
1306 return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_TRANSITION)]) |
|
1307 elif words[0] == "A": |
|
1308 return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_POU), (words[2], ITEM_ACTION)]) |
|
1309 elif words[0] == "C": |
|
1310 return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION)]) |
|
1311 elif words[0] == "R": |
|
1312 return self.RecursiveTypesTreeItemSelection(root, [(words[1], ITEM_CONFIGURATION), (words[2], ITEM_RESOURCE)]) |
|
1313 return False |
|
1314 |
|
1315 def RecursiveTypesTreeItemSelection(self, root, items): |
|
1316 found = False |
|
1317 if self.TypesTree is not None: |
|
1318 if wx.VERSION >= (2, 6, 0): |
|
1319 item, root_cookie = self.TypesTree.GetFirstChild(root) |
|
1320 else: |
|
1321 item, root_cookie = self.TypesTree.GetFirstChild(root, 0) |
|
1322 while item.IsOk() and not found: |
|
1323 if (self.TypesTree.GetItemText(item), self.TypesTree.GetPyData(item)) == items[0]: |
|
1324 if len(items) == 1: |
|
1325 self.SelectedItem = item |
|
1326 self.TypesTree.SelectItem(item) |
|
1327 wx.CallAfter(self.ResetSelectedItem) |
|
1328 return True |
|
1329 else: |
|
1330 found = self.RecursiveTypesTreeItemSelection(item, items[1:]) |
|
1331 else: |
|
1332 found = self.RecursiveTypesTreeItemSelection(item, items) |
|
1333 item, root_cookie = self.TypesTree.GetNextChild(root, root_cookie) |
|
1334 return found |
|
1335 |
|
1336 def OnTypesTreeBeginDrag(self, event): |
|
1337 if wx.Platform == '__WXMSW__': |
|
1338 self.SelectedItem = event.GetItem() |
|
1339 if self.SelectedItem is not None and self.TypesTree.GetPyData(self.SelectedItem) == ITEM_POU: |
|
1340 block_name = self.TypesTree.GetItemText(self.SelectedItem) |
|
1341 block_type = self.Controler.GetPouType(block_name) |
|
1342 if block_type != "program": |
|
1343 data = wx.TextDataObject(str((block_name, block_type, ""))) |
|
1344 dragSource = wx.DropSource(self.TypesTree) |
|
1345 dragSource.SetData(data) |
|
1346 dragSource.DoDragDrop() |
|
1347 self.ResetSelectedItem() |
|
1348 |
|
1349 def OnTypesTreeItemBeginEdit(self, event): |
|
1350 selected = event.GetItem() |
|
1351 if self.TypesTree.GetPyData(selected) in ITEMS_UNEDITABLE: |
|
1352 event.Veto() |
|
1353 else: |
|
1354 event.Skip() |
|
1355 |
|
1356 def OnTypesTreeItemEndEdit(self, event): |
|
1357 message = None |
|
1358 abort = False |
|
1359 new_name = event.GetLabel() |
|
1360 if new_name != "": |
|
1361 if not TestIdentifier(new_name): |
|
1362 message = _("\"%s\" is not a valid identifier!")%new_name |
|
1363 elif new_name.upper() in IEC_KEYWORDS: |
|
1364 message = _("\"%s\" is a keyword. It can't be used!")%new_name |
|
1365 else: |
|
1366 item = event.GetItem() |
|
1367 old_name = self.TypesTree.GetItemText(item) |
|
1368 itemtype = self.TypesTree.GetPyData(item) |
|
1369 if itemtype == ITEM_PROJECT: |
|
1370 self.Controler.SetProjectProperties(name = new_name) |
|
1371 elif itemtype == ITEM_DATATYPE: |
|
1372 if new_name.upper() in [name.upper() for name in self.Controler.GetProjectDataTypeNames() if name != old_name]: |
|
1373 message = _("\"%s\" data type already exists!")%new_name |
|
1374 abort = True |
|
1375 if not abort: |
|
1376 self.Controler.ChangeDataTypeName(old_name, new_name) |
|
1377 self.RefreshEditorNames(self.Controler.ComputeDataTypeName(old_name), |
|
1378 self.Controler.ComputeDataTypeName(new_name)) |
|
1379 self.RefreshPageTitles() |
|
1380 elif itemtype == ITEM_POU: |
|
1381 if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames() if name != old_name]: |
|
1382 message = _("\"%s\" pou already exists!")%new_name |
|
1383 abort = True |
|
1384 elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]: |
|
1385 messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION) |
|
1386 if messageDialog.ShowModal() == wx.ID_NO: |
|
1387 abort = True |
|
1388 messageDialog.Destroy() |
|
1389 if not abort: |
|
1390 self.Controler.ChangePouName(old_name, new_name) |
|
1391 self.RefreshEditorNames(self.Controler.ComputePouName(old_name), |
|
1392 self.Controler.ComputePouName(new_name)) |
|
1393 self.RefreshLibraryTree() |
|
1394 self.RefreshPageTitles() |
|
1395 elif itemtype == ITEM_TRANSITION: |
|
1396 pou_name = GetParentName(self.TypesTree, item, ITEM_POU) |
|
1397 if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: |
|
1398 message = _("A POU named \"%s\" already exists!")%new_name |
|
1399 elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]: |
|
1400 message = _("A variable with \"%s\" as name already exists in this pou!")%new_name |
|
1401 else: |
|
1402 self.Controler.ChangePouTransitionName(pou_name, old_name, new_name) |
|
1403 self.RefreshEditorNames(self.Controler.ComputePouTransitionName(pou_name, old_name), |
|
1404 self.Controler.ComputePouTransitionName(pou_name, new_name)) |
|
1405 self.RefreshPageTitles() |
|
1406 elif itemtype == ITEM_ACTION: |
|
1407 pou_name = GetParentName(self.TypesTree, item, ITEM_POU) |
|
1408 if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: |
|
1409 message = _("A POU named \"%s\" already exists!")%new_name |
|
1410 elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]: |
|
1411 message = _("A variable with \"%s\" as name already exists in this pou!")%new_name |
|
1412 else: |
|
1413 self.Controler.ChangePouActionName(pou_name, old_name, new_name) |
|
1414 self.RefreshEditorNames(self.Controler.ComputePouActionName(pou_name, old_name), |
|
1415 self.Controler.ComputePouActionName(pou_name, new_name)) |
|
1416 self.RefreshPageTitles() |
|
1417 elif itemtype == ITEM_CONFIGURATION: |
|
1418 if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames() if name != old_name]: |
|
1419 message = _("\"%s\" config already exists!")%new_name |
|
1420 abort = True |
|
1421 elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: |
|
1422 messageDialog = wx.MessageDialog(self, _("There is a POU named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION) |
|
1423 if messageDialog.ShowModal() == wx.ID_NO: |
|
1424 abort = True |
|
1425 messageDialog.Destroy() |
|
1426 elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]: |
|
1427 messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION) |
|
1428 if messageDialog.ShowModal() == wx.ID_NO: |
|
1429 abort = True |
|
1430 messageDialog.Destroy() |
|
1431 if not abort: |
|
1432 self.Controler.ChangeConfigurationName(old_name, new_name) |
|
1433 self.RefreshEditorNames(self.Controler.ComputeConfigurationName(old_name), |
|
1434 self.Controler.ComputeConfigurationName(new_name)) |
|
1435 self.RefreshPageTitles() |
|
1436 elif itemtype == ITEM_RESOURCE: |
|
1437 config_name = GetParentName(self.TypesTree, item, ITEM_CONFIGURATION) |
|
1438 if new_name.upper() in [name.upper() for name in self.Controler.GetProjectConfigNames()]: |
|
1439 message = _("\"%s\" config already exists!")%new_name |
|
1440 abort = True |
|
1441 elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]: |
|
1442 messageDialog = wx.MessageDialog(self, _("There is a POU named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION) |
|
1443 if messageDialog.ShowModal() == wx.ID_NO: |
|
1444 abort = True |
|
1445 messageDialog.Destroy() |
|
1446 elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]: |
|
1447 messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION) |
|
1448 if messageDialog.ShowModal() == wx.ID_NO: |
|
1449 abort = True |
|
1450 messageDialog.Destroy() |
|
1451 if not abort: |
|
1452 self.Controler.ChangeConfigurationResourceName(config_name, old_name, new_name) |
|
1453 self.RefreshEditorNames(self.Controler.ComputeConfigurationResourceName(config_name, old_name), |
|
1454 self.Controler.ComputeConfigurationResourceName(config_name, new_name)) |
|
1455 self.RefreshPageTitles() |
|
1456 if message or abort: |
|
1457 if message: |
|
1458 self.ShowErrorMessage(message) |
|
1459 item = event.GetItem() |
|
1460 wx.CallAfter(self.TypesTree.EditLabel, item) |
|
1461 event.Veto() |
|
1462 else: |
|
1463 wx.CallAfter(self.RefreshTypesTree) |
|
1464 self.RefreshEditor() |
|
1465 self._Refresh(TITLE, FILEMENU, EDITMENU) |
|
1466 event.Skip() |
|
1467 |
|
1468 def OnTypesTreeItemActivated(self, event): |
|
1469 selected = event.GetItem() |
|
1470 name = self.TypesTree.GetItemText(selected) |
|
1471 data = self.TypesTree.GetPyData(selected) |
|
1472 if UNEDITABLE_NAMES_DICT.get(name, name) == "Properties": |
|
1473 self.ShowProperties() |
|
1474 if data == ITEM_DATATYPE: |
|
1475 self.EditProjectElement(data, self.Controler.ComputeDataTypeName(name)) |
|
1476 elif data == ITEM_POU: |
|
1477 self.EditProjectElement(data, self.Controler.ComputePouName(name)) |
|
1478 elif data == ITEM_CONFIGURATION: |
|
1479 self.EditProjectElement(data, self.Controler.ComputeConfigurationName(name)) |
|
1480 elif data == ITEM_RESOURCE: |
|
1481 config_name = GetParentName(self.TypesTree, selected, ITEM_CONFIGURATION) |
|
1482 self.EditProjectElement(data, self.Controler.ComputeConfigurationResourceName(config_name, name)) |
|
1483 elif data in [ITEM_TRANSITION, ITEM_ACTION]: |
|
1484 pou_name = GetParentName(self.TypesTree, selected, ITEM_POU) |
|
1485 if data == ITEM_TRANSITION: |
|
1486 tagname = self.Controler.ComputePouTransitionName(pou_name, name) |
|
1487 elif data == ITEM_ACTION: |
|
1488 tagname = self.Controler.ComputePouActionName(pou_name, name) |
|
1489 self.EditProjectElement(data, tagname) |
|
1490 event.Skip() |
|
1491 |
|
1492 def TypesTreeItemSelect(self, select_item): |
|
1493 name = self.TypesTree.GetItemText(select_item) |
|
1494 data = self.TypesTree.GetPyData(select_item) |
|
1495 if data == ITEM_DATATYPE: |
|
1496 self.EditProjectElement(data, self.Controler.ComputeDataTypeName(name), True) |
|
1497 elif data == ITEM_POU: |
|
1498 self.EditProjectElement(data, self.Controler.ComputePouName(name), True) |
|
1499 elif data == ITEM_CONFIGURATION: |
|
1500 self.EditProjectElement(data, self.Controler.ComputeConfigurationName(name), True) |
|
1501 elif data == ITEM_RESOURCE: |
|
1502 config_name = GetParentName(self.TypesTree, select_item, ITEM_CONFIGURATION) |
|
1503 self.EditProjectElement(data, self.Controler.ComputeConfigurationResourceName(config_name, name), True) |
|
1504 elif data in [ITEM_TRANSITION, ITEM_ACTION]: |
|
1505 pou_name = GetParentName(self.TypesTree, select_item, ITEM_POU) |
|
1506 if data == ITEM_TRANSITION: |
|
1507 tagname = self.Controler.ComputePouTransitionName(pou_name, name) |
|
1508 elif data == ITEM_ACTION: |
|
1509 tagname = self.Controler.ComputePouActionName(pou_name, name) |
|
1510 self.EditProjectElement(data, tagname, True) |
|
1511 |
|
1512 def OnTypesTreeLeftUp(self, event): |
|
1513 if self.SelectedItem is not None: |
|
1514 self.TypesTree.SelectItem(self.SelectedItem) |
|
1515 self.TypesTreeItemSelect(self.SelectedItem) |
|
1516 wx.CallAfter(self.ResetSelectedItem) |
|
1517 event.Skip() |
|
1518 |
|
1519 def OnTypesTreeItemSelected(self, event): |
|
1520 self.TypesTreeItemSelect(event.GetItem()) |
|
1521 event.Skip() |
|
1522 |
|
1523 def OnTypesTreeItemChanging(self, event): |
|
1524 if self.TypesTree.GetPyData(event.GetItem()) not in ITEMS_UNEDITABLE and self.SelectedItem is None: |
|
1525 self.SelectedItem = event.GetItem() |
|
1526 event.Veto() |
|
1527 else: |
|
1528 event.Skip() |
|
1529 |
|
1530 def EditProjectElement(self, elementtype, tagname, onlyopened = False): |
|
1531 openedidx = self.IsOpened(tagname) |
|
1532 if openedidx is not None: |
|
1533 old_selected = self.TabsOpened.GetSelection() |
|
1534 if old_selected != openedidx: |
|
1535 if old_selected >= 0: |
|
1536 self.TabsOpened.GetPage(old_selected).ResetBuffer() |
|
1537 self.TabsOpened.SetSelection(openedidx) |
|
1538 self.VariablePanelIndexer.ChangeVariablePanel(tagname) |
|
1539 self.RefreshPageTitles() |
|
1540 self._Refresh(FILEMENU, EDITMENU, TOOLBAR) |
|
1541 elif not onlyopened: |
|
1542 if elementtype == ITEM_CONFIGURATION: |
|
1543 new_window = ConfigurationEditor(self.TabsOpened, tagname, self, self.Controler) |
|
1544 self.AddPage(new_window, "") |
|
1545 self.VariablePanelIndexer.AddVariablePanel(tagname, "config") |
|
1546 elif elementtype == ITEM_RESOURCE: |
|
1547 new_window = ResourceEditor(self.TabsOpened, tagname, self, self.Controler) |
|
1548 self.AddPage(new_window, "") |
|
1549 self.VariablePanelIndexer.AddVariablePanel(tagname, "resource") |
|
1550 elif elementtype in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]: |
|
1551 bodytype = self.Controler.GetEditedElementBodyType(tagname) |
|
1552 if bodytype == "FBD": |
|
1553 new_window = Viewer(self.TabsOpened, tagname, self, self.Controler) |
|
1554 new_window.RefreshScaling(False) |
|
1555 elif bodytype == "LD": |
|
1556 new_window = LD_Viewer(self.TabsOpened, tagname, self, self.Controler) |
|
1557 new_window.RefreshScaling(False) |
|
1558 elif bodytype == "SFC": |
|
1559 new_window = SFC_Viewer(self.TabsOpened, tagname, self, self.Controler) |
|
1560 new_window.RefreshScaling(False) |
|
1561 else: |
|
1562 new_window = TextViewer(self.TabsOpened, tagname, self, self.Controler) |
|
1563 new_window.SetTextSyntax(bodytype) |
|
1564 if bodytype == "IL": |
|
1565 new_window.SetKeywords(IL_KEYWORDS) |
|
1566 else: |
|
1567 new_window.SetKeywords(ST_KEYWORDS) |
|
1568 self.AddPage(new_window, "") |
|
1569 words = tagname.split("::") |
|
1570 self.VariablePanelIndexer.AddVariablePanel(tagname, self.Controler.GetPouType(words[1])) |
|
1571 elif elementtype == ITEM_DATATYPE: |
|
1572 new_window = DataTypeEditor(self.TabsOpened, tagname, self, self.Controler) |
|
1573 self.AddPage(new_window, "") |
|
1574 self.VariablePanelIndexer.ChangeVariablePanel(tagname) |
|
1575 openedidx = self.IsOpened(tagname) |
|
1576 old_selected = self.TabsOpened.GetSelection() |
|
1577 if old_selected != openedidx: |
|
1578 if old_selected >= 0: |
|
1579 self.TabsOpened.GetPage(old_selected).ResetBuffer() |
|
1580 for i in xrange(self.TabsOpened.GetPageCount()): |
|
1581 window = self.TabsOpened.GetPage(i) |
|
1582 if window.GetTagName() == tagname: |
|
1583 self.TabsOpened.SetSelection(i) |
|
1584 window.SetFocus() |
|
1585 self.RefreshPageTitles() |
|
1586 self._Refresh(FILEMENU, EDITMENU, TOOLBAR) |
|
1587 |
|
1588 def OnTypesTreeRightUp(self, event): |
|
1589 if wx.Platform == '__WXMSW__': |
|
1590 item = event.GetItem() |
|
1591 self.TypesTree.SelectItem(item) |
|
1592 else: |
|
1593 item = self.TypesTree.GetSelection() |
|
1594 name = self.TypesTree.GetItemText(item) |
|
1595 type = self.TypesTree.GetPyData(item) |
|
1596 if type == ITEM_POU: |
|
1597 menu = wx.Menu(title='') |
|
1598 if self.Controler.GetPouBodyType(name) == "SFC": |
|
1599 new_id = wx.NewId() |
|
1600 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Transition")) |
|
1601 self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(name), id=new_id) |
|
1602 new_id = wx.NewId() |
|
1603 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action")) |
|
1604 self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(name), id=new_id) |
|
1605 menu.AppendSeparator() |
|
1606 |
|
1607 new_id = wx.NewId() |
|
1608 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Create a new POU from")) |
|
1609 self.Bind(wx.EVT_MENU, self.OnCreatePouFromMenu, id=new_id) |
|
1610 |
|
1611 AppendMenu(menu, help='', id=wx.ID_COPY, kind=wx.ITEM_NORMAL, text=_("Copy")) |
|
1612 self.Bind(wx.EVT_MENU, self.OnCopyPou, id=wx.ID_COPY) |
|
1613 |
|
1614 pou_type = self.Controler.GetPouType(name) |
|
1615 if pou_type in ["function", "functionBlock"]: |
|
1616 change_menu = wx.Menu(title='') |
|
1617 if pou_type == "function": |
|
1618 new_id = wx.NewId() |
|
1619 AppendMenu(change_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Function Block")) |
|
1620 self.Bind(wx.EVT_MENU, self.GenerateChangePouTypeFunction(name, "functionBlock"), id=new_id) |
|
1621 new_id = wx.NewId() |
|
1622 AppendMenu(change_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Program")) |
|
1623 self.Bind(wx.EVT_MENU, self.GenerateChangePouTypeFunction(name, "program"), id=new_id) |
|
1624 menu.AppendMenu(wx.NewId(), _("Change POU Type To"), change_menu) |
|
1625 new_id = wx.NewId() |
|
1626 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Rename")) |
|
1627 self.Bind(wx.EVT_MENU, self.OnRenamePouMenu, id=new_id) |
|
1628 new_id = wx.NewId() |
|
1629 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Delete")) |
|
1630 self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=new_id) |
|
1631 self.PopupMenu(menu) |
|
1632 elif type == ITEM_CONFIGURATION: |
|
1633 menu = wx.Menu(title='') |
|
1634 new_id = wx.NewId() |
|
1635 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Resource")) |
|
1636 self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(name), id=new_id) |
|
1637 new_id = wx.NewId() |
|
1638 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Delete")) |
|
1639 self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=new_id) |
|
1640 self.PopupMenu(menu) |
|
1641 elif type in [ITEM_DATATYPE, ITEM_TRANSITION, ITEM_ACTION, ITEM_RESOURCE]: |
|
1642 menu = wx.Menu(title='') |
|
1643 new_id = wx.NewId() |
|
1644 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Delete")) |
|
1645 self.Bind(wx.EVT_MENU, self.OnDeleteMenu, id=new_id) |
|
1646 self.PopupMenu(menu) |
|
1647 elif type in ITEMS_UNEDITABLE: |
|
1648 name = UNEDITABLE_NAMES_DICT[name] |
|
1649 if name == "Data Types": |
|
1650 menu = wx.Menu(title='') |
|
1651 new_id = wx.NewId() |
|
1652 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add DataType")) |
|
1653 self.Bind(wx.EVT_MENU, self.OnAddDataTypeMenu, id=new_id) |
|
1654 self.PopupMenu(menu) |
|
1655 elif name in ["Functions", "Function Blocks", "Programs"]: |
|
1656 menu = wx.Menu(title='') |
|
1657 |
|
1658 new_id = wx.NewId() |
|
1659 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Pou")) |
|
1660 self.Bind(wx.EVT_MENU, self.GenerateAddPouFunction({"Functions" : "function", "Function Blocks" : "functionBlock", "Programs" : "program"}[name]), id=new_id) |
|
1661 |
|
1662 AppendMenu(menu, help='', id=wx.ID_PASTE, kind=wx.ITEM_NORMAL, text=_("Paste")) |
|
1663 self.Bind(wx.EVT_MENU, self.OnPastePou, id=wx.ID_PASTE) |
|
1664 |
|
1665 if self.GetCopyBuffer() is None: |
|
1666 menu.Enable(wx.ID_PASTE, False) |
|
1667 |
|
1668 self.PopupMenu(menu) |
|
1669 elif name == "Configurations": |
|
1670 menu = wx.Menu(title='') |
|
1671 new_id = wx.NewId() |
|
1672 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Configuration")) |
|
1673 self.Bind(wx.EVT_MENU, self.OnAddConfigurationMenu, id=new_id) |
|
1674 self.PopupMenu(menu) |
|
1675 elif name == "Transitions": |
|
1676 menu = wx.Menu(title='') |
|
1677 new_id = wx.NewId() |
|
1678 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Transition")) |
|
1679 parent = self.TypesTree.GetItemParent(item) |
|
1680 parent_type = self.TypesTree.GetPyData(parent) |
|
1681 while parent_type != ITEM_POU: |
|
1682 parent = self.TypesTree.GetItemParent(parent) |
|
1683 parent_type = self.TypesTree.GetPyData(parent) |
|
1684 self.Bind(wx.EVT_MENU, self.GenerateAddTransitionFunction(self.TypesTree.GetItemText(parent)), id=new_id) |
|
1685 self.PopupMenu(menu) |
|
1686 elif name == "Actions": |
|
1687 menu = wx.Menu(title='') |
|
1688 new_id = wx.NewId() |
|
1689 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Action")) |
|
1690 parent = self.TypesTree.GetItemParent(item) |
|
1691 parent_type = self.TypesTree.GetPyData(parent) |
|
1692 while parent_type != ITEM_POU: |
|
1693 parent = self.TypesTree.GetItemParent(parent) |
|
1694 parent_type = self.TypesTree.GetPyData(parent) |
|
1695 self.Bind(wx.EVT_MENU, self.GenerateAddActionFunction(self.TypesTree.GetItemText(parent)), id=new_id) |
|
1696 self.PopupMenu(menu) |
|
1697 elif name == "Resources": |
|
1698 menu = wx.Menu(title='') |
|
1699 new_id = wx.NewId() |
|
1700 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Add Resource")) |
|
1701 parent = self.TypesTree.GetItemParent(item) |
|
1702 parent_type = self.TypesTree.GetPyData(parent) |
|
1703 while parent_type != ITEM_CONFIGURATION: |
|
1704 parent = self.TypesTree.GetItemParent(parent) |
|
1705 parent_type = self.TypesTree.GetPyData(parent) |
|
1706 self.Bind(wx.EVT_MENU, self.GenerateAddResourceFunction(self.TypesTree.GetItemText(parent)), id=new_id) |
|
1707 self.PopupMenu(menu) |
|
1708 event.Skip() |
|
1709 |
|
1710 |
|
1711 #------------------------------------------------------------------------------- |
|
1712 # Instances Tree Management Functions |
|
1713 #------------------------------------------------------------------------------- |
|
1714 |
|
1715 def RefreshInstancesTree(self): |
|
1716 infos = self.Controler.GetProjectTopology(self.EnableDebug) |
|
1717 root = self.InstancesTree.GetRootItem() |
|
1718 if not root.IsOk(): |
|
1719 root = self.InstancesTree.AddRoot(infos["name"]) |
|
1720 self.GenerateInstancesTreeBranch(root, infos) |
|
1721 self.InstancesTree.Expand(root) |
|
1722 |
|
1723 def GenerateInstancesTreeBranch(self, root, infos): |
|
1724 to_delete = [] |
|
1725 if infos.get("elmt_type", None) is not None: |
|
1726 self.InstancesTree.SetItemText(root, "%s (%s)"%(infos["name"], infos["elmt_type"])) |
|
1727 else: |
|
1728 self.InstancesTree.SetItemText(root, infos["name"]) |
|
1729 self.InstancesTree.SetPyData(root, (infos["type"], infos.get("tagname", None))) |
|
1730 self.InstancesTree.SetItemImage(root, self.TreeImageDict[infos["type"]]) |
|
1731 |
|
1732 if wx.VERSION >= (2, 6, 0): |
|
1733 item, root_cookie = self.InstancesTree.GetFirstChild(root) |
|
1734 else: |
|
1735 item, root_cookie = self.InstancesTree.GetFirstChild(root, 0) |
|
1736 for values in infos["values"]: |
|
1737 if not item.IsOk(): |
|
1738 item = self.InstancesTree.AppendItem(root, "") |
|
1739 if wx.Platform != '__WXMSW__': |
|
1740 item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) |
|
1741 self.GenerateInstancesTreeBranch(item, values) |
|
1742 item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) |
|
1743 while item.IsOk(): |
|
1744 to_delete.append(item) |
|
1745 item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) |
|
1746 for item in to_delete: |
|
1747 self.InstancesTree.Delete(item) |
|
1748 |
|
1749 def OnInstancesTreeBeginDrag(self, event): |
|
1750 if self.Controler.DebugAvailable(): |
|
1751 selected_item = event.GetItem() |
|
1752 selected_infos = self.InstancesTree.GetPyData(selected_item) |
|
1753 if selected_item is not None and selected_infos[0] in ITEMS_VARIABLE: |
|
1754 var_path = self.InstancesTree.GetItemText(selected_item).split(" (")[0] |
|
1755 parent_item = self.InstancesTree.GetItemParent(selected_item) |
|
1756 while self.InstancesTree.GetPyData(parent_item)[0] != ITEM_PROJECT: |
|
1757 parent_name = self.InstancesTree.GetItemText(parent_item).split(" (")[0] |
|
1758 var_path = "%s.%s"%(parent_name, var_path) |
|
1759 parent_item = self.InstancesTree.GetItemParent(parent_item) |
|
1760 data = wx.TextDataObject(str((var_path, "debug"))) |
|
1761 dragSource = wx.DropSource(self.InstancesTree) |
|
1762 dragSource.SetData(data) |
|
1763 dragSource.DoDragDrop() |
|
1764 event.Skip() |
|
1765 else: |
|
1766 event.Veto() |
|
1767 |
|
1768 def OnInstancesTreeItemActivated(self, event): |
|
1769 if self.Controler.DebugAvailable(): |
|
1770 selected_item = event.GetItem() |
|
1771 selected_infos = self.InstancesTree.GetPyData(selected_item) |
|
1772 if selected_item is not None and selected_infos[0] in [ITEM_FUNCTIONBLOCK, ITEM_PROGRAM, ITEM_TRANSITION, ITEM_ACTION]: |
|
1773 instance_path = self.InstancesTree.GetItemText(selected_item).split(" (")[0] |
|
1774 parent_item = self.InstancesTree.GetItemParent(selected_item) |
|
1775 while self.InstancesTree.GetPyData(parent_item)[0] != ITEM_PROJECT: |
|
1776 parent_name = self.InstancesTree.GetItemText(parent_item).split(" (")[0] |
|
1777 instance_path = "%s.%s"%(parent_name, instance_path) |
|
1778 parent_item = self.InstancesTree.GetItemParent(parent_item) |
|
1779 openedidx = self.IsOpened(instance_path) |
|
1780 if openedidx is not None: |
|
1781 old_selected = self.TabsOpened.GetSelection() |
|
1782 if old_selected != openedidx: |
|
1783 if old_selected >= 0: |
|
1784 self.TabsOpened.GetPage(old_selected).ResetBuffer() |
|
1785 self.TabsOpened.SetSelection(openedidx) |
|
1786 elif selected_infos[1] is not None: |
|
1787 bodytype = self.Controler.GetEditedElementBodyType(selected_infos[1], True) |
|
1788 if bodytype == "FBD": |
|
1789 new_window = Viewer(self.TabsOpened, selected_infos[1], self, self.Controler, True, instance_path) |
|
1790 new_window.RefreshScaling(False) |
|
1791 elif bodytype == "LD": |
|
1792 new_window = LD_Viewer(self.TabsOpened, selected_infos[1], self, self.Controler, True, instance_path) |
|
1793 new_window.RefreshScaling(False) |
|
1794 elif bodytype == "SFC": |
|
1795 new_window = SFC_Viewer(self.TabsOpened, selected_infos[1], self, self.Controler, True, instance_path) |
|
1796 new_window.RefreshScaling(False) |
|
1797 else: |
|
1798 new_window = TextViewer(self.TabsOpened, selected_infos[1], self, self.Controler, True, instance_path) |
|
1799 new_window.SetTextSyntax(bodytype) |
|
1800 if bodytype == "IL": |
|
1801 new_window.SetKeywords(IL_KEYWORDS) |
|
1802 else: |
|
1803 new_window.SetKeywords(ST_KEYWORDS) |
|
1804 self.AddPage(new_window, "") |
|
1805 new_window.SetFocus() |
|
1806 self.RefreshPageTitles() |
|
1807 if selected_item is not None and selected_infos[0] in ITEMS_VARIABLE: |
|
1808 var_path, var_type = self.InstancesTree.GetItemText(selected_item).split(" (") |
|
1809 var_type = var_type.split(")")[0] |
|
1810 |
|
1811 if self.Controler.IsOfType(var_type, "ANY_NUM", True) or\ |
|
1812 self.Controler.IsOfType(var_type, "ANY_BIT", True): |
|
1813 parent_item = self.InstancesTree.GetItemParent(selected_item) |
|
1814 while self.InstancesTree.GetPyData(parent_item)[0] != ITEM_PROJECT: |
|
1815 parent_name = self.InstancesTree.GetItemText(parent_item).split(" (")[0] |
|
1816 var_path = "%s.%s"%(parent_name, var_path) |
|
1817 parent_item = self.InstancesTree.GetItemParent(parent_item) |
|
1818 |
|
1819 self.OpenGraphicViewer(var_path) |
|
1820 event.Skip() |
|
1821 |
|
1822 def OpenGraphicViewer(self, var_path): |
|
1823 new_window = GraphicViewer(self.TabsOpened, self, self.Controler, var_path) |
|
1824 self.AddPage(new_window, "") |
|
1825 new_window.SetFocus() |
|
1826 self.RefreshPageTitles() |
|
1827 |
|
1828 def OnInstancesTreeRightUp(self, event): |
|
1829 if self.Controler.DebugAvailable(): |
|
1830 if wx.Platform == '__WXMSW__': |
|
1831 selected_item = event.GetItem() |
|
1832 else: |
|
1833 selected_item = self.InstancesTree.GetSelection() |
|
1834 selected_infos = self.InstancesTree.GetPyData(selected_item) |
|
1835 if selected_item is not None and selected_infos[0] in ITEMS_VARIABLE: |
|
1836 var_path, var_type = self.InstancesTree.GetItemText(selected_item).split(" (") |
|
1837 var_type = var_type.split(")")[0] |
|
1838 |
|
1839 if self.Controler.IsOfType(var_type, "ANY_NUM", True) or\ |
|
1840 self.Controler.IsOfType(var_type, "ANY_BIT", True): |
|
1841 parent_item = self.InstancesTree.GetItemParent(selected_item) |
|
1842 while self.InstancesTree.GetPyData(parent_item)[0] != ITEM_PROJECT: |
|
1843 parent_name = self.InstancesTree.GetItemText(parent_item).split(" (")[0] |
|
1844 var_path = "%s.%s"%(parent_name, var_path) |
|
1845 parent_item = self.InstancesTree.GetItemParent(parent_item) |
|
1846 |
|
1847 menu = wx.Menu(title='') |
|
1848 new_id = wx.NewId() |
|
1849 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Graphic Panel")) |
|
1850 self.Bind(wx.EVT_MENU, self.AddVariableGraphicFunction(var_path), id=new_id) |
|
1851 new_id = wx.NewId() |
|
1852 AppendMenu(menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("CSV Log")) |
|
1853 self.PopupMenu(menu) |
|
1854 event.Skip() |
|
1855 |
|
1856 def AddVariableGraphicFunction(self, iec_path): |
|
1857 def AddVariableGraphic(event): |
|
1858 self.OpenGraphicViewer(iec_path) |
|
1859 event.Skip() |
|
1860 return AddVariableGraphic |
|
1861 |
|
1862 def SelectInstancesTreeItem(self, root, instancepath): |
|
1863 found = False |
|
1864 if self.InstancesTree is not None: |
|
1865 paths = instancepath.split(".", 1) |
|
1866 if wx.VERSION >= (2, 6, 0): |
|
1867 item, root_cookie = self.InstancesTree.GetFirstChild(root) |
|
1868 else: |
|
1869 item, root_cookie = self.InstancesTree.GetFirstChild(root, 0) |
|
1870 while item.IsOk() and not found: |
|
1871 name = self.InstancesTree.GetItemText(item).split(" (")[0] |
|
1872 if name == paths[0]: |
|
1873 if len(paths) == 1: |
|
1874 self.InstancesTree.SelectItem(item) |
|
1875 return True |
|
1876 else: |
|
1877 found = self.SelectInstancesTreeItem(item, paths[1]) |
|
1878 item, root_cookie = self.InstancesTree.GetNextChild(root, root_cookie) |
|
1879 return found |
|
1880 |
|
1881 def ResetGraphicViewers(self): |
|
1882 for i in xrange(self.TabsOpened.GetPageCount()): |
|
1883 editor = self.TabsOpened.GetPage(i) |
|
1884 if isinstance(editor, GraphicViewer): |
|
1885 editor.ResetView() |
|
1886 |
|
1887 #------------------------------------------------------------------------------- |
|
1888 # Library Tree Management Functions |
|
1889 #------------------------------------------------------------------------------- |
|
1890 |
|
1891 def RefreshLibraryTree(self): |
|
1892 to_delete = [] |
|
1893 blocktypes = self.Controler.GetBlockTypes() |
|
1894 root = self.LibraryTree.GetRootItem() |
|
1895 if not root.IsOk(): |
|
1896 if wx.Platform == '__WXMSW__': |
|
1897 root = self.LibraryTree.AddRoot(_("Block Types")) |
|
1898 self.LibraryTree.SetPyData(root, {"type" : CATEGORY}) |
|
1899 else: |
|
1900 root = self.LibraryTree.AddRoot("") |
|
1901 if wx.VERSION >= (2, 6, 0): |
|
1902 category_item, root_cookie = self.LibraryTree.GetFirstChild(root) |
|
1903 else: |
|
1904 category_item, root_cookie = self.LibraryTree.GetFirstChild(root, 0) |
|
1905 for category in blocktypes: |
|
1906 category_name = category["name"] |
|
1907 if not category_item.IsOk(): |
|
1908 category_item = self.LibraryTree.AppendItem(root, _(category_name)) |
|
1909 if wx.Platform != '__WXMSW__': |
|
1910 category_item, root_cookie = self.LibraryTree.GetNextChild(root, root_cookie) |
|
1911 else: |
|
1912 self.LibraryTree.SetItemText(category_item, _(category_name)) |
|
1913 self.LibraryTree.SetPyData(category_item, {"type" : CATEGORY}) |
|
1914 if wx.VERSION >= (2, 6, 0): |
|
1915 blocktype_item, category_cookie = self.LibraryTree.GetFirstChild(category_item) |
|
1916 else: |
|
1917 blocktype_item, category_cookie = self.LibraryTree.GetFirstChild(category_item, 0) |
|
1918 for blocktype in category["list"]: |
|
1919 if not blocktype_item.IsOk(): |
|
1920 blocktype_item = self.LibraryTree.AppendItem(category_item, blocktype["name"]) |
|
1921 if wx.Platform != '__WXMSW__': |
|
1922 blocktype_item, category_cookie = self.LibraryTree.GetNextChild(category_item, category_cookie) |
|
1923 else: |
|
1924 self.LibraryTree.SetItemText(blocktype_item, blocktype["name"]) |
|
1925 self.LibraryTree.SetPyData(blocktype_item, {"type" : BLOCK, "block_type" : blocktype["type"], "inputs" : tuple([type for name, type, modifier in blocktype["inputs"]])}) |
|
1926 blocktype_item, category_cookie = self.LibraryTree.GetNextChild(category_item, category_cookie) |
|
1927 while blocktype_item.IsOk(): |
|
1928 to_delete.append(blocktype_item) |
|
1929 blocktype_item, category_cookie = self.LibraryTree.GetNextChild(category_item, category_cookie) |
|
1930 category_item, root_cookie = self.LibraryTree.GetNextChild(root, root_cookie) |
|
1931 while category_item.IsOk(): |
|
1932 to_delete.append(category_item) |
|
1933 category_item, root_cookie = self.LibraryTree.GetNextChild(root, root_cookie) |
|
1934 for item in to_delete: |
|
1935 self.LibraryTree.Delete(item) |
|
1936 if wx.Platform == '__WXMSW__': |
|
1937 self.LibraryTree.Expand(root) |
|
1938 |
|
1939 def OnLibraryTreeItemSelected(self, event): |
|
1940 selected = event.GetItem() |
|
1941 pydata = self.LibraryTree.GetPyData(selected) |
|
1942 if pydata is not None and pydata["type"] != CATEGORY: |
|
1943 blocktype = self.Controler.GetBlockType(self.LibraryTree.GetItemText(selected), pydata["inputs"]) |
|
1944 if blocktype: |
|
1945 comment = blocktype["comment"] |
|
1946 self.LibraryComment.SetValue(_(comment) + blocktype.get("usage", "")) |
|
1947 else: |
|
1948 self.LibraryComment.SetValue("") |
|
1949 else: |
|
1950 self.LibraryComment.SetValue("") |
|
1951 event.Skip() |
|
1952 |
|
1953 def OnLibraryTreeBeginDrag(self, event): |
|
1954 selected = event.GetItem() |
|
1955 pydata = self.LibraryTree.GetPyData(selected) |
|
1956 if pydata is not None and pydata["type"] == BLOCK: |
|
1957 data = wx.TextDataObject(str((self.LibraryTree.GetItemText(selected), |
|
1958 pydata["block_type"], "", pydata["inputs"]))) |
|
1959 dragSource = wx.DropSource(self.LibraryTree) |
|
1960 dragSource.SetData(data) |
|
1961 dragSource.DoDragDrop() |
|
1962 |
|
1963 #------------------------------------------------------------------------------- |
|
1964 # ToolBar Management Functions |
|
1965 #------------------------------------------------------------------------------- |
|
1966 |
|
1967 def ResetToolBar(self): |
|
1968 for item in self.CurrentToolBar: |
|
1969 if wx.VERSION >= (2, 6, 0): |
|
1970 self.Unbind(wx.EVT_MENU, id=item) |
|
1971 else: |
|
1972 self.Disconnect(id=item, eventType=wx.wxEVT_COMMAND_MENU_SELECTED) |
|
1973 |
|
1974 if USE_AUI: |
|
1975 ToolBar = self.Panes["ToolBar"] |
|
1976 else: |
|
1977 ToolBar = self.ToolBar |
|
1978 if ToolBar: |
|
1979 ToolBar.DeleteTool(item) |
|
1980 ToolBar.Realize() |
|
1981 if USE_AUI: |
|
1982 self.AUIManager.GetPane("ToolBar").BestSize(ToolBar.GetBestSize()) |
|
1983 self.AUIManager.Update() |
|
1984 |
|
1985 def RefreshToolBar(self): |
|
1986 selected = self.TabsOpened.GetSelection() |
|
1987 language = None |
|
1988 if selected != -1: |
|
1989 window = self.TabsOpened.GetPage(selected) |
|
1990 if not window.IsDebugging(): |
|
1991 language = self.Controler.GetEditedElementBodyType(window.GetTagName()) |
|
1992 if language is not None and language != self.CurrentLanguage: |
|
1993 self.ResetToolBar() |
|
1994 self.CurrentLanguage = language |
|
1995 self.CurrentToolBar = [] |
|
1996 if USE_AUI: |
|
1997 ToolBar = self.Panes["ToolBar"] |
|
1998 else: |
|
1999 ToolBar = self.ToolBar |
|
2000 if ToolBar: |
|
2001 for radio, modes, id, method, picture, help in ToolBarItems[language]: |
|
2002 if modes & self.DrawingMode: |
|
2003 if radio or self.DrawingMode == FREEDRAWING_MODE: |
|
2004 ToolBar.AddRadioTool(id, wx.Bitmap(os.path.join(CWD, "Images", picture)), wx.NullBitmap, help) |
|
2005 else: |
|
2006 ToolBar.AddSimpleTool(id, wx.Bitmap(os.path.join(CWD, "Images", picture)), help) |
|
2007 self.Bind(wx.EVT_TOOL, getattr(self, method), id=id) |
|
2008 self.CurrentToolBar.append(id) |
|
2009 ToolBar.Realize() |
|
2010 if USE_AUI: |
|
2011 self.AUIManager.GetPane("ToolBar").BestSize(ToolBar.GetBestSize()) |
|
2012 self.AUIManager.Update() |
|
2013 elif not language: |
|
2014 self.ResetToolBar() |
|
2015 self.CurrentLanguage = language |
|
2016 self.ResetCurrentMode() |
|
2017 |
|
2018 |
|
2019 #------------------------------------------------------------------------------- |
|
2020 # ToolBar Items Functions |
|
2021 #------------------------------------------------------------------------------- |
|
2022 |
|
2023 def ResetCurrentMode(self): |
|
2024 selected = self.TabsOpened.GetSelection() |
|
2025 if selected != -1: |
|
2026 window = self.TabsOpened.GetPage(selected) |
|
2027 window.SetMode(MODE_SELECTION) |
|
2028 if USE_AUI: |
|
2029 ToolBar = self.Panes["ToolBar"] |
|
2030 else: |
|
2031 ToolBar = self.ToolBar |
|
2032 if ToolBar: |
|
2033 ToolBar.ToggleTool(ID_PLCOPENEDITORTOOLBARSELECTION, False) |
|
2034 ToolBar.ToggleTool(ID_PLCOPENEDITORTOOLBARSELECTION, True) |
|
2035 |
|
2036 def ResetToolToggle(self, id): |
|
2037 if USE_AUI: |
|
2038 tool = self.Panes["ToolBar"].FindById(id) |
|
2039 else: |
|
2040 tool = self.ToolBar.FindById(id) |
|
2041 tool.SetToggle(False) |
|
2042 |
|
2043 def OnSelectionTool(self, event): |
|
2044 selected = self.TabsOpened.GetSelection() |
|
2045 if selected != -1: |
|
2046 self.TabsOpened.GetPage(selected).SetMode(MODE_SELECTION) |
|
2047 event.Skip() |
|
2048 |
|
2049 def OnCommentTool(self, event): |
|
2050 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARCOMMENT) |
|
2051 selected = self.TabsOpened.GetSelection() |
|
2052 if selected != -1: |
|
2053 self.TabsOpened.GetPage(selected).SetMode(MODE_COMMENT) |
|
2054 event.Skip() |
|
2055 |
|
2056 def OnVariableTool(self, event): |
|
2057 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARVARIABLE) |
|
2058 selected = self.TabsOpened.GetSelection() |
|
2059 if selected != -1: |
|
2060 self.TabsOpened.GetPage(selected).SetMode(MODE_VARIABLE) |
|
2061 event.Skip() |
|
2062 |
|
2063 def OnBlockTool(self, event): |
|
2064 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARBLOCK) |
|
2065 selected = self.TabsOpened.GetSelection() |
|
2066 if selected != -1: |
|
2067 self.TabsOpened.GetPage(selected).SetMode(MODE_BLOCK) |
|
2068 event.Skip() |
|
2069 |
|
2070 def OnConnectionTool(self, event): |
|
2071 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARCONNECTION) |
|
2072 selected = self.TabsOpened.GetSelection() |
|
2073 if selected != -1: |
|
2074 self.TabsOpened.GetPage(selected).SetMode(MODE_CONNECTION) |
|
2075 event.Skip() |
|
2076 |
|
2077 def OnPowerRailTool(self, event): |
|
2078 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARPOWERRAIL) |
|
2079 selected = self.TabsOpened.GetSelection() |
|
2080 if selected != -1: |
|
2081 self.TabsOpened.GetPage(selected).SetMode(MODE_POWERRAIL) |
|
2082 event.Skip() |
|
2083 |
|
2084 def OnRungTool(self, event): |
|
2085 selected = self.TabsOpened.GetSelection() |
|
2086 if selected != -1: |
|
2087 self.TabsOpened.GetPage(selected).AddLadderRung() |
|
2088 event.Skip() |
|
2089 |
|
2090 def OnCoilTool(self, event): |
|
2091 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARCOIL) |
|
2092 selected = self.TabsOpened.GetSelection() |
|
2093 if selected != -1: |
|
2094 self.TabsOpened.GetPage(selected).SetMode(MODE_COIL) |
|
2095 event.Skip() |
|
2096 |
|
2097 def OnContactTool(self, event): |
|
2098 if self.DrawingMode == FREEDRAWING_MODE: |
|
2099 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARCONTACT) |
|
2100 selected = self.TabsOpened.GetSelection() |
|
2101 if selected != -1: |
|
2102 if self.DrawingMode == FREEDRAWING_MODE: |
|
2103 self.TabsOpened.GetPage(selected).SetMode(MODE_CONTACT) |
|
2104 else: |
|
2105 self.TabsOpened.GetPage(selected).AddLadderContact() |
|
2106 event.Skip() |
|
2107 |
|
2108 def OnBranchTool(self, event): |
|
2109 selected = self.TabsOpened.GetSelection() |
|
2110 if selected != -1: |
|
2111 self.TabsOpened.GetPage(selected).AddLadderBranch() |
|
2112 event.Skip() |
|
2113 |
|
2114 def OnInitialStepTool(self, event): |
|
2115 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARINITIALSTEP) |
|
2116 selected = self.TabsOpened.GetSelection() |
|
2117 if selected != -1: |
|
2118 self.TabsOpened.GetPage(selected).SetMode(MODE_INITIALSTEP) |
|
2119 event.Skip() |
|
2120 |
|
2121 def OnStepTool(self, event): |
|
2122 if self.GetDrawingMode() == FREEDRAWING_MODE: |
|
2123 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARSTEP) |
|
2124 selected = self.TabsOpened.GetSelection() |
|
2125 if selected != -1: |
|
2126 if self.GetDrawingMode() == FREEDRAWING_MODE: |
|
2127 self.TabsOpened.GetPage(selected).SetMode(MODE_STEP) |
|
2128 else: |
|
2129 self.TabsOpened.GetPage(selected).AddStep() |
|
2130 event.Skip() |
|
2131 |
|
2132 def OnActionBlockTool(self, event): |
|
2133 if self.GetDrawingMode() == FREEDRAWING_MODE: |
|
2134 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARACTIONBLOCK) |
|
2135 selected = self.TabsOpened.GetSelection() |
|
2136 if selected != -1: |
|
2137 if self.GetDrawingMode() == FREEDRAWING_MODE: |
|
2138 self.TabsOpened.GetPage(selected).SetMode(MODE_ACTION) |
|
2139 else: |
|
2140 self.TabsOpened.GetPage(selected).AddStepAction() |
|
2141 event.Skip() |
|
2142 |
|
2143 def OnTransitionTool(self, event): |
|
2144 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARTRANSITION) |
|
2145 selected = self.TabsOpened.GetSelection() |
|
2146 if selected != -1: |
|
2147 self.TabsOpened.GetPage(selected).SetMode(MODE_TRANSITION) |
|
2148 event.Skip() |
|
2149 |
|
2150 def OnDivergenceTool(self, event): |
|
2151 if self.GetDrawingMode() == FREEDRAWING_MODE: |
|
2152 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARDIVERGENCE) |
|
2153 selected = self.TabsOpened.GetSelection() |
|
2154 if selected != -1: |
|
2155 if self.GetDrawingMode() == FREEDRAWING_MODE: |
|
2156 self.TabsOpened.GetPage(selected).SetMode(MODE_DIVERGENCE) |
|
2157 else: |
|
2158 self.TabsOpened.GetPage(selected).AddDivergence() |
|
2159 event.Skip() |
|
2160 |
|
2161 def OnJumpTool(self, event): |
|
2162 if self.GetDrawingMode() == FREEDRAWING_MODE: |
|
2163 self.ResetToolToggle(ID_PLCOPENEDITORTOOLBARJUMP) |
|
2164 selected = self.TabsOpened.GetSelection() |
|
2165 if selected != -1: |
|
2166 if self.GetDrawingMode() == FREEDRAWING_MODE: |
|
2167 self.TabsOpened.GetPage(selected).SetMode(MODE_JUMP) |
|
2168 else: |
|
2169 self.TabsOpened.GetPage(selected).AddJump() |
|
2170 event.Skip() |
|
2171 |
|
2172 |
|
2173 #------------------------------------------------------------------------------- |
|
2174 # Add Project Elements Functions |
|
2175 #------------------------------------------------------------------------------- |
|
2176 |
|
2177 def OnAddDataTypeMenu(self, event): |
|
2178 dialog = DataTypeDialog(self, _("Add a new data type"), _("Please enter data type name"), "", wx.OK|wx.CANCEL) |
|
2179 dialog.SetDataTypeNames(self.Controler.GetProjectDataTypeNames()) |
|
2180 if dialog.ShowModal() == wx.ID_OK: |
|
2181 self.Controler.ProjectAddDataType(dialog.GetValue()) |
|
2182 self._Refresh(TITLE, EDITMENU, TYPESTREE) |
|
2183 dialog.Destroy() |
|
2184 event.Skip() |
|
2185 |
|
2186 def GenerateAddPouFunction(self, pou_type): |
|
2187 def OnAddPouMenu(event): |
|
2188 dialog = PouDialog(self, pou_type) |
|
2189 dialog.SetPouNames(self.Controler.GetProjectPouNames()) |
|
2190 dialog.SetPouElementNames(self.Controler.GetProjectPouVariables()) |
|
2191 if dialog.ShowModal() == wx.ID_OK: |
|
2192 values = dialog.GetValues() |
|
2193 self.Controler.ProjectAddPou(values["pouName"], values["pouType"], values["language"]) |
|
2194 self._Refresh(TITLE, EDITMENU, TYPESTREE, LIBRARYTREE) |
|
2195 dialog.Destroy() |
|
2196 event.Skip() |
|
2197 return OnAddPouMenu |
|
2198 |
|
2199 def GenerateAddTransitionFunction(self, pou_name): |
|
2200 def OnAddTransitionMenu(event): |
|
2201 dialog = PouTransitionDialog(self) |
|
2202 dialog.SetPouNames(self.Controler.GetProjectPouNames()) |
|
2203 dialog.SetPouElementNames(self.Controler.GetProjectPouVariables(pou_name)) |
|
2204 if dialog.ShowModal() == wx.ID_OK: |
|
2205 values = dialog.GetValues() |
|
2206 self.Controler.ProjectAddPouTransition(pou_name, values["transitionName"], values["language"]) |
|
2207 self._Refresh(TITLE, EDITMENU, TYPESTREE) |
|
2208 dialog.Destroy() |
|
2209 event.Skip() |
|
2210 return OnAddTransitionMenu |
|
2211 |
|
2212 def GenerateAddActionFunction(self, pou_name): |
|
2213 def OnAddActionMenu(event): |
|
2214 dialog = PouActionDialog(self) |
|
2215 dialog.SetPouNames(self.Controler.GetProjectPouNames()) |
|
2216 dialog.SetPouElementNames(self.Controler.GetProjectPouVariables(pou_name)) |
|
2217 if dialog.ShowModal() == wx.ID_OK: |
|
2218 values = dialog.GetValues() |
|
2219 self.Controler.ProjectAddPouAction(pou_name, values["actionName"], values["language"]) |
|
2220 self._Refresh(TITLE, EDITMENU, TYPESTREE) |
|
2221 dialog.Destroy() |
|
2222 event.Skip() |
|
2223 return OnAddActionMenu |
|
2224 |
|
2225 def OnAddConfigurationMenu(self, event): |
|
2226 dialog = ConfigurationNameDialog(self, _("Please enter configuration name"), _("Add new configuration")) |
|
2227 dialog.SetPouNames(self.Controler.GetProjectPouNames()) |
|
2228 dialog.SetPouElementNames(self.Controler.GetProjectPouVariables()) |
|
2229 if dialog.ShowModal() == wx.ID_OK: |
|
2230 value = dialog.GetValue() |
|
2231 self.Controler.ProjectAddConfiguration(value) |
|
2232 self._Refresh(TITLE, EDITMENU, TYPESTREE, INSTANCESTREE) |
|
2233 dialog.Destroy() |
|
2234 event.Skip() |
|
2235 |
|
2236 def GenerateAddResourceFunction(self, config_name): |
|
2237 def OnAddResourceMenu(event): |
|
2238 dialog = ResourceNameDialog(self, _("Please enter resource name"), _("Add new resource")) |
|
2239 dialog.SetPouNames(self.Controler.GetProjectPouNames()) |
|
2240 dialog.SetPouElementNames(self.Controler.GetProjectPouVariables()) |
|
2241 if dialog.ShowModal() == wx.ID_OK: |
|
2242 value = dialog.GetValue() |
|
2243 self.Controler.ProjectAddConfigurationResource(config_name, value) |
|
2244 self._Refresh(TITLE, EDITMENU, TYPESTREE, INSTANCESTREE) |
|
2245 dialog.Destroy() |
|
2246 event.Skip() |
|
2247 return OnAddResourceMenu |
|
2248 |
|
2249 def GenerateChangePouTypeFunction(self, name, new_type): |
|
2250 def OnChangePouTypeMenu(event): |
|
2251 selected = self.TypesTree.GetSelection() |
|
2252 if self.TypesTree.GetPyData(selected) == ITEM_POU: |
|
2253 self.Controler.ProjectChangePouType(name, new_type) |
|
2254 self._Refresh(TITLE, TOOLBAR, EDITMENU, TYPESTREE, LIBRARYTREE) |
|
2255 event.Skip() |
|
2256 return OnChangePouTypeMenu |
|
2257 |
|
2258 def OnCreatePouFromMenu(self, event): |
|
2259 selected = self.TypesTree.GetSelection() |
|
2260 if self.TypesTree.GetPyData(selected) == ITEM_POU: |
|
2261 dialog = PouNameDialog(self, _("Please enter POU name"), _("Create a new POU from"), "", wx.OK|wx.CANCEL) |
|
2262 dialog.SetPouNames(self.Controler.GetProjectPouNames()) |
|
2263 if dialog.ShowModal() == wx.ID_OK: |
|
2264 self.Controler.ProjectCreatePouFrom(dialog.GetValue(), self.TypesTree.GetItemText(selected)) |
|
2265 self._Refresh(TITLE, TOOLBAR, EDITMENU, TYPESTREE, LIBRARYTREE) |
|
2266 event.Skip() |
|
2267 |
|
2268 def OnCopyPou(self, event): |
|
2269 selected = self.TypesTree.GetSelection() |
|
2270 |
|
2271 pou_name = self.TypesTree.GetItemText(selected) |
|
2272 pou = self.Controler.Project.getpou(pou_name) |
|
2273 |
|
2274 pou_xml = pou.generateXMLText('pou', 0) |
|
2275 self.SetCopyBuffer(pou_xml) |
|
2276 |
|
2277 def OnPastePou(self, event): |
|
2278 selected = self.TypesTree.GetSelection() |
|
2279 |
|
2280 pou_type = self.TypesTree.GetItemText(selected) |
|
2281 pou_type = UNEDITABLE_NAMES_DICT[pou_type] # one of 'Functions', 'Function Blocks' or 'Programs' |
|
2282 pou_type = {'Functions': 'function', 'Function Blocks': 'functionBlock', 'Programs': 'program'}[pou_type] |
|
2283 |
|
2284 pou_xml = self.GetCopyBuffer() |
|
2285 |
|
2286 result = self.Controler.PastePou(pou_type, pou_xml) |
|
2287 |
|
2288 if result is not None: |
|
2289 message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR) |
|
2290 message.ShowModal() |
|
2291 message.Destroy() |
|
2292 else: |
|
2293 self.RefreshTitle() |
|
2294 self.RefreshEditMenu() |
|
2295 self.RefreshTypesTree() |
|
2296 self.RefreshLibraryTree() |
|
2297 self.RefreshToolBar() |
|
2298 |
|
2299 #------------------------------------------------------------------------------- |
|
2300 # Remove Project Elements Functions |
|
2301 #------------------------------------------------------------------------------- |
|
2302 |
|
2303 def OnRemoveDataTypeMenu(self, event): |
|
2304 selected = self.TypesTree.GetSelection() |
|
2305 if self.TypesTree.GetPyData(selected) == ITEM_DATATYPE: |
|
2306 name = self.TypesTree.GetItemText(selected) |
|
2307 if not self.Controler.DataTypeIsUsed(name): |
|
2308 self.Controler.ProjectRemoveDataType(name) |
|
2309 tagname = self.Controler.ComputeDataTypeName(name) |
|
2310 idx = self.IsOpened(tagname) |
|
2311 if idx is not None: |
|
2312 self.TabsOpened.DeletePage(idx) |
|
2313 self._Refresh(TITLE, TOOLBAR, EDITMENU, TYPESTREE) |
|
2314 else: |
|
2315 self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!")) |
|
2316 event.Skip() |
|
2317 |
|
2318 def OnRenamePouMenu(self, event): |
|
2319 selected = self.TypesTree.GetSelection() |
|
2320 if self.TypesTree.GetPyData(selected) == ITEM_POU: |
|
2321 wx.CallAfter(self.TypesTree.EditLabel, selected) |
|
2322 event.Skip() |
|
2323 |
|
2324 def OnRemovePouMenu(self, event): |
|
2325 selected = self.TypesTree.GetSelection() |
|
2326 if self.TypesTree.GetPyData(selected) == ITEM_POU: |
|
2327 name = self.TypesTree.GetItemText(selected) |
|
2328 if not self.Controler.PouIsUsed(name): |
|
2329 self.Controler.ProjectRemovePou(name) |
|
2330 tagname = self.Controler.ComputePouName(name) |
|
2331 idx = self.IsOpened(tagname) |
|
2332 if idx is not None: |
|
2333 self.VariablePanelIndexer.RemoveVariablePanel(tagname) |
|
2334 self.TabsOpened.DeletePage(idx) |
|
2335 self._Refresh(TITLE, TOOLBAR, EDITMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE) |
|
2336 else: |
|
2337 self.ShowErrorMessage(_("\"%s\" is used by one or more POUs. It can't be removed!")) |
|
2338 event.Skip() |
|
2339 |
|
2340 def OnRemoveTransitionMenu(self, event): |
|
2341 selected = self.TypesTree.GetSelection() |
|
2342 if self.TypesTree.GetPyData(selected) == ITEM_TRANSITION: |
|
2343 transition = self.TypesTree.GetItemText(selected) |
|
2344 item = self.TypesTree.GetItemParent(selected) |
|
2345 item_type = self.TypesTree.GetPyData(item) |
|
2346 while item_type != ITEM_POU: |
|
2347 item = self.TypesTree.GetItemParent(item) |
|
2348 item_type = self.TypesTree.GetPyData(item) |
|
2349 pou_name = self.TypesTree.GetItemText(item) |
|
2350 self.Controler.ProjectRemovePouTransition(pou_name, transition) |
|
2351 tagname = self.Controler.ComputePouTransitionName(pou_name, transition) |
|
2352 idx = self.IsOpened(tagname) |
|
2353 if idx is not None: |
|
2354 self.VariablePanelIndexer.RemoveVariablePanel(tagname) |
|
2355 self.TabsOpened.DeletePage(idx) |
|
2356 self._Refresh(TITLE, EDITMENU, TYPESTREE) |
|
2357 event.Skip() |
|
2358 |
|
2359 def OnRemoveActionMenu(self, event): |
|
2360 selected = self.TypesTree.GetSelection() |
|
2361 if self.TypesTree.GetPyData(selected) == ITEM_ACTION: |
|
2362 action = self.TypesTree.GetItemText(selected) |
|
2363 item = self.TypesTree.GetItemParent(selected) |
|
2364 item_type = self.TypesTree.GetPyData(item) |
|
2365 while item_type != ITEM_POU: |
|
2366 item = self.TypesTree.GetItemParent(item) |
|
2367 item_type = self.TypesTree.GetPyData(item) |
|
2368 pou_name = self.TypesTree.GetItemText(item) |
|
2369 self.Controler.ProjectRemovePouAction(pou_name, action) |
|
2370 tagname = self.Controler.ComputePouActionName(pou_name, action) |
|
2371 idx = self.IsOpened(tagname) |
|
2372 if idx is not None: |
|
2373 self.VariablePanelIndexer.RemoveVariablePanel(tagname) |
|
2374 self.TabsOpened.DeletePage(idx) |
|
2375 self._Refresh(TITLE, EDITMENU, TYPESTREE) |
|
2376 event.Skip() |
|
2377 |
|
2378 def OnRemoveConfigurationMenu(self, event): |
|
2379 selected = self.TypesTree.GetSelection() |
|
2380 if self.TypesTree.GetPyData(selected) == ITEM_CONFIGURATION: |
|
2381 name = self.TypesTree.GetItemText(selected) |
|
2382 self.Controler.ProjectRemoveConfiguration(name) |
|
2383 tagname = self.Controler.ComputeConfigurationName(name) |
|
2384 idx = self.IsOpened(tagname) |
|
2385 if idx is not None: |
|
2386 self.VariablePanelIndexer.RemoveVariablePanel(tagname) |
|
2387 self.TabsOpened.DeletePage(idx) |
|
2388 self._Refresh(TITLE, EDITMENU, TYPESTREE, INSTANCESTREE) |
|
2389 event.Skip() |
|
2390 |
|
2391 def OnRemoveResourceMenu(self, event): |
|
2392 selected = self.TypesTree.GetSelection() |
|
2393 if self.TypesTree.GetPyData(selected) == ITEM_RESOURCE: |
|
2394 resource = self.TypesTree.GetItemText(selected) |
|
2395 item = self.TypesTree.GetItemParent(selected) |
|
2396 item_type = self.TypesTree.GetPyData(item) |
|
2397 while item_type != ITEM_CONFIGURATION: |
|
2398 item = self.TypesTree.GetItemParent(item) |
|
2399 item_type = self.TypesTree.GetPyData(item) |
|
2400 config_name = self.TypesTree.GetItemText(item) |
|
2401 self.Controler.ProjectRemoveConfigurationResource(config_name, resource) |
|
2402 tagname = self.Controler.ComputeConfigurationResourceName(config_name, selected) |
|
2403 idx = self.IsOpened(tagname) |
|
2404 if idx is not None: |
|
2405 self.VariablePanelIndexer.RemoveVariablePanel(tagname) |
|
2406 self.TabsOpened.DeletePage(idx) |
|
2407 self._Refresh(TITLE, EDITMENU, TYPESTREE, INSTANCESTREE) |
|
2408 event.Skip() |
|
2409 |
|
2410 def OnPLCOpenEditorMenu(self, event): |
|
2411 wx.MessageBox(_("No documentation available.\nComing soon.")) |
|
2412 #event.Skip() |
|
2413 |
|
2414 def OnPLCOpenMenu(self, event): |
|
2415 open_pdf(os.path.join(CWD, "plcopen", "TC6_XML_V101.pdf")) |
|
2416 event.Skip() |
|
2417 |
|
2418 def OnAboutMenu(self, event): |
|
2419 OpenHtmlFrame(self,_("About PLCOpenEditor"), os.path.join(CWD, "doc","about.html"), wx.Size(350, 350)) |
|
2420 event.Skip() |
|
2421 |
|
2422 |
|
2423 #------------------------------------------------------------------------------- |
|
2424 # Errors showing functions |
|
2425 #------------------------------------------------------------------------------- |
|
2426 |
|
2427 def ShowError(self, infos, start, end): |
|
2428 self.EditProjectElement(self.Controler.GetElementType(infos[0]), infos[0]) |
|
2429 self.SelectTypesTreeItem(infos[0]) |
|
2430 if infos[1] == "name": |
|
2431 self.Errors.append(infos[0]) |
|
2432 self.RefreshTypesTree() |
|
2433 self.TypesTree.Unselect() |
|
2434 elif infos[1] == "variable": |
|
2435 self.VariablePanelIndexer.AddVariableError(infos) |
|
2436 else: |
|
2437 selected = self.TabsOpened.GetSelection() |
|
2438 if selected != -1: |
|
2439 viewer = self.TabsOpened.GetPage(selected) |
|
2440 viewer.AddShownError(infos[1:], start, end) |
|
2441 viewer.RefreshView() |
|
2442 |
|
2443 def ClearErrors(self): |
|
2444 self.Errors = [] |
|
2445 self.RefreshTypesTree() |
|
2446 self.VariablePanelIndexer.ClearErrors() |
|
2447 for i in xrange(self.TabsOpened.GetPageCount()): |
|
2448 viewer = self.TabsOpened.GetPage(i) |
|
2449 viewer.ClearErrors() |
|
2450 |
|
2451 #------------------------------------------------------------------------------- |
|
2452 # PLCOpenEditor Main Class |
|
2453 #------------------------------------------------------------------------------- |
|
2454 |
|
2455 class PLCOpenEditor(IDEFrame): |
|
2456 |
|
2457 # Compatibility function for wx versions < 2.6 |
|
2458 if wx.VERSION < (2, 6, 0): |
|
2459 def Bind(self, event, function, id = None): |
|
2460 if id is not None: |
|
2461 event(self, id, function) |
|
2462 else: |
|
2463 event(self, function) |
|
2464 |
|
2465 def _init_coll_FileMenu_Items(self, parent): |
|
2466 AppendMenu(parent, help='', id=wx.ID_NEW, |
|
2467 kind=wx.ITEM_NORMAL, text=_(u'New\tCTRL+N')) |
|
2468 AppendMenu(parent, help='', id=wx.ID_OPEN, |
|
2469 kind=wx.ITEM_NORMAL, text=_(u'Open\tCTRL+O')) |
|
2470 AppendMenu(parent, help='', id=wx.ID_CLOSE, |
|
2471 kind=wx.ITEM_NORMAL, text=_(u'Close Tab\tCTRL+W')) |
|
2472 AppendMenu(parent, help='', id=wx.ID_CLOSE_ALL, |
|
2473 kind=wx.ITEM_NORMAL, text=_(u'Close Project')) |
|
2474 parent.AppendSeparator() |
|
2475 AppendMenu(parent, help='', id=wx.ID_SAVE, |
|
2476 kind=wx.ITEM_NORMAL, text=_(u'Save\tCTRL+S')) |
|
2477 AppendMenu(parent, help='', id=wx.ID_SAVEAS, |
|
2478 kind=wx.ITEM_NORMAL, text=_(u'Save As...\tCTRL+SHIFT+S')) |
|
2479 AppendMenu(parent, help='', id=ID_PLCOPENEDITORFILEMENUGENERATE, |
|
2480 kind=wx.ITEM_NORMAL, text=_(u'Generate Program\tCTRL+G')) |
|
2481 parent.AppendSeparator() |
|
2482 AppendMenu(parent, help='', id=wx.ID_PAGE_SETUP, |
|
2483 kind=wx.ITEM_NORMAL, text=_(u'Page Setup')) |
|
2484 AppendMenu(parent, help='', id=wx.ID_PREVIEW, |
|
2485 kind=wx.ITEM_NORMAL, text=_(u'Preview')) |
|
2486 AppendMenu(parent, help='', id=wx.ID_PRINT, |
|
2487 kind=wx.ITEM_NORMAL, text=_(u'Print')) |
|
2488 parent.AppendSeparator() |
|
2489 AppendMenu(parent, help='', id=wx.ID_PROPERTIES, |
|
2490 kind=wx.ITEM_NORMAL, text=_(u'Properties')) |
|
2491 parent.AppendSeparator() |
|
2492 AppendMenu(parent, help='', id=wx.ID_EXIT, |
|
2493 kind=wx.ITEM_NORMAL, text=_(u'Quit\tCTRL+Q')) |
|
2494 |
|
2495 self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, id=wx.ID_NEW) |
|
2496 self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, id=wx.ID_OPEN) |
|
2497 self.Bind(wx.EVT_MENU, self.OnCloseTabMenu, id=wx.ID_CLOSE) |
|
2498 self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu, id=wx.ID_CLOSE_ALL) |
|
2499 self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, id=wx.ID_SAVE) |
|
2500 self.Bind(wx.EVT_MENU, self.OnSaveProjectAsMenu, id=wx.ID_SAVEAS) |
|
2501 self.Bind(wx.EVT_MENU, self.OnGenerateProgramMenu, |
|
2502 id=ID_PLCOPENEDITORFILEMENUGENERATE) |
|
2503 self.Bind(wx.EVT_MENU, self.OnPageSetupMenu, id=wx.ID_PAGE_SETUP) |
|
2504 self.Bind(wx.EVT_MENU, self.OnPreviewMenu, id=wx.ID_PREVIEW) |
|
2505 self.Bind(wx.EVT_MENU, self.OnPrintMenu, id=wx.ID_PRINT) |
|
2506 self.Bind(wx.EVT_MENU, self.OnPropertiesMenu, id=wx.ID_PROPERTIES) |
|
2507 self.Bind(wx.EVT_MENU, self.OnQuitMenu, id=wx.ID_EXIT) |
|
2508 |
|
2509 def _init_coll_HelpMenu_Items(self, parent): |
|
2510 AppendMenu(parent, help='', id=wx.ID_HELP, |
|
2511 kind=wx.ITEM_NORMAL, text=_(u'PLCOpenEditor\tF1')) |
|
2512 #AppendMenu(parent, help='', id=wx.ID_HELP_CONTENTS, |
|
2513 # kind=wx.ITEM_NORMAL, text=u'PLCOpen\tF2') |
|
2514 #AppendMenu(parent, help='', id=wx.ID_HELP_CONTEXT, |
|
2515 # kind=wx.ITEM_NORMAL, text=u'IEC 61131-3\tF3') |
|
2516 AppendMenu(parent, help='', id=wx.ID_ABOUT, |
|
2517 kind=wx.ITEM_NORMAL, text=_(u'About')) |
|
2518 self.Bind(wx.EVT_MENU, self.OnPLCOpenEditorMenu, id=wx.ID_HELP) |
|
2519 #self.Bind(wx.EVT_MENU, self.OnPLCOpenMenu, id=wx.ID_HELP_CONTENTS) |
|
2520 self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT) |
|
2521 |
|
2522 ## Constructor of the PLCOpenEditor class. |
|
2523 # @param parent The parent window. |
|
2524 # @param controler The controler been used by PLCOpenEditor (default: None). |
|
2525 # @param fileOpen The filepath to open if no controler defined (default: None). |
|
2526 # @param debug The filepath to open if no controler defined (default: False). |
|
2527 def __init__(self, parent, fileOpen = None): |
|
2528 IDEFrame.__init__(self, parent) |
|
2529 |
|
2530 # Open the filepath if defined |
|
2531 if fileOpen is not None and os.path.isfile(fileOpen): |
|
2532 # Create a new controller |
|
2533 self.Controler = PLCControler() |
|
2534 self.Controler.OpenXMLFile(fileOpen) |
|
2535 self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE) |
|
2536 |
|
2537 # Define PLCOpenEditor icon |
|
2538 self.SetIcon(wx.Icon(os.path.join(CWD,"Images", "poe.ico"),wx.BITMAP_TYPE_ICO)) |
|
2539 |
|
2540 self.Bind(wx.EVT_CLOSE, self.OnCloseFrame) |
|
2541 |
|
2542 self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU) |
|
2543 |
|
2544 def OnCloseFrame(self, event): |
|
2545 if self.Controler is None or self.CheckSaveBeforeClosing(): |
|
2546 if USE_AUI: |
|
2547 self.AUIManager.UnInit() |
|
2548 event.Skip() |
|
2549 else: |
|
2550 event.Veto() |
|
2551 |
|
2552 def RefreshTitle(self): |
|
2553 name = _("PLCOpenEditor") |
|
2554 if self.Controler is not None: |
|
2555 self.SetTitle("%s - %s"%(name, self.Controler.GetFilename())) |
|
2556 else: |
|
2557 self.SetTitle(name) |
|
2558 |
|
2559 #------------------------------------------------------------------------------- |
|
2560 # File Menu Functions |
|
2561 #------------------------------------------------------------------------------- |
|
2562 |
|
2563 def RefreshFileMenu(self): |
|
2564 if self.Controler is not None: |
|
2565 selected = self.TabsOpened.GetSelection() |
|
2566 if selected >= 0: |
|
2567 graphic_viewer = isinstance(self.TabsOpened.GetPage(selected), Viewer) |
|
2568 else: |
|
2569 graphic_viewer = False |
|
2570 if self.TabsOpened.GetPageCount() > 0: |
|
2571 self.FileMenu.Enable(wx.ID_CLOSE, True) |
|
2572 if graphic_viewer: |
|
2573 self.FileMenu.Enable(wx.ID_PREVIEW, True) |
|
2574 self.FileMenu.Enable(wx.ID_PRINT, True) |
|
2575 else: |
|
2576 self.FileMenu.Enable(wx.ID_PREVIEW, False) |
|
2577 self.FileMenu.Enable(wx.ID_PRINT, False) |
|
2578 else: |
|
2579 self.FileMenu.Enable(wx.ID_CLOSE, False) |
|
2580 self.FileMenu.Enable(wx.ID_PREVIEW, False) |
|
2581 self.FileMenu.Enable(wx.ID_PRINT, False) |
|
2582 self.FileMenu.Enable(wx.ID_PAGE_SETUP, True) |
|
2583 self.FileMenu.Enable(wx.ID_SAVE, True) |
|
2584 self.FileMenu.Enable(wx.ID_PROPERTIES, True) |
|
2585 self.FileMenu.Enable(wx.ID_CLOSE_ALL, True) |
|
2586 self.FileMenu.Enable(wx.ID_SAVEAS, True) |
|
2587 self.FileMenu.Enable(ID_PLCOPENEDITORFILEMENUGENERATE, True) |
|
2588 else: |
|
2589 self.FileMenu.Enable(wx.ID_CLOSE, False) |
|
2590 self.FileMenu.Enable(wx.ID_PAGE_SETUP, False) |
|
2591 self.FileMenu.Enable(wx.ID_PREVIEW, False) |
|
2592 self.FileMenu.Enable(wx.ID_PRINT, False) |
|
2593 self.FileMenu.Enable(wx.ID_SAVE, False) |
|
2594 self.FileMenu.Enable(wx.ID_PROPERTIES, False) |
|
2595 self.FileMenu.Enable(wx.ID_CLOSE_ALL, False) |
|
2596 self.FileMenu.Enable(wx.ID_SAVEAS, False) |
|
2597 self.FileMenu.Enable(ID_PLCOPENEDITORFILEMENUGENERATE, False) |
|
2598 |
|
2599 def OnNewProjectMenu(self, event): |
|
2600 if self.Controler is not None and not self.CheckSaveBeforeClosing(): |
|
2601 return |
|
2602 dialog = ProjectDialog(self) |
|
2603 if dialog.ShowModal() == wx.ID_OK: |
|
2604 properties = dialog.GetValues() |
|
2605 self.ResetView() |
|
2606 self.Controler = PLCControler() |
|
2607 self.Controler.CreateNewProject(properties) |
|
2608 self._Refresh(TITLE, FILEMENU, EDITMENU, TYPESTREE, INSTANCESTREE, |
|
2609 LIBRARYTREE) |
|
2610 event.Skip() |
|
2611 |
|
2612 def OnOpenProjectMenu(self, event): |
|
2613 if self.Controler is not None and not self.CheckSaveBeforeClosing(): |
|
2614 return |
|
2615 filepath = "" |
|
2616 if self.Controler is not None: |
|
2617 filepath = self.Controler.GetFilePath() |
|
2618 if filepath != "": |
|
2619 directory = os.path.dirname(filepath) |
|
2620 else: |
|
2621 directory = os.getcwd() |
|
2622 dialog = wx.FileDialog(self, _("Choose a file"), directory, "", _("PLCOpen files (*.xml)|*.xml|All files|*.*"), wx.OPEN) |
|
2623 if dialog.ShowModal() == wx.ID_OK: |
|
2624 filepath = dialog.GetPath() |
|
2625 if os.path.isfile(filepath): |
|
2626 self.ResetView() |
|
2627 self.Controler = PLCControler() |
|
2628 self.Controler.OpenXMLFile(filepath) |
|
2629 self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE) |
|
2630 self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU) |
|
2631 dialog.Destroy() |
|
2632 event.Skip() |
|
2633 |
|
2634 def OnCloseProjectMenu(self, event): |
|
2635 if not self.CheckSaveBeforeClosing(): |
|
2636 return |
|
2637 self.ResetView() |
|
2638 self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU) |
|
2639 event.Skip() |
|
2640 |
|
2641 def OnSaveProjectMenu(self, event): |
|
2642 self.SaveProject() |
|
2643 event.Skip() |
|
2644 |
|
2645 def OnSaveProjectAsMenu(self, event): |
|
2646 self.SaveProjectAs() |
|
2647 event.Skip() |
|
2648 |
|
2649 def OnGenerateProgramMenu(self, event): |
|
2650 dialog = wx.FileDialog(self, _("Choose a file"), os.getcwd(), self.Controler.GetProgramFilePath(), _("ST files (*.st)|*.st|All files|*.*"), wx.SAVE|wx.CHANGE_DIR) |
|
2651 if dialog.ShowModal() == wx.ID_OK: |
|
2652 filepath = dialog.GetPath() |
|
2653 message_text = "" |
|
2654 header, icon = _("Done"), wx.ICON_INFORMATION |
|
2655 if os.path.isdir(os.path.dirname(filepath)): |
|
2656 program, errors, warnings = self.Controler.GenerateProgram(filepath) |
|
2657 message_text += "".join([_("warning: %s\n") for warning in warnings]) |
|
2658 if len(errors) > 0: |
|
2659 message_text += "".join([_("error: %s\n") for warning in warnings]) |
|
2660 message_text += _("Can't generate program to file %s!")%filepath |
|
2661 header, icon = _("Error"), wx.ICON_ERROR |
|
2662 else: |
|
2663 message_text += _("Program was successfully generated!") |
|
2664 else: |
|
2665 message_text += _("\"%s\" is not a valid folder!")%os.path.dirname(filepath) |
|
2666 header, icon = _("Error"), wx.ICON_ERROR |
|
2667 message = wx.MessageDialog(self, message_text, header, wx.OK|icon) |
|
2668 message.ShowModal() |
|
2669 message.Destroy() |
|
2670 dialog.Destroy() |
|
2671 event.Skip() |
|
2672 |
|
2673 def SaveProject(self): |
|
2674 result = self.Controler.SaveXMLFile() |
|
2675 if not result: |
|
2676 self.SaveProjectAs() |
|
2677 else: |
|
2678 self.RefreshTitle() |
|
2679 |
|
2680 def SaveProjectAs(self): |
|
2681 filepath = self.Controler.GetFilePath() |
|
2682 if filepath != "": |
|
2683 directory, filename = os.path.split(filepath) |
|
2684 else: |
|
2685 directory, filename = os.getcwd(), "%(projectName)s.xml"%self.Controler.GetProjectProperties() |
|
2686 dialog = wx.FileDialog(self, _("Choose a file"), directory, filename, _("PLCOpen files (*.xml)|*.xml|All files|*.*"), wx.SAVE|wx.OVERWRITE_PROMPT) |
|
2687 if dialog.ShowModal() == wx.ID_OK: |
|
2688 filepath = dialog.GetPath() |
|
2689 if os.path.isdir(os.path.dirname(filepath)): |
|
2690 result = self.Controler.SaveXMLFile(filepath) |
|
2691 if not result: |
|
2692 self.ShowErrorMessage(_("Can't save project to file %s!")%filepath) |
|
2693 else: |
|
2694 self.ShowErrorMessage(_("\"%s\" is not a valid folder!")%os.path.dirname(filepath)) |
|
2695 self.RefreshTitle() |
|
2696 dialog.Destroy() |
|
2697 |
|
2698 #------------------------------------------------------------------------------- |
|
2699 # Create Project Dialog |
|
2700 #------------------------------------------------------------------------------- |
|
2701 |
|
2702 [ID_SCALINGPANEL, ID_SCALINGPANELXSCALE, |
|
2703 ID_SCALINGPANELYSCALE, ID_SCALINGPANELSTATICTEXT1, |
|
2704 ID_SCALINGPANELSTATICTEXT2, |
|
2705 ] = [wx.NewId() for _init_ctrls in range(5)] |
|
2706 |
|
2707 class ScalingPanel(wx.Panel): |
|
2708 |
|
2709 def _init_coll_ScalingPanelSizer_Items(self, parent): |
|
2710 parent.AddWindow(self.staticText1, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT) |
|
2711 parent.AddWindow(self.XScale, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT) |
|
2712 parent.AddWindow(self.staticText2, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM|wx.LEFT) |
|
2713 parent.AddWindow(self.YScale, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT) |
|
2714 |
|
2715 def _init_coll_ScalingPanelSizer_Growables(self, parent): |
|
2716 parent.AddGrowableCol(1) |
|
2717 |
|
2718 def _init_sizers(self): |
|
2719 self.ScalingPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5) |
|
2720 |
|
2721 self._init_coll_ScalingPanelSizer_Items(self.ScalingPanelSizer) |
|
2722 self._init_coll_ScalingPanelSizer_Growables(self.ScalingPanelSizer) |
|
2723 |
|
2724 self.SetSizer(self.ScalingPanelSizer) |
|
2725 |
|
2726 def _init_ctrls(self, prnt): |
|
2727 wx.Panel.__init__(self, id=ID_SCALINGPANEL, |
|
2728 name='ScalingPanel', parent=prnt, pos=wx.Point(0, 0), |
|
2729 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) |
|
2730 |
|
2731 self.staticText1 = wx.StaticText(id=ID_SCALINGPANELSTATICTEXT1, |
|
2732 label=_('X Scale:'), name='staticText1', parent=self, |
|
2733 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2734 |
|
2735 self.XScale = wx.SpinCtrl(id=ID_SCALINGPANELXSCALE, |
|
2736 name='XScale', parent=self, pos=wx.Point(0, 0), |
|
2737 size=wx.Size(0, 24), style=0, min=0, max=2**16) |
|
2738 |
|
2739 self.staticText2 = wx.StaticText(id=ID_SCALINGPANELSTATICTEXT2, |
|
2740 label=_('Y Scale:'), name='staticText2', parent=self, |
|
2741 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2742 |
|
2743 self.YScale = wx.SpinCtrl(id=ID_SCALINGPANELYSCALE, |
|
2744 name='YScale', parent=self, pos=wx.Point(0, 0), |
|
2745 size=wx.Size(0, 24), style=0, min=0, max=2**16) |
|
2746 |
|
2747 self._init_sizers() |
|
2748 |
|
2749 def __init__(self, parent): |
|
2750 self._init_ctrls(parent) |
|
2751 |
|
2752 def SetScaling(self, x, y): |
|
2753 self.XScale.SetValue(x) |
|
2754 self.YScale.SetValue(y) |
|
2755 |
|
2756 def GetScaling(self): |
|
2757 return self.XScale.GetValue(), self.YScale.GetValue() |
|
2758 |
|
2759 [ID_PROJECTDIALOG, ID_PROJECTDIALOGMAINNOTEBOOK, |
|
2760 ID_PROJECTDIALOGPROJECTPANEL, ID_PROJECTDIALOGAUTHORPANEL, |
|
2761 ID_PROJECTDIALOGGRAPHICSPANEL, ID_PROJECTDIALOGMISCELLANEOUSPANEL, |
|
2762 ID_PROJECTDIALOGPROJECTNAME, ID_PROJECTDIALOGPROJECTVERSION, |
|
2763 ID_PROJECTDIALOGPRODUCTNAME, ID_PROJECTDIALOGPRODUCTVERSION, |
|
2764 ID_PROJECTDIALOGPRODUCTRELEASE, ID_PROJECTDIALOGCOMPANYNAME, |
|
2765 ID_PROJECTDIALOGCOMPANYURL, ID_PROJECTDIALOGAUTHORNAME, |
|
2766 ID_PROJECTDIALOGORGANIZATION, ID_PROJECTDIALOGLANGUAGE, |
|
2767 ID_PROJECTDIALOGCONTENTDESCRIPTION, ID_PROJECTDIALOGSCALINGNOTEBOOK, |
|
2768 ID_PROJECTDIALOGPAGEWIDTH, ID_PROJECTDIALOGPAGEHEIGHT, |
|
2769 ID_PROJECTDIALOGSTATICTEXT1, ID_PROJECTDIALOGSTATICTEXT2, |
|
2770 ID_PROJECTDIALOGSTATICTEXT3, ID_PROJECTDIALOGSTATICTEXT4, |
|
2771 ID_PROJECTDIALOGSTATICTEXT5, ID_PROJECTDIALOGSTATICTEXT6, |
|
2772 ID_PROJECTDIALOGSTATICTEXT7, ID_PROJECTDIALOGSTATICTEXT8, |
|
2773 ID_PROJECTDIALOGSTATICTEXT9, ID_PROJECTDIALOGSTATICTEXT10, |
|
2774 ID_PROJECTDIALOGSTATICTEXT11, ID_PROJECTDIALOGSTATICTEXT12, |
|
2775 ID_PROJECTDIALOGSTATICTEXT13, ID_PROJECTDIALOGSTATICTEXT14, |
|
2776 ID_PROJECTDIALOGSTATICTEXT15, |
|
2777 ] = [wx.NewId() for _init_ctrls in range(35)] |
|
2778 |
|
2779 class ProjectDialog(wx.Dialog): |
|
2780 if wx.VERSION < (2, 6, 0): |
|
2781 def Bind(self, event, function, id = None): |
|
2782 if id is not None: |
|
2783 event(self, id, function) |
|
2784 else: |
|
2785 event(self, function) |
|
2786 |
|
2787 def _init_coll_flexGridSizer1_Items(self, parent): |
|
2788 parent.AddSizer(self.MainNotebook, 0, border=0, flag=wx.GROW) |
|
2789 parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) |
|
2790 |
|
2791 def _init_coll_flexGridSizer1_Growables(self, parent): |
|
2792 parent.AddGrowableCol(0) |
|
2793 parent.AddGrowableRow(0) |
|
2794 |
|
2795 def _init_coll_ProjectPanelSizer_Items(self, parent): |
|
2796 parent.AddWindow(self.staticText1, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT) |
|
2797 parent.AddWindow(self.ProjectName, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT) |
|
2798 parent.AddWindow(self.staticText2, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) |
|
2799 parent.AddWindow(self.ProjectVersion, 0, border=10, flag=wx.GROW|wx.RIGHT) |
|
2800 parent.AddWindow(self.staticText3, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) |
|
2801 parent.AddWindow(self.ProductName, 0, border=10, flag=wx.GROW|wx.RIGHT) |
|
2802 parent.AddWindow(self.staticText4, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) |
|
2803 parent.AddWindow(self.ProductVersion, 0, border=10, flag=wx.GROW|wx.RIGHT) |
|
2804 parent.AddWindow(self.staticText5, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM|wx.LEFT) |
|
2805 parent.AddWindow(self.ProductRelease, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT) |
|
2806 |
|
2807 def _init_coll_ProjectPanelSizer_Growables(self, parent): |
|
2808 parent.AddGrowableCol(1) |
|
2809 |
|
2810 def _init_coll_AuthorPanelSizer_Items(self, parent): |
|
2811 parent.AddWindow(self.staticText6, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT) |
|
2812 parent.AddWindow(self.CompanyName, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT) |
|
2813 parent.AddWindow(self.staticText7, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) |
|
2814 parent.AddWindow(self.CompanyURL, 0, border=10, flag=wx.GROW|wx.RIGHT) |
|
2815 parent.AddWindow(self.staticText8, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) |
|
2816 parent.AddWindow(self.AuthorName, 0, border=10, flag=wx.GROW|wx.RIGHT) |
|
2817 parent.AddWindow(self.staticText9, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM|wx.LEFT) |
|
2818 parent.AddWindow(self.Organization, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT) |
|
2819 |
|
2820 def _init_coll_AuthorPanelSizer_Growables(self, parent): |
|
2821 parent.AddGrowableCol(1) |
|
2822 |
|
2823 def _init_coll_GraphicsPanelSizer_Items(self, parent): |
|
2824 parent.AddWindow(self.staticText12, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT|wx.RIGHT) |
|
2825 parent.AddSizer(self.GraphicsPageSizeSizer, 0, border=10, flag=wx.GROW|wx.LEFT|wx.RIGHT) |
|
2826 parent.AddWindow(self.staticText15, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT) |
|
2827 parent.AddWindow(self.ScalingNotebook, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT) |
|
2828 |
|
2829 def _init_coll_GraphicsPanelSizer_Growables(self, parent): |
|
2830 parent.AddGrowableCol(0) |
|
2831 parent.AddGrowableRow(3) |
|
2832 |
|
2833 def _init_coll_GraphicsPageSizeSizer_Items(self, parent): |
|
2834 parent.AddWindow(self.staticText13, 0, border=12, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) |
|
2835 parent.AddWindow(self.PageWidth, 0, border=0, flag=wx.GROW) |
|
2836 parent.AddWindow(self.staticText14, 0, border=12, flag=wx.ALIGN_CENTER_VERTICAL|wx.LEFT) |
|
2837 parent.AddWindow(self.PageHeight, 0, border=0, flag=wx.GROW) |
|
2838 |
|
2839 def _init_coll_GraphicsPageSizeSizer_Growables(self, parent): |
|
2840 parent.AddGrowableCol(1) |
|
2841 |
|
2842 def _init_coll_MiscellaneousPanelSizer_Items(self, parent): |
|
2843 parent.AddWindow(self.staticText10, 0, border=10, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP|wx.LEFT) |
|
2844 parent.AddWindow(self.Language, 0, border=10, flag=wx.GROW|wx.TOP|wx.RIGHT) |
|
2845 parent.AddWindow(self.staticText11, 0, border=10, flag=wx.BOTTOM|wx.LEFT) |
|
2846 parent.AddWindow(self.ContentDescription, 0, border=10, flag=wx.GROW|wx.BOTTOM|wx.RIGHT) |
|
2847 |
|
2848 def _init_coll_MiscellaneousPanelSizer_Growables(self, parent): |
|
2849 parent.AddGrowableCol(1) |
|
2850 parent.AddGrowableRow(1) |
|
2851 |
|
2852 def _init_sizers(self): |
|
2853 self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) |
|
2854 self.ProjectPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=5, vgap=15) |
|
2855 self.AuthorPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=4, vgap=15) |
|
2856 self.GraphicsPanelSizer = wx.FlexGridSizer(cols=1, hgap=5, rows=4, vgap=5) |
|
2857 self.GraphicsPageSizeSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=5) |
|
2858 self.MiscellaneousPanelSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=15) |
|
2859 |
|
2860 self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) |
|
2861 self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1) |
|
2862 self._init_coll_ProjectPanelSizer_Items(self.ProjectPanelSizer) |
|
2863 self._init_coll_ProjectPanelSizer_Growables(self.ProjectPanelSizer) |
|
2864 self._init_coll_AuthorPanelSizer_Items(self.AuthorPanelSizer) |
|
2865 self._init_coll_AuthorPanelSizer_Growables(self.AuthorPanelSizer) |
|
2866 self._init_coll_GraphicsPanelSizer_Items(self.GraphicsPanelSizer) |
|
2867 self._init_coll_GraphicsPanelSizer_Growables(self.GraphicsPanelSizer) |
|
2868 self._init_coll_GraphicsPageSizeSizer_Items(self.GraphicsPageSizeSizer) |
|
2869 self._init_coll_GraphicsPageSizeSizer_Growables(self.GraphicsPageSizeSizer) |
|
2870 self._init_coll_MiscellaneousPanelSizer_Items(self.MiscellaneousPanelSizer) |
|
2871 self._init_coll_MiscellaneousPanelSizer_Growables(self.MiscellaneousPanelSizer) |
|
2872 |
|
2873 self.SetSizer(self.flexGridSizer1) |
|
2874 self.ProjectPanel.SetSizer(self.ProjectPanelSizer) |
|
2875 self.AuthorPanel.SetSizer(self.AuthorPanelSizer) |
|
2876 self.GraphicsPanel.SetSizer(self.GraphicsPanelSizer) |
|
2877 self.MiscellaneousPanel.SetSizer(self.MiscellaneousPanelSizer) |
|
2878 |
|
2879 def _init_ctrls(self, prnt): |
|
2880 wx.Dialog.__init__(self, id=ID_PROJECTDIALOG, |
|
2881 name='ProjectDialog', parent=prnt, pos=wx.Point(376, 223), |
|
2882 size=wx.Size(500, 350), style=wx.DEFAULT_DIALOG_STYLE, |
|
2883 title=_('Project properties')) |
|
2884 self.SetClientSize(wx.Size(500, 350)) |
|
2885 |
|
2886 self.MainNotebook = wx.Notebook(id=ID_PROJECTDIALOGMAINNOTEBOOK, |
|
2887 name='MainNotebook', parent=self, pos=wx.Point(0, |
|
2888 0), size=wx.Size(0, 0), style=0) |
|
2889 |
|
2890 # Project Panel elements |
|
2891 |
|
2892 self.ProjectPanel = wx.Panel(id=ID_PROJECTDIALOGPROJECTPANEL, |
|
2893 name='ProjectPanel', parent=self.MainNotebook, pos=wx.Point(0, 0), |
|
2894 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) |
|
2895 |
|
2896 self.staticText1 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT1, |
|
2897 label=_('Project Name (required):'), name='staticText1', parent=self.ProjectPanel, |
|
2898 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2899 |
|
2900 self.ProjectName = wx.TextCtrl(id=ID_PROJECTDIALOGPROJECTNAME, |
|
2901 name='ProjectName', parent=self.ProjectPanel, pos=wx.Point(0, 0), |
|
2902 size=wx.Size(0, 24), style=0) |
|
2903 |
|
2904 self.staticText2 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT2, |
|
2905 label=_('Project Version (optional):'), name='staticText2', parent=self.ProjectPanel, |
|
2906 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2907 |
|
2908 self.ProjectVersion = wx.TextCtrl(id=ID_PROJECTDIALOGPROJECTVERSION, |
|
2909 name='ProjectVersion', parent=self.ProjectPanel, pos=wx.Point(0, 0), |
|
2910 size=wx.Size(0, 24), style=0) |
|
2911 |
|
2912 self.staticText3 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT3, |
|
2913 label=_('Product Name (required):'), name='staticText3', parent=self.ProjectPanel, |
|
2914 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2915 |
|
2916 self.ProductName = wx.TextCtrl(id=ID_PROJECTDIALOGPRODUCTNAME, |
|
2917 name='ProductName', parent=self.ProjectPanel, pos=wx.Point(0, 0), |
|
2918 size=wx.Size(0, 24), style=0) |
|
2919 |
|
2920 self.staticText4 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT4, |
|
2921 label=_('Product Version (required):'), name='staticText4', parent=self.ProjectPanel, |
|
2922 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2923 |
|
2924 self.ProductVersion = wx.TextCtrl(id=ID_PROJECTDIALOGPRODUCTVERSION, |
|
2925 name='ProductVersion', parent=self.ProjectPanel, pos=wx.Point(0, 0), |
|
2926 size=wx.Size(0, 24), style=0) |
|
2927 |
|
2928 self.staticText5 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT5, |
|
2929 label=_('Product Release (optional):'), name='staticText5', parent=self.ProjectPanel, |
|
2930 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2931 |
|
2932 self.ProductRelease = wx.TextCtrl(id=ID_PROJECTDIALOGPRODUCTRELEASE, |
|
2933 name='ProductRelease', parent=self.ProjectPanel, pos=wx.Point(0, 0), |
|
2934 size=wx.Size(0, 24), style=0) |
|
2935 |
|
2936 self.MainNotebook.AddPage(self.ProjectPanel, _("Project")) |
|
2937 |
|
2938 # Author Panel elements |
|
2939 |
|
2940 self.AuthorPanel = wx.Panel(id=ID_PROJECTDIALOGAUTHORPANEL, |
|
2941 name='AuthorPanel', parent=self.MainNotebook, pos=wx.Point(0, 0), |
|
2942 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) |
|
2943 |
|
2944 self.staticText6 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT6, |
|
2945 label=_('Company Name (required):'), name='staticText6', parent=self.AuthorPanel, |
|
2946 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2947 |
|
2948 self.CompanyName = wx.TextCtrl(id=ID_PROJECTDIALOGCOMPANYNAME, |
|
2949 name='CompanyName', parent=self.AuthorPanel, pos=wx.Point(0, 0), |
|
2950 size=wx.Size(0, 24), style=0) |
|
2951 |
|
2952 self.staticText7 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT7, |
|
2953 label=_('Company URL (optional):'), name='staticText7', parent=self.AuthorPanel, |
|
2954 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2955 |
|
2956 self.CompanyURL = wx.TextCtrl(id=ID_PROJECTDIALOGCOMPANYURL, |
|
2957 name='CompanyURL', parent=self.AuthorPanel, pos=wx.Point(0, 0), |
|
2958 size=wx.Size(0, 24), style=0) |
|
2959 |
|
2960 self.staticText8 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT8, |
|
2961 label=_('Author Name (optional):'), name='staticText8', parent=self.AuthorPanel, |
|
2962 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2963 |
|
2964 self.AuthorName = wx.TextCtrl(id=ID_PROJECTDIALOGAUTHORNAME, |
|
2965 name='AuthorName', parent=self.AuthorPanel, pos=wx.Point(0, 0), |
|
2966 size=wx.Size(0, 24), style=0) |
|
2967 |
|
2968 self.staticText9 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT9, |
|
2969 label=_('Organization (optional):'), name='staticText9', parent=self.AuthorPanel, |
|
2970 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2971 |
|
2972 self.Organization = wx.TextCtrl(id=ID_PROJECTDIALOGORGANIZATION, |
|
2973 name='Organization', parent=self.AuthorPanel, pos=wx.Point(0, 0), |
|
2974 size=wx.Size(0, 24), style=0) |
|
2975 |
|
2976 self.MainNotebook.AddPage(self.AuthorPanel, _("Author")) |
|
2977 |
|
2978 # Graphics Panel elements |
|
2979 |
|
2980 self.GraphicsPanel = wx.Panel(id=ID_PROJECTDIALOGGRAPHICSPANEL, |
|
2981 name='GraphicsPanel', parent=self.MainNotebook, pos=wx.Point(0, 0), |
|
2982 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) |
|
2983 |
|
2984 self.staticText12 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT12, |
|
2985 label=_('Page Size (optional):'), name='staticText12', parent=self.GraphicsPanel, |
|
2986 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2987 |
|
2988 self.staticText13 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT13, |
|
2989 label=_('Width:'), name='staticText13', parent=self.GraphicsPanel, |
|
2990 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2991 |
|
2992 self.PageWidth = wx.SpinCtrl(id=ID_PROJECTDIALOGPAGEWIDTH, |
|
2993 name='PageWidth', parent=self.GraphicsPanel, pos=wx.Point(0, 0), |
|
2994 size=wx.Size(0, 24), style=0, min=0, max=2**16) |
|
2995 |
|
2996 self.staticText14 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT14, |
|
2997 label=_('Height:'), name='staticText14', parent=self.GraphicsPanel, |
|
2998 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
2999 |
|
3000 self.PageHeight = wx.SpinCtrl(id=ID_PROJECTDIALOGPAGEHEIGHT, |
|
3001 name='PageHeight', parent=self.GraphicsPanel, pos=wx.Point(0, 0), |
|
3002 size=wx.Size(0, 24), style=0, min=0, max=2**16) |
|
3003 |
|
3004 self.staticText15 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT15, |
|
3005 label=_('Scaling:'), name='staticText15', parent=self.GraphicsPanel, |
|
3006 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
3007 |
|
3008 self.ScalingNotebook = wx.Notebook(id=ID_PROJECTDIALOGSCALINGNOTEBOOK, |
|
3009 name='ScalingNotebook', parent=self.GraphicsPanel, pos=wx.Point(0, |
|
3010 0), size=wx.Size(0, 0), style=0) |
|
3011 |
|
3012 self.Scalings = {} |
|
3013 for language, translation in [("FBD",_("FBD")), ("LD",_("LD")), ("SFC",_("SFC"))]: |
|
3014 window = ScalingPanel(self.ScalingNotebook) |
|
3015 self.Scalings[language] = window |
|
3016 self.ScalingNotebook.AddPage(window, translation) |
|
3017 |
|
3018 self.MainNotebook.AddPage(self.GraphicsPanel, _("Graphics")) |
|
3019 |
|
3020 # Miscellaneous Panel elements |
|
3021 |
|
3022 self.MiscellaneousPanel = wx.Panel(id=ID_PROJECTDIALOGMISCELLANEOUSPANEL, |
|
3023 name='MiscellaneousPanel', parent=self.MainNotebook, pos=wx.Point(0, 0), |
|
3024 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) |
|
3025 |
|
3026 self.staticText10 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT10, |
|
3027 label=_('Language (optional):'), name='staticText10', parent=self.MiscellaneousPanel, |
|
3028 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
3029 |
|
3030 self.Language = wx.ComboBox(id=ID_PROJECTDIALOGLANGUAGE, |
|
3031 name='Language', parent=self.MiscellaneousPanel, pos=wx.Point(0, 0), |
|
3032 size=wx.Size(0, 28), style=wx.CB_READONLY) |
|
3033 |
|
3034 self.staticText11 = wx.StaticText(id=ID_PROJECTDIALOGSTATICTEXT11, |
|
3035 label=_('Content Description (optional):'), name='staticText11', parent=self.MiscellaneousPanel, |
|
3036 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
3037 |
|
3038 self.ContentDescription = wx.TextCtrl(id=ID_PROJECTDIALOGCONTENTDESCRIPTION, |
|
3039 name='ContentDescription', parent=self.MiscellaneousPanel, pos=wx.Point(0, 0), |
|
3040 size=wx.Size(0, 24), style=wx.TE_MULTILINE) |
|
3041 |
|
3042 self.MainNotebook.AddPage(self.MiscellaneousPanel, _("Miscellaneous")) |
|
3043 |
|
3044 self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) |
|
3045 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId()) |
|
3046 |
|
3047 self._init_sizers() |
|
3048 |
|
3049 def __init__(self, parent): |
|
3050 self._init_ctrls(parent) |
|
3051 |
|
3052 languages = ["", "en-US", "fr-FR", "zh-CN"] |
|
3053 |
|
3054 for language in languages: |
|
3055 self.Language.Append(language) |
|
3056 |
|
3057 def OnOK(self, event): |
|
3058 error = [] |
|
3059 if self.ProjectName.GetValue() == "": |
|
3060 error.append("Project Name") |
|
3061 if self.CompanyName.GetValue() == "": |
|
3062 error.append("Company Name") |
|
3063 if self.ProductName.GetValue() == "": |
|
3064 error.append("Product Name") |
|
3065 if self.ProductVersion.GetValue() == "": |
|
3066 error.append("Product Version") |
|
3067 if len(error) > 0: |
|
3068 text = "" |
|
3069 for i, item in enumerate(error): |
|
3070 if i == 0: |
|
3071 text += item |
|
3072 elif i == len(error) - 1: |
|
3073 text += " and %s"%item |
|
3074 else: |
|
3075 text += ", %s"%item |
|
3076 message = wx.MessageDialog(self, _("Form isn't complete. %s must be filled!")%text, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3077 message.ShowModal() |
|
3078 message.Destroy() |
|
3079 else: |
|
3080 self.EndModal(wx.ID_OK) |
|
3081 |
|
3082 def SetValues(self, values): |
|
3083 for item, value in values.items(): |
|
3084 if item == "projectName": |
|
3085 self.ProjectName.SetValue(value) |
|
3086 elif item == "projectVersion": |
|
3087 self.ProjectVersion.SetValue(value) |
|
3088 elif item == "productName": |
|
3089 self.ProductName.SetValue(value) |
|
3090 elif item == "productVersion": |
|
3091 self.ProductVersion.SetValue(value) |
|
3092 elif item == "productRelease": |
|
3093 self.ProductRelease.SetValue(value) |
|
3094 elif item == "companyName": |
|
3095 self.CompanyName.SetValue(value) |
|
3096 elif item == "companyURL": |
|
3097 self.CompanyURL.SetValue(value) |
|
3098 elif item == "authorName": |
|
3099 self.AuthorName.SetValue(value) |
|
3100 elif item == "organization": |
|
3101 self.Organization.SetValue(value) |
|
3102 elif item == "language": |
|
3103 self.Language.SetStringSelection(value) |
|
3104 elif item == "contentDescription": |
|
3105 self.ContentDescription.SetValue(value) |
|
3106 elif item == "pageSize": |
|
3107 self.PageWidth.SetValue(value[0]) |
|
3108 self.PageHeight.SetValue(value[1]) |
|
3109 elif item == "scaling": |
|
3110 for language, (x, y) in value.items(): |
|
3111 if language in self.Scalings: |
|
3112 self.Scalings[language].SetScaling(x, y) |
|
3113 |
|
3114 def GetValues(self): |
|
3115 values = {} |
|
3116 values["projectName"] = self.ProjectName.GetValue() |
|
3117 if self.ProjectVersion.GetValue() != "": |
|
3118 values["projectVersion"] = self.ProjectVersion.GetValue() |
|
3119 values["productName"] = self.ProductName.GetValue() |
|
3120 values["productVersion"] = self.ProductVersion.GetValue() |
|
3121 if self.ProductRelease.GetValue() != "": |
|
3122 values["productRelease"] = self.ProductRelease.GetValue() |
|
3123 values["companyName"] = self.CompanyName.GetValue() |
|
3124 if self.CompanyURL.GetValue() != "": |
|
3125 values["companyURL"] = self.CompanyURL.GetValue() |
|
3126 if self.AuthorName.GetValue() != "": |
|
3127 values["authorName"] = self.AuthorName.GetValue() |
|
3128 if self.Organization.GetValue() != "": |
|
3129 values["organization"] = self.Organization.GetValue() |
|
3130 if self.Language.GetStringSelection() != "": |
|
3131 values["language"] = self.Language.GetStringSelection() |
|
3132 if self.ProductRelease.GetValue() != "": |
|
3133 values["contentDescription"] = self.ContentDescription.GetValue() |
|
3134 values["pageSize"] = (self.PageWidth.GetValue(), self.PageHeight.GetValue()) |
|
3135 values["scaling"] = {} |
|
3136 for language in ["FBD", "LD", "SFC"]: |
|
3137 values["scaling"][language] = self.Scalings[language].GetScaling() |
|
3138 return values |
|
3139 |
|
3140 #------------------------------------------------------------------------------- |
|
3141 # Edit Step Name Dialog |
|
3142 #------------------------------------------------------------------------------- |
|
3143 |
|
3144 class DataTypeDialog(wx.TextEntryDialog): |
|
3145 |
|
3146 if wx.VERSION < (2, 6, 0): |
|
3147 def Bind(self, event, function, id = None): |
|
3148 if id is not None: |
|
3149 event(self, id, function) |
|
3150 else: |
|
3151 event(self, function) |
|
3152 |
|
3153 def __init__(self, parent, message, caption = _("Please enter text"), defaultValue = "", |
|
3154 style = wx.OK|wx.CANCEL|wx.CENTRE, pos = wx.DefaultPosition): |
|
3155 wx.TextEntryDialog.__init__(self, parent, message, caption, defaultValue, style, pos) |
|
3156 |
|
3157 self.DataTypeNames = [] |
|
3158 if wx.VERSION >= (2, 8, 0): |
|
3159 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(2).GetSizer().GetItem(1).GetSizer().GetAffirmativeButton().GetId()) |
|
3160 elif wx.VERSION >= (2, 6, 0): |
|
3161 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetAffirmativeButton().GetId()) |
|
3162 else: |
|
3163 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetChildren()[0].GetSizer().GetChildren()[0].GetWindow().GetId()) |
|
3164 |
|
3165 def OnOK(self, event): |
|
3166 datatype_name = self.GetSizer().GetItem(1).GetWindow().GetValue() |
|
3167 if datatype_name == "": |
|
3168 message = wx.MessageDialog(self, _("You must type a name!"), _("Error"), wx.OK|wx.ICON_ERROR) |
|
3169 message.ShowModal() |
|
3170 message.Destroy() |
|
3171 elif not TestIdentifier(datatype_name): |
|
3172 message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%datatype_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3173 message.ShowModal() |
|
3174 message.Destroy() |
|
3175 elif datatype_name.upper() in IEC_KEYWORDS: |
|
3176 message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%datatype_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3177 message.ShowModal() |
|
3178 message.Destroy() |
|
3179 elif datatype_name.upper() in self.DataTypeNames: |
|
3180 message = wx.MessageDialog(self, _("\"%s\" data type already exists!")%datatype_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3181 message.ShowModal() |
|
3182 message.Destroy() |
|
3183 else: |
|
3184 self.EndModal(wx.ID_OK) |
|
3185 |
|
3186 def SetDataTypeNames(self, datatype_names): |
|
3187 self.DataTypeNames = [datatype_name.upper() for datatype_name in datatype_names] |
|
3188 |
|
3189 def GetValue(self): |
|
3190 return self.GetSizer().GetItem(1).GetWindow().GetValue() |
|
3191 |
|
3192 #------------------------------------------------------------------------------- |
|
3193 # Create Pou Dialog |
|
3194 #------------------------------------------------------------------------------- |
|
3195 |
|
3196 [ID_POUDIALOG, ID_POUDIALOGPOUNAME, |
|
3197 ID_POUDIALOGPOUTYPE, ID_POUDIALOGLANGUAGE, ID_POUDIALOGSTATICTEXT1, |
|
3198 ID_POUDIALOGSTATICTEXT2, ID_POUDIALOGSTATICTEXT3, |
|
3199 ] = [wx.NewId() for _init_ctrls in range(7)] |
|
3200 |
|
3201 def GetTransitionLanguages(): |
|
3202 _ = lambda x : x |
|
3203 return [_("IL"), _("ST"), _("LD"), _("FBD")] |
|
3204 TRANSITION_LANGUAGES_DICT = dict([(_(language), language) for language in GetTransitionLanguages()]) |
|
3205 |
|
3206 def GetPouTypes(): |
|
3207 _ = lambda x : x |
|
3208 return [_("function"), _("functionBlock"), _("program")] |
|
3209 POU_TYPES_DICT = dict([(_(pou_type), pou_type) for pou_type in GetPouTypes()]) |
|
3210 |
|
3211 def GetPouLanguages(): |
|
3212 _ = lambda x : x |
|
3213 return [_("IL"), _("ST"), _("LD"), _("FBD"), _("SFC")] |
|
3214 POU_LANGUAGES_DICT = dict([(_(language), language) for language in GetPouLanguages()]) |
|
3215 |
|
3216 class PouDialog(wx.Dialog): |
|
3217 if wx.VERSION < (2, 6, 0): |
|
3218 def Bind(self, event, function, id = None): |
|
3219 if id is not None: |
|
3220 event(self, id, function) |
|
3221 else: |
|
3222 event(self, function) |
|
3223 |
|
3224 def _init_coll_flexGridSizer1_Items(self, parent): |
|
3225 parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) |
|
3226 parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) |
|
3227 |
|
3228 def _init_coll_flexGridSizer1_Growables(self, parent): |
|
3229 parent.AddGrowableCol(0) |
|
3230 parent.AddGrowableRow(0) |
|
3231 |
|
3232 def _init_coll_MainSizer_Items(self, parent): |
|
3233 parent.AddWindow(self.staticText1, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) |
|
3234 parent.AddWindow(self.PouName, 0, border=0, flag=wx.GROW) |
|
3235 parent.AddWindow(self.staticText2, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) |
|
3236 parent.AddWindow(self.PouType, 0, border=0, flag=wx.GROW) |
|
3237 parent.AddWindow(self.staticText3, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) |
|
3238 parent.AddWindow(self.Language, 0, border=0, flag=wx.GROW) |
|
3239 |
|
3240 def _init_coll_MainSizer_Growables(self, parent): |
|
3241 parent.AddGrowableCol(1) |
|
3242 |
|
3243 def _init_sizers(self): |
|
3244 self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) |
|
3245 self.MainSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=3, vgap=15) |
|
3246 |
|
3247 self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) |
|
3248 self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1) |
|
3249 self._init_coll_MainSizer_Items(self.MainSizer) |
|
3250 self._init_coll_MainSizer_Growables(self.MainSizer) |
|
3251 |
|
3252 self.SetSizer(self.flexGridSizer1) |
|
3253 |
|
3254 def _init_ctrls(self, prnt): |
|
3255 wx.Dialog.__init__(self, id=ID_POUDIALOG, |
|
3256 name='PouDialog', parent=prnt, pos=wx.Point(376, 223), |
|
3257 size=wx.Size(300, 200), style=wx.DEFAULT_DIALOG_STYLE, |
|
3258 title=_('Create a new POU')) |
|
3259 self.SetClientSize(wx.Size(300, 200)) |
|
3260 |
|
3261 self.staticText1 = wx.StaticText(id=ID_POUDIALOGSTATICTEXT1, |
|
3262 label=_('POU Name:'), name='staticText1', parent=self, |
|
3263 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
3264 |
|
3265 self.PouName = wx.TextCtrl(id=ID_POUDIALOGPOUNAME, |
|
3266 name='POUName', parent=self, pos=wx.Point(0, 0), |
|
3267 size=wx.Size(0, 24), style=0) |
|
3268 |
|
3269 self.staticText2 = wx.StaticText(id=ID_POUDIALOGSTATICTEXT2, |
|
3270 label=_('POU Type:'), name='staticText2', parent=self, |
|
3271 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
3272 |
|
3273 self.PouType = wx.ComboBox(id=ID_POUDIALOGPOUTYPE, |
|
3274 name='POUType', parent=self, pos=wx.Point(0, 0), |
|
3275 size=wx.Size(0, 28), style=wx.CB_READONLY) |
|
3276 self.Bind(wx.EVT_COMBOBOX, self.OnTypeChanged, id=ID_POUDIALOGPOUTYPE) |
|
3277 |
|
3278 self.staticText3 = wx.StaticText(id=ID_POUDIALOGSTATICTEXT3, |
|
3279 label=_('Language:'), name='staticText3', parent=self, |
|
3280 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
3281 |
|
3282 self.Language = wx.ComboBox(id=ID_POUDIALOGLANGUAGE, |
|
3283 name='Language', parent=self, pos=wx.Point(0, 0), |
|
3284 size=wx.Size(0, 28), style=wx.CB_READONLY) |
|
3285 |
|
3286 self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) |
|
3287 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId()) |
|
3288 |
|
3289 self._init_sizers() |
|
3290 |
|
3291 def __init__(self, parent, pou_type = None): |
|
3292 self._init_ctrls(parent) |
|
3293 |
|
3294 for option in GetPouTypes(): |
|
3295 self.PouType.Append(_(option)) |
|
3296 if pou_type is not None: |
|
3297 self.PouType.SetStringSelection(_(pou_type)) |
|
3298 self.RefreshLanguage() |
|
3299 |
|
3300 self.PouNames = [] |
|
3301 self.PouElementNames = [] |
|
3302 |
|
3303 def OnOK(self, event): |
|
3304 error = [] |
|
3305 pou_name = self.PouName.GetValue() |
|
3306 if pou_name == "": |
|
3307 error.append(_("POU Name")) |
|
3308 if self.PouType.GetSelection() == -1: |
|
3309 error.append(_("POU Type")) |
|
3310 if self.Language.GetSelection() == -1: |
|
3311 error.append(_("Language")) |
|
3312 if len(error) > 0: |
|
3313 text = "" |
|
3314 for i, item in enumerate(error): |
|
3315 if i == 0: |
|
3316 text += item |
|
3317 elif i == len(error) - 1: |
|
3318 text += _(" and %s")%item |
|
3319 else: |
|
3320 text += _(", %s")%item |
|
3321 message = wx.MessageDialog(self, _("Form isn't complete. %s must be filled!")%text, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3322 message.ShowModal() |
|
3323 message.Destroy() |
|
3324 elif not TestIdentifier(pou_name): |
|
3325 message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%pou_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3326 message.ShowModal() |
|
3327 message.Destroy() |
|
3328 elif pou_name.upper() in IEC_KEYWORDS: |
|
3329 message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%pou_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3330 message.ShowModal() |
|
3331 message.Destroy() |
|
3332 elif pou_name.upper() in self.PouNames: |
|
3333 message = wx.MessageDialog(self, _("\"%s\" pou already exists!")%pou_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3334 message.ShowModal() |
|
3335 message.Destroy() |
|
3336 elif pou_name.upper() in self.PouElementNames: |
|
3337 message = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%pou_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION) |
|
3338 result = message.ShowModal() |
|
3339 message.Destroy() |
|
3340 if result == wx.ID_YES: |
|
3341 self.EndModal(wx.ID_OK) |
|
3342 else: |
|
3343 self.EndModal(wx.ID_OK) |
|
3344 |
|
3345 def RefreshLanguage(self): |
|
3346 selection = POU_LANGUAGES_DICT.get(self.Language.GetStringSelection(), "") |
|
3347 self.Language.Clear() |
|
3348 for language in GetPouLanguages(): |
|
3349 if language != "SFC" or POU_TYPES_DICT[self.PouType.GetStringSelection()] != "function": |
|
3350 self.Language.Append(language) |
|
3351 if self.Language.FindString(_(selection)) != wx.NOT_FOUND: |
|
3352 self.Language.SetStringSelection(_(selection)) |
|
3353 |
|
3354 def OnTypeChanged(self, event): |
|
3355 self.RefreshLanguage() |
|
3356 event.Skip() |
|
3357 |
|
3358 def SetPouNames(self, pou_names): |
|
3359 self.PouNames = [pou_name.upper() for pou_name in pou_names] |
|
3360 |
|
3361 def SetPouElementNames(self, element_names): |
|
3362 self.PouElementNames = [element_name.upper() for element_name in element_names] |
|
3363 |
|
3364 def SetValues(self, values): |
|
3365 for item, value in values.items(): |
|
3366 if item == "pouName": |
|
3367 self.PouName.SetValue(value) |
|
3368 elif item == "pouType": |
|
3369 self.PouType.SetStringSelection(_(value)) |
|
3370 elif item == "language": |
|
3371 self.Language.SetStringSelection(_(POU_LANGUAGES_DICT)) |
|
3372 |
|
3373 def GetValues(self): |
|
3374 values = {} |
|
3375 values["pouName"] = self.PouName.GetValue() |
|
3376 values["pouType"] = POU_TYPES_DICT[self.PouType.GetStringSelection()] |
|
3377 values["language"] = POU_LANGUAGES_DICT[self.Language.GetStringSelection()] |
|
3378 return values |
|
3379 |
|
3380 |
|
3381 #------------------------------------------------------------------------------- |
|
3382 # Create Pou Transition Dialog |
|
3383 #------------------------------------------------------------------------------- |
|
3384 |
|
3385 [ID_POUTRANSITIONDIALOG, ID_POUTRANSITIONDIALOGTRANSITIONNAME, |
|
3386 ID_POUTRANSITIONDIALOGLANGUAGE, ID_POUTRANSITIONDIALOGSTATICTEXT1, |
|
3387 ID_POUTRANSITIONDIALOGSTATICTEXT2, |
|
3388 ] = [wx.NewId() for _init_ctrls in range(5)] |
|
3389 |
|
3390 def GetTransitionLanguages(): |
|
3391 _ = lambda x : x |
|
3392 return [_("IL"), _("ST"), _("LD"), _("FBD")] |
|
3393 TRANSITION_LANGUAGES_DICT = dict([(_(language), language) for language in GetTransitionLanguages()]) |
|
3394 |
|
3395 class PouTransitionDialog(wx.Dialog): |
|
3396 if wx.VERSION < (2, 6, 0): |
|
3397 def Bind(self, event, function, id = None): |
|
3398 if id is not None: |
|
3399 event(self, id, function) |
|
3400 else: |
|
3401 event(self, function) |
|
3402 |
|
3403 def _init_coll_flexGridSizer1_Items(self, parent): |
|
3404 parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) |
|
3405 parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) |
|
3406 |
|
3407 def _init_coll_flexGridSizer1_Growables(self, parent): |
|
3408 parent.AddGrowableCol(0) |
|
3409 parent.AddGrowableRow(0) |
|
3410 |
|
3411 def _init_coll_MainSizer_Items(self, parent): |
|
3412 parent.AddWindow(self.staticText1, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) |
|
3413 parent.AddWindow(self.TransitionName, 0, border=0, flag=wx.GROW) |
|
3414 parent.AddWindow(self.staticText2, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) |
|
3415 parent.AddWindow(self.Language, 0, border=0, flag=wx.GROW) |
|
3416 |
|
3417 def _init_coll_MainSizer_Growables(self, parent): |
|
3418 parent.AddGrowableCol(1) |
|
3419 |
|
3420 def _init_sizers(self): |
|
3421 self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) |
|
3422 self.MainSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=15) |
|
3423 |
|
3424 self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) |
|
3425 self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1) |
|
3426 self._init_coll_MainSizer_Items(self.MainSizer) |
|
3427 self._init_coll_MainSizer_Growables(self.MainSizer) |
|
3428 |
|
3429 self.SetSizer(self.flexGridSizer1) |
|
3430 |
|
3431 def _init_ctrls(self, prnt): |
|
3432 wx.Dialog.__init__(self, id=ID_POUTRANSITIONDIALOG, |
|
3433 name='PouTransitionDialog', parent=prnt, pos=wx.Point(376, 223), |
|
3434 size=wx.Size(350, 200), style=wx.DEFAULT_DIALOG_STYLE, |
|
3435 title=_('Create a new transition')) |
|
3436 self.SetClientSize(wx.Size(350, 160)) |
|
3437 |
|
3438 self.staticText1 = wx.StaticText(id=ID_POUTRANSITIONDIALOGSTATICTEXT1, |
|
3439 label=_('Transition Name:'), name='staticText1', parent=self, |
|
3440 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
3441 |
|
3442 self.TransitionName = wx.TextCtrl(id=ID_POUTRANSITIONDIALOGTRANSITIONNAME, |
|
3443 name='TransitionName', parent=self, pos=wx.Point(0, 0), |
|
3444 size=wx.Size(0, 24), style=0) |
|
3445 |
|
3446 self.staticText2 = wx.StaticText(id=ID_POUTRANSITIONDIALOGSTATICTEXT2, |
|
3447 label=_('Language:'), name='staticText2', parent=self, |
|
3448 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
3449 |
|
3450 self.Language = wx.ComboBox(id=ID_POUTRANSITIONDIALOGLANGUAGE, |
|
3451 name='Language', parent=self, pos=wx.Point(0, 0), |
|
3452 size=wx.Size(0, 28), style=wx.CB_READONLY) |
|
3453 |
|
3454 self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) |
|
3455 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId()) |
|
3456 |
|
3457 self._init_sizers() |
|
3458 |
|
3459 def __init__(self, parent): |
|
3460 self._init_ctrls(parent) |
|
3461 |
|
3462 for language in GetTransitionLanguages(): |
|
3463 self.Language.Append(_(language)) |
|
3464 |
|
3465 self.PouNames = [] |
|
3466 self.PouElementNames = [] |
|
3467 |
|
3468 def OnOK(self, event): |
|
3469 error = [] |
|
3470 transition_name = self.TransitionName.GetValue() |
|
3471 if self.TransitionName.GetValue() == "": |
|
3472 error.append(_("Transition Name")) |
|
3473 if self.Language.GetSelection() == -1: |
|
3474 error.append(_("Language")) |
|
3475 if len(error) > 0: |
|
3476 text = "" |
|
3477 for i, item in enumerate(error): |
|
3478 if i == 0: |
|
3479 text += item |
|
3480 elif i == len(error) - 1: |
|
3481 text += _(" and %s")%item |
|
3482 else: |
|
3483 text += _(", %s")%item |
|
3484 message = wx.MessageDialog(self, _("Form isn't complete. %s must be filled!")%text, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3485 message.ShowModal() |
|
3486 message.Destroy() |
|
3487 elif not TestIdentifier(transition_name): |
|
3488 message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3489 message.ShowModal() |
|
3490 message.Destroy() |
|
3491 elif transition_name.upper() in IEC_KEYWORDS: |
|
3492 message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3493 message.ShowModal() |
|
3494 message.Destroy() |
|
3495 elif transition_name.upper() in self.PouNames: |
|
3496 message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3497 message.ShowModal() |
|
3498 message.Destroy() |
|
3499 elif transition_name.upper() in self.PouElementNames: |
|
3500 message = wx.MessageDialog(self, _("\"%s\" element for this pou already exists!")%transition_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3501 message.ShowModal() |
|
3502 message.Destroy() |
|
3503 else: |
|
3504 self.EndModal(wx.ID_OK) |
|
3505 |
|
3506 def SetPouNames(self, pou_names): |
|
3507 self.PouNames = [pou_name.upper() for pou_name in pou_names] |
|
3508 |
|
3509 def SetPouElementNames(self, pou_names): |
|
3510 self.PouElementNames = [pou_name.upper() for pou_name in pou_names] |
|
3511 |
|
3512 def SetValues(self, values): |
|
3513 for item, value in values.items(): |
|
3514 if item == "transitionName": |
|
3515 self.TransitionName.SetValue(value) |
|
3516 elif item == "language": |
|
3517 self.Language.SetSelection(_(value)) |
|
3518 |
|
3519 def GetValues(self): |
|
3520 values = {} |
|
3521 values["transitionName"] = self.TransitionName.GetValue() |
|
3522 values["language"] = TRANSITION_LANGUAGES_DICT[self.Language.GetStringSelection()] |
|
3523 return values |
|
3524 |
|
3525 #------------------------------------------------------------------------------- |
|
3526 # Create Pou Action Dialog |
|
3527 #------------------------------------------------------------------------------- |
|
3528 |
|
3529 [ID_POUACTIONDIALOG, ID_POUACTIONDIALOGACTIONNAME, |
|
3530 ID_POUACTIONDIALOGLANGUAGE, ID_POUACTIONDIALOGSTATICTEXT1, |
|
3531 ID_POUACTIONDIALOGSTATICTEXT2, |
|
3532 ] = [wx.NewId() for _init_ctrls in range(5)] |
|
3533 |
|
3534 def GetActionLanguages(): |
|
3535 _ = lambda x : x |
|
3536 return [_("IL"), _("ST"), _("LD"), _("FBD")] |
|
3537 ACTION_LANGUAGES_DICT = dict([(_(language), language) for language in GetActionLanguages()]) |
|
3538 |
|
3539 class PouActionDialog(wx.Dialog): |
|
3540 if wx.VERSION < (2, 6, 0): |
|
3541 def Bind(self, event, function, id = None): |
|
3542 if id is not None: |
|
3543 event(self, id, function) |
|
3544 else: |
|
3545 event(self, function) |
|
3546 |
|
3547 def _init_coll_flexGridSizer1_Items(self, parent): |
|
3548 parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) |
|
3549 parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) |
|
3550 |
|
3551 def _init_coll_flexGridSizer1_Growables(self, parent): |
|
3552 parent.AddGrowableCol(0) |
|
3553 parent.AddGrowableRow(0) |
|
3554 |
|
3555 def _init_coll_MainSizer_Items(self, parent): |
|
3556 parent.AddWindow(self.staticText1, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) |
|
3557 parent.AddWindow(self.ActionName, 0, border=0, flag=wx.GROW) |
|
3558 parent.AddWindow(self.staticText2, 0, border=4, flag=wx.ALIGN_CENTER_VERTICAL|wx.TOP) |
|
3559 parent.AddWindow(self.Language, 0, border=0, flag=wx.GROW) |
|
3560 |
|
3561 def _init_coll_MainSizer_Growables(self, parent): |
|
3562 parent.AddGrowableCol(1) |
|
3563 |
|
3564 def _init_sizers(self): |
|
3565 self.flexGridSizer1 = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10) |
|
3566 self.MainSizer = wx.FlexGridSizer(cols=2, hgap=5, rows=2, vgap=15) |
|
3567 |
|
3568 self._init_coll_flexGridSizer1_Items(self.flexGridSizer1) |
|
3569 self._init_coll_flexGridSizer1_Growables(self.flexGridSizer1) |
|
3570 self._init_coll_MainSizer_Items(self.MainSizer) |
|
3571 self._init_coll_MainSizer_Growables(self.MainSizer) |
|
3572 |
|
3573 self.SetSizer(self.flexGridSizer1) |
|
3574 |
|
3575 def _init_ctrls(self, prnt): |
|
3576 wx.Dialog.__init__(self, id=ID_POUACTIONDIALOG, |
|
3577 name='PouActionDialog', parent=prnt, pos=wx.Point(376, 223), |
|
3578 size=wx.Size(320, 200), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER, |
|
3579 title=_('Create a new action')) |
|
3580 self.SetClientSize(wx.Size(320, 160)) |
|
3581 |
|
3582 self.staticText1 = wx.StaticText(id=ID_POUACTIONDIALOGSTATICTEXT1, |
|
3583 label=_('Action Name:'), name='staticText1', parent=self, |
|
3584 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
3585 |
|
3586 self.ActionName = wx.TextCtrl(id=ID_POUACTIONDIALOGACTIONNAME, |
|
3587 name='ActionName', parent=self, pos=wx.Point(0, 0), |
|
3588 size=wx.Size(0, 24), style=0) |
|
3589 |
|
3590 self.staticText2 = wx.StaticText(id=ID_POUACTIONDIALOGSTATICTEXT2, |
|
3591 label=_('Language:'), name='staticText2', parent=self, |
|
3592 pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) |
|
3593 |
|
3594 self.Language = wx.ComboBox(id=ID_POUACTIONDIALOGLANGUAGE, |
|
3595 name='Language', parent=self, pos=wx.Point(0, 0), |
|
3596 size=wx.Size(0, 28), style=wx.CB_READONLY) |
|
3597 |
|
3598 self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) |
|
3599 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.ButtonSizer.GetAffirmativeButton().GetId()) |
|
3600 |
|
3601 self._init_sizers() |
|
3602 |
|
3603 def __init__(self, parent): |
|
3604 self._init_ctrls(parent) |
|
3605 |
|
3606 for option in GetActionLanguages(): |
|
3607 self.Language.Append(_(option)) |
|
3608 |
|
3609 self.PouNames = [] |
|
3610 self.PouElementNames = [] |
|
3611 |
|
3612 def OnOK(self, event): |
|
3613 error = [] |
|
3614 action_name = self.ActionName.GetValue() |
|
3615 if action_name == "": |
|
3616 error.append(_("Action Name")) |
|
3617 if self.Language.GetSelection() == -1: |
|
3618 error.append(_("Language")) |
|
3619 if len(error) > 0: |
|
3620 text = "" |
|
3621 for i, item in enumerate(error): |
|
3622 if i == 0: |
|
3623 text += item |
|
3624 elif i == len(error) - 1: |
|
3625 text += _(" and %s")%item |
|
3626 else: |
|
3627 text += _(", %s")%item |
|
3628 message = wx.MessageDialog(self, _("Form isn't complete. %s must be filled!")%text, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3629 message.ShowModal() |
|
3630 message.Destroy() |
|
3631 elif not TestIdentifier(action_name): |
|
3632 message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3633 message.ShowModal() |
|
3634 message.Destroy() |
|
3635 elif action_name.upper() in IEC_KEYWORDS: |
|
3636 message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3637 message.ShowModal() |
|
3638 message.Destroy() |
|
3639 elif action_name.upper() in self.PouNames: |
|
3640 message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3641 message.ShowModal() |
|
3642 message.Destroy() |
|
3643 elif action_name.upper() in self.PouElementNames: |
|
3644 message = wx.MessageDialog(self, _("\"%s\" element for this pou already exists!")%action_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3645 message.ShowModal() |
|
3646 message.Destroy() |
|
3647 else: |
|
3648 self.EndModal(wx.ID_OK) |
|
3649 |
|
3650 def SetPouNames(self, pou_names): |
|
3651 self.PouNames = [pou_name.upper() for pou_name in pou_names] |
|
3652 |
|
3653 def SetPouElementNames(self, element_names): |
|
3654 self.PouElementNames = [element_name.upper() for element_name in element_names] |
|
3655 |
|
3656 def SetValues(self, values): |
|
3657 for item, value in values.items(): |
|
3658 if item == "actionName": |
|
3659 self.ActionName.SetValue(value) |
|
3660 elif item == "language": |
|
3661 self.Language.SetStringSelection(_(value)) |
|
3662 |
|
3663 def GetValues(self): |
|
3664 values = {} |
|
3665 values["actionName"] = self.ActionName.GetValue() |
|
3666 values["language"] = ACTION_LANGUAGES_DICT[self.Language.GetStringSelection()] |
|
3667 return values |
|
3668 |
|
3669 #------------------------------------------------------------------------------- |
|
3670 # Configuration Name Dialog |
|
3671 #------------------------------------------------------------------------------- |
|
3672 |
|
3673 class ConfigurationNameDialog(wx.TextEntryDialog): |
|
3674 |
|
3675 if wx.VERSION < (2, 6, 0): |
|
3676 def Bind(self, event, function, id = None): |
|
3677 if id is not None: |
|
3678 event(self, id, function) |
|
3679 else: |
|
3680 event(self, function) |
|
3681 |
|
3682 def __init__(self, parent, message, caption = _("Please enter configuration name"), defaultValue = "", |
|
3683 style = wx.OK|wx.CANCEL|wx.CENTRE, pos = wx.DefaultPosition): |
|
3684 wx.TextEntryDialog.__init__(self, parent, message, caption, defaultValue, style, pos) |
|
3685 |
|
3686 self.PouNames = [] |
|
3687 self.PouElementNames = [] |
|
3688 |
|
3689 if wx.VERSION >= (2, 8, 0): |
|
3690 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(2).GetSizer().GetItem(1).GetSizer().GetAffirmativeButton().GetId()) |
|
3691 elif wx.VERSION >= (2, 6, 0): |
|
3692 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetAffirmativeButton().GetId()) |
|
3693 else: |
|
3694 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetChildren()[0].GetSizer().GetChildren()[0].GetWindow().GetId()) |
|
3695 |
|
3696 def OnOK(self, event): |
|
3697 config_name = self.GetSizer().GetItem(1).GetWindow().GetValue() |
|
3698 if config_name == "": |
|
3699 message = wx.MessageDialog(self, _("You must type a name!"), _("Error"), wx.OK|wx.ICON_ERROR) |
|
3700 message.ShowModal() |
|
3701 message.Destroy() |
|
3702 elif not TestIdentifier(config_name): |
|
3703 message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%config_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3704 message.ShowModal() |
|
3705 message.Destroy() |
|
3706 elif config_name.upper() in IEC_KEYWORDS: |
|
3707 message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%config_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3708 message.ShowModal() |
|
3709 message.Destroy() |
|
3710 elif config_name.upper() in self.PouNames: |
|
3711 message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%config_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3712 message.ShowModal() |
|
3713 message.Destroy() |
|
3714 elif config_name.upper() in self.PouElementNames: |
|
3715 message = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%config_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION) |
|
3716 result = message.ShowModal() |
|
3717 message.Destroy() |
|
3718 if result == wx.ID_YES: |
|
3719 self.EndModal(wx.ID_OK) |
|
3720 else: |
|
3721 self.EndModal(wx.ID_OK) |
|
3722 |
|
3723 def SetPouNames(self, pou_names): |
|
3724 self.PouNames = [pou_name.upper() for pou_name in pou_names] |
|
3725 |
|
3726 def SetPouElementNames(self, pou_names): |
|
3727 self.PouElementNames = [pou_name.upper() for pou_name in pou_names] |
|
3728 |
|
3729 def GetValue(self): |
|
3730 return self.GetSizer().GetItem(1).GetWindow().GetValue() |
|
3731 |
|
3732 #------------------------------------------------------------------------------- |
|
3733 # Resource Name Dialog |
|
3734 #------------------------------------------------------------------------------- |
|
3735 |
|
3736 class ResourceNameDialog(wx.TextEntryDialog): |
|
3737 |
|
3738 if wx.VERSION < (2, 6, 0): |
|
3739 def Bind(self, event, function, id = None): |
|
3740 if id is not None: |
|
3741 event(self, id, function) |
|
3742 else: |
|
3743 event(self, function) |
|
3744 |
|
3745 def __init__(self, parent, message, caption = _("Please enter resource name"), defaultValue = "", |
|
3746 style = wx.OK|wx.CANCEL|wx.CENTRE, pos = wx.DefaultPosition): |
|
3747 wx.TextEntryDialog.__init__(self, parent, message, caption, defaultValue, style, pos) |
|
3748 |
|
3749 self.PouNames = [] |
|
3750 self.PouElementNames = [] |
|
3751 |
|
3752 if wx.VERSION >= (2, 8, 0): |
|
3753 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(2).GetSizer().GetItem(1).GetSizer().GetAffirmativeButton().GetId()) |
|
3754 elif wx.VERSION >= (2, 6, 0): |
|
3755 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetAffirmativeButton().GetId()) |
|
3756 else: |
|
3757 self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetChildren()[0].GetSizer().GetChildren()[0].GetWindow().GetId()) |
|
3758 |
|
3759 def OnOK(self, event): |
|
3760 resource_name = self.GetSizer().GetItem(1).GetWindow().GetValue() |
|
3761 if resource_name == "": |
|
3762 message = wx.MessageDialog(self, _("You must type a name!"), _("Error"), wx.OK|wx.ICON_ERROR) |
|
3763 message.ShowModal() |
|
3764 message.Destroy() |
|
3765 elif not TestIdentifier(resource_name): |
|
3766 message = wx.MessageDialog(self, _("\"%s\" is not a valid identifier!")%resource_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3767 message.ShowModal() |
|
3768 message.Destroy() |
|
3769 elif resource_name.upper() in IEC_KEYWORDS: |
|
3770 message = wx.MessageDialog(self, _("\"%s\" is a keyword. It can't be used!")%resource_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3771 message.ShowModal() |
|
3772 message.Destroy() |
|
3773 elif resource_name.upper() in self.PouNames: |
|
3774 message = wx.MessageDialog(self, _("A POU named \"%s\" already exists!")%resource_name, _("Error"), wx.OK|wx.ICON_ERROR) |
|
3775 message.ShowModal() |
|
3776 message.Destroy() |
|
3777 elif resource_name.upper() in self.PouElementNames: |
|
3778 message = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%resource_name, _("Warning"), wx.YES_NO|wx.ICON_EXCLAMATION) |
|
3779 result = message.ShowModal() |
|
3780 message.Destroy() |
|
3781 if result == wx.ID_YES: |
|
3782 self.EndModal(wx.ID_OK) |
|
3783 else: |
|
3784 self.EndModal(wx.ID_OK) |
|
3785 |
|
3786 def SetPouNames(self, pou_names): |
|
3787 self.PouNames = [pou_name.upper() for pou_name in pou_names] |
|
3788 |
|
3789 def SetPouElementNames(self, pou_names): |
|
3790 self.PouElementNames = [pou_name.upper() for pou_name in pou_names] |
|
3791 |
|
3792 def GetValue(self): |
|
3793 return self.GetSizer().GetItem(1).GetWindow().GetValue() |
|
3794 |
|
3795 #------------------------------------------------------------------------------- |
|
3796 # Variables Editor Panel |
|
3797 #------------------------------------------------------------------------------- |
|
3798 |
|
3799 class VariablePanelIndexer(wx.Panel): |
|
3800 |
|
3801 def _init_sizers(self): |
|
3802 self.MainSizer = wx.BoxSizer(wx.HORIZONTAL) |
|
3803 |
|
3804 self.SetSizer(self.MainSizer) |
|
3805 |
|
3806 def _init_ctrls(self, prnt): |
|
3807 wx.Panel.__init__(self, id=wx.NewId(), |
|
3808 name='VariablePanelIndexer', parent=prnt, pos=wx.Point(0, 0), |
|
3809 size=wx.Size(0, 300), style=wx.TAB_TRAVERSAL) |
|
3810 |
|
3811 self._init_sizers() |
|
3812 |
|
3813 def __init__(self, parent, window): |
|
3814 self._init_ctrls(parent) |
|
3815 |
|
3816 self.ParentWindow = window |
|
3817 |
|
3818 self.VariablePanelList = {} |
|
3819 self.CurrentPanel = None |
|
3820 |
|
3821 def AddVariablePanel(self, tagname, element_type): |
|
3822 new_panel = VariablePanel(self, self.ParentWindow, self.ParentWindow.Controler, element_type) |
|
3823 new_panel.SetTagName(tagname) |
|
3824 new_panel.Hide() |
|
3825 new_panel.RefreshView() |
|
3826 self.MainSizer.AddWindow(new_panel, 1, border=0, flag=wx.GROW) |
|
3827 self.VariablePanelList[tagname] = new_panel |
|
3828 |
|
3829 def RemoveVariablePanel(self, tagname): |
|
3830 if tagname in self.VariablePanelList: |
|
3831 panel = self.VariablePanelList.pop(tagname) |
|
3832 self.MainSizer.Remove(panel) |
|
3833 panel.Destroy() |
|
3834 if self.CurrentPanel == tagname: |
|
3835 self.CurrentPanel = None |
|
3836 |
|
3837 def RemoveAllPanels(self): |
|
3838 for tagname in self.VariablePanelList.keys(): |
|
3839 self.RemoveVariablePanel(tagname) |
|
3840 |
|
3841 def UpdateVariablePanelTagName(self, old_tagname, new_tagname): |
|
3842 if old_tagname in self.VariablePanelList: |
|
3843 self.VariablePanelList[new_tagname] = self.VariablePanelList.pop(old_tagname) |
|
3844 if self.CurrentPanel == old_tagname: |
|
3845 self.CurrentPanel = new_tagname |
|
3846 |
|
3847 def ChangeVariablePanel(self, tagname): |
|
3848 if tagname in self.VariablePanelList: |
|
3849 if tagname != self.CurrentPanel: |
|
3850 if self.CurrentPanel is not None: |
|
3851 self.VariablePanelList[self.CurrentPanel].Hide() |
|
3852 self.CurrentPanel = tagname |
|
3853 self.VariablePanelList[self.CurrentPanel].RefreshView() |
|
3854 self.VariablePanelList[self.CurrentPanel].Show() |
|
3855 self.MainSizer.Layout() |
|
3856 else: |
|
3857 if self.CurrentPanel is not None: |
|
3858 self.VariablePanelList[self.CurrentPanel].Hide() |
|
3859 self.CurrentPanel = None |
|
3860 self.MainSizer.Layout() |
|
3861 |
|
3862 def RefreshVariablePanel(self, tagname): |
|
3863 if tagname in self.VariablePanelList: |
|
3864 self.VariablePanelList[self.CurrentPanel].RefreshView() |
|
3865 |
|
3866 def AddVariableError(self, infos): |
|
3867 self.ChangeVariablePanel(infos[0]) |
|
3868 if self.CurrentPanel is not None: |
|
3869 self.VariablePanelList[self.CurrentPanel].AddVariableError(infos[2:]) |
|
3870 |
|
3871 def ClearErrors(self): |
|
3872 for panel in self.VariablePanelList.values(): |
|
3873 panel.ClearErrors() |
|
3874 |
|
3875 #------------------------------------------------------------------------------- |
|
3876 # Debug Variables Panel |
|
3877 #------------------------------------------------------------------------------- |
|
3878 |
|
3879 def GetDebugVariablesTableColnames(): |
|
3880 _ = lambda x : x |
|
3881 return [_("Variable"), _("Value")] |
|
3882 |
|
3883 class VariableTableItem(DebugDataConsumer): |
|
3884 |
|
3885 def __init__(self, parent, variable, value): |
|
3886 DebugDataConsumer.__init__(self) |
|
3887 self.Parent = parent |
|
3888 self.Variable = variable |
|
3889 self.Value = value |
|
3890 |
|
3891 def __del__(self): |
|
3892 self.Parent = None |
|
3893 |
|
3894 def SetVariable(self, variable): |
|
3895 if self.Parent and self.Variable != variable: |
|
3896 self.Variable = variable |
|
3897 self.Parent.RefreshGrid() |
|
3898 |
|
3899 def GetVariable(self): |
|
3900 return self.Variable |
|
3901 |
|
3902 def SetValue(self, value): |
|
3903 if self.Value != value: |
|
3904 self.Value = value |
|
3905 self.Parent.HasNewData = True |
|
3906 |
|
3907 def GetValue(self): |
|
3908 return self.Value |
|
3909 |
|
3910 class DebugVariableTable(wx.grid.PyGridTableBase): |
|
3911 |
|
3912 """ |
|
3913 A custom wx.grid.Grid Table using user supplied data |
|
3914 """ |
|
3915 def __init__(self, parent, data, colnames): |
|
3916 # The base class must be initialized *first* |
|
3917 wx.grid.PyGridTableBase.__init__(self) |
|
3918 self.data = data |
|
3919 self.colnames = colnames |
|
3920 self.Parent = parent |
|
3921 # XXX |
|
3922 # we need to store the row length and collength to |
|
3923 # see if the table has changed size |
|
3924 self._rows = self.GetNumberRows() |
|
3925 self._cols = self.GetNumberCols() |
|
3926 |
|
3927 def GetNumberCols(self): |
|
3928 return len(self.colnames) |
|
3929 |
|
3930 def GetNumberRows(self): |
|
3931 return len(self.data) |
|
3932 |
|
3933 def GetColLabelValue(self, col, translate=True): |
|
3934 if col < len(self.colnames): |
|
3935 if translate: |
|
3936 return _(self.colnames[col]) |
|
3937 return self.colnames[col] |
|
3938 |
|
3939 def GetRowLabelValues(self, row, translate=True): |
|
3940 return row |
|
3941 |
|
3942 def GetValue(self, row, col): |
|
3943 if row < self.GetNumberRows(): |
|
3944 return self.GetValueByName(row, self.GetColLabelValue(col, False)) |
|
3945 return "" |
|
3946 |
|
3947 def SetValue(self, row, col, value): |
|
3948 if col < len(self.colnames): |
|
3949 self.SetValueByName(row, self.GetColLabelValue(col, False), value) |
|
3950 |
|
3951 def GetValueByName(self, row, colname): |
|
3952 if row < self.GetNumberRows(): |
|
3953 if colname == "Variable": |
|
3954 return self.data[row].GetVariable() |
|
3955 elif colname == "Value": |
|
3956 return self.data[row].GetValue() |
|
3957 return "" |
|
3958 |
|
3959 def SetValueByName(self, row, colname, value): |
|
3960 if row < self.GetNumberRows(): |
|
3961 if colname == "Variable": |
|
3962 self.data[row].SetVariable(value) |
|
3963 elif colname == "Value": |
|
3964 self.data[row].SetValue(value) |
|
3965 |
|
3966 def ResetView(self, grid): |
|
3967 """ |
|
3968 (wx.grid.Grid) -> Reset the grid view. Call this to |
|
3969 update the grid if rows and columns have been added or deleted |
|
3970 """ |
|
3971 grid.BeginBatch() |
|
3972 for current, new, delmsg, addmsg in [ |
|
3973 (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED), |
|
3974 (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED), |
|
3975 ]: |
|
3976 if new < current: |
|
3977 msg = wx.grid.GridTableMessage(self,delmsg,new,current-new) |
|
3978 grid.ProcessTableMessage(msg) |
|
3979 elif new > current: |
|
3980 msg = wx.grid.GridTableMessage(self,addmsg,new-current) |
|
3981 grid.ProcessTableMessage(msg) |
|
3982 self.UpdateValues(grid) |
|
3983 grid.EndBatch() |
|
3984 |
|
3985 self._rows = self.GetNumberRows() |
|
3986 self._cols = self.GetNumberCols() |
|
3987 # update the column rendering scheme |
|
3988 self._updateColAttrs(grid) |
|
3989 |
|
3990 # update the scrollbars and the displayed part of the grid |
|
3991 grid.AdjustScrollbars() |
|
3992 grid.ForceRefresh() |
|
3993 |
|
3994 def UpdateValues(self, grid): |
|
3995 """Update all displayed values""" |
|
3996 # This sends an event to the grid table to update all of the values |
|
3997 msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES) |
|
3998 grid.ProcessTableMessage(msg) |
|
3999 |
|
4000 def _updateColAttrs(self, grid): |
|
4001 """ |
|
4002 wx.grid.Grid -> update the column attributes to add the |
|
4003 appropriate renderer given the column name. |
|
4004 |
|
4005 Otherwise default to the default renderer. |
|
4006 """ |
|
4007 |
|
4008 for row in range(self.GetNumberRows()): |
|
4009 for col in range(self.GetNumberCols()): |
|
4010 grid.SetReadOnly(row, col, True) |
|
4011 |
|
4012 def SetData(self, data): |
|
4013 self.data = data |
|
4014 |
|
4015 def GetData(self): |
|
4016 return self.data |
|
4017 |
|
4018 def AppendItem(self, data): |
|
4019 self.data.append(data) |
|
4020 |
|
4021 def InsertItem(self, idx, data): |
|
4022 self.data.insert(idx, data) |
|
4023 |
|
4024 def RemoveItem(self, idx): |
|
4025 self.data.pop(idx) |
|
4026 |
|
4027 def MoveItem(self, idx, new_idx): |
|
4028 self.data.insert(new_idx, self.data.pop(idx)) |
|
4029 |
|
4030 def GetItem(self, idx): |
|
4031 return self.data[idx] |
|
4032 |
|
4033 def Empty(self): |
|
4034 self.data = [] |
|
4035 |
|
4036 class DebugVariableDropTarget(wx.TextDropTarget): |
|
4037 |
|
4038 def __init__(self, parent): |
|
4039 wx.TextDropTarget.__init__(self) |
|
4040 self.ParentWindow = parent |
|
4041 |
|
4042 def OnDropText(self, x, y, data): |
|
4043 x, y = self.ParentWindow.VariablesGrid.CalcUnscrolledPosition(x, y) |
|
4044 row = self.ParentWindow.VariablesGrid.YToRow(y - self.ParentWindow.VariablesGrid.GetColLabelSize()) |
|
4045 if row == wx.NOT_FOUND: |
|
4046 row = self.ParentWindow.Table.GetNumberRows() |
|
4047 message = None |
|
4048 try: |
|
4049 values = eval(data) |
|
4050 except: |
|
4051 message = _("Invalid value \"%s\" for debug variable")%data |
|
4052 values = None |
|
4053 if not isinstance(values, TupleType): |
|
4054 message = _("Invalid value \"%s\" for debug variable")%data |
|
4055 values = None |
|
4056 if values is not None and values[1] == "debug": |
|
4057 self.ParentWindow.InsertValue(row, values[0]) |
|
4058 if message is not None: |
|
4059 wx.CallAfter(self.ShowMessage, message) |
|
4060 |
|
4061 def ShowMessage(self, message): |
|
4062 message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR) |
|
4063 message.ShowModal() |
|
4064 message.Destroy() |
|
4065 |
|
4066 [ID_DEBUGVARIABLEPANEL, ID_DEBUGVARIABLEPANELVARIABLESGRID, |
|
4067 ID_DEBUGVARIABLEPANELUPBUTTON, ID_DEBUGVARIABLEPANELDOWNBUTTON, |
|
4068 ID_DEBUGVARIABLEPANELDELETEBUTTON, |
|
4069 ] = [wx.NewId() for _init_ctrls in range(5)] |
|
4070 |
|
4071 class DebugVariablePanel(wx.Panel, DebugViewer): |
|
4072 |
|
4073 if wx.VERSION < (2, 6, 0): |
|
4074 def Bind(self, event, function, id = None): |
|
4075 if id is not None: |
|
4076 event(self, id, function) |
|
4077 else: |
|
4078 event(self, function) |
|
4079 |
|
4080 def _init_coll_MainSizer_Items(self, parent): |
|
4081 parent.AddSizer(self.ButtonPanelSizer, 0, border=5, flag=wx.ALIGN_RIGHT|wx.ALL) |
|
4082 parent.AddWindow(self.VariablesGrid, 0, border=0, flag=wx.GROW) |
|
4083 |
|
4084 def _init_coll_MainSizer_Growables(self, parent): |
|
4085 parent.AddGrowableCol(0) |
|
4086 parent.AddGrowableRow(1) |
|
4087 |
|
4088 def _init_coll_ButtonPanelSizer_Items(self, parent): |
|
4089 parent.AddWindow(self.UpButton, 0, border=5, flag=wx.RIGHT) |
|
4090 parent.AddWindow(self.DownButton, 0, border=5, flag=wx.RIGHT) |
|
4091 parent.AddWindow(self.DeleteButton, 0, border=0, flag=0) |
|
4092 |
|
4093 def _init_sizers(self): |
|
4094 self.MainSizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=0) |
|
4095 self.ButtonPanelSizer = wx.BoxSizer(wx.HORIZONTAL) |
|
4096 |
|
4097 self._init_coll_MainSizer_Items(self.MainSizer) |
|
4098 self._init_coll_MainSizer_Growables(self.MainSizer) |
|
4099 self._init_coll_ButtonPanelSizer_Items(self.ButtonPanelSizer) |
|
4100 |
|
4101 self.SetSizer(self.MainSizer) |
|
4102 |
|
4103 def _init_ctrls(self, prnt): |
|
4104 wx.Panel.__init__(self, id=ID_DEBUGVARIABLEPANEL, |
|
4105 name='DebugVariablePanel', parent=prnt, pos=wx.Point(0, 0), |
|
4106 size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) |
|
4107 |
|
4108 self.VariablesGrid = wx.grid.Grid(id=ID_DEBUGVARIABLEPANELVARIABLESGRID, |
|
4109 name='VariablesGrid', parent=self, pos=wx.Point(0, 0), |
|
4110 size=wx.Size(0, 150), style=wx.VSCROLL) |
|
4111 self.VariablesGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False, |
|
4112 'Sans')) |
|
4113 self.VariablesGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL, |
|
4114 False, 'Sans')) |
|
4115 self.VariablesGrid.SetSelectionBackground(wx.WHITE) |
|
4116 self.VariablesGrid.SetSelectionForeground(wx.BLACK) |
|
4117 self.VariablesGrid.SetDropTarget(DebugVariableDropTarget(self)) |
|
4118 |
|
4119 self.UpButton = wx.Button(id=ID_DEBUGVARIABLEPANELUPBUTTON, label='^', |
|
4120 name='UpButton', parent=self, pos=wx.Point(0, 0), |
|
4121 size=wx.Size(32, 32), style=0) |
|
4122 self.Bind(wx.EVT_BUTTON, self.OnUpButton, id=ID_DEBUGVARIABLEPANELUPBUTTON) |
|
4123 |
|
4124 self.DownButton = wx.Button(id=ID_DEBUGVARIABLEPANELDOWNBUTTON, label='v', |
|
4125 name='DownButton', parent=self, pos=wx.Point(0, 0), |
|
4126 size=wx.Size(32, 32), style=0) |
|
4127 self.Bind(wx.EVT_BUTTON, self.OnDownButton, id=ID_DEBUGVARIABLEPANELDOWNBUTTON) |
|
4128 |
|
4129 self.DeleteButton = wx.Button(id=ID_DEBUGVARIABLEPANELDELETEBUTTON, label=_('Delete'), |
|
4130 name='DeleteButton', parent=self, pos=wx.Point(0, 0), |
|
4131 size=wx.DefaultSize, style=0) |
|
4132 self.Bind(wx.EVT_BUTTON, self.OnDeleteButton, id=ID_DEBUGVARIABLEPANELDELETEBUTTON) |
|
4133 |
|
4134 self._init_sizers() |
|
4135 |
|
4136 def __init__(self, parent, producer): |
|
4137 self._init_ctrls(parent) |
|
4138 DebugViewer.__init__(self, producer, True) |
|
4139 self.HasNewData = False |
|
4140 |
|
4141 self.Table = DebugVariableTable(self, [], GetDebugVariablesTableColnames()) |
|
4142 self.VariablesGrid.SetTable(self.Table) |
|
4143 self.VariablesGrid.SetRowLabelSize(0) |
|
4144 |
|
4145 for col in range(self.Table.GetNumberCols()): |
|
4146 attr = wx.grid.GridCellAttr() |
|
4147 attr.SetAlignment(wx.ALIGN_RIGHT, wx.ALIGN_CENTER) |
|
4148 self.VariablesGrid.SetColAttr(col, attr) |
|
4149 self.VariablesGrid.SetColSize(col, 100) |
|
4150 |
|
4151 self.Table.ResetView(self.VariablesGrid) |
|
4152 |
|
4153 def RefreshNewData(self): |
|
4154 if self.HasNewData: |
|
4155 self.HasNewData = False |
|
4156 self.RefreshGrid() |
|
4157 DebugViewer.RefreshNewData(self) |
|
4158 |
|
4159 def RefreshGrid(self): |
|
4160 self.Freeze() |
|
4161 self.Table.ResetView(self.VariablesGrid) |
|
4162 self.Thaw() |
|
4163 |
|
4164 def ResetGrid(self): |
|
4165 self.DeleteDataConsumers() |
|
4166 self.Table.Empty() |
|
4167 self.Freeze() |
|
4168 self.Table.ResetView(self.VariablesGrid) |
|
4169 self.Thaw() |
|
4170 |
|
4171 def OnDeleteButton(self, event): |
|
4172 idx = self.VariablesGrid.GetGridCursorRow() |
|
4173 item = self.Table.GetItem(idx) |
|
4174 self.RemoveDataConsumer(item) |
|
4175 self.Table.RemoveItem(idx) |
|
4176 self.RefreshGrid() |
|
4177 event.Skip() |
|
4178 |
|
4179 def OnUpButton(self, event): |
|
4180 self.MoveValue(self.VariablesGrid.GetGridCursorRow(), -1) |
|
4181 event.Skip() |
|
4182 |
|
4183 def OnDownButton(self, event): |
|
4184 self.MoveValue(self.VariablesGrid.GetGridCursorRow(), 1) |
|
4185 event.Skip() |
|
4186 |
|
4187 def InsertValue(self, idx, iec_path): |
|
4188 for item in self.Table.GetData(): |
|
4189 if iec_path == item.GetVariable(): |
|
4190 return |
|
4191 item = VariableTableItem(self, iec_path, "") |
|
4192 result = self.AddDataConsumer(iec_path.upper(), item) |
|
4193 if result is not None: |
|
4194 self.Table.InsertItem(idx, item) |
|
4195 self.RefreshGrid() |
|
4196 |
|
4197 def MoveValue(self, idx, move): |
|
4198 new_idx = max(0, min(idx + move, self.Table.GetNumberRows() - 1)) |
|
4199 if new_idx != idx: |
|
4200 self.Table.MoveItem(idx, new_idx) |
|
4201 self.RefreshGrid() |
|
4202 self.VariablesGrid.SetGridCursor(new_idx, self.VariablesGrid.GetGridCursorCol()) |
|
4203 |
|
4204 #------------------------------------------------------------------------------- |
|
4205 # Viewer Printout |
|
4206 #------------------------------------------------------------------------------- |
|
4207 |
|
4208 UPPER_DIV = lambda x, y: (x / y) + {True : 0, False : 1}[(x % y) == 0] |
|
4209 |
|
4210 class GraphicPrintout(wx.Printout): |
|
4211 def __init__(self, viewer, page_size, margins, preview = False): |
|
4212 wx.Printout.__init__(self) |
|
4213 self.Viewer = viewer |
|
4214 self.PageSize = page_size |
|
4215 if self.PageSize[0] == 0 or self.PageSize[1] == 0: |
|
4216 self.PageSize = (1050, 1485) |
|
4217 self.Preview = preview |
|
4218 self.Margins = margins |
|
4219 self.FontSize = 5 |
|
4220 self.TextMargin = 3 |
|
4221 |
|
4222 maxx, maxy = viewer.GetMaxSize() |
|
4223 self.PageGrid = (UPPER_DIV(maxx, self.PageSize[0]), |
|
4224 UPPER_DIV(maxy, self.PageSize[1])) |
|
4225 |
|
4226 def GetPageNumber(self): |
|
4227 return self.PageGrid[0] * self.PageGrid[1] |
|
4228 |
|
4229 def HasPage(self, page): |
|
4230 return page <= self.GetPageNumber() |
|
4231 |
|
4232 def GetPageInfo(self): |
|
4233 page_number = self.GetPageNumber() |
|
4234 return (1, page_number, 1, page_number) |
|
4235 |
|
4236 def OnBeginDocument(self, startPage, endPage): |
|
4237 dc = self.GetDC() |
|
4238 if not self.Preview and isinstance(dc, wx.PostScriptDC): |
|
4239 dc.SetResolution(720) |
|
4240 super(GraphicPrintout, self).OnBeginDocument(startPage, endPage) |
|
4241 |
|
4242 def OnPrintPage(self, page): |
|
4243 dc = self.GetDC() |
|
4244 dc.SetUserScale(1.0, 1.0) |
|
4245 dc.SetDeviceOrigin(0, 0) |
|
4246 dc.printing = not self.Preview |
|
4247 |
|
4248 # Get the size of the DC in pixels |
|
4249 ppiPrinterX, ppiPrinterY = self.GetPPIPrinter() |
|
4250 ppiScreenX, ppiScreenY = self.GetPPIScreen() |
|
4251 pw, ph = self.GetPageSizePixels() |
|
4252 dw, dh = dc.GetSizeTuple() |
|
4253 Xscale = (float(dw) * float(ppiPrinterX)) / (float(pw) * 25.4) |
|
4254 Yscale = (float(dh) * float(ppiPrinterY)) / (float(ph) * 25.4) |
|
4255 |
|
4256 fontsize = self.FontSize * Yscale |
|
4257 text_margin = self.TextMargin * Yscale |
|
4258 |
|
4259 margin_left = self.Margins[0].x * Xscale |
|
4260 margin_top = self.Margins[0].y * Yscale |
|
4261 area_width = dw - self.Margins[1].x * Xscale - margin_left |
|
4262 area_height = dh - self.Margins[1].y * Yscale - margin_top |
|
4263 |
|
4264 dc.SetPen(wx.BLACK_PEN) |
|
4265 dc.SetBrush(wx.TRANSPARENT_BRUSH) |
|
4266 dc.DrawRectangle(margin_left, margin_top, area_width, area_height) |
|
4267 |
|
4268 dc.SetFont(wx.Font(fontsize, wx.DEFAULT, wx.NORMAL, wx.NORMAL)) |
|
4269 dc.SetTextForeground(wx.BLACK) |
|
4270 block_name = " - ".join(self.Viewer.GetTagName().split("::")[1:]) |
|
4271 text_width, text_height = dc.GetTextExtent(block_name) |
|
4272 dc.DrawText(block_name, margin_left, margin_top - text_height - self.TextMargin) |
|
4273 dc.DrawText(_("Page: %d") % page, margin_left, margin_top + area_height + self.TextMargin) |
|
4274 |
|
4275 # Calculate the position on the DC for centering the graphic |
|
4276 posX = area_width * ((page - 1) % self.PageGrid[0]) |
|
4277 posY = area_height * ((page - 1) / self.PageGrid[0]) |
|
4278 |
|
4279 scaleX = float(area_width) / float(self.PageSize[0]) |
|
4280 scaleY = float(area_height) / float(self.PageSize[1]) |
|
4281 scale = min(scaleX, scaleY) |
|
4282 |
|
4283 # Set the scale and origin |
|
4284 dc.SetDeviceOrigin(-posX + margin_left, -posY + margin_top) |
|
4285 dc.SetClippingRegion(posX, posY, self.PageSize[0] * scale, self.PageSize[1] * scale) |
|
4286 dc.SetUserScale(scale, scale) |
|
4287 |
|
4288 #------------------------------------------- |
|
4289 |
|
4290 self.Viewer.DoDrawing(dc, True) |
|
4291 |
|
4292 return True |
|
4293 |
|
4294 #------------------------------------------------------------------------------- |
|
4295 # Exception Handler |
|
4296 #------------------------------------------------------------------------------- |
|
4297 |
|
4298 Max_Traceback_List_Size = 20 |
|
4299 |
|
4300 def Display_Exception_Dialog(e_type,e_value,e_tb): |
|
4301 trcbck_lst = [] |
|
4302 for i,line in enumerate(traceback.extract_tb(e_tb)): |
|
4303 trcbck = " " + str(i+1) + _(". ") |
|
4304 if line[0].find(os.getcwd()) == -1: |
|
4305 trcbck += _("file : ") + str(line[0]) + _(", ") |
|
4306 else: |
|
4307 trcbck += _("file : ") + str(line[0][len(os.getcwd()):]) + _(", ") |
|
4308 trcbck += _("line : ") + str(line[1]) + _(", ") + _("function : ") + str(line[2]) |
|
4309 trcbck_lst.append(trcbck) |
|
4310 |
|
4311 # Allow clicking.... |
|
4312 cap = wx.Window_GetCapture() |
|
4313 if cap: |
|
4314 cap.ReleaseMouse() |
|
4315 |
|
4316 dlg = wx.SingleChoiceDialog(None, |
|
4317 _(""" |
|
4318 An error has occurred. |
|
4319 |
|
4320 Click OK to save an error report. |
|
4321 |
|
4322 Please contact LOLITech at: |
|
4323 +33 (0)3 29 57 60 42 |
|
4324 bugs_PLCOpenEditor@lolitech.fr |
|
4325 |
|
4326 |
|
4327 Error: |
|
4328 """) + |
|
4329 str(e_type) + _(" : ") + str(e_value), |
|
4330 _("Error"), |
|
4331 trcbck_lst) |
|
4332 try: |
|
4333 res = (dlg.ShowModal() == wx.ID_OK) |
|
4334 finally: |
|
4335 dlg.Destroy() |
|
4336 |
|
4337 return res |
|
4338 |
|
4339 def Display_Error_Dialog(e_value): |
|
4340 message = wx.MessageDialog(None, str(e_value), _("Error"), wx.OK|wx.ICON_ERROR) |
|
4341 message.ShowModal() |
|
4342 message.Destroy() |
|
4343 |
|
4344 def get_last_traceback(tb): |
|
4345 while tb.tb_next: |
|
4346 tb = tb.tb_next |
|
4347 return tb |
|
4348 |
|
4349 |
|
4350 def format_namespace(d, indent=' '): |
|
4351 return '\n'.join(['%s%s: %s' % (indent, k, repr(v)[:10000]) for k, v in d.iteritems()]) |
|
4352 |
|
4353 |
|
4354 ignored_exceptions = [] # a problem with a line in a module is only reported once per session |
|
4355 |
|
4356 def AddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]): |
|
4357 |
|
4358 def handle_exception(e_type, e_value, e_traceback): |
|
4359 traceback.print_exception(e_type, e_value, e_traceback) # this is very helpful when there's an exception in the rest of this func |
|
4360 last_tb = get_last_traceback(e_traceback) |
|
4361 ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno) |
|
4362 if str(e_value).startswith("!!!"): |
|
4363 Display_Error_Dialog(e_value) |
|
4364 elif ex not in ignored_exceptions: |
|
4365 result = Display_Exception_Dialog(e_type,e_value,e_traceback) |
|
4366 if result: |
|
4367 ignored_exceptions.append(ex) |
|
4368 info = { |
|
4369 'app-title' : wx.GetApp().GetAppName(), # app_title |
|
4370 'app-version' : app_version, |
|
4371 'wx-version' : wx.VERSION_STRING, |
|
4372 'wx-platform' : wx.Platform, |
|
4373 'python-version' : platform.python_version(), #sys.version.split()[0], |
|
4374 'platform' : platform.platform(), |
|
4375 'e-type' : e_type, |
|
4376 'e-value' : e_value, |
|
4377 'date' : time.ctime(), |
|
4378 'cwd' : os.getcwd(), |
|
4379 } |
|
4380 if e_traceback: |
|
4381 info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value) |
|
4382 last_tb = get_last_traceback(e_traceback) |
|
4383 exception_locals = last_tb.tb_frame.f_locals # the locals at the level of the stack trace where the exception actually occurred |
|
4384 info['locals'] = format_namespace(exception_locals) |
|
4385 if 'self' in exception_locals: |
|
4386 info['self'] = format_namespace(exception_locals['self'].__dict__) |
|
4387 |
|
4388 output = open(path+os.sep+"bug_report_"+info['date'].replace(':','-').replace(' ','_')+".txt",'w') |
|
4389 lst = info.keys() |
|
4390 lst.sort() |
|
4391 for a in lst: |
|
4392 output.write(a+":\n"+str(info[a])+"\n\n") |
|
4393 |
|
4394 #sys.excepthook = lambda *args: wx.CallAfter(handle_exception, *args) |
|
4395 sys.excepthook = handle_exception |
|
4396 |
|
4397 if __name__ == '__main__': |
|
4398 wx.InitAllImageHandlers() |
|
4399 |
|
4400 # Install a exception handle for bug reports |
|
4401 AddExceptHook(os.getcwd(),__version__) |
|
4402 |
|
4403 frame = PLCOpenEditor(None, fileOpen=fileOpen) |
|
4404 |
|
4405 frame.Show() |
|
4406 app.MainLoop() |
|
4407 |
|