etherlab/ConfigEditor.py
changeset 2429 15f18dc8b56a
parent 2406 ffd091b51cd0
child 2437 105c20fdeb19
equal deleted inserted replaced
2428:e0f16317668e 2429:15f18dc8b56a
     7 #                          RTES Lab : CRKim, JBLee, youcu
     7 #                          RTES Lab : CRKim, JBLee, youcu
     8 #                          Higen Motor : Donggu Kang
     8 #                          Higen Motor : Donggu Kang
     9 #
     9 #
    10 # See COPYING file for copyrights details.
    10 # See COPYING file for copyrights details.
    11 
    11 
       
    12 from __future__ import absolute_import
    12 import os
    13 import os
    13 import re
    14 import re
    14 from types import TupleType
    15 from types import TupleType
    15 
    16 
    16 import wx
    17 import wx
    18 import wx.gizmos
    19 import wx.gizmos
    19 import wx.lib.buttons
    20 import wx.lib.buttons
    20 
    21 
    21 from plcopen.structures import IEC_KEYWORDS, TestIdentifier
    22 from plcopen.structures import IEC_KEYWORDS, TestIdentifier
    22 from controls import CustomGrid, CustomTable, FolderTree
    23 from controls import CustomGrid, CustomTable, FolderTree
       
    24 from controls.CustomStyledTextCtrl import NAVIGATION_KEYS
    23 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor, SCROLLBAR_UNIT
    25 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor, SCROLLBAR_UNIT
    24 from util.BitmapLibrary import GetBitmap
    26 from util.BitmapLibrary import GetBitmap
    25 from controls.CustomStyledTextCtrl import NAVIGATION_KEYS
    27 from util.TranslationCatalogs import NoTranslate
    26 
    28 
    27 # -----------------------------------------------------------------------
    29 # -----------------------------------------------------------------------
    28 from EtherCATManagementEditor import EtherCATManagementTreebook, MasterStatePanelClass
    30 from etherlab.EtherCATManagementEditor import EtherCATManagementTreebook, MasterStatePanelClass
    29 # -----------------------------------------------------------------------
    31 # -----------------------------------------------------------------------
    30 
    32 
    31 [ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE] = range(3)
    33 [ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE] = range(3)
       
    34 
    32 
    35 
    33 def AppendMenu(parent, help, id, kind, text):
    36 def AppendMenu(parent, help, id, kind, text):
    34     if wx.VERSION >= (2, 6, 0):
    37     if wx.VERSION >= (2, 6, 0):
    35         parent.Append(help=help, id=id, kind=kind, text=text)
    38         parent.Append(help=help, id=id, kind=kind, text=text)
    36     else:
    39     else:
    37         parent.Append(helpString=help, id=id, kind=kind, item=text)
    40         parent.Append(helpString=help, id=id, kind=kind, item=text)
    38 
    41 
       
    42 
    39 def GetVariablesTableColnames(position=False):
    43 def GetVariablesTableColnames(position=False):
    40     _ = lambda x : x
    44     _ = NoTranslate
    41     colname = ["#"]
    45     colname = ["#"]
    42     if position:
    46     if position:
    43         colname.append(_("Position"))
    47         colname.append(_("Position"))
    44     return colname + [_("Name"), _("Index"), _("SubIndex"), _("Type"), _("Access")]
    48     return colname + [_("Name"), _("Index"), _("SubIndex"), _("Type"), _("Access")]
    45 
    49 
       
    50 
    46 ACCESS_TYPES = {
    51 ACCESS_TYPES = {
    47     'ro': 'R',
    52     'ro': 'R',
    48     'wo': 'W',
    53     'wo': 'W',
    49     'rw': 'R/W'}
    54     'rw': 'R/W'}
       
    55 
    50 
    56 
    51 def GetAccessValue(access, pdo_mapping):
    57 def GetAccessValue(access, pdo_mapping):
    52     value = "SDO: %s" % ACCESS_TYPES.get(access, "")
    58     value = "SDO: %s" % ACCESS_TYPES.get(access, "")
    53     if pdo_mapping != "":
    59     if pdo_mapping != "":
    54         value += ", PDO: %s" % pdo_mapping
    60         value += ", PDO: %s" % pdo_mapping
    55     return value
    61     return value
    56 
    62 
       
    63 
    57 VARIABLES_FILTERS = [
    64 VARIABLES_FILTERS = [
    58     (_("All"), (0x0000, 0xffff)),
    65     (_("All"), (0x0000, 0xffff)),
    59     (_("Communication Parameters"), (0x1000, 0x1fff)),
    66     (_("Communication Parameters"), (0x1000, 0x1fff)),
    60     (_("Manufacturer Specific"), (0x2000, 0x5fff)),
    67     (_("Manufacturer Specific"), (0x2000, 0x5fff)),
    61     (_("Standardized Device Profile"), (0x6000, 0x9fff))]
    68     (_("Standardized Device Profile"), (0x6000, 0x9fff))]
    64 
    71 
    65 ETHERCAT_INDEX_MODEL = re.compile("#x([0-9a-fA-F]{0,4})$")
    72 ETHERCAT_INDEX_MODEL = re.compile("#x([0-9a-fA-F]{0,4})$")
    66 ETHERCAT_SUBINDEX_MODEL = re.compile("#x([0-9a-fA-F]{0,2})$")
    73 ETHERCAT_SUBINDEX_MODEL = re.compile("#x([0-9a-fA-F]{0,2})$")
    67 LOCATION_MODEL = re.compile("(?:%[IQM](?:[XBWLD]?([0-9]+(?:\.[0-9]+)*)))$")
    74 LOCATION_MODEL = re.compile("(?:%[IQM](?:[XBWLD]?([0-9]+(?:\.[0-9]+)*)))$")
    68 
    75 
       
    76 
    69 class NodeVariablesSizer(wx.FlexGridSizer):
    77 class NodeVariablesSizer(wx.FlexGridSizer):
    70     
    78 
    71     def __init__(self, parent, controler, position_column=False):
    79     def __init__(self, parent, controler, position_column=False):
    72         wx.FlexGridSizer.__init__(self, cols=1, hgap=0, rows=2, vgap=5)
    80         wx.FlexGridSizer.__init__(self, cols=1, hgap=0, rows=2, vgap=5)
    73         self.AddGrowableCol(0)
    81         self.AddGrowableCol(0)
    74         self.AddGrowableRow(1)
    82         self.AddGrowableRow(1)
    75         
    83 
    76         self.Controler = controler
    84         self.Controler = controler
    77         self.PositionColumn = position_column
    85         self.PositionColumn = position_column
    78         
    86 
    79         self.VariablesFilter = wx.ComboBox(parent, style=wx.TE_PROCESS_ENTER)
    87         self.VariablesFilter = wx.ComboBox(parent, style=wx.TE_PROCESS_ENTER)
    80         self.VariablesFilter.Bind(wx.EVT_COMBOBOX, self.OnVariablesFilterChanged)
    88         self.VariablesFilter.Bind(wx.EVT_COMBOBOX, self.OnVariablesFilterChanged)
    81         self.VariablesFilter.Bind(wx.EVT_TEXT_ENTER, self.OnVariablesFilterChanged)
    89         self.VariablesFilter.Bind(wx.EVT_TEXT_ENTER, self.OnVariablesFilterChanged)
    82         self.VariablesFilter.Bind(wx.EVT_CHAR, self.OnVariablesFilterKeyDown)
    90         self.VariablesFilter.Bind(wx.EVT_CHAR, self.OnVariablesFilterKeyDown)
    83         self.AddWindow(self.VariablesFilter, flag=wx.GROW)
    91         self.AddWindow(self.VariablesFilter, flag=wx.GROW)
    84         
    92 
    85         self.VariablesGrid = wx.gizmos.TreeListCtrl(parent, 
    93         self.VariablesGrid = wx.gizmos.TreeListCtrl(parent,
    86                 style=wx.TR_DEFAULT_STYLE |
    94                                                     style=wx.TR_DEFAULT_STYLE |
    87                       wx.TR_ROW_LINES |
    95                                                     wx.TR_ROW_LINES |
    88                       wx.TR_COLUMN_LINES |
    96                                                     wx.TR_COLUMN_LINES |
    89                       wx.TR_HIDE_ROOT |
    97                                                     wx.TR_HIDE_ROOT |
    90                       wx.TR_FULL_ROW_HIGHLIGHT)
    98                                                     wx.TR_FULL_ROW_HIGHLIGHT)
    91         self.VariablesGrid.GetMainWindow().Bind(wx.EVT_LEFT_DOWN,
    99         self.VariablesGrid.GetMainWindow().Bind(wx.EVT_LEFT_DOWN,
    92             self.OnVariablesGridLeftClick)
   100                                                 self.OnVariablesGridLeftClick)
    93         self.AddWindow(self.VariablesGrid, flag=wx.GROW)
   101         self.AddWindow(self.VariablesGrid, flag=wx.GROW)
    94         
   102 
    95         self.Filters = []
   103         self.Filters = []
    96         for desc, value in VARIABLES_FILTERS:
   104         for desc, value in VARIABLES_FILTERS:
    97             self.VariablesFilter.Append(desc)
   105             self.VariablesFilter.Append(desc)
    98             self.Filters.append(value)
   106             self.Filters.append(value)
    99         
   107 
   100         self.VariablesFilter.SetSelection(0)
   108         self.VariablesFilter.SetSelection(0)
   101         self.CurrentFilter = self.Filters[0]
   109         self.CurrentFilter = self.Filters[0]
   102         self.VariablesFilterFirstCharacter = True
   110         self.VariablesFilterFirstCharacter = True
   103         
   111 
   104         if position_column:
   112         if position_column:
   105             for colname, colsize, colalign in zip(GetVariablesTableColnames(position_column),
   113             for colname, colsize, colalign in zip(GetVariablesTableColnames(position_column),
   106                                                   [40, 80, 350, 80, 100, 80, 150],
   114                                                   [40, 80, 350, 80, 100, 80, 150],
   107                                                   [wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, 
   115                                                   [wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT,
   108                                                    wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT, 
   116                                                    wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT,
   109                                                    wx.ALIGN_LEFT]):
   117                                                    wx.ALIGN_LEFT]):
   110                 self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
   118                 self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
   111             self.VariablesGrid.SetMainColumn(2)
   119             self.VariablesGrid.SetMainColumn(2)
   112         else:
   120         else:
   113             for colname, colsize, colalign in zip(GetVariablesTableColnames(),
   121             for colname, colsize, colalign in zip(GetVariablesTableColnames(),
   114                                                   [40, 350, 80, 100, 80, 150],
   122                                                   [40, 350, 80, 100, 80, 150],
   115                                                   [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT, 
   123                                                   [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_RIGHT,
   116                                                    wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]):
   124                                                    wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]):
   117                 self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
   125                 self.VariablesGrid.AddColumn(_(colname), colsize, colalign)
   118             self.VariablesGrid.SetMainColumn(1)
   126             self.VariablesGrid.SetMainColumn(1)
   119     
   127 
   120     def RefreshView(self):
   128     def RefreshView(self):
   121         entries = self.Controler.GetSlaveVariables(self.CurrentFilter)
   129         entries = self.Controler.GetSlaveVariables(self.CurrentFilter)
   122         self.RefreshVariablesGrid(entries)
   130         self.RefreshVariablesGrid(entries)
   123     
   131 
   124     def RefreshVariablesGrid(self, entries):
   132     def RefreshVariablesGrid(self, entries):
   125         root = self.VariablesGrid.GetRootItem()
   133         root = self.VariablesGrid.GetRootItem()
   126         if not root.IsOk():
   134         if not root.IsOk():
   127             root = self.VariablesGrid.AddRoot(_("Slave entries"))
   135             root = self.VariablesGrid.AddRoot(_("Slave entries"))
   128         self.GenerateVariablesGridBranch(root, entries, GetVariablesTableColnames(self.PositionColumn))
   136         self.GenerateVariablesGridBranch(root, entries, GetVariablesTableColnames(self.PositionColumn))
   129         self.VariablesGrid.Expand(root)
   137         self.VariablesGrid.Expand(root)
   130         
   138 
   131     def GenerateVariablesGridBranch(self, root, entries, colnames, idx=0):
   139     def GenerateVariablesGridBranch(self, root, entries, colnames, idx=0):
   132         item, root_cookie = self.VariablesGrid.GetFirstChild(root)
   140         item, root_cookie = self.VariablesGrid.GetFirstChild(root)
   133         
   141 
   134         no_more_items = not item.IsOk()
   142         no_more_items = not item.IsOk()
   135         for entry in entries:
   143         for entry in entries:
   136             idx += 1
   144             idx += 1
   137             if no_more_items:
   145             if no_more_items:
   138                 item = self.VariablesGrid.AppendItem(root, "")
   146                 item = self.VariablesGrid.AppendItem(root, "")
   151             self.VariablesGrid.SetItemPyData(item, entry)
   159             self.VariablesGrid.SetItemPyData(item, entry)
   152             idx = self.GenerateVariablesGridBranch(item, entry["children"], colnames, idx)
   160             idx = self.GenerateVariablesGridBranch(item, entry["children"], colnames, idx)
   153             if not no_more_items:
   161             if not no_more_items:
   154                 item, root_cookie = self.VariablesGrid.GetNextChild(root, root_cookie)
   162                 item, root_cookie = self.VariablesGrid.GetNextChild(root, root_cookie)
   155                 no_more_items = not item.IsOk()
   163                 no_more_items = not item.IsOk()
   156         
   164 
   157         if not no_more_items:
   165         if not no_more_items:
   158             to_delete = []
   166             to_delete = []
   159             while item.IsOk():
   167             while item.IsOk():
   160                 to_delete.append(item)
   168                 to_delete.append(item)
   161                 item, root_cookie = self.VariablesGrid.GetNextChild(root, root_cookie)
   169                 item, root_cookie = self.VariablesGrid.GetNextChild(root, root_cookie)
   162             for item in to_delete:
   170             for item in to_delete:
   163                 self.VariablesGrid.Delete(item)
   171                 self.VariablesGrid.Delete(item)
   164         
   172 
   165         return idx
   173         return idx
   166     
   174 
   167     def OnVariablesFilterChanged(self, event):
   175     def OnVariablesFilterChanged(self, event):
   168         filter = self.VariablesFilter.GetSelection()
   176         filter = self.VariablesFilter.GetSelection()
   169         if filter != -1:
   177         if filter != -1:
   170             self.CurrentFilter = self.Filters[filter]
   178             self.CurrentFilter = self.Filters[filter]
   171             self.RefreshView()
   179             self.RefreshView()
   181                         value = result.group(1)
   189                         value = result.group(1)
   182                     index = int(value, 16)
   190                     index = int(value, 16)
   183                     self.CurrentFilter = (index, index)
   191                     self.CurrentFilter = (index, index)
   184                     self.VariablesFilter.SetValue(VARIABLE_INDEX_FILTER_FORMAT % index)
   192                     self.VariablesFilter.SetValue(VARIABLE_INDEX_FILTER_FORMAT % index)
   185                 self.RefreshView()
   193                 self.RefreshView()
   186             except:
   194             except Exception:
   187                 if self.CurrentFilter in self.Filters:
   195                 if self.CurrentFilter in self.Filters:
   188                     self.VariablesFilter.SetSelection(self.Filters.index(self.CurrentFilter))
   196                     self.VariablesFilter.SetSelection(self.Filters.index(self.CurrentFilter))
   189                 else:
   197                 else:
   190                     self.VariablesFilter.SetValue(VARIABLE_INDEX_FILTER_FORMAT % self.CurrentFilter[0])
   198                     self.VariablesFilter.SetValue(VARIABLE_INDEX_FILTER_FORMAT % self.CurrentFilter[0])
   191         self.VariablesFilterFirstCharacter = True
   199         self.VariablesFilterFirstCharacter = True
   192         event.Skip()
   200         event.Skip()
   193     
   201 
   194     def OnVariablesFilterKeyDown(self, event):
   202     def OnVariablesFilterKeyDown(self, event):
   195         if self.VariablesFilterFirstCharacter:
   203         if self.VariablesFilterFirstCharacter:
   196             keycode = event.GetKeyCode()
   204             keycode = event.GetKeyCode()
   197             if keycode not in [wx.WXK_RETURN, 
   205             if keycode not in [wx.WXK_RETURN,
   198                                wx.WXK_NUMPAD_ENTER]:
   206                                wx.WXK_NUMPAD_ENTER]:
   199                 self.VariablesFilterFirstCharacter = False
   207                 self.VariablesFilterFirstCharacter = False
   200                 if keycode not in NAVIGATION_KEYS:
   208                 if keycode not in NAVIGATION_KEYS:
   201                     self.VariablesFilter.SetValue("")
   209                     self.VariablesFilter.SetValue("")
   202             if keycode not in [wx.WXK_DELETE, 
   210             if keycode not in [wx.WXK_DELETE,
   203                                wx.WXK_NUMPAD_DELETE, 
   211                                wx.WXK_NUMPAD_DELETE,
   204                                wx.WXK_BACK]:
   212                                wx.WXK_BACK]:
   205                 event.Skip()
   213                 event.Skip()
   206         else:
   214         else:
   207             event.Skip()
   215             event.Skip()
   208     
   216 
   209     def OnVariablesGridLeftClick(self, event):
   217     def OnVariablesGridLeftClick(self, event):
   210         item, flags, col = self.VariablesGrid.HitTest(event.GetPosition())
   218         item, _flags, col = self.VariablesGrid.HitTest(event.GetPosition())
   211         if item.IsOk():
   219         if item.IsOk():
   212             entry = self.VariablesGrid.GetItemPyData(item)
   220             entry = self.VariablesGrid.GetItemPyData(item)
   213             data_type = entry.get("Type", "")
   221             data_type = entry.get("Type", "")
   214             data_size = self.Controler.GetSizeOfType(data_type)
   222             data_size = self.Controler.GetSizeOfType(data_type)
   215             
   223 
   216             if col == -1 and data_size is not None:
   224             if col == -1 and data_size is not None:
   217                 pdo_mapping = entry.get("PDOMapping", "")
   225                 pdo_mapping = entry.get("PDOMapping", "")
   218                 access = entry.get("Access", "")
   226                 access = entry.get("Access", "")
   219                 entry_index = self.Controler.ExtractHexDecValue(entry.get("Index", "0"))
   227                 entry_index = self.Controler.ExtractHexDecValue(entry.get("Index", "0"))
   220                 entry_subindex = self.Controler.ExtractHexDecValue(entry.get("SubIndex", "0"))
   228                 entry_subindex = self.Controler.ExtractHexDecValue(entry.get("SubIndex", "0"))
   223                     slave_pos = self.Controler.ExtractHexDecValue(entry.get("Position", "0"))
   231                     slave_pos = self.Controler.ExtractHexDecValue(entry.get("Position", "0"))
   224                     location += (slave_pos,)
   232                     location += (slave_pos,)
   225                     node_name = self.Controler.GetSlaveName(slave_pos)
   233                     node_name = self.Controler.GetSlaveName(slave_pos)
   226                 else:
   234                 else:
   227                     node_name = self.Controler.CTNName()
   235                     node_name = self.Controler.CTNName()
   228                 
   236 
   229                 if pdo_mapping != "":
   237                 if pdo_mapping != "":
   230                     var_name = "%s_%4.4x_%2.2x" % (node_name, entry_index, entry_subindex)
   238                     var_name = "%s_%4.4x_%2.2x" % (node_name, entry_index, entry_subindex)
   231                     if pdo_mapping == "T":
   239                     if pdo_mapping == "T":
   232                         dir = "%I"
   240                         dir = "%I"
   233                     else:
   241                     else:
   234                         dir = "%Q"
   242                         dir = "%Q"
   235                     location = "%s%s" % (dir, data_size) + \
   243                     location = "%s%s" % (dir, data_size) + \
   236                                ".".join(map(lambda x:str(x), location + (entry_index, entry_subindex)))
   244                                ".".join(map(str, location + (entry_index, entry_subindex)))
   237                     
   245 
   238                     data = wx.TextDataObject(str((location, "location", data_type, var_name, "", access)))
   246                     data = wx.TextDataObject(str((location, "location", data_type, var_name, "", access)))
   239                     dragSource = wx.DropSource(self.VariablesGrid)
   247                     dragSource = wx.DropSource(self.VariablesGrid)
   240                     dragSource.SetData(data)
   248                     dragSource.SetData(data)
   241                     dragSource.DoDragDrop()
   249                     dragSource.DoDragDrop()
   242                     return
   250                     return
   243                 
   251 
   244                 elif self.PositionColumn:
   252                 elif self.PositionColumn:
   245                     location = self.Controler.GetCurrentLocation() +\
   253                     location = self.Controler.GetCurrentLocation() +\
   246                                (slave_pos, entry_index, entry_subindex)
   254                                (slave_pos, entry_index, entry_subindex)
   247                     data = wx.TextDataObject(str((location, "variable", access)))
   255                     data = wx.TextDataObject(str((location, "variable", access)))
   248                     dragSource = wx.DropSource(self.VariablesGrid)
   256                     dragSource = wx.DropSource(self.VariablesGrid)
   249                     dragSource.SetData(data)
   257                     dragSource.SetData(data)
   250                     dragSource.DoDragDrop()
   258                     dragSource.DoDragDrop()
   251                     return
   259                     return
   252         
   260 
   253         event.Skip()
   261         event.Skip()
   254 
   262 
       
   263 
   255 class NodeEditor(ConfTreeNodeEditor):
   264 class NodeEditor(ConfTreeNodeEditor):
   256     
   265 
   257     CONFNODEEDITOR_TABS = [
   266     CONFNODEEDITOR_TABS = [
   258         (_("Ethercat node"), "_create_EthercatNodeEditor"),
   267         (_("Ethercat node"), "_create_EthercatNodeEditor"),
   259         # Add Notebook Tab for EtherCAT Management Treebook
   268         # Add Notebook Tab for EtherCAT Management Treebook
   260         (_("EtherCAT Management"), "_create_EtherCATManagementEditor")
   269         (_("EtherCAT Management"), "_create_EtherCATManagementEditor")
   261         ]
   270         ]
   262     
   271 
   263     def _create_EthercatNodeEditor(self, prnt):
   272     def _create_EthercatNodeEditor(self, prnt):
   264         self.EthercatNodeEditor = wx.Panel(prnt, style=wx.TAB_TRAVERSAL)
   273         self.EthercatNodeEditor = wx.Panel(prnt, style=wx.TAB_TRAVERSAL)
   265         
   274 
   266         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
   275         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
   267         main_sizer.AddGrowableCol(0)
   276         main_sizer.AddGrowableCol(0)
   268         main_sizer.AddGrowableRow(1)
   277         main_sizer.AddGrowableRow(1)
   269         
   278 
   270         variables_label = wx.StaticText(self.EthercatNodeEditor,
   279         variables_label = wx.StaticText(self.EthercatNodeEditor,
   271               label=_('Variable entries:'))
   280                                         label=_('Variable entries:'))
   272         main_sizer.AddWindow(variables_label, border=10, flag=wx.TOP|wx.LEFT|wx.RIGHT)
   281         main_sizer.AddWindow(variables_label, border=10, flag=wx.TOP | wx.LEFT | wx.RIGHT)
   273         
   282 
   274         self.NodeVariables = NodeVariablesSizer(self.EthercatNodeEditor, self.Controler)
   283         self.NodeVariables = NodeVariablesSizer(self.EthercatNodeEditor, self.Controler)
   275         main_sizer.AddSizer(self.NodeVariables, border=10, 
   284         main_sizer.AddSizer(self.NodeVariables, border=10,
   276             flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT)
   285                             flag=wx.GROW | wx.BOTTOM | wx.LEFT | wx.RIGHT)
   277                 
   286 
   278         self.EthercatNodeEditor.SetSizer(main_sizer)
   287         self.EthercatNodeEditor.SetSizer(main_sizer)
   279 
   288 
   280         return self.EthercatNodeEditor
   289         return self.EthercatNodeEditor
   281     
   290 
   282     def __init__(self, parent, controler, window):
   291     def __init__(self, parent, controler, window):
   283         ConfTreeNodeEditor.__init__(self, parent, controler, window)
   292         ConfTreeNodeEditor.__init__(self, parent, controler, window)
   284         
   293 
   285         # add Contoler for use EthercatSlave.py Method
   294         # add Contoler for use EthercatSlave.py Method
   286         self.Controler = controler
   295         self.Controler = controler
   287         
   296 
   288     def GetBufferState(self):
   297     def GetBufferState(self):
   289         return False, False
   298         return False, False
   290         
   299 
   291     def RefreshView(self):
   300     def RefreshView(self):
   292         ConfTreeNodeEditor.RefreshView(self)
   301         ConfTreeNodeEditor.RefreshView(self)
   293     
   302 
   294         self.NodeVariables.RefreshView()
   303         self.NodeVariables.RefreshView()
   295 
   304 
   296     # -------------------For EtherCAT Management ----------------------------------------------    
   305     # -------------------For EtherCAT Management ----------------------------------------------
   297     def _create_EtherCATManagementEditor(self, prnt):
   306     def _create_EtherCATManagementEditor(self, prnt):
   298         self.EtherCATManagementEditor = wx.ScrolledWindow(prnt,
   307         self.EtherCATManagementEditor = wx.ScrolledWindow(prnt,
   299             style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL)
   308                                                           style=wx.TAB_TRAVERSAL | wx.HSCROLL | wx.VSCROLL)
   300         self.EtherCATManagementEditor.Bind(wx.EVT_SIZE, self.OnResize)
   309         self.EtherCATManagementEditor.Bind(wx.EVT_SIZE, self.OnResize)
   301 
   310 
   302         self.EtherCATManagermentEditor_Main_Sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
   311         self.EtherCATManagermentEditor_Main_Sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
   303         self.EtherCATManagermentEditor_Main_Sizer.AddGrowableCol(0)
   312         self.EtherCATManagermentEditor_Main_Sizer.AddGrowableCol(0)
   304         self.EtherCATManagermentEditor_Main_Sizer.AddGrowableRow(0)
   313         self.EtherCATManagermentEditor_Main_Sizer.AddGrowableRow(0)
   305         
   314 
   306         self.EtherCATManagementTreebook = EtherCATManagementTreebook(self.EtherCATManagementEditor, self.Controler, self)
   315         self.EtherCATManagementTreebook = EtherCATManagementTreebook(self.EtherCATManagementEditor, self.Controler, self)
   307           
   316 
   308         self.EtherCATManagermentEditor_Main_Sizer.AddSizer(self.EtherCATManagementTreebook, border=10, flag=wx.GROW)
   317         self.EtherCATManagermentEditor_Main_Sizer.AddSizer(self.EtherCATManagementTreebook, border=10, flag=wx.GROW)
   309 
   318 
   310         self.EtherCATManagementEditor.SetSizer(self.EtherCATManagermentEditor_Main_Sizer)
   319         self.EtherCATManagementEditor.SetSizer(self.EtherCATManagermentEditor_Main_Sizer)
   311         return self.EtherCATManagementEditor
   320         return self.EtherCATManagementEditor
   312     
   321 
   313     def OnResize(self, event):
   322     def OnResize(self, event):
   314         self.EtherCATManagementEditor.GetBestSize()
   323         self.EtherCATManagementEditor.GetBestSize()
   315         xstart, ystart = self.EtherCATManagementEditor.GetViewStart()
   324         xstart, ystart = self.EtherCATManagementEditor.GetViewStart()
   316         window_size = self.EtherCATManagementEditor.GetClientSize()
   325         window_size = self.EtherCATManagementEditor.GetClientSize()
   317         maxx, maxy = self.EtherCATManagementEditor.GetMinSize()
   326         maxx, maxy = self.EtherCATManagementEditor.GetMinSize()
   318         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
   327         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
   319         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
   328         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
   320         self.EtherCATManagementEditor.Scroll(posx, posy)
   329         self.EtherCATManagementEditor.Scroll(posx, posy)
   321         self.EtherCATManagementEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
   330         self.EtherCATManagementEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
   322                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
   331                                                     maxx / SCROLLBAR_UNIT,
       
   332                                                     maxy / SCROLLBAR_UNIT,
       
   333                                                     posx, posy)
   323         event.Skip()
   334         event.Skip()
   324     # -------------------------------------------------------------------------------------------------------
   335     # -------------------------------------------------------------------------------------------------------
   325 
   336 
       
   337 
   326 CIA402NodeEditor = NodeEditor
   338 CIA402NodeEditor = NodeEditor
   327 
   339 
   328 
   340 
   329 def GetProcessVariablesTableColnames():
   341 def GetProcessVariablesTableColnames():
   330     _ = lambda x : x
   342     _ = NoTranslate
   331     return ["#", _("Name"), 
   343     return ["#", _("Name"),
   332             _("Read from (nodeid, index, subindex)"), 
   344             _("Read from (nodeid, index, subindex)"),
   333             _("Write to (nodeid, index, subindex)"),
   345             _("Write to (nodeid, index, subindex)"),
   334             _("Description")]
   346             _("Description")]
   335 
   347 
       
   348 
   336 class ProcessVariablesTable(CustomTable):
   349 class ProcessVariablesTable(CustomTable):
   337     
   350 
   338     def GetValue(self, row, col):
   351     def GetValue(self, row, col):
   339         if row < self.GetNumberRows():
   352         if row < self.GetNumberRows():
   340             if col == 0:
   353             if col == 0:
   341                 return row + 1
   354                 return row + 1
   342             colname = self.GetColLabelValue(col, False)
   355             colname = self.GetColLabelValue(col, False)
   349                 value = self.data[row].get("WriteTo", "")
   362                 value = self.data[row].get("WriteTo", "")
   350                 if value == "":
   363                 if value == "":
   351                     return value
   364                     return value
   352                 return "%d, #x%0.4X, #x%0.2X" % value
   365                 return "%d, #x%0.4X, #x%0.2X" % value
   353             return self.data[row].get(colname, "")
   366             return self.data[row].get(colname, "")
   354     
   367 
   355     def SetValue(self, row, col, value):
   368     def SetValue(self, row, col, value):
   356         if col < len(self.colnames):
   369         if col < len(self.colnames):
   357             colname = self.GetColLabelValue(col, False)
   370             colname = self.GetColLabelValue(col, False)
   358             if colname.startswith("Read from"):
   371             if colname.startswith("Read from"):
   359                 self.data[row]["ReadFrom"] = value
   372                 self.data[row]["ReadFrom"] = value
   360             elif colname.startswith("Write to"):
   373             elif colname.startswith("Write to"):
   361                 self.data[row]["WriteTo"] = value
   374                 self.data[row]["WriteTo"] = value
   362             else:
   375             else:
   363                 self.data[row][colname] = value
   376                 self.data[row][colname] = value
   364     
   377 
   365     def _updateColAttrs(self, grid):
   378     def _updateColAttrs(self, grid):
   366         """
   379         """
   367         wx.grid.Grid -> update the column attributes to add the
   380         wx.grid.Grid -> update the column attributes to add the
   368         appropriate renderer given the column name.
   381         appropriate renderer given the column name.
   369 
   382 
   378                     editor = wx.grid.GridCellTextEditor()
   391                     editor = wx.grid.GridCellTextEditor()
   379                     renderer = wx.grid.GridCellStringRenderer()
   392                     renderer = wx.grid.GridCellStringRenderer()
   380                     grid.SetReadOnly(row, col, False)
   393                     grid.SetReadOnly(row, col, False)
   381                 else:
   394                 else:
   382                     grid.SetReadOnly(row, col, True)
   395                     grid.SetReadOnly(row, col, True)
   383                 
   396 
   384                 grid.SetCellEditor(row, col, editor)
   397                 grid.SetCellEditor(row, col, editor)
   385                 grid.SetCellRenderer(row, col, renderer)
   398                 grid.SetCellRenderer(row, col, renderer)
   386                 
   399 
   387             self.ResizeRow(grid, row)
   400             self.ResizeRow(grid, row)
   388 
   401 
       
   402 
   389 class ProcessVariableDropTarget(wx.TextDropTarget):
   403 class ProcessVariableDropTarget(wx.TextDropTarget):
   390     
   404 
   391     def __init__(self, parent):
   405     def __init__(self, parent):
   392         wx.TextDropTarget.__init__(self)
   406         wx.TextDropTarget.__init__(self)
   393         self.ParentWindow = parent
   407         self.ParentWindow = parent
   394     
   408 
   395     def OnDropText(self, x, y, data):
   409     def OnDropText(self, x, y, data):
   396         self.ParentWindow.Select()
   410         self.ParentWindow.Select()
   397         x, y = self.ParentWindow.ProcessVariablesGrid.CalcUnscrolledPosition(x, y)
   411         x, y = self.ParentWindow.ProcessVariablesGrid.CalcUnscrolledPosition(x, y)
   398         col = self.ParentWindow.ProcessVariablesGrid.XToCol(x)
   412         col = self.ParentWindow.ProcessVariablesGrid.XToCol(x)
   399         row = self.ParentWindow.ProcessVariablesGrid.YToRow(y - self.ParentWindow.ProcessVariablesGrid.GetColLabelSize())
   413         row = self.ParentWindow.ProcessVariablesGrid.YToRow(y - self.ParentWindow.ProcessVariablesGrid.GetColLabelSize())
   400         message = None
   414         message = None
   401         try:
   415         try:
   402             values = eval(data)
   416             values = eval(data)
   403         except:
   417         except Exception:
   404             message = _("Invalid value \"%s\" for process variable")%data
   418             message = _("Invalid value \"%s\" for process variable") % data
   405             values = None
   419             values = None
   406         if not isinstance(values, TupleType):
   420         if not isinstance(values, TupleType):
   407             message = _("Invalid value \"%s\" for process variable")%data
   421             message = _("Invalid value \"%s\" for process variable") % data
   408             values = None
   422             values = None
   409         if values is not None and col != wx.NOT_FOUND and row != wx.NOT_FOUND and 2 <= col <= 3:
   423         if values is not None and col != wx.NOT_FOUND and row != wx.NOT_FOUND and 2 <= col <= 3:
   410             location = None
   424             location = None
   411             if values[1] == "location":
   425             if values[1] == "location":
   412                 result = LOCATION_MODEL.match(values[0])
   426                 result = LOCATION_MODEL.match(values[0])
   413                 if result is not None:
   427                 if result is not None:
   414                     location = map(int, result.group(1).split('.'))
   428                     location = map(int, result.group(1).split('.'))
   415                 master_location = self.ParentWindow.GetMasterLocation()
   429                 master_location = self.ParentWindow.GetMasterLocation()
   416                 if (master_location == tuple(location[:len(master_location)]) and 
   430                 if master_location == tuple(location[:len(master_location)]) and \
   417                     len(location) - len(master_location) == 3):
   431                    len(location) - len(master_location) == 3:
   418                     values = tuple(location[len(master_location):])
   432                     values = tuple(location[len(master_location):])
   419                     var_type = self.ParentWindow.Controler.GetSlaveVariableDataType(*values)
   433                     var_type = self.ParentWindow.Controler.GetSlaveVariableDataType(*values)
   420                     if col == 2:
   434                     if col == 2:
   421                         other_values = self.ParentWindow.ProcessVariablesTable.GetValueByName(row, "WriteTo")
   435                         other_values = self.ParentWindow.ProcessVariablesTable.GetValueByName(row, "WriteTo")
   422                     else:
   436                     else:
   433                         self.ParentWindow.SaveProcessVariables()
   447                         self.ParentWindow.SaveProcessVariables()
   434                         self.ParentWindow.RefreshProcessVariables()
   448                         self.ParentWindow.RefreshProcessVariables()
   435                     else:
   449                     else:
   436                         message = _("'Read from' and 'Write to' variables types are not compatible")
   450                         message = _("'Read from' and 'Write to' variables types are not compatible")
   437                 else:
   451                 else:
   438                     message = _("Invalid value \"%s\" for process variable")%data
   452                     message = _("Invalid value \"%s\" for process variable") % data
   439                     
   453 
   440         if message is not None:
   454         if message is not None:
   441             wx.CallAfter(self.ShowMessage, message)
   455             wx.CallAfter(self.ShowMessage, message)
   442     
   456 
   443     def ShowMessage(self, message):
   457     def ShowMessage(self, message):
   444         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
   458         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK | wx.ICON_ERROR)
   445         message.ShowModal()
   459         message.ShowModal()
   446         message.Destroy()
   460         message.Destroy()
   447 
   461 
       
   462 
   448 def GetStartupCommandsTableColnames():
   463 def GetStartupCommandsTableColnames():
   449     _ = lambda x : x
   464     _ = NoTranslate
   450     return [_("Position"), _("Index"), _("Subindex"), _("Value"), _("Description")]
   465     return [_("Position"), _("Index"), _("Subindex"), _("Value"), _("Description")]
   451 
   466 
       
   467 
   452 class StartupCommandDropTarget(wx.TextDropTarget):
   468 class StartupCommandDropTarget(wx.TextDropTarget):
   453     
   469 
   454     def __init__(self, parent):
   470     def __init__(self, parent):
   455         wx.TextDropTarget.__init__(self)
   471         wx.TextDropTarget.__init__(self)
   456         self.ParentWindow = parent
   472         self.ParentWindow = parent
   457     
   473 
   458     def OnDropText(self, x, y, data):
   474     def OnDropText(self, x, y, data):
   459         self.ParentWindow.Select()
   475         self.ParentWindow.Select()
   460         message = None
   476         message = None
   461         try:
   477         try:
   462             values = eval(data)
   478             values = eval(data)
   463         except:
   479         except Exception:
   464             message = _("Invalid value \"%s\" for startup command")%data
   480             message = _("Invalid value \"%s\" for startup command") % data
   465             values = None
   481             values = None
   466         if not isinstance(values, TupleType):
   482         if not isinstance(values, TupleType):
   467             message = _("Invalid value \"%s\" for startup command")%data
   483             message = _("Invalid value \"%s\" for startup command") % data
   468             values = None
   484             values = None
   469         if values is not None:
   485         if values is not None:
   470             location = None
   486             location = None
   471             if values[1] == "location":
   487             if values[1] == "location":
   472                 result = LOCATION_MODEL.match(values[0])
   488                 result = LOCATION_MODEL.match(values[0])
   476             elif values[1] == "variable":
   492             elif values[1] == "variable":
   477                 location = values[0]
   493                 location = values[0]
   478                 access = values[2]
   494                 access = values[2]
   479             if location is not None:
   495             if location is not None:
   480                 master_location = self.ParentWindow.GetMasterLocation()
   496                 master_location = self.ParentWindow.GetMasterLocation()
   481                 if (master_location == tuple(location[:len(master_location)]) and 
   497                 if master_location == tuple(location[:len(master_location)]) and \
   482                     len(location) - len(master_location) == 3):
   498                    len(location) - len(master_location) == 3:
   483                     if access in ["wo", "rw"]:
   499                     if access in ["wo", "rw"]:
   484                         self.ParentWindow.AddStartupCommand(*location[len(master_location):])
   500                         self.ParentWindow.AddStartupCommand(*location[len(master_location):])
   485                     else:
   501                     else:
   486                         message = _("Entry can't be write through SDO")
   502                         message = _("Entry can't be write through SDO")
   487                 else:
   503                 else:
   488                     message = _("Invalid value \"%s\" for startup command")%data
   504                     message = _("Invalid value \"%s\" for startup command") % data
   489                     
   505 
   490         if message is not None:
   506         if message is not None:
   491             wx.CallAfter(self.ShowMessage, message)
   507             wx.CallAfter(self.ShowMessage, message)
   492     
   508 
   493     def ShowMessage(self, message):
   509     def ShowMessage(self, message):
   494         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
   510         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK | wx.ICON_ERROR)
   495         message.ShowModal()
   511         message.ShowModal()
   496         message.Destroy()
   512         message.Destroy()
       
   513 
   497 
   514 
   498 class StartupCommandsTable(CustomTable):
   515 class StartupCommandsTable(CustomTable):
   499 
   516 
   500     """
   517     """
   501     A custom wx.grid.Grid Table using user supplied data
   518     A custom wx.grid.Grid Table using user supplied data
   512             if colname == "Index":
   529             if colname == "Index":
   513                 return "#x%0.4X" % value
   530                 return "#x%0.4X" % value
   514             elif colname == "Subindex":
   531             elif colname == "Subindex":
   515                 return "#x%0.2X" % value
   532                 return "#x%0.2X" % value
   516             return value
   533             return value
   517     
   534 
   518     def SetValue(self, row, col, value):
   535     def SetValue(self, row, col, value):
   519         if col < len(self.colnames):
   536         if col < len(self.colnames):
   520             colname = self.GetColLabelValue(col, False)
   537             colname = self.GetColLabelValue(col, False)
   521             if colname in ["Index", "Subindex"]:
   538             if colname in ["Index", "Subindex"]:
   522                 if colname == "Index":
   539                 if colname == "Index":
   530                 value = int(value)
   547                 value = int(value)
   531             elif colname == "Position":
   548             elif colname == "Position":
   532                 self.old_value = self.data[row][colname]
   549                 self.old_value = self.data[row][colname]
   533                 value = int(value)
   550                 value = int(value)
   534             self.data[row][colname] = value
   551             self.data[row][colname] = value
   535     
   552 
   536     def GetOldValue(self):
   553     def GetOldValue(self):
   537         return self.old_value
   554         return self.old_value
   538     
   555 
   539     def _updateColAttrs(self, grid):
   556     def _updateColAttrs(self, grid):
   540         """
   557         """
   541         wx.grid.Grid -> update the column attributes to add the
   558         wx.grid.Grid -> update the column attributes to add the
   542         appropriate renderer given the column name.
   559         appropriate renderer given the column name.
   543 
   560 
   552                     editor = wx.grid.GridCellNumberEditor()
   569                     editor = wx.grid.GridCellNumberEditor()
   553                     renderer = wx.grid.GridCellNumberRenderer()
   570                     renderer = wx.grid.GridCellNumberRenderer()
   554                 else:
   571                 else:
   555                     editor = wx.grid.GridCellTextEditor()
   572                     editor = wx.grid.GridCellTextEditor()
   556                     renderer = wx.grid.GridCellStringRenderer()
   573                     renderer = wx.grid.GridCellStringRenderer()
   557                 
   574 
   558                 grid.SetCellEditor(row, col, editor)
   575                 grid.SetCellEditor(row, col, editor)
   559                 grid.SetCellRenderer(row, col, renderer)
   576                 grid.SetCellRenderer(row, col, renderer)
   560                 grid.SetReadOnly(row, col, False)
   577                 grid.SetReadOnly(row, col, False)
   561                 
   578 
   562             self.ResizeRow(grid, row)
   579             self.ResizeRow(grid, row)
   563     
   580 
   564     def GetCommandIndex(self, position, command_idx):
   581     def GetCommandIndex(self, position, command_idx):
   565         for row, command in enumerate(self.data):
   582         for row, command in enumerate(self.data):
   566             if command["Position"] == position and command["command_idx"] == command_idx:
   583             if command["Position"] == position and command["command_idx"] == command_idx:
   567                 return row
   584                 return row
   568         return None
   585         return None
   569 
   586 
       
   587 
   570 class MasterNodesVariablesSizer(NodeVariablesSizer):
   588 class MasterNodesVariablesSizer(NodeVariablesSizer):
   571     
   589 
   572     def __init__(self, parent, controler):
   590     def __init__(self, parent, controler):
   573         NodeVariablesSizer.__init__(self, parent, controler, True)
   591         NodeVariablesSizer.__init__(self, parent, controler, True)
   574         
   592 
   575         self.CurrentNodesFilter = {}
   593         self.CurrentNodesFilter = {}
   576     
   594 
   577     def SetCurrentNodesFilter(self, nodes_filter):
   595     def SetCurrentNodesFilter(self, nodes_filter):
   578         self.CurrentNodesFilter = nodes_filter
   596         self.CurrentNodesFilter = nodes_filter
   579         
   597 
   580     def RefreshView(self):
   598     def RefreshView(self):
   581         if self.CurrentNodesFilter is not None:
   599         if self.CurrentNodesFilter is not None:
   582             args = self.CurrentNodesFilter.copy()
   600             args = self.CurrentNodesFilter.copy()
   583             args["limits"] = self.CurrentFilter
   601             args["limits"] = self.CurrentFilter
   584             entries = self.Controler.GetNodesVariables(**args)
   602             entries = self.Controler.GetNodesVariables(**args)
   585             self.RefreshVariablesGrid(entries)
   603             self.RefreshVariablesGrid(entries)
   586 
   604 
       
   605 
   587 NODE_POSITION_FILTER_FORMAT = _("Node Position: %d")
   606 NODE_POSITION_FILTER_FORMAT = _("Node Position: %d")
   588 
   607 
       
   608 
   589 class MasterEditor(ConfTreeNodeEditor):
   609 class MasterEditor(ConfTreeNodeEditor):
   590     
   610 
   591     CONFNODEEDITOR_TABS = [
   611     CONFNODEEDITOR_TABS = [
   592         (_("Network"), "_create_EthercatMasterEditor"),
   612         (_("Network"), "_create_EthercatMasterEditor"),
   593         (_("Master State"), "_create_MasterStateEditor")
   613         (_("Master State"), "_create_MasterStateEditor")
   594         ]
   614         ]
   595     
   615 
   596     def _create_MasterStateEditor(self, prnt):
   616     def _create_MasterStateEditor(self, prnt):
   597         self.MasterStateEditor = wx.ScrolledWindow(prnt, style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL)
   617         self.MasterStateEditor = wx.ScrolledWindow(prnt, style=wx.TAB_TRAVERSAL | wx.HSCROLL | wx.VSCROLL)
   598         self.MasterStateEditor.Bind(wx.EVT_SIZE, self.OnResize)
   618         self.MasterStateEditor.Bind(wx.EVT_SIZE, self.OnResize)
   599         
   619 
   600         self.MasterStateEditor_Panel_Main_Sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
   620         self.MasterStateEditor_Panel_Main_Sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5)
   601         self.MasterStateEditor_Panel_Main_Sizer.AddGrowableCol(0)
   621         self.MasterStateEditor_Panel_Main_Sizer.AddGrowableCol(0)
   602         self.MasterStateEditor_Panel_Main_Sizer.AddGrowableRow(0)
   622         self.MasterStateEditor_Panel_Main_Sizer.AddGrowableRow(0)
   603         
   623 
   604         self.MasterStateEditor_Panel = MasterStatePanelClass(self.MasterStateEditor, self.Controler)
   624         self.MasterStateEditor_Panel = MasterStatePanelClass(self.MasterStateEditor, self.Controler)
   605         
   625 
   606         self.MasterStateEditor_Panel_Main_Sizer.AddSizer(self.MasterStateEditor_Panel, border=10, flag=wx.GROW)
   626         self.MasterStateEditor_Panel_Main_Sizer.AddSizer(self.MasterStateEditor_Panel, border=10, flag=wx.GROW)
   607          
   627 
   608         self.MasterStateEditor.SetSizer(self.MasterStateEditor_Panel_Main_Sizer)
   628         self.MasterStateEditor.SetSizer(self.MasterStateEditor_Panel_Main_Sizer)
   609         return self.MasterStateEditor
   629         return self.MasterStateEditor
   610     
   630 
   611     def OnResize(self, event):
       
   612         self.MasterStateEditor.GetBestSize()
       
   613         xstart, ystart = self.MasterStateEditor.GetViewStart()
       
   614         window_size = self.MasterStateEditor.GetClientSize()
       
   615         maxx, maxy = self.MasterStateEditor.GetMinSize()
       
   616         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
       
   617         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
       
   618         self.MasterStateEditor.Scroll(posx, posy)
       
   619         self.MasterStateEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
       
   620                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
       
   621         event.Skip()
       
   622     
       
   623     def _create_EthercatMasterEditor(self, prnt):
   631     def _create_EthercatMasterEditor(self, prnt):
   624         self.EthercatMasterEditor = wx.ScrolledWindow(prnt, 
   632         self.EthercatMasterEditor = wx.ScrolledWindow(prnt,
   625             style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL)
   633                                                       style=wx.TAB_TRAVERSAL | wx.HSCROLL | wx.VSCROLL)
   626         self.EthercatMasterEditor.Bind(wx.EVT_SIZE, self.OnResize)
   634         self.EthercatMasterEditor.Bind(wx.EVT_SIZE, self.OnResize)
   627         
   635 
   628         self.EthercatMasterEditorSizer = wx.BoxSizer(wx.VERTICAL)
   636         self.EthercatMasterEditorSizer = wx.BoxSizer(wx.VERTICAL)
   629         
   637 
   630         self.NodesFilter = wx.ComboBox(self.EthercatMasterEditor,
   638         self.NodesFilter = wx.ComboBox(self.EthercatMasterEditor,
   631             style=wx.TE_PROCESS_ENTER)
   639                                        style=wx.TE_PROCESS_ENTER)
   632         self.Bind(wx.EVT_COMBOBOX, self.OnNodesFilterChanged, self.NodesFilter)
   640         self.Bind(wx.EVT_COMBOBOX, self.OnNodesFilterChanged, self.NodesFilter)
   633         self.Bind(wx.EVT_TEXT_ENTER, self.OnNodesFilterChanged, self.NodesFilter)
   641         self.Bind(wx.EVT_TEXT_ENTER, self.OnNodesFilterChanged, self.NodesFilter)
   634         self.NodesFilter.Bind(wx.EVT_CHAR, self.OnNodesFilterKeyDown)
   642         self.NodesFilter.Bind(wx.EVT_CHAR, self.OnNodesFilterKeyDown)
   635         
   643 
   636         process_variables_header = wx.BoxSizer(wx.HORIZONTAL)
   644         process_variables_header = wx.BoxSizer(wx.HORIZONTAL)
   637         
   645 
   638         process_variables_label = wx.StaticText(self.EthercatMasterEditor,
   646         process_variables_label = wx.StaticText(self.EthercatMasterEditor,
   639               label=_("Process variables mapped between nodes:"))
   647                                                 label=_("Process variables mapped between nodes:"))
   640         process_variables_header.AddWindow(process_variables_label, 1,
   648         process_variables_header.AddWindow(process_variables_label, 1,
   641               flag=wx.ALIGN_CENTER_VERTICAL)
   649                                            flag=wx.ALIGN_CENTER_VERTICAL)
   642         
   650 
   643         for name, bitmap, help in [
   651         for name, bitmap, help in [
   644                 ("AddVariableButton", "add_element", _("Add process variable")),
   652                 ("AddVariableButton", "add_element", _("Add process variable")),
   645                 ("DeleteVariableButton", "remove_element", _("Remove process variable")),
   653                 ("DeleteVariableButton", "remove_element", _("Remove process variable")),
   646                 ("UpVariableButton", "up", _("Move process variable up")),
   654                 ("UpVariableButton", "up", _("Move process variable up")),
   647                 ("DownVariableButton", "down", _("Move process variable down"))]:
   655                 ("DownVariableButton", "down", _("Move process variable down"))]:
   648             button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap), 
   656             button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap),
   649                   size=wx.Size(28, 28), style=wx.NO_BORDER)
   657                                                     size=wx.Size(28, 28), style=wx.NO_BORDER)
   650             button.SetToolTipString(help)
   658             button.SetToolTipString(help)
   651             setattr(self, name, button)
   659             setattr(self, name, button)
   652             process_variables_header.AddWindow(button, border=5, flag=wx.LEFT)
   660             process_variables_header.AddWindow(button, border=5, flag=wx.LEFT)
   653         
   661 
   654         self.ProcessVariablesGrid = CustomGrid(self.EthercatMasterEditor, style=wx.VSCROLL)
   662         self.ProcessVariablesGrid = CustomGrid(self.EthercatMasterEditor, style=wx.VSCROLL)
   655         self.ProcessVariablesGrid.SetMinSize(wx.Size(0, 150))
   663         self.ProcessVariablesGrid.SetMinSize(wx.Size(0, 150))
   656         self.ProcessVariablesGrid.SetDropTarget(ProcessVariableDropTarget(self))
   664         self.ProcessVariablesGrid.SetDropTarget(ProcessVariableDropTarget(self))
   657         self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, 
   665         self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
   658               self.OnProcessVariablesGridCellChange)
   666                                        self.OnProcessVariablesGridCellChange)
   659         self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, 
   667         self.ProcessVariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK,
   660               self.OnProcessVariablesGridCellLeftClick)
   668                                        self.OnProcessVariablesGridCellLeftClick)
   661         self.ProcessVariablesGrid.Bind(wx.EVT_KEY_DOWN, self.OnProcessVariablesGridKeyDown)
   669         self.ProcessVariablesGrid.Bind(wx.EVT_KEY_DOWN, self.OnProcessVariablesGridKeyDown)
   662         
   670 
   663         startup_commands_header = wx.BoxSizer(wx.HORIZONTAL)
   671         startup_commands_header = wx.BoxSizer(wx.HORIZONTAL)
   664         
   672 
   665         startup_commands_label = wx.StaticText(self.EthercatMasterEditor,
   673         startup_commands_label = wx.StaticText(self.EthercatMasterEditor,
   666               label=_("Startup service variables assignments:"))
   674                                                label=_("Startup service variables assignments:"))
   667         startup_commands_header.AddWindow(startup_commands_label, 1,
   675         startup_commands_header.AddWindow(startup_commands_label, 1,
   668               flag=wx.ALIGN_CENTER_VERTICAL)
   676                                           flag=wx.ALIGN_CENTER_VERTICAL)
   669         
   677 
   670         for name, bitmap, help in [
   678         for name, bitmap, help in [
   671                 ("AddCommandButton", "add_element", _("Add startup service variable")),
   679                 ("AddCommandButton", "add_element", _("Add startup service variable")),
   672                 ("DeleteCommandButton", "remove_element", _("Remove startup service variable"))]:
   680                 ("DeleteCommandButton", "remove_element", _("Remove startup service variable"))]:
   673             button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap), 
   681             button = wx.lib.buttons.GenBitmapButton(self.EthercatMasterEditor, bitmap=GetBitmap(bitmap),
   674                   size=wx.Size(28, 28), style=wx.NO_BORDER)
   682                                                     size=wx.Size(28, 28), style=wx.NO_BORDER)
   675             button.SetToolTipString(help)
   683             button.SetToolTipString(help)
   676             setattr(self, name, button)
   684             setattr(self, name, button)
   677             startup_commands_header.AddWindow(button, border=5, flag=wx.LEFT)
   685             startup_commands_header.AddWindow(button, border=5, flag=wx.LEFT)
   678         
   686 
   679         self.StartupCommandsGrid = CustomGrid(self.EthercatMasterEditor, style=wx.VSCROLL)
   687         self.StartupCommandsGrid = CustomGrid(self.EthercatMasterEditor, style=wx.VSCROLL)
   680         self.StartupCommandsGrid.SetDropTarget(StartupCommandDropTarget(self))
   688         self.StartupCommandsGrid.SetDropTarget(StartupCommandDropTarget(self))
   681         self.StartupCommandsGrid.SetMinSize(wx.Size(0, 150))
   689         self.StartupCommandsGrid.SetMinSize(wx.Size(0, 150))
   682         self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, 
   690         self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
   683               self.OnStartupCommandsGridCellChange)
   691                                       self.OnStartupCommandsGridCellChange)
   684         self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, 
   692         self.StartupCommandsGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN,
   685               self.OnStartupCommandsGridEditorShow)
   693                                       self.OnStartupCommandsGridEditorShow)
   686         
   694 
   687         self.NodesVariables = MasterNodesVariablesSizer(self.EthercatMasterEditor, self.Controler)
   695         self.NodesVariables = MasterNodesVariablesSizer(self.EthercatMasterEditor, self.Controler)
   688         
   696 
   689         main_staticbox = wx.StaticBox(self.EthercatMasterEditor, label=_("Node filter:"))
   697         main_staticbox = wx.StaticBox(self.EthercatMasterEditor, label=_("Node filter:"))
   690         staticbox_sizer = wx.StaticBoxSizer(main_staticbox, wx.VERTICAL)
   698         staticbox_sizer = wx.StaticBoxSizer(main_staticbox, wx.VERTICAL)
   691         self.EthercatMasterEditorSizer.AddSizer(staticbox_sizer, 0, border=10, flag=wx.GROW|wx.ALL)
   699         self.EthercatMasterEditorSizer.AddSizer(staticbox_sizer, 0, border=10, flag=wx.GROW | wx.ALL)
   692         
   700 
   693         main_staticbox_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=6, vgap=0)
   701         main_staticbox_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=6, vgap=0)
   694         main_staticbox_sizer.AddGrowableCol(0)
   702         main_staticbox_sizer.AddGrowableCol(0)
   695         main_staticbox_sizer.AddGrowableRow(2)
   703         main_staticbox_sizer.AddGrowableRow(2)
   696         main_staticbox_sizer.AddGrowableRow(4)
   704         main_staticbox_sizer.AddGrowableRow(4)
   697         main_staticbox_sizer.AddGrowableRow(5)
   705         main_staticbox_sizer.AddGrowableRow(5)
   698         staticbox_sizer.AddSizer(main_staticbox_sizer, 1, flag=wx.GROW)
   706         staticbox_sizer.AddSizer(main_staticbox_sizer, 1, flag=wx.GROW)
   699         main_staticbox_sizer.AddWindow(self.NodesFilter, border=5, flag=wx.GROW|wx.ALL)
   707         main_staticbox_sizer.AddWindow(self.NodesFilter, border=5, flag=wx.GROW | wx.ALL)
   700         main_staticbox_sizer.AddSizer(process_variables_header, border=5, 
   708         main_staticbox_sizer.AddSizer(process_variables_header, border=5,
   701               flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
   709                                       flag=wx.GROW | wx.LEFT | wx.RIGHT | wx.BOTTOM)
   702         main_staticbox_sizer.AddWindow(self.ProcessVariablesGrid, 1, 
   710         main_staticbox_sizer.AddWindow(self.ProcessVariablesGrid, 1,
   703               border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
   711                                        border=5, flag=wx.GROW | wx.LEFT | wx.RIGHT | wx.BOTTOM)
   704         main_staticbox_sizer.AddSizer(startup_commands_header, 
   712         main_staticbox_sizer.AddSizer(startup_commands_header,
   705               border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
   713                                       border=5, flag=wx.GROW | wx.LEFT | wx.RIGHT | wx.BOTTOM)
   706         main_staticbox_sizer.AddWindow(self.StartupCommandsGrid, 1, 
   714         main_staticbox_sizer.AddWindow(self.StartupCommandsGrid, 1,
   707               border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
   715                                        border=5, flag=wx.GROW | wx.LEFT | wx.RIGHT | wx.BOTTOM)
   708         
   716 
   709         second_staticbox = wx.StaticBox(self.EthercatMasterEditor, label=_("Nodes variables filter:"))
   717         second_staticbox = wx.StaticBox(self.EthercatMasterEditor, label=_("Nodes variables filter:"))
   710         second_staticbox_sizer = wx.StaticBoxSizer(second_staticbox, wx.VERTICAL)
   718         second_staticbox_sizer = wx.StaticBoxSizer(second_staticbox, wx.VERTICAL)
   711         second_staticbox_sizer.AddSizer(self.NodesVariables, 1, border=5, flag=wx.GROW|wx.ALL)
   719         second_staticbox_sizer.AddSizer(self.NodesVariables, 1, border=5, flag=wx.GROW | wx.ALL)
   712         
   720 
   713         main_staticbox_sizer.AddSizer(second_staticbox_sizer, 1, 
   721         main_staticbox_sizer.AddSizer(second_staticbox_sizer, 1,
   714             border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM)
   722                                       border=5, flag=wx.GROW | wx.LEFT | wx.RIGHT | wx.BOTTOM)
   715         
   723 
   716         self.EthercatMasterEditor.SetSizer(self.EthercatMasterEditorSizer)
   724         self.EthercatMasterEditor.SetSizer(self.EthercatMasterEditorSizer)
   717         
   725 
   718         return self.EthercatMasterEditor
   726         return self.EthercatMasterEditor
   719 
   727 
   720     def __init__(self, parent, controler, window):
   728     def __init__(self, parent, controler, window):
   721         ConfTreeNodeEditor.__init__(self, parent, controler, window)
   729         ConfTreeNodeEditor.__init__(self, parent, controler, window)
   722         
   730 
   723         # ------------------------------------------------------------------
   731         # ------------------------------------------------------------------
   724         self.Controler = controler
   732         self.Controler = controler
   725         # ------------------------------------------------------------------
   733         # ------------------------------------------------------------------
   726         
   734 
   727         self.ProcessVariables = []
   735         self.ProcessVariables = []
   728         self.CellShown = None
   736         self.CellShown = None
   729         self.NodesFilterFirstCharacter = True
   737         self.NodesFilterFirstCharacter = True
   730         
   738 
   731         self.ProcessVariablesDefaultValue = {"Name": "", "ReadFrom": "", "WriteTo": "", "Description": ""}
   739         self.ProcessVariablesDefaultValue = {"Name": "", "ReadFrom": "", "WriteTo": "", "Description": ""}
   732         self.ProcessVariablesTable = ProcessVariablesTable(self, [], GetProcessVariablesTableColnames())
   740         self.ProcessVariablesTable = ProcessVariablesTable(self, [], GetProcessVariablesTableColnames())
   733         self.ProcessVariablesColSizes = [40, 100, 150, 150, 200]
   741         self.ProcessVariablesColSizes = [40, 100, 150, 150, 200]
   734         self.ProcessVariablesColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
   742         self.ProcessVariablesColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
   735         
   743 
   736         self.ProcessVariablesGrid.SetTable(self.ProcessVariablesTable)
   744         self.ProcessVariablesGrid.SetTable(self.ProcessVariablesTable)
   737         self.ProcessVariablesGrid.SetButtons({"Add": self.AddVariableButton,
   745         self.ProcessVariablesGrid.SetButtons({"Add": self.AddVariableButton,
   738                                               "Delete": self.DeleteVariableButton,
   746                                               "Delete": self.DeleteVariableButton,
   739                                               "Up": self.UpVariableButton,
   747                                               "Up": self.UpVariableButton,
   740                                               "Down": self.DownVariableButton})
   748                                               "Down": self.DownVariableButton})
   741         
   749 
   742         def _AddVariablesElement(new_row):
   750         def _AddVariablesElement(new_row):
   743             self.ProcessVariablesTable.InsertRow(new_row, self.ProcessVariablesDefaultValue.copy())
   751             self.ProcessVariablesTable.InsertRow(new_row, self.ProcessVariablesDefaultValue.copy())
   744             self.SaveProcessVariables()
   752             self.SaveProcessVariables()
   745             self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
   753             self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
   746             return new_row
   754             return new_row
   747         setattr(self.ProcessVariablesGrid, "_AddRow", _AddVariablesElement)
   755         setattr(self.ProcessVariablesGrid, "_AddRow", _AddVariablesElement)
   748         
   756 
   749         def _DeleteVariablesElement(row):
   757         def _DeleteVariablesElement(row):
   750             self.ProcessVariablesTable.RemoveRow(row)
   758             self.ProcessVariablesTable.RemoveRow(row)
   751             self.SaveProcessVariables()
   759             self.SaveProcessVariables()
   752             self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
   760             self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
   753         setattr(self.ProcessVariablesGrid, "_DeleteRow", _DeleteVariablesElement)
   761         setattr(self.ProcessVariablesGrid, "_DeleteRow", _DeleteVariablesElement)
   754             
   762 
   755         def _MoveVariablesElement(row, move):
   763         def _MoveVariablesElement(row, move):
   756             new_row = self.ProcessVariablesTable.MoveRow(row, move)
   764             new_row = self.ProcessVariablesTable.MoveRow(row, move)
   757             if new_row != row:
   765             if new_row != row:
   758                 self.SaveProcessVariables()
   766                 self.SaveProcessVariables()
   759                 self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
   767                 self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
   760             return new_row
   768             return new_row
   761         setattr(self.ProcessVariablesGrid, "_MoveRow", _MoveVariablesElement)
   769         setattr(self.ProcessVariablesGrid, "_MoveRow", _MoveVariablesElement)
   762         
   770 
   763         _refresh_buttons = getattr(self.ProcessVariablesGrid, "RefreshButtons")
   771         _refresh_buttons = getattr(self.ProcessVariablesGrid, "RefreshButtons")
       
   772 
   764         def _RefreshButtons():
   773         def _RefreshButtons():
   765             if self.NodesFilter.GetSelection() == 0:
   774             if self.NodesFilter.GetSelection() == 0:
   766                 _refresh_buttons()
   775                 _refresh_buttons()
   767             else:
   776             else:
   768                 self.AddVariableButton.Enable(False)
   777                 self.AddVariableButton.Enable(False)
   769                 self.DeleteVariableButton.Enable(False)
   778                 self.DeleteVariableButton.Enable(False)
   770                 self.UpVariableButton.Enable(False)
   779                 self.UpVariableButton.Enable(False)
   771                 self.DownVariableButton.Enable(False)
   780                 self.DownVariableButton.Enable(False)
   772         setattr(self.ProcessVariablesGrid, "RefreshButtons", _RefreshButtons)
   781         setattr(self.ProcessVariablesGrid, "RefreshButtons", _RefreshButtons)
   773         
   782 
   774         self.ProcessVariablesGrid.SetRowLabelSize(0)
   783         self.ProcessVariablesGrid.SetRowLabelSize(0)
   775         for col in range(self.ProcessVariablesTable.GetNumberCols()):
   784         for col in range(self.ProcessVariablesTable.GetNumberCols()):
   776             attr = wx.grid.GridCellAttr()
   785             attr = wx.grid.GridCellAttr()
   777             attr.SetAlignment(self.ProcessVariablesColAlignements[col], wx.ALIGN_CENTRE)
   786             attr.SetAlignment(self.ProcessVariablesColAlignements[col], wx.ALIGN_CENTRE)
   778             self.ProcessVariablesGrid.SetColAttr(col, attr)
   787             self.ProcessVariablesGrid.SetColAttr(col, attr)
   779             self.ProcessVariablesGrid.SetColMinimalWidth(col, self.ProcessVariablesColSizes[col])
   788             self.ProcessVariablesGrid.SetColMinimalWidth(col, self.ProcessVariablesColSizes[col])
   780             self.ProcessVariablesGrid.AutoSizeColumn(col, False)
   789             self.ProcessVariablesGrid.AutoSizeColumn(col, False)
   781         self.ProcessVariablesGrid.RefreshButtons()
   790         self.ProcessVariablesGrid.RefreshButtons()
   782     
   791 
   783         self.StartupCommandsDefaultValue = {"Position": 0, "Index": 0, "Subindex": 0, "Value": 0, "Description": ""}
   792         self.StartupCommandsDefaultValue = {"Position": 0, "Index": 0, "Subindex": 0, "Value": 0, "Description": ""}
   784         self.StartupCommandsTable = StartupCommandsTable(self, [], GetStartupCommandsTableColnames())
   793         self.StartupCommandsTable = StartupCommandsTable(self, [], GetStartupCommandsTableColnames())
   785         self.StartupCommandsColSizes = [100, 100, 50, 100, 200]
   794         self.StartupCommandsColSizes = [100, 100, 50, 100, 200]
   786         self.StartupCommandsColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT]
   795         self.StartupCommandsColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_RIGHT, wx.ALIGN_LEFT]
   787         
   796 
   788         self.StartupCommandsGrid.SetTable(self.StartupCommandsTable)
   797         self.StartupCommandsGrid.SetTable(self.StartupCommandsTable)
   789         self.StartupCommandsGrid.SetButtons({"Add": self.AddCommandButton,
   798         self.StartupCommandsGrid.SetButtons({"Add": self.AddCommandButton,
   790                                              "Delete": self.DeleteCommandButton})
   799                                              "Delete": self.DeleteCommandButton})
   791         
   800 
   792         def _AddCommandsElement(new_row):
   801         def _AddCommandsElement(new_row):
   793             command = self.StartupCommandsDefaultValue.copy()
   802             command = self.StartupCommandsDefaultValue.copy()
   794             command_idx = self.Controler.AppendStartupCommand(command)
   803             command_idx = self.Controler.AppendStartupCommand(command)
   795             self.RefreshStartupCommands()
   804             self.RefreshStartupCommands()
   796             self.RefreshBuffer()
   805             self.RefreshBuffer()
   797             return self.StartupCommandsTable.GetCommandIndex(command["Position"], command_idx)
   806             return self.StartupCommandsTable.GetCommandIndex(command["Position"], command_idx)
   798         setattr(self.StartupCommandsGrid, "_AddRow", _AddCommandsElement)
   807         setattr(self.StartupCommandsGrid, "_AddRow", _AddCommandsElement)
   799         
   808 
   800         def _DeleteCommandsElement(row):
   809         def _DeleteCommandsElement(row):
   801             command = self.StartupCommandsTable.GetRow(row)
   810             command = self.StartupCommandsTable.GetRow(row)
   802             self.Controler.RemoveStartupCommand(command["Position"], command["command_idx"])
   811             self.Controler.RemoveStartupCommand(command["Position"], command["command_idx"])
   803             self.RefreshStartupCommands()
   812             self.RefreshStartupCommands()
   804             self.RefreshBuffer()
   813             self.RefreshBuffer()
   805         setattr(self.StartupCommandsGrid, "_DeleteRow", _DeleteCommandsElement)
   814         setattr(self.StartupCommandsGrid, "_DeleteRow", _DeleteCommandsElement)
   806         
   815 
   807         self.StartupCommandsGrid.SetRowLabelSize(0)
   816         self.StartupCommandsGrid.SetRowLabelSize(0)
   808         for col in range(self.StartupCommandsTable.GetNumberCols()):
   817         for col in range(self.StartupCommandsTable.GetNumberCols()):
   809             attr = wx.grid.GridCellAttr()
   818             attr = wx.grid.GridCellAttr()
   810             attr.SetAlignment(self.StartupCommandsColAlignements[col], wx.ALIGN_CENTRE)
   819             attr.SetAlignment(self.StartupCommandsColAlignements[col], wx.ALIGN_CENTRE)
   811             self.StartupCommandsGrid.SetColAttr(col, attr)
   820             self.StartupCommandsGrid.SetColAttr(col, attr)
   812             self.StartupCommandsGrid.SetColMinimalWidth(col, self.StartupCommandsColSizes[col])
   821             self.StartupCommandsGrid.SetColMinimalWidth(col, self.StartupCommandsColSizes[col])
   813             self.StartupCommandsGrid.AutoSizeColumn(col, False)
   822             self.StartupCommandsGrid.AutoSizeColumn(col, False)
   814         self.StartupCommandsGrid.RefreshButtons()
   823         self.StartupCommandsGrid.RefreshButtons()
   815     
   824 
   816     def RefreshBuffer(self):
   825     def RefreshBuffer(self):
   817         self.ParentWindow.RefreshTitle()
   826         self.ParentWindow.RefreshTitle()
   818         self.ParentWindow.RefreshFileMenu()
   827         self.ParentWindow.RefreshFileMenu()
   819         self.ParentWindow.RefreshEditMenu()
   828         self.ParentWindow.RefreshEditMenu()
   820         self.ParentWindow.RefreshPageTitles()
   829         self.ParentWindow.RefreshPageTitles()
   821     
   830 
   822     def GetBufferState(self):
   831     def GetBufferState(self):
   823         return self.Controler.GetBufferState()
   832         return self.Controler.GetBufferState()
   824     
   833 
   825     def Undo(self):
   834     def Undo(self):
   826         self.Controler.LoadPrevious()
   835         self.Controler.LoadPrevious()
   827         self.RefreshView()
   836         self.RefreshView()
   828             
   837 
   829     def Redo(self):
   838     def Redo(self):
   830         self.Controler.LoadNext()
   839         self.Controler.LoadNext()
   831         self.RefreshView()
   840         self.RefreshView()
   832     
   841 
   833     def RefreshView(self):
   842     def RefreshView(self):
   834         ConfTreeNodeEditor.RefreshView(self)
   843         ConfTreeNodeEditor.RefreshView(self)
   835         
   844 
   836         self.RefreshNodesFilter()
   845         self.RefreshNodesFilter()
   837         self.RefreshProcessVariables()
   846         self.RefreshProcessVariables()
   838         self.RefreshStartupCommands()
   847         self.RefreshStartupCommands()
   839         self.NodesVariables.RefreshView()
   848         self.NodesVariables.RefreshView()
   840     
   849 
   841     def RefreshNodesFilter(self):
   850     def RefreshNodesFilter(self):
   842         value = self.NodesFilter.GetValue()
   851         value = self.NodesFilter.GetValue()
   843         self.NodesFilter.Clear()
   852         self.NodesFilter.Clear()
   844         self.NodesFilter.Append(_("All"))
   853         self.NodesFilter.Append(_("All"))
   845         self.NodesFilterValues = [{}]
   854         self.NodesFilterValues = [{}]
   852             self.NodesFilter.SetStringSelection(value)
   861             self.NodesFilter.SetStringSelection(value)
   853         else:
   862         else:
   854             try:
   863             try:
   855                 int(value)
   864                 int(value)
   856                 self.NodesFilter.SetValue(value)
   865                 self.NodesFilter.SetValue(value)
   857             except:
   866             except Exception:
   858                 self.NodesFilter.SetSelection(0)
   867                 self.NodesFilter.SetSelection(0)
   859         self.RefreshCurrentNodesFilter()
   868         self.RefreshCurrentNodesFilter()
   860     
   869 
   861     def RefreshCurrentNodesFilter(self):
   870     def RefreshCurrentNodesFilter(self):
   862         filter = self.NodesFilter.GetSelection()
   871         filter = self.NodesFilter.GetSelection()
   863         if filter != -1:
   872         if filter != -1:
   864             self.CurrentNodesFilter = self.NodesFilterValues[filter]
   873             self.CurrentNodesFilter = self.NodesFilterValues[filter]
   865         else:
   874         else:
   870                     self.NodesFilter.SetSelection(0)
   879                     self.NodesFilter.SetSelection(0)
   871                 else:
   880                 else:
   872                     position = int(self.NodesFilter.GetValue())
   881                     position = int(self.NodesFilter.GetValue())
   873                     self.CurrentNodesFilter = {"slave_pos": position}
   882                     self.CurrentNodesFilter = {"slave_pos": position}
   874                     self.NodesFilter.SetValue(NODE_POSITION_FILTER_FORMAT % position)
   883                     self.NodesFilter.SetValue(NODE_POSITION_FILTER_FORMAT % position)
   875             except:
   884             except Exception:
   876                 if self.CurrentNodesFilter in self.NodesFilterValues:
   885                 if self.CurrentNodesFilter in self.NodesFilterValues:
   877                     self.NodesFilter.SetSelection(self.NodesFilterValues.index(self.CurrentNodesFilter))
   886                     self.NodesFilter.SetSelection(self.NodesFilterValues.index(self.CurrentNodesFilter))
   878                 else:
   887                 else:
   879                     self.NodesFilter.SetValue(NODE_POSITION_FILTER_FORMAT % self.CurrentNodesFilter["slave_pos"])
   888                     self.NodesFilter.SetValue(NODE_POSITION_FILTER_FORMAT % self.CurrentNodesFilter["slave_pos"])
   880         self.NodesFilterFirstCharacter = True
   889         self.NodesFilterFirstCharacter = True
   881         self.NodesVariables.SetCurrentNodesFilter(self.CurrentNodesFilter)
   890         self.NodesVariables.SetCurrentNodesFilter(self.CurrentNodesFilter)
   882     
   891 
   883     def RefreshProcessVariables(self):
   892     def RefreshProcessVariables(self):
   884         if self.CurrentNodesFilter is not None:
   893         if self.CurrentNodesFilter is not None:
   885             self.ProcessVariables = self.Controler.GetProcessVariables()
   894             self.ProcessVariables = self.Controler.GetProcessVariables()
   886             slaves = self.Controler.GetSlaves(**self.CurrentNodesFilter)
   895             slaves = self.Controler.GetSlaves(**self.CurrentNodesFilter)
   887             data = []
   896             data = []
   888             for variable in self.ProcessVariables:
   897             for variable in self.ProcessVariables:
   889                 if (variable["ReadFrom"] == "" or variable["ReadFrom"][0] in slaves or
   898                 if variable["ReadFrom"] == "" or variable["ReadFrom"][0] in slaves or \
   890                     variable["WriteTo"] == "" or variable["WriteTo"][0] in slaves):
   899                    variable["WriteTo"] == "" or variable["WriteTo"][0] in slaves:
   891                     data.append(variable)
   900                     data.append(variable)
   892             self.ProcessVariablesTable.SetData(data)
   901             self.ProcessVariablesTable.SetData(data)
   893             self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
   902             self.ProcessVariablesTable.ResetView(self.ProcessVariablesGrid)
   894             self.ProcessVariablesGrid.RefreshButtons()
   903             self.ProcessVariablesGrid.RefreshButtons()
   895     
   904 
   896     def SaveProcessVariables(self):
   905     def SaveProcessVariables(self):
   897         if self.CurrentNodesFilter is not None:
   906         if self.CurrentNodesFilter is not None:
   898             if len(self.CurrentNodesFilter) > 0:
   907             if len(self.CurrentNodesFilter) > 0:
   899                 self.Controler.SetProcessVariables(self.ProcessVariables)
   908                 self.Controler.SetProcessVariables(self.ProcessVariables)
   900             else:
   909             else:
   901                 self.Controler.SetProcessVariables(self.ProcessVariablesTable.GetData())
   910                 self.Controler.SetProcessVariables(self.ProcessVariablesTable.GetData())
   902             self.RefreshBuffer()
   911             self.RefreshBuffer()
   903     
   912 
   904     def RefreshStartupCommands(self, position=None, command_idx=None):
   913     def RefreshStartupCommands(self, position=None, command_idx=None):
   905         if self.CurrentNodesFilter is not None:
   914         if self.CurrentNodesFilter is not None:
   906             col = max(self.StartupCommandsGrid.GetGridCursorCol(), 0)
   915             col = max(self.StartupCommandsGrid.GetGridCursorCol(), 0)
   907             self.StartupCommandsTable.SetData(
   916             self.StartupCommandsTable.SetData(
   908                 self.Controler.GetStartupCommands(**self.CurrentNodesFilter))
   917                 self.Controler.GetStartupCommands(**self.CurrentNodesFilter))
   909             self.StartupCommandsTable.ResetView(self.StartupCommandsGrid)
   918             self.StartupCommandsTable.ResetView(self.StartupCommandsGrid)
   910             if position is not None and command_idx is not None:
   919             if position is not None and command_idx is not None:
   911                 self.SelectStartupCommand(position, command_idx, col)
   920                 self.SelectStartupCommand(position, command_idx, col)
   912     
   921 
   913     def SelectStartupCommand(self, position, command_idx, col):
   922     def SelectStartupCommand(self, position, command_idx, col):
   914         self.StartupCommandsGrid.SetSelectedCell(
   923         self.StartupCommandsGrid.SetSelectedCell(
   915             self.StartupCommandsTable.GetCommandIndex(position, command_idx),
   924             self.StartupCommandsTable.GetCommandIndex(position, command_idx),
   916             col)
   925             col)
   917     
   926 
   918     def GetMasterLocation(self):
   927     def GetMasterLocation(self):
   919         return self.Controler.GetCurrentLocation()
   928         return self.Controler.GetCurrentLocation()
   920     
   929 
   921     def AddStartupCommand(self, position, index, subindex):
   930     def AddStartupCommand(self, position, index, subindex):
   922         col = max(self.StartupCommandsGrid.GetGridCursorCol(), 0)
   931         col = max(self.StartupCommandsGrid.GetGridCursorCol(), 0)
   923         command = self.StartupCommandsDefaultValue.copy()
   932         command = self.StartupCommandsDefaultValue.copy()
   924         command["Position"] = position
   933         command["Position"] = position
   925         command["Index"] = index
   934         command["Index"] = index
   926         command["Subindex"] = subindex
   935         command["Subindex"] = subindex
   927         command_idx = self.Controler.AppendStartupCommand(command)
   936         command_idx = self.Controler.AppendStartupCommand(command)
   928         self.RefreshStartupCommands()
   937         self.RefreshStartupCommands()
   929         self.RefreshBuffer()
   938         self.RefreshBuffer()
   930         self.SelectStartupCommand(position, command_idx, col)
   939         self.SelectStartupCommand(position, command_idx, col)
   931     
   940 
   932     def OnNodesFilterChanged(self, event):
   941     def OnNodesFilterChanged(self, event):
   933         self.RefreshCurrentNodesFilter()
   942         self.RefreshCurrentNodesFilter()
   934         if self.CurrentNodesFilter is not None:
   943         if self.CurrentNodesFilter is not None:
   935             self.RefreshProcessVariables()
   944             self.RefreshProcessVariables()
   936             self.RefreshStartupCommands()
   945             self.RefreshStartupCommands()
   937             self.NodesVariables.RefreshView()
   946             self.NodesVariables.RefreshView()
   938         event.Skip()
   947         event.Skip()
   939     
   948 
   940     def OnNodesFilterKeyDown(self, event):
   949     def OnNodesFilterKeyDown(self, event):
   941         if self.NodesFilterFirstCharacter:
   950         if self.NodesFilterFirstCharacter:
   942             keycode = event.GetKeyCode()
   951             keycode = event.GetKeyCode()
   943             if keycode not in [wx.WXK_RETURN, 
   952             if keycode not in [wx.WXK_RETURN,
   944                                wx.WXK_NUMPAD_ENTER]:
   953                                wx.WXK_NUMPAD_ENTER]:
   945                 self.NodesFilterFirstCharacter = False
   954                 self.NodesFilterFirstCharacter = False
   946                 if keycode not in NAVIGATION_KEYS:
   955                 if keycode not in NAVIGATION_KEYS:
   947                     self.NodesFilter.SetValue("")
   956                     self.NodesFilter.SetValue("")
   948             if keycode not in [wx.WXK_DELETE, 
   957             if keycode not in [wx.WXK_DELETE,
   949                                wx.WXK_NUMPAD_DELETE, 
   958                                wx.WXK_NUMPAD_DELETE,
   950                                wx.WXK_BACK]:
   959                                wx.WXK_BACK]:
   951                 event.Skip()
   960                 event.Skip()
   952         else:
   961         else:
   953             event.Skip()
   962             event.Skip()
   954     
   963 
   955     def OnProcessVariablesGridCellChange(self, event):
   964     def OnProcessVariablesGridCellChange(self, event):
   956         row, col = event.GetRow(), event.GetCol()
   965         row, col = event.GetRow(), event.GetCol()
   957         colname = self.ProcessVariablesTable.GetColLabelValue(col, False)
   966         colname = self.ProcessVariablesTable.GetColLabelValue(col, False)
   958         value = self.ProcessVariablesTable.GetValue(row, col)
   967         value = self.ProcessVariablesTable.GetValue(row, col)
   959         message = None
   968         message = None
   967         if message is None:
   976         if message is None:
   968             self.SaveProcessVariables()
   977             self.SaveProcessVariables()
   969             wx.CallAfter(self.ProcessVariablesTable.ResetView, self.ProcessVariablesGrid)
   978             wx.CallAfter(self.ProcessVariablesTable.ResetView, self.ProcessVariablesGrid)
   970             event.Skip()
   979             event.Skip()
   971         else:
   980         else:
   972             dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
   981             dialog = wx.MessageDialog(self, message, _("Error"), wx.OK | wx.ICON_ERROR)
   973             dialog.ShowModal()
   982             dialog.ShowModal()
   974             dialog.Destroy()
   983             dialog.Destroy()
   975             event.Veto()
   984             event.Veto()
   976     
   985 
   977     def OnProcessVariablesGridCellLeftClick(self, event):
   986     def OnProcessVariablesGridCellLeftClick(self, event):
   978         row = event.GetRow()
   987         row = event.GetRow()
   979         if event.GetCol() == 0:
   988         if event.GetCol() == 0:
   980             var_name = self.ProcessVariablesTable.GetValueByName(row, "Name")
   989             var_name = self.ProcessVariablesTable.GetValueByName(row, "Name")
   981             var_type = self.Controler.GetSlaveVariableDataType(
   990             var_type = self.Controler.GetSlaveVariableDataType(
   982                 *self.ProcessVariablesTable.GetValueByName(row, "ReadFrom"))
   991                 *self.ProcessVariablesTable.GetValueByName(row, "ReadFrom"))
   983             data_size = self.Controler.GetSizeOfType(var_type)
   992             data_size = self.Controler.GetSizeOfType(var_type)
   984             number = self.ProcessVariablesTable.GetValueByName(row, "Number")
   993             number = self.ProcessVariablesTable.GetValueByName(row, "Number")
   985             location = "%%M%s" % data_size + \
   994             location = "%%M%s" % data_size + \
   986                        ".".join(map(lambda x:str(x), self.Controler.GetCurrentLocation() + (number,)))
   995                        ".".join(map(str, self.Controler.GetCurrentLocation() + (number,)))
   987             
   996 
   988             data = wx.TextDataObject(str((location, "location", var_type, var_name, "")))
   997             data = wx.TextDataObject(str((location, "location", var_type, var_name, "")))
   989             dragSource = wx.DropSource(self.ProcessVariablesGrid)
   998             dragSource = wx.DropSource(self.ProcessVariablesGrid)
   990             dragSource.SetData(data)
   999             dragSource.SetData(data)
   991             dragSource.DoDragDrop()
  1000             dragSource.DoDragDrop()
   992         event.Skip()
  1001         event.Skip()
   993     
  1002 
   994     def OnProcessVariablesGridKeyDown(self, event):
  1003     def OnProcessVariablesGridKeyDown(self, event):
   995         keycode = event.GetKeyCode()
  1004         keycode = event.GetKeyCode()
   996         col = self.ProcessVariablesGrid.GetGridCursorCol()
  1005         col = self.ProcessVariablesGrid.GetGridCursorCol()
   997         row = self.ProcessVariablesGrid.GetGridCursorRow()
  1006         row = self.ProcessVariablesGrid.GetGridCursorRow()
   998         colname = self.ProcessVariablesTable.GetColLabelValue(col, False)
  1007         colname = self.ProcessVariablesTable.GetColLabelValue(col, False)
   999         if (keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and 
  1008         if keycode in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and \
  1000             (colname.startswith("Read from") or colname.startswith("Write to"))):
  1009            (colname.startswith("Read from") or colname.startswith("Write to")):
  1001             self.ProcessVariablesTable.SetValue(row, col, "")
  1010             self.ProcessVariablesTable.SetValue(row, col, "")
  1002             self.SaveProcessVariables()
  1011             self.SaveProcessVariables()
  1003             wx.CallAfter(self.ProcessVariablesTable.ResetView, self.ProcessVariablesGrid)
  1012             wx.CallAfter(self.ProcessVariablesTable.ResetView, self.ProcessVariablesGrid)
  1004         else:
  1013         else:
  1005             event.Skip()
  1014             event.Skip()
  1006     
  1015 
  1007     def OnStartupCommandsGridEditorShow(self, event):
  1016     def OnStartupCommandsGridEditorShow(self, event):
  1008         self.CellShown = event.GetRow(), event.GetCol()
  1017         self.CellShown = event.GetRow(), event.GetCol()
  1009         event.Skip()
  1018         event.Skip()
  1010     
  1019 
  1011     def OnStartupCommandsGridCellChange(self, event):
  1020     def OnStartupCommandsGridCellChange(self, event):
  1012         row, col = event.GetRow(), event.GetCol()
  1021         row, col = event.GetRow(), event.GetCol()
  1013         if self.CellShown == (row, col):
  1022         if self.CellShown == (row, col):
  1014             self.CellShown = None
  1023             self.CellShown = None
  1015             colname = self.StartupCommandsTable.GetColLabelValue(col, False)
  1024             colname = self.StartupCommandsTable.GetColLabelValue(col, False)
  1027                     command_idx = self.Controler.AppendStartupCommand(command)
  1036                     command_idx = self.Controler.AppendStartupCommand(command)
  1028                     wx.CallAfter(self.RefreshStartupCommands, command["Position"], command_idx)
  1037                     wx.CallAfter(self.RefreshStartupCommands, command["Position"], command_idx)
  1029             else:
  1038             else:
  1030                 command = self.StartupCommandsTable.GetRow(row)
  1039                 command = self.StartupCommandsTable.GetRow(row)
  1031                 self.Controler.SetStartupCommandInfos(command)
  1040                 self.Controler.SetStartupCommandInfos(command)
  1032                 if colname in ["Index", "SubIndex"]: 
  1041                 if colname in ["Index", "SubIndex"]:
  1033                     wx.CallAfter(self.RefreshStartupCommands, command["Position"], command["command_idx"])
  1042                     wx.CallAfter(self.RefreshStartupCommands, command["Position"], command["command_idx"])
  1034             if message is None:
  1043             if message is None:
  1035                 self.RefreshBuffer()
  1044                 self.RefreshBuffer()
  1036                 event.Skip()
  1045                 event.Skip()
  1037             else:
  1046             else:
  1038                 dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
  1047                 dialog = wx.MessageDialog(self, message, _("Error"), wx.OK | wx.ICON_ERROR)
  1039                 dialog.ShowModal()
  1048                 dialog.ShowModal()
  1040                 dialog.Destroy()
  1049                 dialog.Destroy()
  1041                 event.Veto()
  1050                 event.Veto()
  1042         else:
  1051         else:
  1043             event.Veto()
  1052             event.Veto()
  1044     
  1053 
  1045     def OnResize(self, event):
  1054     def OnResize(self, event):
  1046         self.EthercatMasterEditor.GetBestSize()
  1055         self.EthercatMasterEditor.GetBestSize()
  1047         xstart, ystart = self.EthercatMasterEditor.GetViewStart()
  1056         xstart, ystart = self.EthercatMasterEditor.GetViewStart()
  1048         window_size = self.EthercatMasterEditor.GetClientSize()
  1057         window_size = self.EthercatMasterEditor.GetClientSize()
  1049         maxx, maxy = self.EthercatMasterEditorSizer.GetMinSize()
  1058         maxx, maxy = self.EthercatMasterEditorSizer.GetMinSize()
  1050         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
  1059         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
  1051         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
  1060         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
  1052         self.EthercatMasterEditor.Scroll(posx, posy)
  1061         self.EthercatMasterEditor.Scroll(posx, posy)
  1053         self.EthercatMasterEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
  1062         self.EthercatMasterEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
  1054                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
  1063                                                 maxx / SCROLLBAR_UNIT,
       
  1064                                                 maxy / SCROLLBAR_UNIT,
       
  1065                                                 posx, posy)
  1055         event.Skip()
  1066         event.Skip()
  1056         
  1067 
  1057     #def OnButtonClick(self, event):
  1068     # def OnButtonClick(self, event):
  1058     #    self.MasterState = self.Controler.getMasterState()
  1069     #    self.MasterState = self.Controler.getMasterState()
  1059     #    if self.MasterState:
  1070     #    if self.MasterState:
  1060     #        self.Phase.SetValue(self.MasterState["phase"])
  1071     #        self.Phase.SetValue(self.MasterState["phase"])
  1061     #        self.Active.SetValue(self.MasterState["active"])
  1072     #        self.Active.SetValue(self.MasterState["active"])
  1062     #        self.SlaveCount.SetValue(self.MasterState["slave"])
  1073     #        self.SlaveCount.SetValue(self.MasterState["slave"])
  1065     #        self.TxFrames.SetValue(self.MasterState["TXframe"])
  1076     #        self.TxFrames.SetValue(self.MasterState["TXframe"])
  1066     #        self.RxFrames.SetValue(self.MasterState["RXframe"])
  1077     #        self.RxFrames.SetValue(self.MasterState["RXframe"])
  1067     #        self.TxByte.SetValue(self.MasterState["TXbyte"])
  1078     #        self.TxByte.SetValue(self.MasterState["TXbyte"])
  1068     #        self.TxError.SetValue(self.MasterState["TXerror"])
  1079     #        self.TxError.SetValue(self.MasterState["TXerror"])
  1069     #        self.LostFrames.SetValue(self.MasterState["lost"])
  1080     #        self.LostFrames.SetValue(self.MasterState["lost"])
  1070             
  1081 
  1071     #        self.TxFrameRate1.SetValue(self.MasterState["TXframerate1"])
  1082     #        self.TxFrameRate1.SetValue(self.MasterState["TXframerate1"])
  1072     #        self.TxFrameRate2.SetValue(self.MasterState["TXframerate2"])
  1083     #        self.TxFrameRate2.SetValue(self.MasterState["TXframerate2"])
  1073     #        self.TxFrameRate3.SetValue(self.MasterState["TXframerate3"])
  1084     #        self.TxFrameRate3.SetValue(self.MasterState["TXframerate3"])
  1074     #        self.TxRate1.SetValue(self.MasterState["TXrate1"])
  1085     #        self.TxRate1.SetValue(self.MasterState["TXrate1"])
  1075     #        self.TxRate2.SetValue(self.MasterState["TXrate2"])
  1086     #        self.TxRate2.SetValue(self.MasterState["TXrate2"])
  1078     #        self.LossRate2.SetValue(self.MasterState["loss2"])
  1089     #        self.LossRate2.SetValue(self.MasterState["loss2"])
  1079     #        self.LossRate3.SetValue(self.MasterState["loss3"])
  1090     #        self.LossRate3.SetValue(self.MasterState["loss3"])
  1080     #        self.FrameLoss1.SetValue(self.MasterState["frameloss1"])
  1091     #        self.FrameLoss1.SetValue(self.MasterState["frameloss1"])
  1081     #        self.FrameLoss2.SetValue(self.MasterState["frameloss2"])
  1092     #        self.FrameLoss2.SetValue(self.MasterState["frameloss2"])
  1082     #        self.FrameLoss3.SetValue(self.MasterState["frameloss3"])
  1093     #        self.FrameLoss3.SetValue(self.MasterState["frameloss3"])
  1083     
  1094 
       
  1095 
  1084 class LibraryEditorSizer(wx.FlexGridSizer):
  1096 class LibraryEditorSizer(wx.FlexGridSizer):
  1085     
  1097 
  1086     def __init__(self, parent, module_library, buttons):
  1098     def __init__(self, parent, module_library, buttons):
  1087         wx.FlexGridSizer.__init__(self, cols=1, hgap=0, rows=4, vgap=5)
  1099         wx.FlexGridSizer.__init__(self, cols=1, hgap=0, rows=4, vgap=5)
  1088         
  1100 
  1089         self.ModuleLibrary = module_library
  1101         self.ModuleLibrary = module_library
  1090         self.ParentWindow = parent
  1102         self.ParentWindow = parent
  1091         
  1103 
  1092         self.AddGrowableCol(0)
  1104         self.AddGrowableCol(0)
  1093         self.AddGrowableRow(1)
  1105         self.AddGrowableRow(1)
  1094         self.AddGrowableRow(3)
  1106         self.AddGrowableRow(3)
  1095         
  1107 
  1096         ESI_files_label = wx.StaticText(parent, 
  1108         ESI_files_label = wx.StaticText(parent,
  1097             label=_("ESI Files:"))
  1109                                         label=_("ESI Files:"))
  1098         self.AddWindow(ESI_files_label, border=10, 
  1110         self.AddWindow(ESI_files_label, border=10,
  1099             flag=wx.TOP|wx.LEFT|wx.RIGHT)
  1111                        flag=wx.TOP | wx.LEFT | wx.RIGHT)
  1100         
  1112 
  1101         folder_tree_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=1, vgap=0)
  1113         folder_tree_sizer = wx.FlexGridSizer(cols=2, hgap=5, rows=1, vgap=0)
  1102         folder_tree_sizer.AddGrowableCol(0)
  1114         folder_tree_sizer.AddGrowableCol(0)
  1103         folder_tree_sizer.AddGrowableRow(0)
  1115         folder_tree_sizer.AddGrowableRow(0)
  1104         self.AddSizer(folder_tree_sizer, border=10, 
  1116         self.AddSizer(folder_tree_sizer, border=10,
  1105             flag=wx.GROW|wx.LEFT|wx.RIGHT)
  1117                       flag=wx.GROW | wx.LEFT | wx.RIGHT)
  1106         
  1118 
  1107         self.ESIFiles = FolderTree(parent, self.GetPath(), editable=False)
  1119         self.ESIFiles = FolderTree(parent, self.GetPath(), editable=False)
  1108         self.ESIFiles.SetFilter(".xml")
  1120         self.ESIFiles.SetFilter(".xml")
  1109         folder_tree_sizer.AddWindow(self.ESIFiles, flag=wx.GROW)
  1121         folder_tree_sizer.AddWindow(self.ESIFiles, flag=wx.GROW)
  1110         
  1122 
  1111         buttons_sizer = wx.BoxSizer(wx.VERTICAL)
  1123         buttons_sizer = wx.BoxSizer(wx.VERTICAL)
  1112         folder_tree_sizer.AddSizer(buttons_sizer, 
  1124         folder_tree_sizer.AddSizer(buttons_sizer,
  1113             flag=wx.ALIGN_CENTER_VERTICAL)
  1125                                    flag=wx.ALIGN_CENTER_VERTICAL)
  1114         
  1126 
  1115         for idx, (name, bitmap, help, callback) in enumerate(buttons):
  1127         for idx, (name, bitmap, help, callback) in enumerate(buttons):
  1116             button = wx.lib.buttons.GenBitmapButton(parent, 
  1128             button = wx.lib.buttons.GenBitmapButton(parent,
  1117                   bitmap=GetBitmap(bitmap), 
  1129                                                     bitmap=GetBitmap(bitmap),
  1118                   size=wx.Size(28, 28), style=wx.NO_BORDER)
  1130                                                     size=wx.Size(28, 28),
       
  1131                                                     style=wx.NO_BORDER)
  1119             button.SetToolTipString(help)
  1132             button.SetToolTipString(help)
  1120             setattr(self, name, button)
  1133             setattr(self, name, button)
  1121             if idx > 0:
  1134             if idx > 0:
  1122                 flag = wx.TOP
  1135                 flag = wx.TOP
  1123             else:
  1136             else:
  1125             if callback is None:
  1138             if callback is None:
  1126                 callback = getattr(self, "On" + name, None)
  1139                 callback = getattr(self, "On" + name, None)
  1127             if callback is not None:
  1140             if callback is not None:
  1128                 parent.Bind(wx.EVT_BUTTON, callback, button)
  1141                 parent.Bind(wx.EVT_BUTTON, callback, button)
  1129             buttons_sizer.AddWindow(button, border=10, flag=flag)
  1142             buttons_sizer.AddWindow(button, border=10, flag=flag)
  1130         
  1143 
  1131         modules_label = wx.StaticText(parent, 
  1144         modules_label = wx.StaticText(parent,
  1132             label=_("Modules library:"))
  1145                                       label=_("Modules library:"))
  1133         self.AddSizer(modules_label, border=10, 
  1146         self.AddSizer(modules_label, border=10,
  1134             flag=wx.LEFT|wx.RIGHT)
  1147                       flag=wx.LEFT | wx.RIGHT)
  1135         
  1148 
  1136         self.ModulesGrid = wx.gizmos.TreeListCtrl(parent,
  1149         self.ModulesGrid = wx.gizmos.TreeListCtrl(parent,
  1137               style=wx.TR_DEFAULT_STYLE |
  1150                                                   style=wx.TR_DEFAULT_STYLE |
  1138                     wx.TR_ROW_LINES |
  1151                                                   wx.TR_ROW_LINES |
  1139                     wx.TR_COLUMN_LINES |
  1152                                                   wx.TR_COLUMN_LINES |
  1140                     wx.TR_HIDE_ROOT |
  1153                                                   wx.TR_HIDE_ROOT |
  1141                     wx.TR_FULL_ROW_HIGHLIGHT)
  1154                                                   wx.TR_FULL_ROW_HIGHLIGHT)
  1142         self.ModulesGrid.GetMainWindow().Bind(wx.EVT_LEFT_DOWN,
  1155         self.ModulesGrid.GetMainWindow().Bind(wx.EVT_LEFT_DOWN,
  1143             self.OnModulesGridLeftDown)
  1156                                               self.OnModulesGridLeftDown)
  1144         self.ModulesGrid.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT,
  1157         self.ModulesGrid.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT,
  1145             self.OnModulesGridBeginLabelEdit)
  1158                               self.OnModulesGridBeginLabelEdit)
  1146         self.ModulesGrid.Bind(wx.EVT_TREE_END_LABEL_EDIT,
  1159         self.ModulesGrid.Bind(wx.EVT_TREE_END_LABEL_EDIT,
  1147             self.OnModulesGridEndLabelEdit)
  1160                               self.OnModulesGridEndLabelEdit)
  1148         self.ModulesGrid.GetHeaderWindow().Bind(wx.EVT_MOTION, 
  1161         self.ModulesGrid.GetHeaderWindow().Bind(wx.EVT_MOTION,
  1149             self.OnModulesGridHeaderMotion)
  1162                                                 self.OnModulesGridHeaderMotion)
  1150         self.AddWindow(self.ModulesGrid, border=10, 
  1163         self.AddWindow(self.ModulesGrid, border=10,
  1151             flag=wx.GROW|wx.BOTTOM|wx.LEFT|wx.RIGHT)
  1164                        flag=wx.GROW | wx.BOTTOM | wx.LEFT | wx.RIGHT)
  1152         
  1165 
  1153         for colname, colsize, colalign in zip(
  1166         for colname, colsize, colalign in zip(
  1154                 [_("Name")] + [param_infos["column_label"] 
  1167                 [_("Name")] + [param_infos["column_label"]
  1155                                for param, param_infos in 
  1168                                for _param, param_infos in
  1156                                self.ModuleLibrary.MODULES_EXTRA_PARAMS],
  1169                                self.ModuleLibrary.MODULES_EXTRA_PARAMS],
  1157                 [400] + [param_infos["column_size"] 
  1170                 [400] + [param_infos["column_size"]
  1158                          for param, param_infos in 
  1171                          for _param, param_infos in
  1159                          self.ModuleLibrary.MODULES_EXTRA_PARAMS],
  1172                          self.ModuleLibrary.MODULES_EXTRA_PARAMS],
  1160                 [wx.ALIGN_LEFT] + [wx.ALIGN_RIGHT] * len(self.ModuleLibrary.MODULES_EXTRA_PARAMS)):
  1173                 [wx.ALIGN_LEFT] + [wx.ALIGN_RIGHT] * len(self.ModuleLibrary.MODULES_EXTRA_PARAMS)):
  1161             self.ModulesGrid.AddColumn(_(colname), colsize, colalign, edit=True)
  1174             self.ModulesGrid.AddColumn(_(colname), colsize, colalign, edit=True)
  1162         self.ModulesGrid.SetMainColumn(0)
  1175         self.ModulesGrid.SetMainColumn(0)
  1163         
  1176 
  1164         self.CurrentSelectedCol = None
  1177         self.CurrentSelectedCol = None
  1165         self.LastToolTipCol = None
  1178         self.LastToolTipCol = None
  1166     
  1179 
  1167     def GetPath(self):
  1180     def GetPath(self):
  1168         return self.ModuleLibrary.GetPath()
  1181         return self.ModuleLibrary.GetPath()
  1169     
  1182 
  1170     def SetControlMinSize(self, size):
  1183     def SetControlMinSize(self, size):
  1171         self.ESIFiles.SetMinSize(size)
  1184         self.ESIFiles.SetMinSize(size)
  1172         self.ModulesGrid.SetMinSize(size)
  1185         self.ModulesGrid.SetMinSize(size)
  1173         
  1186 
  1174     def GetSelectedFilePath(self):
  1187     def GetSelectedFilePath(self):
  1175         return self.ESIFiles.GetPath()
  1188         return self.ESIFiles.GetPath()
  1176     
  1189 
  1177     def RefreshView(self):
  1190     def RefreshView(self):
  1178         self.ESIFiles.RefreshTree()
  1191         self.ESIFiles.RefreshTree()
  1179         self.RefreshModulesGrid()
  1192         self.RefreshModulesGrid()
  1180     
  1193 
  1181     def RefreshModulesGrid(self):
  1194     def RefreshModulesGrid(self):
  1182         root = self.ModulesGrid.GetRootItem()
  1195         root = self.ModulesGrid.GetRootItem()
  1183         if not root.IsOk():
  1196         if not root.IsOk():
  1184             root = self.ModulesGrid.AddRoot("Modules")
  1197             root = self.ModulesGrid.AddRoot("Modules")
  1185         self.GenerateModulesGridBranch(root, 
  1198         self.GenerateModulesGridBranch(root,
  1186             self.ModuleLibrary.GetModulesLibrary(), 
  1199                                        self.ModuleLibrary.GetModulesLibrary(),
  1187             GetVariablesTableColnames())
  1200                                        GetVariablesTableColnames())
  1188         self.ModulesGrid.Expand(root)
  1201         self.ModulesGrid.Expand(root)
  1189             
  1202 
  1190     def GenerateModulesGridBranch(self, root, modules, colnames):
  1203     def GenerateModulesGridBranch(self, root, modules, colnames):
  1191         item, root_cookie = self.ModulesGrid.GetFirstChild(root)
  1204         item, root_cookie = self.ModulesGrid.GetFirstChild(root)
  1192         
  1205 
  1193         no_more_items = not item.IsOk()
  1206         no_more_items = not item.IsOk()
  1194         for module in modules:
  1207         for module in modules:
  1195             if no_more_items:
  1208             if no_more_items:
  1196                 item = self.ModulesGrid.AppendItem(root, "")
  1209                 item = self.ModulesGrid.AppendItem(root, "")
  1197             self.ModulesGrid.SetItemText(item, module["name"], 0)
  1210             self.ModulesGrid.SetItemText(item, module["name"], 0)
  1198             if module["infos"] is not None:
  1211             if module["infos"] is not None:
  1199                 for param_idx, (param, param_infos) in enumerate(self.ModuleLibrary.MODULES_EXTRA_PARAMS):
  1212                 for param_idx, (param, _param_infos) in enumerate(self.ModuleLibrary.MODULES_EXTRA_PARAMS):
  1200                     self.ModulesGrid.SetItemText(item, 
  1213                     self.ModulesGrid.SetItemText(item,
  1201                                                  str(module["infos"][param]), 
  1214                                                  str(module["infos"][param]),
  1202                                                  param_idx + 1)
  1215                                                  param_idx + 1)
  1203             else:
  1216             else:
  1204                 self.ModulesGrid.SetItemBackgroundColour(item, wx.LIGHT_GREY)
  1217                 self.ModulesGrid.SetItemBackgroundColour(item, wx.LIGHT_GREY)
  1205             self.ModulesGrid.SetItemPyData(item, module["infos"])
  1218             self.ModulesGrid.SetItemPyData(item, module["infos"])
  1206             self.GenerateModulesGridBranch(item, module["children"], colnames)
  1219             self.GenerateModulesGridBranch(item, module["children"], colnames)
  1207             if not no_more_items:
  1220             if not no_more_items:
  1208                 item, root_cookie = self.ModulesGrid.GetNextChild(root, root_cookie)
  1221                 item, root_cookie = self.ModulesGrid.GetNextChild(root, root_cookie)
  1209                 no_more_items = not item.IsOk()
  1222                 no_more_items = not item.IsOk()
  1210         
  1223 
  1211         if not no_more_items:
  1224         if not no_more_items:
  1212             to_delete = []
  1225             to_delete = []
  1213             while item.IsOk():
  1226             while item.IsOk():
  1214                 to_delete.append(item)
  1227                 to_delete.append(item)
  1215                 item, root_cookie = self.ModulesGrid.GetNextChild(root, root_cookie)
  1228                 item, root_cookie = self.ModulesGrid.GetNextChild(root, root_cookie)
  1216             for item in to_delete:
  1229             for item in to_delete:
  1217                 self.ModulesGrid.Delete(item)
  1230                 self.ModulesGrid.Delete(item)
  1218     
  1231 
  1219     def OnImportButton(self, event):
  1232     def OnImportButton(self, event):
  1220         dialog = wx.FileDialog(self.ParentWindow,
  1233         dialog = wx.FileDialog(self.ParentWindow,
  1221              _("Choose an XML file"), 
  1234                                _("Choose an XML file"),
  1222              os.getcwd(), "",  
  1235                                os.getcwd(), "",
  1223              _("XML files (*.xml)|*.xml|All files|*.*"), wx.OPEN)
  1236                                _("XML files (*.xml)|*.xml|All files|*.*"),
  1224         
  1237                                wx.OPEN)
       
  1238 
  1225         if dialog.ShowModal() == wx.ID_OK:
  1239         if dialog.ShowModal() == wx.ID_OK:
  1226             filepath = dialog.GetPath()
  1240             filepath = dialog.GetPath()
  1227             if self.ModuleLibrary.ImportModuleLibrary(filepath):
  1241             if self.ModuleLibrary.ImportModuleLibrary(filepath):
  1228                 wx.CallAfter(self.RefreshView)
  1242                 wx.CallAfter(self.RefreshView)
  1229             else:
  1243             else:
  1230                 message = wx.MessageDialog(self, 
  1244                 message = wx.MessageDialog(self,
  1231                     _("No such XML file: %s\n") % filepath, 
  1245                                            _("No such XML file: %s\n") % filepath,
  1232                     _("Error"), wx.OK|wx.ICON_ERROR)
  1246                                            _("Error"),
       
  1247                                            wx.OK | wx.ICON_ERROR)
  1233                 message.ShowModal()
  1248                 message.ShowModal()
  1234                 message.Destroy()
  1249                 message.Destroy()
  1235         dialog.Destroy()
  1250         dialog.Destroy()
  1236         
  1251 
  1237         event.Skip()
  1252         event.Skip()
  1238     
  1253 
  1239     def OnDeleteButton(self, event):
  1254     def OnDeleteButton(self, event):
  1240         filepath = self.GetSelectedFilePath()
  1255         filepath = self.GetSelectedFilePath()
  1241         if os.path.isfile(filepath):
  1256         if os.path.isfile(filepath):
  1242             folder, filename = os.path.split(filepath)
  1257             _folder, filename = os.path.split(filepath)
  1243             
  1258 
  1244             dialog = wx.MessageDialog(self.ParentWindow, 
  1259             dialog = wx.MessageDialog(self.ParentWindow,
  1245                   _("Do you really want to delete the file '%s'?") % filename, 
  1260                                       _("Do you really want to delete the file '%s'?") % filename,
  1246                   _("Delete File"), wx.YES_NO|wx.ICON_QUESTION)
  1261                                       _("Delete File"),
       
  1262                                       wx.YES_NO | wx.ICON_QUESTION)
  1247             remove = dialog.ShowModal() == wx.ID_YES
  1263             remove = dialog.ShowModal() == wx.ID_YES
  1248             dialog.Destroy()
  1264             dialog.Destroy()
  1249             
  1265 
  1250             if remove:
  1266             if remove:
  1251                 os.remove(filepath)
  1267                 os.remove(filepath)
  1252                 self.ModuleLibrary.LoadModules()
  1268                 self.ModuleLibrary.LoadModules()
  1253                 wx.CallAfter(self.RefreshView)
  1269                 wx.CallAfter(self.RefreshView)
  1254         event.Skip()
  1270         event.Skip()
  1255     
  1271 
  1256     def OnModulesGridLeftDown(self, event):
  1272     def OnModulesGridLeftDown(self, event):
  1257         item, flags, col = self.ModulesGrid.HitTest(event.GetPosition())
  1273         item, _flags, col = self.ModulesGrid.HitTest(event.GetPosition())
  1258         if item.IsOk():
  1274         if item.IsOk():
  1259             entry_infos = self.ModulesGrid.GetItemPyData(item)
  1275             entry_infos = self.ModulesGrid.GetItemPyData(item)
  1260             if entry_infos is not None and col > 0:
  1276             if entry_infos is not None and col > 0:
  1261                 self.CurrentSelectedCol = col
  1277                 self.CurrentSelectedCol = col
  1262             else:
  1278             else:
  1291                         param,
  1307                         param,
  1292                         int(event.GetLabel()))
  1308                         int(event.GetLabel()))
  1293                     wx.CallAfter(self.RefreshModulesGrid)
  1309                     wx.CallAfter(self.RefreshModulesGrid)
  1294                     event.Skip()
  1310                     event.Skip()
  1295                 except ValueError:
  1311                 except ValueError:
  1296                     message = wx.MessageDialog(self, 
  1312                     message = wx.MessageDialog(self,
  1297                         _("Module %s must be an integer!") % stripped_column_label, 
  1313                                                _("Module %s must be an integer!") % stripped_column_label,
  1298                         _("Error"), wx.OK|wx.ICON_ERROR)
  1314                                                _("Error"),
       
  1315                                                wx.OK | wx.ICON_ERROR)
  1299                     message.ShowModal()
  1316                     message.ShowModal()
  1300                     message.Destroy()
  1317                     message.Destroy()
  1301                     event.Veto()
  1318                     event.Veto()
  1302             else:
  1319             else:
  1303                 event.Veto()
  1320                 event.Veto()
  1304         else:
  1321         else:
  1305             event.Veto()
  1322             event.Veto()
  1306                 
  1323 
  1307     def OnModulesGridHeaderMotion(self, event):
  1324     def OnModulesGridHeaderMotion(self, event):
  1308         item, flags, col = self.ModulesGrid.HitTest(event.GetPosition())
  1325         _item, _flags, col = self.ModulesGrid.HitTest(event.GetPosition())
  1309         if col != self.LastToolTipCol and self.LastToolTipCol is not None:
  1326         if col != self.LastToolTipCol and self.LastToolTipCol is not None:
  1310             self.ModulesGrid.GetHeaderWindow().SetToolTip(None)
  1327             self.ModulesGrid.GetHeaderWindow().SetToolTip(None)
  1311             self.LastToolTipCol = None
  1328             self.LastToolTipCol = None
  1312         if col > 0 and self.LastToolTipCol != col:
  1329         if col > 0 and self.LastToolTipCol != col:
  1313             self.LastToolTipCol = col
  1330             self.LastToolTipCol = col
  1314             param, param_infos = self.ModuleLibrary.MODULES_EXTRA_PARAMS[col - 1]
  1331             _param, param_infos = self.ModuleLibrary.MODULES_EXTRA_PARAMS[col - 1]
  1315             wx.CallAfter(self.ModulesGrid.GetHeaderWindow().SetToolTipString, 
  1332             wx.CallAfter(self.ModulesGrid.GetHeaderWindow().SetToolTipString,
  1316                          param_infos["description"])
  1333                          param_infos["description"])
  1317         event.Skip()
  1334         event.Skip()
  1318 
  1335 
       
  1336 
  1319 class DatabaseManagementDialog(wx.Dialog):
  1337 class DatabaseManagementDialog(wx.Dialog):
  1320     
  1338 
  1321     def __init__(self, parent, database):
  1339     def __init__(self, parent, database):
  1322         wx.Dialog.__init__(self, parent,
  1340         wx.Dialog.__init__(self, parent,
  1323               size=wx.Size(700, 500), title=_('ESI Files Database management'),
  1341                            size=wx.Size(700, 500),
  1324               style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
  1342                            title=_('ESI Files Database management'),
  1325         
  1343                            style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
       
  1344 
  1326         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
  1345         main_sizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=10)
  1327         main_sizer.AddGrowableCol(0)
  1346         main_sizer.AddGrowableCol(0)
  1328         main_sizer.AddGrowableRow(0)
  1347         main_sizer.AddGrowableRow(0)
  1329         
  1348 
  1330         self.DatabaseSizer = LibraryEditorSizer(self, database,
  1349         self.DatabaseSizer = LibraryEditorSizer(
  1331             [("ImportButton", "ImportESI", _("Import file to ESI files database"), None),
  1350             self, database,
  1332              ("DeleteButton", "remove_element", _("Remove file from database"), None)])
  1351             [
       
  1352                 ("ImportButton", "ImportESI", _("Import file to ESI files database"), None),
       
  1353                 ("DeleteButton", "remove_element", _("Remove file from database"), None)
       
  1354             ])
  1333         self.DatabaseSizer.SetControlMinSize(wx.Size(0, 0))
  1355         self.DatabaseSizer.SetControlMinSize(wx.Size(0, 0))
  1334         main_sizer.AddSizer(self.DatabaseSizer, border=10,
  1356         main_sizer.AddSizer(self.DatabaseSizer, border=10,
  1335             flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
  1357                             flag=wx.GROW | wx.TOP | wx.LEFT | wx.RIGHT)
  1336         
  1358 
  1337         button_sizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
  1359         button_sizer = self.CreateButtonSizer(wx.OK | wx.CANCEL | wx.CENTRE)
  1338         button_sizer.GetAffirmativeButton().SetLabel(_("Add file to project"))
  1360         button_sizer.GetAffirmativeButton().SetLabel(_("Add file to project"))
  1339         button_sizer.GetCancelButton().SetLabel(_("Close"))
  1361         button_sizer.GetCancelButton().SetLabel(_("Close"))
  1340         main_sizer.AddSizer(button_sizer, border=10, 
  1362         main_sizer.AddSizer(button_sizer, border=10,
  1341               flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
  1363                             flag=wx.ALIGN_RIGHT | wx.BOTTOM | wx.LEFT | wx.RIGHT)
  1342         
  1364 
  1343         self.SetSizer(main_sizer)
  1365         self.SetSizer(main_sizer)
  1344         
  1366 
  1345         self.DatabaseSizer.RefreshView()
  1367         self.DatabaseSizer.RefreshView()
  1346         
  1368 
  1347     def GetValue(self):
  1369     def GetValue(self):
  1348         return self.DatabaseSizer.GetSelectedFilePath()
  1370         return self.DatabaseSizer.GetSelectedFilePath()
  1349 
  1371 
       
  1372 
  1350 class LibraryEditor(ConfTreeNodeEditor):
  1373 class LibraryEditor(ConfTreeNodeEditor):
  1351     
  1374 
  1352     CONFNODEEDITOR_TABS = [
  1375     CONFNODEEDITOR_TABS = [
  1353         (_("Modules Library"), "_create_ModuleLibraryEditor")]
  1376         (_("Modules Library"), "_create_ModuleLibraryEditor")]
  1354     
  1377 
  1355     def _create_ModuleLibraryEditor(self, prnt):
  1378     def _create_ModuleLibraryEditor(self, prnt):
  1356         self.ModuleLibraryEditor = wx.ScrolledWindow(prnt,
  1379         self.ModuleLibraryEditor = wx.ScrolledWindow(prnt,
  1357             style=wx.TAB_TRAVERSAL|wx.HSCROLL|wx.VSCROLL)
  1380                                                      style=wx.TAB_TRAVERSAL | wx.HSCROLL | wx.VSCROLL)
  1358         self.ModuleLibraryEditor.Bind(wx.EVT_SIZE, self.OnResize)
  1381         self.ModuleLibraryEditor.Bind(wx.EVT_SIZE, self.OnResize)
  1359         
  1382 
  1360         self.ModuleLibrarySizer = LibraryEditorSizer(self.ModuleLibraryEditor,
  1383         self.ModuleLibrarySizer = LibraryEditorSizer(
       
  1384             self.ModuleLibraryEditor,
  1361             self.Controler.GetModulesLibraryInstance(),
  1385             self.Controler.GetModulesLibraryInstance(),
  1362             [("ImportButton", "ImportESI", _("Import ESI file"), None),
  1386             [
  1363              ("AddButton", "ImportDatabase", _("Add file from ESI files database"), self.OnAddButton),
  1387                 ("ImportButton", "ImportESI", _("Import ESI file"), None),
  1364              ("DeleteButton", "remove_element", _("Remove file from library"), None)])
  1388                 ("AddButton", "ImportDatabase", _("Add file from ESI files database"), self.OnAddButton),
       
  1389                 ("DeleteButton", "remove_element", _("Remove file from library"), None)
       
  1390             ])
  1365         self.ModuleLibrarySizer.SetControlMinSize(wx.Size(0, 200))
  1391         self.ModuleLibrarySizer.SetControlMinSize(wx.Size(0, 200))
  1366         self.ModuleLibraryEditor.SetSizer(self.ModuleLibrarySizer)
  1392         self.ModuleLibraryEditor.SetSizer(self.ModuleLibrarySizer)
  1367         
  1393 
  1368         return self.ModuleLibraryEditor
  1394         return self.ModuleLibraryEditor
  1369 
  1395 
  1370     def __init__(self, parent, controler, window):
  1396     def __init__(self, parent, controler, window):
  1371         ConfTreeNodeEditor.__init__(self, parent, controler, window)
  1397         ConfTreeNodeEditor.__init__(self, parent, controler, window)
  1372     
  1398 
  1373         self.RefreshView()
  1399         self.RefreshView()
  1374     
  1400 
  1375     def RefreshView(self):
  1401     def RefreshView(self):
  1376         ConfTreeNodeEditor.RefreshView(self)
  1402         ConfTreeNodeEditor.RefreshView(self)
  1377         self.ModuleLibrarySizer.RefreshView()
  1403         self.ModuleLibrarySizer.RefreshView()
  1378 
  1404 
  1379     def OnAddButton(self, event):
  1405     def OnAddButton(self, event):
  1380         dialog = DatabaseManagementDialog(self, 
  1406         dialog = DatabaseManagementDialog(self,
  1381             self.Controler.GetModulesDatabaseInstance())
  1407                                           self.Controler.GetModulesDatabaseInstance())
  1382         
  1408 
  1383         if dialog.ShowModal() == wx.ID_OK:
  1409         if dialog.ShowModal() == wx.ID_OK:
  1384             module_library = self.Controler.GetModulesLibraryInstance()
  1410             module_library = self.Controler.GetModulesLibraryInstance()
  1385             module_library.ImportModuleLibrary(dialog.GetValue())
  1411             module_library.ImportModuleLibrary(dialog.GetValue())
  1386             
  1412 
  1387         dialog.Destroy()
  1413         dialog.Destroy()
  1388         
  1414 
  1389         wx.CallAfter(self.ModuleLibrarySizer.RefreshView)
  1415         wx.CallAfter(self.ModuleLibrarySizer.RefreshView)
  1390         
  1416 
  1391         event.Skip()
  1417         event.Skip()
  1392 
  1418 
  1393     def OnResize(self, event):
  1419     def OnResize(self, event):
  1394         self.ModuleLibraryEditor.GetBestSize()
  1420         self.ModuleLibraryEditor.GetBestSize()
  1395         xstart, ystart = self.ModuleLibraryEditor.GetViewStart()
  1421         xstart, ystart = self.ModuleLibraryEditor.GetViewStart()
  1396         window_size = self.ModuleLibraryEditor.GetClientSize()
  1422         window_size = self.ModuleLibraryEditor.GetClientSize()
  1397         maxx, maxy = self.ModuleLibraryEditor.GetMinSize()
  1423         maxx, maxy = self.ModuleLibraryEditor.GetMinSize()
  1398         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
  1424         posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT))
  1399         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
  1425         posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT))
  1400         self.ModuleLibraryEditor.Scroll(posx, posy)
  1426         self.ModuleLibraryEditor.Scroll(posx, posy)
  1401         self.ModuleLibraryEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
  1427         self.ModuleLibraryEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT,
  1402                 maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy)
  1428                                                maxx / SCROLLBAR_UNIT,
       
  1429                                                maxy / SCROLLBAR_UNIT,
       
  1430                                                posx, posy)
  1403         event.Skip()
  1431         event.Skip()
  1404