57 'size' : 18, |
57 'size' : 18, |
58 } |
58 } |
59 |
59 |
60 CWD = os.path.split(os.path.realpath(__file__))[0] |
60 CWD = os.path.split(os.path.realpath(__file__))[0] |
61 |
61 |
|
62 # Some helpers to tweak GenBitmapTextButtons |
|
63 # TODO: declare customized classes instead. |
62 gen_mini_GetBackgroundBrush = lambda obj:lambda dc: wx.Brush(obj.GetParent().GetBackgroundColour(), wx.SOLID) |
64 gen_mini_GetBackgroundBrush = lambda obj:lambda dc: wx.Brush(obj.GetParent().GetBackgroundColour(), wx.SOLID) |
63 gen_mini_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenBitmapTextButton._GetLabelSize(obj)[:-1] + (False,)) |
|
64 gen_textbutton_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenButton._GetLabelSize(obj)[:-1] + (False,)) |
65 gen_textbutton_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenButton._GetLabelSize(obj)[:-1] + (False,)) |
65 |
66 |
66 def make_genbitmaptogglebutton_flat(button): |
67 def make_genbitmaptogglebutton_flat(button): |
67 button.GetBackgroundBrush = gen_mini_GetBackgroundBrush(button) |
68 button.GetBackgroundBrush = gen_mini_GetBackgroundBrush(button) |
68 button.labelDelta = 0 |
69 button.labelDelta = 0 |
69 button.SetBezelWidth(0) |
70 button.SetBezelWidth(0) |
70 button.SetUseFocusIndicator(False) |
71 button.SetUseFocusIndicator(False) |
71 |
72 |
72 def GenerateEmptyBitmap(width, height, color): |
73 # Patch wx.lib.imageutils so that gray is supported on alpha images |
73 # bitmap = wx.EmptyBitmap(width, height) |
74 import wx.lib.imageutils |
74 # dc = wx.MemoryDC(bitmap) |
75 def grayOut(anImage): |
75 # dc.SetPen(wx.Pen(color)) |
76 """ |
76 # dc.SetBrush(wx.Brush(color)) |
77 Convert the given image (in place) to a grayed-out |
77 # dc.DrawRectangle(0, 0, width, height) |
78 version, appropriate for a 'disabled' appearance. |
78 # return bitmap |
79 """ |
79 return wx.Bitmap(os.path.join(CWD, "images", "empty.png")) |
80 factor = 0.7 # 0 < f < 1. Higher is grayer. |
|
81 if anImage.HasMask(): |
|
82 maskColor = (anImage.GetMaskRed(), anImage.GetMaskGreen(), anImage.GetMaskBlue()) |
|
83 else: |
|
84 maskColor = None |
|
85 |
|
86 if anImage.HasAlpha(): |
|
87 AlphaData = anImage.GetAlphaData() |
|
88 else : |
|
89 AlphaData = None |
|
90 |
|
91 data = map(ord, list(anImage.GetData())) |
|
92 |
|
93 for i in range(0, len(data), 3): |
|
94 pixel = (data[i], data[i+1], data[i+2]) |
|
95 pixel = wx.lib.imageutils.makeGray(pixel, factor, maskColor) |
|
96 for x in range(3): |
|
97 data[i+x] = pixel[x] |
|
98 anImage.SetData(''.join(map(chr, data))) |
|
99 |
|
100 if AlphaData is not None: |
|
101 anImage.SetAlphaData(AlphaData) |
|
102 |
|
103 wx.lib.imageutils.grayOut = grayOut |
|
104 |
|
105 class GenBitmapTextButton(wx.lib.buttons.GenBitmapTextButton): |
|
106 def _GetLabelSize(self): |
|
107 return wx.lib.buttons.GenBitmapTextButton._GetLabelSize(self)[:-1] + (False,) |
80 |
108 |
81 class GenStaticBitmap(wx.lib.statbmp.GenStaticBitmap): |
109 class GenStaticBitmap(wx.lib.statbmp.GenStaticBitmap): |
|
110 """ Customized GenStaticBitmap, fix transparency redraw bug on wx2.8/win32, |
|
111 and accept image name as __init__ parameter, fail silently if file do not exist""" |
82 def __init__(self, parent, ID, bitmapname, |
112 def __init__(self, parent, ID, bitmapname, |
83 pos = wx.DefaultPosition, size = wx.DefaultSize, |
113 pos = wx.DefaultPosition, size = wx.DefaultSize, |
84 style = 0, |
114 style = 0, |
85 name = "genstatbmp"): |
115 name = "genstatbmp"): |
86 |
116 |
405 maxx, maxy = sizer.GetMinSize() |
435 maxx, maxy = sizer.GetMinSize() |
406 self.PLCConfig.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, |
436 self.PLCConfig.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, |
407 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, xstart, ystart) |
437 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, xstart, ystart) |
408 |
438 |
409 def RefreshPLCParams(self): |
439 def RefreshPLCParams(self): |
|
440 self.Freeze() |
410 self.ClearSizer(self.PLCParamsSizer) |
441 self.ClearSizer(self.PLCParamsSizer) |
411 |
442 |
412 if self.PluginRoot.HasProjectOpened(): |
443 if self.PluginRoot.HasProjectOpened(): |
413 plcwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1)) |
444 plcwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1)) |
414 plcwindow.SetBackgroundColour(TITLE_COLOUR) |
445 plcwindow.SetBackgroundColour(TITLE_COLOUR) |
481 event.Skip() |
512 event.Skip() |
482 minimizebutton.Bind(wx.EVT_BUTTON, togglewindow, id=minimizebutton_id) |
513 minimizebutton.Bind(wx.EVT_BUTTON, togglewindow, id=minimizebutton_id) |
483 |
514 |
484 self.PLCConfigMainSizer.Layout() |
515 self.PLCConfigMainSizer.Layout() |
485 self.RefreshScrollBars() |
516 self.RefreshScrollBars() |
|
517 self.Thaw() |
486 |
518 |
487 # def GenerateAddButtonSizer(self, plugin, parent, horizontal = True): |
519 # def GenerateAddButtonSizer(self, plugin, parent, horizontal = True): |
488 # if horizontal: |
520 # if horizontal: |
489 # addsizer = wx.FlexGridSizer(cols=len(plugin.PluginMethods)) |
521 # addsizer = wx.FlexGridSizer(cols=len(plugin.PluginMethods)) |
490 # else: |
522 # else: |
510 else: |
542 else: |
511 msizer = wx.FlexGridSizer(cols=1) |
543 msizer = wx.FlexGridSizer(cols=1) |
512 for plugin_method in plugin.PluginMethods: |
544 for plugin_method in plugin.PluginMethods: |
513 if "method" in plugin_method: |
545 if "method" in plugin_method: |
514 id = wx.NewId() |
546 id = wx.NewId() |
515 button = wx.lib.buttons.GenBitmapTextButton(id=id, parent=parent, |
547 button = GenBitmapTextButton(id=id, parent=parent, |
516 bitmap=wx.Bitmap(os.path.join(CWD, "%s24x24.png"%plugin_method.get("bitmap", os.path.join("images", "Unknown")))), label=plugin_method["name"], |
548 bitmap=wx.Bitmap(os.path.join(CWD, "%s24x24.png"%plugin_method.get("bitmap", os.path.join("images", "Unknown")))), label=plugin_method["name"], |
517 name=plugin_method["name"], pos=wx.DefaultPosition, style=wx.NO_BORDER) |
549 name=plugin_method["name"], pos=wx.DefaultPosition, style=wx.NO_BORDER) |
518 button.SetToolTipString(plugin_method["tooltip"]) |
550 button.SetToolTipString(plugin_method["tooltip"]) |
519 button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(plugin, plugin_method["method"]), id=id) |
551 button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(plugin, plugin_method["method"]), id=id) |
520 #hack to force size to mini |
552 #hack to force size to mini |
521 button._GetLabelSize = gen_mini_GetLabelSize(button) |
553 if not plugin_method.get("enabled",True): |
522 #button._GetLabelSize = lambda :(-1,-1,False) |
554 button.Disable() |
523 msizer.AddWindow(button, 0, border=0, flag=0) |
555 msizer.AddWindow(button, 0, border=0, flag=0) |
524 return msizer |
556 return msizer |
525 |
557 |
526 def RefreshPluginTree(self): |
558 def RefreshPluginTree(self): |
|
559 self.Freeze() |
527 self.ClearSizer(self.PluginTreeSizer) |
560 self.ClearSizer(self.PluginTreeSizer) |
528 if self.PluginRoot.HasProjectOpened(): |
561 if self.PluginRoot.HasProjectOpened(): |
529 index = [0] |
562 index = [0] |
530 for child in self.PluginRoot.IECSortedChilds(): |
563 for child in self.PluginRoot.IECSortedChilds(): |
531 self.GenerateTreeBranch(child, index) |
564 self.GenerateTreeBranch(child, index) |
532 if not self.PluginInfos[child]["expanded"]: |
565 if not self.PluginInfos[child]["expanded"]: |
533 self.CollapsePlugin(child) |
566 self.CollapsePlugin(child) |
534 self.PLCConfigMainSizer.Layout() |
567 self.PLCConfigMainSizer.Layout() |
535 self.RefreshScrollBars() |
568 self.RefreshScrollBars() |
|
569 self.Thaw() |
536 |
570 |
537 def ExpandPlugin(self, plugin, force = False): |
571 def ExpandPlugin(self, plugin, force = False): |
538 for child in self.PluginInfos[plugin]["children"]: |
572 for child in self.PluginInfos[plugin]["children"]: |
539 self.PluginTreeSizer.Show(self.PluginInfos[child]["left"]) |
573 self.PluginTreeSizer.Show(self.PluginInfos[child]["left"]) |
540 self.PluginTreeSizer.Show(self.PluginInfos[child]["middle"]) |
574 self.PluginTreeSizer.Show(self.PluginInfos[child]["middle"]) |
580 leftsizer = wx.BoxSizer(wx.VERTICAL) |
614 leftsizer = wx.BoxSizer(wx.VERTICAL) |
581 leftbuttonsizer.AddSizer(leftsizer, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) |
615 leftbuttonsizer.AddSizer(leftsizer, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) |
582 |
616 |
583 rolesizer = wx.BoxSizer(wx.HORIZONTAL) |
617 rolesizer = wx.BoxSizer(wx.HORIZONTAL) |
584 leftsizer.AddSizer(rolesizer, 0, border=0, flag=wx.GROW|wx.RIGHT) |
618 leftsizer.AddSizer(rolesizer, 0, border=0, flag=wx.GROW|wx.RIGHT) |
585 |
|
586 roletext = wx.StaticText(leftwindow, -1) |
|
587 roletext.SetLabel(plugin.PlugHelp) |
|
588 rolesizer.AddWindow(roletext, 0, border=5, flag=wx.RIGHT|wx.ALIGN_LEFT) |
|
589 |
619 |
590 enablebutton_id = wx.NewId() |
620 enablebutton_id = wx.NewId() |
591 enablebutton = wx.lib.buttons.GenBitmapToggleButton(id=enablebutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'Disabled.png')), |
621 enablebutton = wx.lib.buttons.GenBitmapToggleButton(id=enablebutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'Disabled.png')), |
592 name='EnableButton', parent=leftwindow, size=wx.Size(16, 16), pos=wx.Point(0, 0), style=0)#wx.NO_BORDER) |
622 name='EnableButton', parent=leftwindow, size=wx.Size(16, 16), pos=wx.Point(0, 0), style=0)#wx.NO_BORDER) |
593 enablebutton.SetToolTipString("Enable/Disable this plugin") |
623 enablebutton.SetToolTipString("Enable/Disable this plugin") |
600 enablebutton.SetToggle(res) |
630 enablebutton.SetToggle(res) |
601 event.Skip() |
631 event.Skip() |
602 enablebutton.Bind(wx.EVT_BUTTON, toggleenablebutton, id=enablebutton_id) |
632 enablebutton.Bind(wx.EVT_BUTTON, toggleenablebutton, id=enablebutton_id) |
603 rolesizer.AddWindow(enablebutton, 0, border=0, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) |
633 rolesizer.AddWindow(enablebutton, 0, border=0, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) |
604 |
634 |
|
635 roletext = wx.StaticText(leftwindow, -1) |
|
636 roletext.SetLabel(plugin.PlugHelp) |
|
637 rolesizer.AddWindow(roletext, 0, border=5, flag=wx.RIGHT|wx.ALIGN_LEFT) |
605 |
638 |
606 plugin_IECChannel = plugin.BaseParams.getIEC_Channel() |
639 plugin_IECChannel = plugin.BaseParams.getIEC_Channel() |
607 |
640 |
608 iecsizer = wx.BoxSizer(wx.HORIZONTAL) |
641 iecsizer = wx.BoxSizer(wx.HORIZONTAL) |
609 leftsizer.AddSizer(iecsizer, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) |
642 leftsizer.AddSizer(iecsizer, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) |
803 infos["variable_list"].Clear() |
836 infos["variable_list"].Clear() |
804 for location in locations: |
837 for location in locations: |
805 infos["variable_list"].Append(location["NAME"].replace("__", "%").replace("_", ".")) |
838 infos["variable_list"].Append(location["NAME"].replace("__", "%").replace("_", ".")) |
806 self.PLCConfigMainSizer.Layout() |
839 self.PLCConfigMainSizer.Layout() |
807 self.RefreshScrollBars() |
840 self.RefreshScrollBars() |
808 |
841 |
|
842 def RefreshAll(self): |
|
843 self.RefreshPLCParams() |
|
844 self.RefreshPluginTree() |
|
845 |
809 def GetItemChannelChangedFunction(self, plugin, value): |
846 def GetItemChannelChangedFunction(self, plugin, value): |
810 def OnPluginTreeItemChannelChanged(event): |
847 def OnPluginTreeItemChannelChanged(event): |
811 res, StructChanged = plugin.SetParamsAttribute("BaseParams.IEC_Channel", value, self.Log) |
848 res, StructChanged = plugin.SetParamsAttribute("BaseParams.IEC_Channel", value, self.Log) |
812 wx.CallAfter(self.RefreshPluginTree) |
849 wx.CallAfter(self.RefreshPluginTree) |
813 event.Skip() |
850 event.Skip() |
832 return AddPluginMenu |
869 return AddPluginMenu |
833 |
870 |
834 def GetButtonCallBackFunction(self, plugin, method): |
871 def GetButtonCallBackFunction(self, plugin, method): |
835 def OnButtonClick(event): |
872 def OnButtonClick(event): |
836 getattr(plugin,method)(self.Log) |
873 getattr(plugin,method)(self.Log) |
837 self.RefreshVariableLists() |
874 #self.RefreshVariableLists() |
|
875 wx.CallAfter(self.RefreshAll) |
838 event.Skip() |
876 event.Skip() |
839 return OnButtonClick |
877 return OnButtonClick |
840 |
878 |
841 def GetChoiceCallBackFunction(self, choicectrl, plugin, path): |
879 def GetChoiceCallBackFunction(self, choicectrl, plugin, path): |
842 def OnChoiceChanged(event): |
880 def OnChoiceChanged(event): |
1164 # Exception Handler |
1202 # Exception Handler |
1165 #------------------------------------------------------------------------------- |
1203 #------------------------------------------------------------------------------- |
1166 |
1204 |
1167 Max_Traceback_List_Size = 20 |
1205 Max_Traceback_List_Size = 20 |
1168 |
1206 |
1169 def Display_Exception_Dialog(e_type,e_value,e_tb): |
1207 def Display_Exception_Dialog(e_type, e_value, e_tb, bug_report_path): |
1170 trcbck_lst = [] |
1208 trcbck_lst = [] |
1171 for i,line in enumerate(traceback.extract_tb(e_tb)): |
1209 for i,line in enumerate(traceback.extract_tb(e_tb)): |
1172 trcbck = " " + str(i+1) + ". " |
1210 trcbck = " " + str(i+1) + ". " |
1173 if line[0].find(os.getcwd()) == -1: |
1211 if line[0].find(os.getcwd()) == -1: |
1174 trcbck += "file : " + str(line[0]) + ", " |
1212 trcbck += "file : " + str(line[0]) + ", " |
1229 last_tb = get_last_traceback(e_traceback) |
1266 last_tb = get_last_traceback(e_traceback) |
1230 ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno) |
1267 ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno) |
1231 if str(e_value).startswith("!!!"): |
1268 if str(e_value).startswith("!!!"): |
1232 Display_Error_Dialog(e_value) |
1269 Display_Error_Dialog(e_value) |
1233 elif ex not in ignored_exceptions: |
1270 elif ex not in ignored_exceptions: |
1234 result = Display_Exception_Dialog(e_type,e_value,e_traceback) |
1271 date = time.ctime() |
|
1272 bug_report_path = path+os.sep+"bug_report_"+date.replace(':','-').replace(' ','_')+".txt" |
|
1273 result = Display_Exception_Dialog(e_type,e_value,e_traceback,bug_report_path) |
1235 if result: |
1274 if result: |
1236 ignored_exceptions.append(ex) |
1275 ignored_exceptions.append(ex) |
1237 info = { |
1276 info = { |
1238 'app-title' : wx.GetApp().GetAppName(), # app_title |
1277 'app-title' : wx.GetApp().GetAppName(), # app_title |
1239 'app-version' : app_version, |
1278 'app-version' : app_version, |
1241 'wx-platform' : wx.Platform, |
1280 'wx-platform' : wx.Platform, |
1242 'python-version' : platform.python_version(), #sys.version.split()[0], |
1281 'python-version' : platform.python_version(), #sys.version.split()[0], |
1243 'platform' : platform.platform(), |
1282 'platform' : platform.platform(), |
1244 'e-type' : e_type, |
1283 'e-type' : e_type, |
1245 'e-value' : e_value, |
1284 'e-value' : e_value, |
1246 'date' : time.ctime(), |
1285 'date' : date, |
1247 'cwd' : os.getcwd(), |
1286 'cwd' : os.getcwd(), |
1248 } |
1287 } |
1249 if e_traceback: |
1288 if e_traceback: |
1250 info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value) |
1289 info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value) |
1251 last_tb = get_last_traceback(e_traceback) |
1290 last_tb = get_last_traceback(e_traceback) |
1252 exception_locals = last_tb.tb_frame.f_locals # the locals at the level of the stack trace where the exception actually occurred |
1291 exception_locals = last_tb.tb_frame.f_locals # the locals at the level of the stack trace where the exception actually occurred |
1253 info['locals'] = format_namespace(exception_locals) |
1292 info['locals'] = format_namespace(exception_locals) |
1254 if 'self' in exception_locals: |
1293 if 'self' in exception_locals: |
1255 info['self'] = format_namespace(exception_locals['self'].__dict__) |
1294 info['self'] = format_namespace(exception_locals['self'].__dict__) |
1256 |
1295 |
1257 output = open(path+os.sep+"bug_report_"+info['date'].replace(':','-').replace(' ','_')+".txt",'w') |
1296 output = open(bug_report_path,'w') |
1258 lst = info.keys() |
1297 lst = info.keys() |
1259 lst.sort() |
1298 lst.sort() |
1260 for a in lst: |
1299 for a in lst: |
1261 output.write(a+":\n"+str(info[a])+"\n\n") |
1300 output.write(a+":\n"+str(info[a])+"\n\n") |
1262 |
1301 |