Beremiz.py
changeset 650 26236e691330
parent 636 35c59bfc54f2
child 662 037d2beecfb9
equal deleted inserted replaced
649:c48023b6f0ec 650:26236e691330
    24 
    24 
    25 
    25 
    26 updateinfo_url = None
    26 updateinfo_url = None
    27 
    27 
    28 import os, sys, getopt, wx
    28 import os, sys, getopt, wx
       
    29 import __builtin__
    29 from wx.lib.agw.advancedsplash import AdvancedSplash
    30 from wx.lib.agw.advancedsplash import AdvancedSplash
    30 import tempfile
    31 import tempfile
    31 import shutil
    32 import shutil
    32 import random
    33 import random
    33 import time
    34 import time
    68     else:
    69     else:
    69         projectOpen = None
    70         projectOpen = None
    70         buildpath = None
    71         buildpath = None
    71     
    72     
    72     if os.path.exists("BEREMIZ_DEBUG"):
    73     if os.path.exists("BEREMIZ_DEBUG"):
    73         __builtins__.BMZ_DBG = True
    74         __builtin__.__dict__["BMZ_DBG"] = True
    74     else :
    75     else :
    75         __builtins__.BMZ_DBG = False
    76         __builtin__.__dict__["BMZ_DBG"] = False
    76 
    77 
    77     app = wx.PySimpleApp(redirect=BMZ_DBG)
    78     app = wx.PySimpleApp(redirect=BMZ_DBG)
    78     app.SetAppName('beremiz')
    79     app.SetAppName('beremiz')
    79     wx.InitAllImageHandlers()
    80     wx.InitAllImageHandlers()
    80     
    81     
   104         splash.SetText(text=updateinfo)
   105         splash.SetText(text=updateinfo)
   105         wx.Yield()
   106         wx.Yield()
   106 
   107 
   107 # Import module for internationalization
   108 # Import module for internationalization
   108 import gettext
   109 import gettext
   109 import __builtin__
       
   110 
   110 
   111 # Get folder containing translation files
   111 # Get folder containing translation files
   112 localedir = os.path.join(CWD,"locale")
   112 localedir = os.path.join(CWD,"locale")
   113 # Get the default language
   113 # Get the default language
   114 langid = wx.LANGUAGE_DEFAULT
   114 langid = wx.LANGUAGE_DEFAULT
   146 import types, time, re, platform, time, traceback, commands
   146 import types, time, re, platform, time, traceback, commands
   147 from plugger import PluginsRoot, MATIEC_ERROR_MODEL
   147 from plugger import PluginsRoot, MATIEC_ERROR_MODEL
   148 from wxPopen import ProcessLogger
   148 from wxPopen import ProcessLogger
   149 
   149 
   150 from docutils import *
   150 from docutils import *
   151 from PLCOpenEditor import IDEFrame, Viewer, AppendMenu, TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE, SCALING, PAGETITLES
   151 from PLCOpenEditor import IDEFrame, Viewer, AppendMenu, TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, TYPESTREE, INSTANCESTREE, LIBRARYTREE, SCALING, PAGETITLES, USE_AUI
   152 from PLCControler import LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
   152 from PLCControler import LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
   153 
   153 
   154 SCROLLBAR_UNIT = 10
   154 SCROLLBAR_UNIT = 10
   155 WINDOW_COLOUR = wx.Colour(240,240,240)
   155 WINDOW_COLOUR = wx.Colour(240,240,240)
   156 TITLE_COLOUR = wx.Colour(200,200,220)
   156 TITLE_COLOUR = wx.Colour(200,200,220)
   421             accels += [wx.AcceleratorEntry(wx.ACCEL_NORMAL, shortcut,newid)]
   421             accels += [wx.AcceleratorEntry(wx.ACCEL_NORMAL, shortcut,newid)]
   422         
   422         
   423         self.SetAcceleratorTable(wx.AcceleratorTable(accels))
   423         self.SetAcceleratorTable(wx.AcceleratorTable(accels))
   424         
   424         
   425         self.PLCConfig = wx.ScrolledWindow(id=ID_BEREMIZPLCCONFIG,
   425         self.PLCConfig = wx.ScrolledWindow(id=ID_BEREMIZPLCCONFIG,
   426               name='PLCConfig', parent=self.LeftNoteBook, pos=wx.Point(0, 0),
   426               name='PLCConfig', parent=self.BottomNoteBook, pos=wx.Point(0, 0),
   427               size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL)
   427               size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL)
   428         self.PLCConfig.SetBackgroundColour(wx.WHITE)
   428         self.PLCConfig.SetBackgroundColour(wx.WHITE)
   429         self.PLCConfig.Bind(wx.EVT_LEFT_DOWN, self.OnPanelLeftDown)
   429         self.PLCConfig.Bind(wx.EVT_LEFT_DOWN, self.OnPanelLeftDown)
   430         self.PLCConfig.Bind(wx.EVT_SIZE, self.OnMoveWindow)
   430         self.PLCConfig.Bind(wx.EVT_SIZE, self.OnMoveWindow)
   431         self.PLCConfig.Bind(wx.EVT_MOUSEWHEEL, self.OnPLCConfigScroll)
   431         self.PLCConfig.Bind(wx.EVT_MOUSEWHEEL, self.OnPLCConfigScroll)
   434         self.LogConsole = wx.TextCtrl(id=ID_BEREMIZLOGCONSOLE, value='',
   434         self.LogConsole = wx.TextCtrl(id=ID_BEREMIZLOGCONSOLE, value='',
   435                   name='LogConsole', parent=self.BottomNoteBook, pos=wx.Point(0, 0),
   435                   name='LogConsole', parent=self.BottomNoteBook, pos=wx.Point(0, 0),
   436                   size=wx.Size(0, 0), style=wx.TE_MULTILINE|wx.TE_RICH2)
   436                   size=wx.Size(0, 0), style=wx.TE_MULTILINE|wx.TE_RICH2)
   437         self.LogConsole.Bind(wx.EVT_LEFT_DCLICK, self.OnLogConsoleDClick)
   437         self.LogConsole.Bind(wx.EVT_LEFT_DCLICK, self.OnLogConsoleDClick)
   438         self.BottomNoteBook.AddPage(self.LogConsole, _("Log Console"))
   438         self.BottomNoteBook.AddPage(self.LogConsole, _("Log Console"))
   439         self.BottomNoteBook.Split(self.BottomNoteBook.GetPageIndex(self.LogConsole), wx.RIGHT)
   439         if USE_AUI:
       
   440             self.BottomNoteBook.Split(self.BottomNoteBook.GetPageIndex(self.LogConsole), wx.RIGHT)
   440         
   441         
   441         self._init_beremiz_sizers()
   442         self._init_beremiz_sizers()
   442 
   443 
   443     def __init__(self, parent, projectOpen=None, buildpath=None, plugin_root=None, debug=True):
   444     def __init__(self, parent, projectOpen=None, buildpath=None, plugin_root=None, debug=True):
   444         IDEFrame.__init__(self, parent, debug)
   445         IDEFrame.__init__(self, parent, debug)
   451         self.DisableEvents = False
   452         self.DisableEvents = False
   452         # Variable allowing disabling of PLCConfig scroll when Popup shown 
   453         # Variable allowing disabling of PLCConfig scroll when Popup shown 
   453         self.ScrollingEnabled = True
   454         self.ScrollingEnabled = True
   454         
   455         
   455         self.PluginInfos = {}
   456         self.PluginInfos = {}
       
   457         
       
   458         # Define Tree item icon list
       
   459         self.LocationImageList = wx.ImageList(16, 16)
       
   460         self.LocationImageDict = {}
       
   461         
       
   462         # Icons for location items
       
   463         for imgname, itemtype in [
       
   464             ("CONFIGURATION", LOCATION_PLUGIN),
       
   465             ("RESOURCE",      LOCATION_MODULE),
       
   466             ("PROGRAM",       LOCATION_GROUP),
       
   467             ("VAR_INPUT",     LOCATION_VAR_INPUT),
       
   468             ("VAR_OUTPUT",    LOCATION_VAR_OUTPUT),
       
   469             ("VAR_LOCAL",     LOCATION_VAR_MEMORY)]:
       
   470             self.LocationImageDict[itemtype]=self.LocationImageList.Add(wx.Bitmap(os.path.join(base_folder, "plcopeneditor", 'Images', '%s.png'%imgname)))
       
   471         
       
   472         # Add beremiz's icon in top left corner of the frame
       
   473         self.SetIcon(wx.Icon(Bpath( "images", "brz.ico"), wx.BITMAP_TYPE_ICO))
   456         
   474         
   457         if projectOpen is not None and os.path.isdir(projectOpen):
   475         if projectOpen is not None and os.path.isdir(projectOpen):
   458             self.PluginRoot = PluginsRoot(self, self.Log)
   476             self.PluginRoot = PluginsRoot(self, self.Log)
   459             self.Controler = self.PluginRoot
   477             self.Controler = self.PluginRoot
   460             result = self.PluginRoot.LoadProject(projectOpen, buildpath)
   478             result = self.PluginRoot.LoadProject(projectOpen, buildpath)
   470             if plugin_root is not None:
   488             if plugin_root is not None:
   471                 self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
   489                 self._Refresh(TYPESTREE, INSTANCESTREE, LIBRARYTREE)
   472                 self.RefreshAll()
   490                 self.RefreshAll()
   473         if self.EnableDebug:
   491         if self.EnableDebug:
   474             self.DebugVariablePanel.SetDataProducer(self.PluginRoot)
   492             self.DebugVariablePanel.SetDataProducer(self.PluginRoot)
   475                 
       
   476         
       
   477         # Add beremiz's icon in top left corner of the frame
       
   478         self.SetIcon(wx.Icon(Bpath( "images", "brz.ico"), wx.BITMAP_TYPE_ICO))
       
   479         
   493         
   480         self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
   494         self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
   481         
   495         
   482         self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
   496         self._Refresh(TITLE, TOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU)
   483         self.LogConsole.SetFocus()
   497         self.LogConsole.SetFocus()
   814         if locations_infos is not None:
   828         if locations_infos is not None:
   815             self.CollapseLocation(locations_infos, "root", force)
   829             self.CollapseLocation(locations_infos, "root", force)
   816             if force:
   830             if force:
   817                 locations_infos["root"]["expanded"] = False
   831                 locations_infos["root"]["expanded"] = False
   818 
   832 
   819     def ExpandLocation(self, locations_infos, group, force = False):
   833     def ExpandLocation(self, locations_infos, group, force = False, refresh_size=True):
   820         for child in locations_infos[group]["children"]:
   834         locations_infos[group]["expanded"] = True
   821             locations_infos[child]["left"].Show()
   835         if group == "root":
   822             locations_infos[child]["right"].Show()
   836             if locations_infos[group]["left"] is not None:
   823             if force or locations_infos[child]["expanded"]:
   837                 locations_infos[group]["left"].Show()
   824                 self.ExpandLocation(locations_infos, child, force)
   838             if locations_infos[group]["right"] is not None:
   825                 if force:
   839                 locations_infos[group]["right"].Show()
   826                     locations_infos[child]["expanded"] = True
   840         elif locations_infos["root"]["left"] is not None:
   827     
   841             locations_infos["root"]["left"].Expand(locations_infos[group]["item"])
   828     def CollapseLocation(self, locations_infos, group, force = False):
       
   829         for child in locations_infos[group]["children"]:
       
   830             locations_infos[child]["left"].Hide()
       
   831             locations_infos[child]["right"].Hide()
       
   832             self.CollapseLocation(locations_infos, child, force)
       
   833             if force:
   842             if force:
   834                 locations_infos[child]["expanded"] = False
   843                 for child in locations_infos[group]["children"]:
   835 
   844                     self.ExpandLocation(locations_infos, child, force, False)
       
   845         if locations_infos["root"]["left"] is not None and refresh_size:
       
   846             self.RefreshTreeCtrlSize(locations_infos["root"]["left"])
       
   847         
       
   848     def CollapseLocation(self, locations_infos, group, force = False, refresh_size=True):
       
   849         locations_infos[group]["expanded"] = False
       
   850         if group == "root":
       
   851             if locations_infos[group]["left"] is not None:
       
   852                 locations_infos[group]["left"].Hide()
       
   853             if locations_infos[group]["right"] is not None:
       
   854                 locations_infos[group]["right"].Hide()
       
   855         elif locations_infos["root"]["left"] is not None:
       
   856             locations_infos["root"]["left"].Collapse(locations_infos[group]["item"])
       
   857             if force:
       
   858                 for child in locations_infos[group]["children"]:
       
   859                     self.CollapseLocation(locations_infos, child, force, False)
       
   860         if locations_infos["root"]["left"] is not None and refresh_size:
       
   861             self.RefreshTreeCtrlSize(locations_infos["root"]["left"])
       
   862                 
   836     def GenerateTreeBranch(self, plugin):
   863     def GenerateTreeBranch(self, plugin):
   837         leftwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
   864         leftwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
   838         if plugin.PlugTestModified():
   865         if plugin.PlugTestModified():
   839             bkgdclr=CHANGED_WINDOW_COLOUR
   866             bkgdclr=CHANGED_WINDOW_COLOUR
   840         else:
   867         else:
   849         plugin_locations = []
   876         plugin_locations = []
   850         if len(self.PluginInfos[plugin]["children"]) == 0:
   877         if len(self.PluginInfos[plugin]["children"]) == 0:
   851             plugin_locations = plugin.GetVariableLocationTree()["children"]
   878             plugin_locations = plugin.GetVariableLocationTree()["children"]
   852             if not self.PluginInfos[plugin].has_key("locations_infos"):
   879             if not self.PluginInfos[plugin].has_key("locations_infos"):
   853                 self.PluginInfos[plugin]["locations_infos"] = {"root": {"expanded" : False}}
   880                 self.PluginInfos[plugin]["locations_infos"] = {"root": {"expanded" : False}}
   854                 
   881             
       
   882             self.PluginInfos[plugin]["locations_infos"]["root"]["left"] = None
       
   883             self.PluginInfos[plugin]["locations_infos"]["root"]["right"] = None
   855             self.PluginInfos[plugin]["locations_infos"]["root"]["children"] = []
   884             self.PluginInfos[plugin]["locations_infos"]["root"]["children"] = []
   856         
   885         
   857         self.PluginTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW)
   886         self.PluginTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW)
   858         
   887         
   859         leftwindowsizer = wx.FlexGridSizer(cols=1, rows=2)
   888         leftwindowsizer = wx.FlexGridSizer(cols=1, rows=2)
  1045         self.PluginInfos[plugin]["right"] = rightwindow
  1074         self.PluginInfos[plugin]["right"] = rightwindow
  1046         for child in self.PluginInfos[plugin]["children"]:
  1075         for child in self.PluginInfos[plugin]["children"]:
  1047             self.GenerateTreeBranch(child)
  1076             self.GenerateTreeBranch(child)
  1048             if not self.PluginInfos[child]["expanded"]:
  1077             if not self.PluginInfos[child]["expanded"]:
  1049                 self.CollapsePlugin(child)
  1078                 self.CollapsePlugin(child)
       
  1079         
  1050         if len(plugin_locations) > 0:
  1080         if len(plugin_locations) > 0:
  1051             locations_infos = self.PluginInfos[plugin]["locations_infos"]
  1081             locations_infos = self.PluginInfos[plugin]["locations_infos"]
       
  1082             treectrl = wx.TreeCtrl(self.PLCConfig, -1, size=wx.DefaultSize, 
       
  1083                                    style=wx.TR_HAS_BUTTONS|wx.TR_SINGLE|wx.NO_BORDER|wx.TR_HIDE_ROOT|wx.TR_NO_LINES|wx.TR_LINES_AT_ROOT)
       
  1084             treectrl.SetImageList(self.LocationImageList)
       
  1085             treectrl.Bind(wx.EVT_TREE_BEGIN_DRAG, self.GenerateLocationBeginDragFunction(locations_infos))
       
  1086             treectrl.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.GenerateLocationExpandCollapseFunction(locations_infos, True))
       
  1087             treectrl.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.GenerateLocationExpandCollapseFunction(locations_infos, False))
       
  1088             
       
  1089             treectrl.AddRoot("")
       
  1090             self.PluginTreeSizer.AddWindow(treectrl, 0, border=0, flag=0)
       
  1091             
       
  1092             rightwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
       
  1093             rightwindow.SetBackgroundColour(wx.WHITE)
       
  1094             self.PluginTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
       
  1095             
       
  1096             locations_infos["root"]["left"] = treectrl
       
  1097             locations_infos["root"]["right"] = rightwindow
  1052             for location in plugin_locations:
  1098             for location in plugin_locations:
  1053                 locations_infos["root"]["children"].append("root.%s" % location["name"])
  1099                 locations_infos["root"]["children"].append("root.%s" % location["name"])
  1054                 self.GenerateLocationTreeBranch(locations_infos, "root", location)
  1100                 self.GenerateLocationTreeBranch(treectrl, treectrl.GetRootItem(), locations_infos, "root", location)
  1055             if not locations_infos["root"]["expanded"]:
  1101                 treectrl.Expand(treectrl.GetRootItem())
  1056                 self.CollapseLocation(locations_infos, "root")
  1102             if locations_infos["root"]["expanded"]:
  1057         
  1103                 self.ExpandLocation(locations_infos, "root")
  1058     LOCATION_BITMAP = {LOCATION_PLUGIN: "CONFIGURATION",
  1104             else:
  1059                        LOCATION_MODULE: "RESOURCE",
  1105                 self.RefreshTreeCtrlSize(treectrl)
  1060                        LOCATION_GROUP: "PROGRAM",
  1106     
  1061                        LOCATION_VAR_INPUT: "VAR_INPUT",
  1107     def GenerateLocationTreeBranch(self, treectrl, root, locations_infos, parent, location):
  1062                        LOCATION_VAR_OUTPUT: "VAR_OUTPUT",
       
  1063                        LOCATION_VAR_MEMORY: "VAR_LOCAL"}
       
  1064     
       
  1065     def GenerateLocationTreeBranch(self, locations_infos, parent, location):
       
  1066         leftwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
       
  1067         self.PluginTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW)
       
  1068         
       
  1069         leftwindowsizer = wx.BoxSizer(wx.HORIZONTAL)
       
  1070         leftwindow.SetSizer(leftwindowsizer)
       
  1071         
       
  1072         rightwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1))
       
  1073         self.PluginTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW)
       
  1074         
       
  1075         location_name = "%s.%s" % (parent, location["name"])
  1108         location_name = "%s.%s" % (parent, location["name"])
  1076         if not locations_infos.has_key(location_name):
  1109         if not locations_infos.has_key(location_name):
  1077             locations_infos[location_name] = {"expanded" : False}
  1110             locations_infos[location_name] = {"expanded" : False}
  1078         
  1111         
  1079         if location["type"] in [LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP]:
  1112         if location["type"] in [LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY]:
  1080             if location["type"] == LOCATION_GROUP:
  1113             label = "%(name)s (%(location)s)" % location
  1081                 leftwindow.SetBackgroundColour(wx.WHITE)
  1114         elif location["location"] != "":
  1082                 rightwindow.SetBackgroundColour(wx.WHITE)
  1115             label = "%(location)s: %(name)s" % location
  1083             else:
       
  1084                 leftwindow.SetBackgroundColour(WINDOW_COLOUR)
       
  1085                 rightwindow.SetBackgroundColour(WINDOW_COLOUR)
       
  1086             
       
  1087             st = wx.StaticText(leftwindow, -1)
       
  1088             st.SetFont(wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
       
  1089             st.SetLabel(location["location"])
       
  1090             leftwindowsizer.AddWindow(st, 0, border=5, flag=wx.RIGHT)
       
  1091             
       
  1092             expandbutton_id = wx.NewId()
       
  1093             expandbutton = wx.lib.buttons.GenBitmapToggleButton(id=expandbutton_id, bitmap=wx.Bitmap(Bpath( 'images', 'plus.png')),
       
  1094                   name='ExpandButton', parent=leftwindow, pos=wx.Point(0, 0),
       
  1095                   size=wx.Size(13, 13), style=wx.NO_BORDER)
       
  1096             expandbutton.labelDelta = 0
       
  1097             expandbutton.SetBezelWidth(0)
       
  1098             expandbutton.SetUseFocusIndicator(False)
       
  1099             expandbutton.SetBitmapSelected(wx.Bitmap(Bpath( 'images', 'minus.png')))
       
  1100             expandbutton.SetToggle(locations_infos[location_name]["expanded"])
       
  1101                 
       
  1102             if len(location["children"]) > 0:
       
  1103                 def togglebutton(event):
       
  1104                     if expandbutton.GetToggle():
       
  1105                         self.ExpandLocation(locations_infos, location_name)
       
  1106                     else:
       
  1107                         self.CollapseLocation(locations_infos, location_name)
       
  1108                     locations_infos[location_name]["expanded"] = expandbutton.GetToggle()
       
  1109                     self.PLCConfigMainSizer.Layout()
       
  1110                     self.RefreshScrollBars()
       
  1111                     event.Skip()
       
  1112                 expandbutton.Bind(wx.EVT_BUTTON, togglebutton, id=expandbutton_id)
       
  1113             else:
       
  1114                 expandbutton.Enable(False)
       
  1115             leftwindowsizer.AddWindow(expandbutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
       
  1116             
       
  1117         else:
  1116         else:
  1118             leftwindow.SetBackgroundColour(wx.WHITE)
  1117             label = location["name"]
  1119             rightwindow.SetBackgroundColour(wx.WHITE)
  1118         item = treectrl.AppendItem(root, label)
  1120             
  1119         treectrl.SetPyData(item, location_name)
  1121             leftwindowsizer.Add(wx.Size(20, 16), 0)
  1120         treectrl.SetItemImage(item, self.LocationImageDict[location["type"]])
  1122         
  1121         
  1123         sb = wx.StaticBitmap(leftwindow, -1)
  1122         locations_infos[location_name]["item"] = item
  1124         icon = location.get("icon")
       
  1125         if icon is None:
       
  1126             icon = os.path.join(base_folder, "plcopeneditor", 'Images', '%s.png' % self.LOCATION_BITMAP[location["type"]])
       
  1127         sb.SetBitmap(wx.Bitmap(icon))
       
  1128         leftwindowsizer.AddWindow(sb, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
       
  1129         
       
  1130         st_id = wx.NewId()
       
  1131         st = wx.StaticText(leftwindow, st_id, size=wx.DefaultSize, style=wx.NO_BORDER)
       
  1132         label = location["name"]
       
  1133         if location["type"] in [LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY]:
       
  1134             label += " (%s)" % location["location"]
       
  1135             infos = location.copy()
       
  1136             infos.pop("children")
       
  1137             st.SetFont(wx.Font(faces["size"] * 0.5, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = faces["helv"]))
       
  1138             leftcallback = self.GenerateLocationLeftDownFunction(infos)
       
  1139             st.Bind(wx.EVT_LEFT_DOWN, leftcallback)
       
  1140             sb.Bind(wx.EVT_LEFT_DOWN, leftcallback)
       
  1141         elif location["type"] == LOCATION_GROUP:
       
  1142             st.SetFont(wx.Font(faces["size"] * 0.6, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = faces["helv"]))
       
  1143         else:
       
  1144             st.SetFont(wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"]))
       
  1145         st.SetLabel(label)
       
  1146         leftwindowsizer.AddWindow(st, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL)
       
  1147         
       
  1148         locations_infos[location_name]["left"] = leftwindow
       
  1149         locations_infos[location_name]["right"] = rightwindow
       
  1150         locations_infos[location_name]["children"] = []
  1123         locations_infos[location_name]["children"] = []
       
  1124         infos = location.copy()
       
  1125         infos.pop("children")
       
  1126         locations_infos[location_name]["infos"] = infos
  1151         for child in location["children"]:
  1127         for child in location["children"]:
  1152             child_name = "%s.%s" % (location_name, child["name"])
  1128             child_name = "%s.%s" % (location_name, child["name"])
  1153             locations_infos[location_name]["children"].append(child_name)
  1129             locations_infos[location_name]["children"].append(child_name)
  1154             self.GenerateLocationTreeBranch(locations_infos, location_name, child)
  1130             self.GenerateLocationTreeBranch(treectrl, item, locations_infos, location_name, child)
  1155         if not locations_infos[location_name]["expanded"]:
  1131         if locations_infos[location_name]["expanded"]:
  1156             self.CollapseLocation(locations_infos, location_name)
  1132             self.ExpandLocation(locations_infos, location_name)
  1157     
  1133     
  1158     def GenerateLocationLeftDownFunction(self, infos):
  1134     def GenerateLocationBeginDragFunction(self, locations_infos):
  1159         def OnLocationLeftDownFunction(event):
  1135         def OnLocationBeginDragFunction(event):
  1160             data = wx.TextDataObject(str((infos["location"], "location", infos["IEC_type"], infos["name"], infos["description"])))
  1136             item = event.GetItem()
  1161             dragSource = wx.DropSource(self)
  1137             location_name = locations_infos["root"]["left"].GetPyData(item)
  1162             dragSource.SetData(data)
  1138             if location_name is not None:
  1163             dragSource.DoDragDrop()
  1139                 infos = locations_infos[location_name]["infos"]
       
  1140                 if infos["type"] in [LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY]:
       
  1141                     data = wx.TextDataObject(str((infos["location"], "location", infos["IEC_type"], infos["name"], infos["description"])))
       
  1142                     dragSource = wx.DropSource(self)
       
  1143                     dragSource.SetData(data)
       
  1144                     dragSource.DoDragDrop()
       
  1145         return OnLocationBeginDragFunction
       
  1146     
       
  1147     def RefreshTreeCtrlSize(self, treectrl):
       
  1148         rect = self.GetTreeCtrlItemRect(treectrl, treectrl.GetRootItem())
       
  1149         treectrl.SetMinSize(wx.Size(max(rect.width, rect.x + rect.width) + 20, max(rect.height, rect.y + rect.height) + 10))
       
  1150         self.PLCConfigMainSizer.Layout()
       
  1151         self.PLCConfig.Refresh()
       
  1152     
       
  1153     def GetTreeCtrlItemRect(self, treectrl, item):
       
  1154         item_rect = treectrl.GetBoundingRect(item, True)
       
  1155         if item_rect is not None:
       
  1156             minx, miny = item_rect.x, item_rect.y
       
  1157             maxx, maxy = item_rect.x + item_rect.width, item_rect.y + item_rect.height
       
  1158         else:
       
  1159             minx = miny = maxx = maxy = 0
       
  1160         
       
  1161         if treectrl.ItemHasChildren(item) and (item == treectrl.GetRootItem() or treectrl.IsExpanded(item)):
       
  1162             if wx.VERSION >= (2, 6, 0):
       
  1163                 child, item_cookie = treectrl.GetFirstChild(item)
       
  1164             else:
       
  1165                 child, item_cookie = treectrl.GetFirstChild(item, 0)
       
  1166             while child.IsOk():
       
  1167                 child_rect = self.GetTreeCtrlItemRect(treectrl, child)
       
  1168                 minx = min(minx, child_rect.x)
       
  1169                 miny = min(miny, child_rect.y)
       
  1170                 maxx = max(maxx, child_rect.x + child_rect.width)
       
  1171                 maxy = max(maxy, child_rect.y + child_rect.height)
       
  1172                 child, item_cookie = treectrl.GetNextChild(item, item_cookie)
       
  1173                 
       
  1174         return wx.Rect(minx, miny, maxx - minx, maxy - miny)
       
  1175     
       
  1176     def GenerateLocationExpandCollapseFunction(self, locations_infos, expand):
       
  1177         def OnLocationExpandedFunction(event):
       
  1178             item = event.GetItem()
       
  1179             location_name = locations_infos["root"]["left"].GetPyData(item)
       
  1180             if location_name is not None:
       
  1181                 locations_infos[location_name]["expanded"] = expand
       
  1182                 self.RefreshTreeCtrlSize(locations_infos["root"]["left"])
  1164             event.Skip()
  1183             event.Skip()
  1165         return OnLocationLeftDownFunction
  1184         return OnLocationExpandedFunction
  1166     
  1185     
  1167     def RefreshAll(self):
  1186     def RefreshAll(self):
  1168         self.RefreshPLCParams()
  1187         self.RefreshPLCParams()
  1169         self.RefreshPluginTree()
  1188         self.RefreshPluginTree()
  1170         
  1189