controls/VariablePanel.py
changeset 1412 50192dd2f5ff
parent 1380 10ac2b18437b
child 1414 8a3998d10b81
equal deleted inserted replaced
1411:805d13d216c0 1412:50192dd2f5ff
     1 #!/usr/bin/env python
     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     2 # -*- coding: utf-8 -*-
     3 
     3 
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
     5 #based on the plcopen standard. 
     5 #based on the plcopen standard.
     6 #
     6 #
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     8 #
     8 #
     9 #See COPYING file for copyrights details.
     9 #See COPYING file for copyrights details.
    10 #
    10 #
    28 
    28 
    29 import wx
    29 import wx
    30 import wx.grid
    30 import wx.grid
    31 import wx.lib.buttons
    31 import wx.lib.buttons
    32 
    32 
    33 from plcopen.structures import LOCATIONDATATYPES, TestIdentifier, IEC_KEYWORDS
    33 from plcopen.structures import LOCATIONDATATYPES, TestIdentifier, IEC_KEYWORDS, DefaultType
    34 from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD, ERROR_HIGHLIGHT
    34 from graphics.GraphicCommons import REFRESH_HIGHLIGHT_PERIOD, ERROR_HIGHLIGHT
    35 from dialogs.ArrayTypeDialog import ArrayTypeDialog
    35 from dialogs.ArrayTypeDialog import ArrayTypeDialog
    36 from CustomGrid import CustomGrid
    36 from CustomGrid import CustomGrid
    37 from CustomTable import CustomTable
    37 from CustomTable import CustomTable
    38 from LocationCellEditor import LocationCellEditor
    38 from LocationCellEditor import LocationCellEditor
    47     if wx.VERSION >= (2, 6, 0):
    47     if wx.VERSION >= (2, 6, 0):
    48         parent.Append(help=help, id=id, kind=kind, text=text)
    48         parent.Append(help=help, id=id, kind=kind, text=text)
    49     else:
    49     else:
    50         parent.Append(helpString=help, id=id, kind=kind, item=text)
    50         parent.Append(helpString=help, id=id, kind=kind, item=text)
    51 
    51 
    52 [TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE, 
    52 [TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE,
    53  POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
    53  POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES
    54 ] = range(10)
    54 ] = range(10)
    55 
    55 
    56 def GetVariableTableColnames(location):
    56 def GetVariableTableColnames(location):
    57     _ = lambda x : x
    57     _ = lambda x : x
    71     return options
    71     return options
    72 OPTIONS_DICT = dict([(_(option), option) for option in GetOptions()])
    72 OPTIONS_DICT = dict([(_(option), option) for option in GetOptions()])
    73 
    73 
    74 def GetFilterChoiceTransfer():
    74 def GetFilterChoiceTransfer():
    75     _ = lambda x : x
    75     _ = lambda x : x
    76     return {_("All"): _("All"), _("Interface"): _("Interface"), 
    76     return {_("All"): _("All"), _("Interface"): _("Interface"),
    77             _("   Input"): _("Input"), _("   Output"): _("Output"), _("   InOut"): _("InOut"), 
    77             _("   Input"): _("Input"), _("   Output"): _("Output"), _("   InOut"): _("InOut"),
    78             _("   External"): _("External"), _("Variables"): _("Variables"), _("   Local"): _("Local"),
    78             _("   External"): _("External"), _("Variables"): _("Variables"), _("   Local"): _("Local"),
    79             _("   Temp"): _("Temp"), _("Global"): _("Global")}#, _("Access") : _("Access")}
    79             _("   Temp"): _("Temp"), _("Global"): _("Global")}#, _("Access") : _("Access")}
    80 VARIABLE_CHOICES_DICT = dict([(_(_class), _class) for _class in GetFilterChoiceTransfer().iterkeys()])
    80 VARIABLE_CHOICES_DICT = dict([(_(_class), _class) for _class in GetFilterChoiceTransfer().iterkeys()])
    81 VARIABLE_CLASSES_DICT = dict([(_(_class), _class) for _class in GetFilterChoiceTransfer().itervalues()])
    81 VARIABLE_CLASSES_DICT = dict([(_(_class), _class) for _class in GetFilterChoiceTransfer().itervalues()])
    82 
    82 
    95 #-------------------------------------------------------------------------------
    95 #-------------------------------------------------------------------------------
    96 #                            Variables Panel Table
    96 #                            Variables Panel Table
    97 #-------------------------------------------------------------------------------
    97 #-------------------------------------------------------------------------------
    98 
    98 
    99 class VariableTable(CustomTable):
    99 class VariableTable(CustomTable):
   100     
   100 
   101     """
   101     """
   102     A custom wx.grid.Grid Table using user supplied data
   102     A custom wx.grid.Grid Table using user supplied data
   103     """
   103     """
   104     def __init__(self, parent, data, colnames):
   104     def __init__(self, parent, data, colnames):
   105         # The base class must be initialized *first*
   105         # The base class must be initialized *first*
   106         CustomTable.__init__(self, parent, data, colnames)
   106         CustomTable.__init__(self, parent, data, colnames)
   107         self.old_value = None
   107         self.old_value = None
   108     
   108 
   109     def GetValueByName(self, row, colname):
   109     def GetValueByName(self, row, colname):
   110         if row < self.GetNumberRows():
   110         if row < self.GetNumberRows():
   111             return getattr(self.data[row], colname)
   111             return getattr(self.data[row], colname)
   112 
   112 
   113     def SetValueByName(self, row, colname, value):
   113     def SetValueByName(self, row, colname, value):
   114         if row < self.GetNumberRows():
   114         if row < self.GetNumberRows():
   115             setattr(self.data[row], colname, value)
   115             setattr(self.data[row], colname, value)
   116     
   116 
   117     def GetValue(self, row, col):
   117     def GetValue(self, row, col):
   118         if row < self.GetNumberRows():
   118         if row < self.GetNumberRows():
   119             if col == 0:
   119             if col == 0:
   120                 return self.data[row].Number
   120                 return self.data[row].Number
   121             colname = self.GetColLabelValue(col, False)
   121             colname = self.GetColLabelValue(col, False)
   128             if not isinstance(value, (StringType, UnicodeType)):
   128             if not isinstance(value, (StringType, UnicodeType)):
   129                 value = str(value)
   129                 value = str(value)
   130             if colname in ["Class", "Option"]:
   130             if colname in ["Class", "Option"]:
   131                 return _(value)
   131                 return _(value)
   132             return value
   132             return value
   133     
   133 
   134     def SetValue(self, row, col, value):
   134     def SetValue(self, row, col, value):
   135         if col < len(self.colnames):
   135         if col < len(self.colnames):
   136             colname = self.GetColLabelValue(col, False)
   136             colname = self.GetColLabelValue(col, False)
   137             if colname == "Name":
   137             if colname == "Name":
   138                 self.old_value = getattr(self.data[row], colname)
   138                 self.old_value = getattr(self.data[row], colname)
   207                                 if self.Parent.IsFunctionBlockType(var_type):
   207                                 if self.Parent.IsFunctionBlockType(var_type):
   208                                     excluded.extend(["Local","Temp"])
   208                                     excluded.extend(["Local","Temp"])
   209                                 editor.SetParameters(",".join([_(choice) for choice in self.Parent.ClassList if choice not in excluded]))
   209                                 editor.SetParameters(",".join([_(choice) for choice in self.Parent.ClassList if choice not in excluded]))
   210                     elif colname != "Documentation":
   210                     elif colname != "Documentation":
   211                         grid.SetReadOnly(row, col, True)
   211                         grid.SetReadOnly(row, col, True)
   212                 
   212 
   213                 grid.SetCellEditor(row, col, editor)
   213                 grid.SetCellEditor(row, col, editor)
   214                 grid.SetCellRenderer(row, col, renderer)
   214                 grid.SetCellRenderer(row, col, renderer)
   215                 
   215 
   216                 if colname == "Location" and LOCATION_MODEL.match(self.GetValueByName(row, colname)) is None:
   216                 if colname == "Location" and LOCATION_MODEL.match(self.GetValueByName(row, colname)) is None:
   217                     highlight_colours = ERROR_HIGHLIGHT
   217                     highlight_colours = ERROR_HIGHLIGHT
   218                 else:
   218                 else:
   219                     highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
   219                     highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
   220                 grid.SetCellBackgroundColour(row, col, highlight_colours[0])
   220                 grid.SetCellBackgroundColour(row, col, highlight_colours[0])
   221                 grid.SetCellTextColour(row, col, highlight_colours[1])
   221                 grid.SetCellTextColour(row, col, highlight_colours[1])
   222             self.ResizeRow(grid, row)
   222             self.ResizeRow(grid, row)
   223 
   223 
   224 #-------------------------------------------------------------------------------
   224 #-------------------------------------------------------------------------------
   225 #                         Variable Panel Drop Target
   225 #                         Variable Panel Drop Target
   226 #-------------------------------------------------------------------------------   
   226 #-------------------------------------------------------------------------------
   227 
   227 
   228 class VariableDropTarget(wx.TextDropTarget):
   228 class VariableDropTarget(wx.TextDropTarget):
   229     '''
   229     '''
   230     This allows dragging a variable location from somewhere to the Location
   230     This allows dragging a variable location from somewhere to the Location
   231     column of a variable row.
   231     column of a variable row.
   232     
   232 
   233     The drag source should be a TextDataObject containing a Python tuple like:
   233     The drag source should be a TextDataObject containing a Python tuple like:
   234         ('%ID0.0.0', 'location', 'REAL')
   234         ('%ID0.0.0', 'location', 'REAL')
   235     
   235 
   236     c_ext/CFileEditor.py has an example of this (you can drag a C extension
   236     c_ext/CFileEditor.py has an example of this (you can drag a C extension
   237     variable to the Location column of the variable panel).
   237     variable to the Location column of the variable panel).
   238     '''
   238     '''
   239     def __init__(self, parent):
   239     def __init__(self, parent):
   240         wx.TextDropTarget.__init__(self)
   240         wx.TextDropTarget.__init__(self)
   241         self.ParentWindow = parent
   241         self.ParentWindow = parent
   242     
   242 
   243     def OnDropText(self, x, y, data):
   243     def OnDropText(self, x, y, data):
   244         self.ParentWindow.ParentWindow.Select()
   244         self.ParentWindow.ParentWindow.Select()
   245         x, y = self.ParentWindow.VariablesGrid.CalcUnscrolledPosition(x, y)
   245         x, y = self.ParentWindow.VariablesGrid.CalcUnscrolledPosition(x, y)
   246         col = self.ParentWindow.VariablesGrid.XToCol(x)
   246         col = self.ParentWindow.VariablesGrid.XToCol(x)
   247         row = self.ParentWindow.VariablesGrid.YToRow(y - self.ParentWindow.VariablesGrid.GetColLabelSize())
   247         row = self.ParentWindow.VariablesGrid.YToRow(y - self.ParentWindow.VariablesGrid.GetColLabelSize())
   248         message = None
   248         message = None
   249         element_type = self.ParentWindow.ElementType
   249         element_type = self.ParentWindow.ElementType
   250         try:
   250         try:
   251             values = eval(data)    
   251             values = eval(data)
   252         except:
   252         except:
   253             message = _("Invalid value \"%s\" for variable grid element")%data
   253             message = _("Invalid value \"%s\" for variable grid element")%data
   254             values = None
   254             values = None
   255         if not isinstance(values, TupleType):
   255         if not isinstance(values, TupleType):
   256             message = _("Invalid value \"%s\" for variable grid element")%data
   256             message = _("Invalid value \"%s\" for variable grid element")%data
   265                         message = _("Can only give a location to local or global variables")
   265                         message = _("Can only give a location to local or global variables")
   266                     else:
   266                     else:
   267                         location = values[0]
   267                         location = values[0]
   268                         variable_type = self.ParentWindow.Table.GetValueByName(row, "Type")
   268                         variable_type = self.ParentWindow.Table.GetValueByName(row, "Type")
   269                         base_type = self.ParentWindow.Controler.GetBaseType(variable_type)
   269                         base_type = self.ParentWindow.Controler.GetBaseType(variable_type)
   270                         
   270 
   271                         if values[2] is not None:
   271                         if values[2] is not None:
   272                             base_location_type = self.ParentWindow.Controler.GetBaseType(values[2])
   272                             base_location_type = self.ParentWindow.Controler.GetBaseType(values[2])
   273                             if values[2] != variable_type and base_type != base_location_type:
   273                             if values[2] != variable_type and base_type != base_location_type:
   274                                 message = _("Incompatible data types between \"%s\" and \"%s\"")%(values[2], variable_type)
   274                                 message = _("Incompatible data types between \"%s\" and \"%s\"")%(values[2], variable_type)
   275                         
   275 
   276                         if message is None:
   276                         if message is None:
   277                             if not location.startswith("%"):
   277                             if not location.startswith("%"):
   278                                 if location[0].isdigit() and base_type != "BOOL":
   278                                 if location[0].isdigit() and base_type != "BOOL":
   279                                     message = _("Incompatible size of data between \"%s\" and \"BOOL\"")%location
   279                                     message = _("Incompatible size of data between \"%s\" and \"BOOL\"")%location
   280                                 elif location[0] not in LOCATIONDATATYPES:
   280                                 elif location[0] not in LOCATIONDATATYPES:
   281                                     message = _("Unrecognized data size \"%s\"")%location[0]
   281                                     message = _("Unrecognized data size \"%s\"")%location[0]
   282                                 elif base_type not in LOCATIONDATATYPES[location[0]]:
   282                                 elif base_type not in LOCATIONDATATYPES[location[0]]:
   283                                     message = _("Incompatible size of data between \"%s\" and \"%s\"")%(location, variable_type)
   283                                     message = _("Incompatible size of data between \"%s\" and \"%s\"")%(location, variable_type)
   284                                 else:
   284                                 else:
   285                                     dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow.ParentWindow, 
   285                                     dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow.ParentWindow,
   286                                           _("Select a variable class:"), _("Variable class"), 
   286                                           _("Select a variable class:"), _("Variable class"),
   287                                           ["Input", "Output", "Memory"], 
   287                                           ["Input", "Output", "Memory"],
   288                                           wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   288                                           wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   289                                     if dialog.ShowModal() == wx.ID_OK:
   289                                     if dialog.ShowModal() == wx.ID_OK:
   290                                         selected = dialog.GetSelection()
   290                                         selected = dialog.GetSelection()
   291                                     else:
   291                                     else:
   292                                         selected = None
   292                                         selected = None
   297                                         location = "%I" + location
   297                                         location = "%I" + location
   298                                     elif selected == 1:
   298                                     elif selected == 1:
   299                                         location = "%Q" + location
   299                                         location = "%Q" + location
   300                                     else:
   300                                     else:
   301                                         location = "%M" + location
   301                                         location = "%M" + location
   302                                         
   302 
   303                             if message is None:
   303                             if message is None:
   304                                 self.ParentWindow.Table.SetValue(row, col, location)
   304                                 self.ParentWindow.Table.SetValue(row, col, location)
   305                                 self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid)
   305                                 self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid)
   306                                 self.ParentWindow.SaveValues()
   306                                 self.ParentWindow.SaveValues()
   307                 elif colname == "Initial Value" and values[1] == "Constant":
   307                 elif colname == "Initial Value" and values[1] == "Constant":
   309                         message = _("Can't set an initial value to a function block instance")
   309                         message = _("Can't set an initial value to a function block instance")
   310                     else:
   310                     else:
   311                         self.ParentWindow.Table.SetValue(row, col, values[0])
   311                         self.ParentWindow.Table.SetValue(row, col, values[0])
   312                         self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid)
   312                         self.ParentWindow.Table.ResetView(self.ParentWindow.VariablesGrid)
   313                         self.ParentWindow.SaveValues()
   313                         self.ParentWindow.SaveValues()
   314             elif (element_type not in ["config", "resource", "function"] and values[1] == "Global" and 
   314             elif (element_type not in ["config", "resource", "function"] and values[1] == "Global" and
   315                   self.ParentWindow.Filter in ["All", "Interface", "External"] or
   315                   self.ParentWindow.Filter in ["All", "Interface", "External"] or
   316                   element_type != "function" and values[1] == "location"):
   316                   element_type != "function" and values[1] == "location"):
   317                 if values[1] == "location":
   317                 if values[1] == "location":
   318                     var_name = values[3]
   318                     var_name = values[3]
   319                 else:
   319                 else:
   320                     var_name = values[0]
   320                     var_name = values[0]
   321                 tagname = self.ParentWindow.GetTagName()
   321                 tagname = self.ParentWindow.GetTagName()
   322                 if var_name.upper() in [name.upper() 
   322                 if var_name.upper() in [name.upper()
   323                         for name in self.ParentWindow.Controler.\
   323                         for name in self.ParentWindow.Controler.\
   324                             GetProjectPouNames(self.ParentWindow.Debug)]:
   324                             GetProjectPouNames(self.ParentWindow.Debug)]:
   325                     message = _("\"%s\" pou already exists!")%var_name
   325                     message = _("\"%s\" pou already exists!")%var_name
   326                 elif not var_name.upper() in [name.upper() 
   326                 elif not var_name.upper() in [name.upper()
   327                         for name in self.ParentWindow.Controler.\
   327                         for name in self.ParentWindow.Controler.\
   328                             GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
   328                             GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
   329                     var_infos = self.ParentWindow.DefaultValue.copy()
   329                     var_infos = self.ParentWindow.DefaultValue.copy()
   330                     var_infos.Name = var_name
   330                     var_infos.Name = var_name
   331                     var_infos.Type = values[2]
   331                     var_infos.Type = values[2]
   332                     if values[1] == "location":
   332                     if values[1] == "location":
   333                         location = values[0]
   333                         location = values[0]
   334                         if not location.startswith("%"):
   334                         if not location.startswith("%"):
   335                             dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow.ParentWindow, 
   335                             dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow.ParentWindow,
   336                                   _("Select a variable class:"), _("Variable class"), 
   336                                   _("Select a variable class:"), _("Variable class"),
   337                                   ["Input", "Output", "Memory"], 
   337                                   ["Input", "Output", "Memory"],
   338                                   wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   338                                   wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
   339                             if dialog.ShowModal() == wx.ID_OK:
   339                             if dialog.ShowModal() == wx.ID_OK:
   340                                 selected = dialog.GetSelection()
   340                                 selected = dialog.GetSelection()
   341                             else:
   341                             else:
   342                                 selected = None
   342                                 selected = None
   352                         if element_type == "functionBlock":
   352                         if element_type == "functionBlock":
   353                             configs = self.ParentWindow.Controler.GetProjectConfigNames(
   353                             configs = self.ParentWindow.Controler.GetProjectConfigNames(
   354                                                                 self.ParentWindow.Debug)
   354                                                                 self.ParentWindow.Debug)
   355                             if len(configs) == 0:
   355                             if len(configs) == 0:
   356                                 return
   356                                 return
   357                             if not var_name.upper() in [name.upper() 
   357                             if not var_name.upper() in [name.upper()
   358                                 for name in self.ParentWindow.Controler.\
   358                                 for name in self.ParentWindow.Controler.\
   359                                     GetConfigurationVariableNames(configs[0])]:
   359                                     GetConfigurationVariableNames(configs[0])]:
   360                                 self.ParentWindow.Controler.AddConfigurationGlobalVar(
   360                                 self.ParentWindow.Controler.AddConfigurationGlobalVar(
   361                                     configs[0], values[2], var_name, location, "")
   361                                     configs[0], values[2], var_name, location, "")
   362                             var_infos.Class = "External"
   362                             var_infos.Class = "External"
   370                         var_infos.Class = "External"
   370                         var_infos.Class = "External"
   371                     var_infos.Number = len(self.ParentWindow.Values)
   371                     var_infos.Number = len(self.ParentWindow.Values)
   372                     self.ParentWindow.Values.append(var_infos)
   372                     self.ParentWindow.Values.append(var_infos)
   373                     self.ParentWindow.SaveValues()
   373                     self.ParentWindow.SaveValues()
   374                     self.ParentWindow.RefreshValues()
   374                     self.ParentWindow.RefreshValues()
   375         
   375 
   376         if message is not None:
   376         if message is not None:
   377             wx.CallAfter(self.ShowMessage, message)
   377             wx.CallAfter(self.ShowMessage, message)
   378     
   378 
   379     def ShowMessage(self, message):
   379     def ShowMessage(self, message):
   380         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
   380         message = wx.MessageDialog(self.ParentWindow, message, _("Error"), wx.OK|wx.ICON_ERROR)
   381         message.ShowModal()
   381         message.ShowModal()
   382         message.Destroy()
   382         message.Destroy()
   383 
   383 
   384 #-------------------------------------------------------------------------------
   384 #-------------------------------------------------------------------------------
   385 #                               Variable Panel
   385 #                               Variable Panel
   386 #-------------------------------------------------------------------------------   
   386 #-------------------------------------------------------------------------------
   387 
   387 
   388 class VariablePanel(wx.Panel):
   388 class VariablePanel(wx.Panel):
   389     
   389 
   390     def __init__(self, parent, window, controler, element_type, debug=False):
   390     def __init__(self, parent, window, controler, element_type, debug=False):
   391         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
   391         wx.Panel.__init__(self, parent, style=wx.TAB_TRAVERSAL)
   392         
   392 
   393         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=0)
   393         self.MainSizer = wx.FlexGridSizer(cols=1, hgap=10, rows=2, vgap=0)
   394         self.MainSizer.AddGrowableCol(0)
   394         self.MainSizer.AddGrowableCol(0)
   395         self.MainSizer.AddGrowableRow(1)
   395         self.MainSizer.AddGrowableRow(1)
   396         
   396 
   397         controls_sizer = wx.FlexGridSizer(cols=10, hgap=5, rows=1, vgap=5)
   397         controls_sizer = wx.FlexGridSizer(cols=10, hgap=5, rows=1, vgap=5)
   398         controls_sizer.AddGrowableCol(5)
   398         controls_sizer.AddGrowableCol(5)
   399         controls_sizer.AddGrowableRow(0)
   399         controls_sizer.AddGrowableRow(0)
   400         self.MainSizer.AddSizer(controls_sizer, border=5, flag=wx.GROW|wx.ALL)
   400         self.MainSizer.AddSizer(controls_sizer, border=5, flag=wx.GROW|wx.ALL)
   401         
   401 
   402         self.ReturnTypeLabel = wx.StaticText(self, label=_('Return Type:'))
   402         self.ReturnTypeLabel = wx.StaticText(self, label=_('Return Type:'))
   403         controls_sizer.AddWindow(self.ReturnTypeLabel, flag=wx.ALIGN_CENTER_VERTICAL)
   403         controls_sizer.AddWindow(self.ReturnTypeLabel, flag=wx.ALIGN_CENTER_VERTICAL)
   404         
   404 
   405         self.ReturnType = wx.ComboBox(self,
   405         self.ReturnType = wx.ComboBox(self,
   406               size=wx.Size(145, -1), style=wx.CB_READONLY)
   406               size=wx.Size(145, -1), style=wx.CB_READONLY)
   407         self.Bind(wx.EVT_COMBOBOX, self.OnReturnTypeChanged, self.ReturnType)
   407         self.Bind(wx.EVT_COMBOBOX, self.OnReturnTypeChanged, self.ReturnType)
   408         controls_sizer.AddWindow(self.ReturnType)
   408         controls_sizer.AddWindow(self.ReturnType)
   409         
   409 
   410         self.DescriptionLabel = wx.StaticText(self, label=_('Description:'))
   410         self.DescriptionLabel = wx.StaticText(self, label=_('Description:'))
   411         controls_sizer.AddWindow(self.DescriptionLabel, flag=wx.ALIGN_CENTER_VERTICAL)
   411         controls_sizer.AddWindow(self.DescriptionLabel, flag=wx.ALIGN_CENTER_VERTICAL)
   412         
   412 
   413         self.Description = wx.TextCtrl(self,
   413         self.Description = wx.TextCtrl(self,
   414               size=wx.Size(250, -1), style=wx.TE_PROCESS_ENTER)
   414               size=wx.Size(250, -1), style=wx.TE_PROCESS_ENTER)
   415         self.Bind(wx.EVT_TEXT_ENTER, self.OnDescriptionChanged, self.Description)
   415         self.Bind(wx.EVT_TEXT_ENTER, self.OnDescriptionChanged, self.Description)
   416         self.Description.Bind(wx.EVT_KILL_FOCUS, self.OnDescriptionChanged)
   416         self.Description.Bind(wx.EVT_KILL_FOCUS, self.OnDescriptionChanged)
   417         controls_sizer.AddWindow(self.Description) 
   417         controls_sizer.AddWindow(self.Description)
   418         
   418 
   419         class_filter_label = wx.StaticText(self, label=_('Class Filter:'))
   419         class_filter_label = wx.StaticText(self, label=_('Class Filter:'))
   420         controls_sizer.AddWindow(class_filter_label, flag=wx.ALIGN_CENTER_VERTICAL)
   420         controls_sizer.AddWindow(class_filter_label, flag=wx.ALIGN_CENTER_VERTICAL)
   421         
   421 
   422         self.ClassFilter = wx.ComboBox(self, 
   422         self.ClassFilter = wx.ComboBox(self,
   423               size=wx.Size(145, -1), style=wx.CB_READONLY)
   423               size=wx.Size(145, -1), style=wx.CB_READONLY)
   424         self.Bind(wx.EVT_COMBOBOX, self.OnClassFilter, self.ClassFilter)
   424         self.Bind(wx.EVT_COMBOBOX, self.OnClassFilter, self.ClassFilter)
   425         controls_sizer.AddWindow(self.ClassFilter)
   425         controls_sizer.AddWindow(self.ClassFilter)
   426         
   426 
   427         for name, bitmap, help in [
   427         for name, bitmap, help in [
   428                 ("AddButton", "add_element", _("Add variable")),
   428                 ("AddButton", "add_element", _("Add variable")),
   429                 ("DeleteButton", "remove_element", _("Remove variable")),
   429                 ("DeleteButton", "remove_element", _("Remove variable")),
   430                 ("UpButton", "up", _("Move variable up")),
   430                 ("UpButton", "up", _("Move variable up")),
   431                 ("DownButton", "down", _("Move variable down"))]:
   431                 ("DownButton", "down", _("Move variable down"))]:
   432             button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap), 
   432             button = wx.lib.buttons.GenBitmapButton(self, bitmap=GetBitmap(bitmap),
   433                   size=wx.Size(28, 28), style=wx.NO_BORDER)
   433                   size=wx.Size(28, 28), style=wx.NO_BORDER)
   434             button.SetToolTipString(help)
   434             button.SetToolTipString(help)
   435             setattr(self, name, button)
   435             setattr(self, name, button)
   436             controls_sizer.AddWindow(button)
   436             controls_sizer.AddWindow(button)
   437         
   437 
   438         self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL)
   438         self.VariablesGrid = CustomGrid(self, style=wx.VSCROLL)
   439         self.VariablesGrid.SetDropTarget(VariableDropTarget(self))
   439         self.VariablesGrid.SetDropTarget(VariableDropTarget(self))
   440         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, 
   440         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
   441               self.OnVariablesGridCellChange)
   441               self.OnVariablesGridCellChange)
   442         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, 
   442         self.VariablesGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK,
   443               self.OnVariablesGridCellLeftClick)
   443               self.OnVariablesGridCellLeftClick)
   444         self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, 
   444         self.VariablesGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN,
   445               self.OnVariablesGridEditorShown)
   445               self.OnVariablesGridEditorShown)
   446         self.MainSizer.AddWindow(self.VariablesGrid, flag=wx.GROW)
   446         self.MainSizer.AddWindow(self.VariablesGrid, flag=wx.GROW)
   447         
   447 
   448         self.SetSizer(self.MainSizer)
   448         self.SetSizer(self.MainSizer)
   449         
   449 
   450         self.ParentWindow = window
   450         self.ParentWindow = window
   451         self.Controler = controler
   451         self.Controler = controler
   452         self.ElementType = element_type
   452         self.ElementType = element_type
   453         self.Debug = debug
   453         self.Debug = debug
   454         
   454 
   455         self.RefreshHighlightsTimer = wx.Timer(self, -1)
   455         self.RefreshHighlightsTimer = wx.Timer(self, -1)
   456         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, 
   456         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer,
   457               self.RefreshHighlightsTimer)
   457               self.RefreshHighlightsTimer)
   458         
   458 
   459         self.Filter = "All"
   459         self.Filter = "All"
   460         self.FilterChoices = []
   460         self.FilterChoices = []
   461         self.FilterChoiceTransfer = GetFilterChoiceTransfer()
   461         self.FilterChoiceTransfer = GetFilterChoiceTransfer()
   462         
   462 
   463         self.DefaultValue = _VariableInfos("", "", "", "", "", True, "", "INT", ([], []), 0)
   463         self.DefaultValue = _VariableInfos("", "", "", "", "", True, "", DefaultType, ([], []), 0)
   464         
   464 
   465         if element_type in ["config", "resource"]:
   465         if element_type in ["config", "resource"]:
   466             self.DefaultTypes = {"All" : "Global"}
   466             self.DefaultTypes = {"All" : "Global"}
   467         else:
   467         else:
   468             self.DefaultTypes = {"All" : "Local", "Interface" : "Input", "Variables" : "Local"}
   468             self.DefaultTypes = {"All" : "Local", "Interface" : "Input", "Variables" : "Local"}
   469 
   469 
   479                                         "Interface", "   Input", "   Output", "   InOut", "   External",
   479                                         "Interface", "   Input", "   Output", "   InOut", "   External",
   480                                         "Variables", "   Local", "   Temp"]#,"Access"]
   480                                         "Variables", "   Local", "   Temp"]#,"Access"]
   481 
   481 
   482             # these condense the ColAlignements list
   482             # these condense the ColAlignements list
   483             l = wx.ALIGN_LEFT
   483             l = wx.ALIGN_LEFT
   484             c = wx.ALIGN_CENTER 
   484             c = wx.ALIGN_CENTER
   485 
   485 
   486             #                      Num  Name    Class   Type    Loc     Init    Option   Doc
   486             #                      Num  Name    Class   Type    Loc     Init    Option   Doc
   487             self.ColSizes       = [40,  80,     70,     80,     80,     80,     100,     80]
   487             self.ColSizes       = [40,  80,     70,     80,     80,     80,     100,     80]
   488             self.ColAlignements = [c,   l,      l,      l,      l,      l,      l,       l]
   488             self.ColAlignements = [c,   l,      l,      l,      l,      l,      l,       l]
   489 
   489 
   500                                         "Interface", "   Input", "   Output", "   InOut", "   External",
   500                                         "Interface", "   Input", "   Output", "   InOut", "   External",
   501                                         "Variables", "   Local", "   Temp"]
   501                                         "Variables", "   Local", "   Temp"]
   502 
   502 
   503             # these condense the ColAlignements list
   503             # these condense the ColAlignements list
   504             l = wx.ALIGN_LEFT
   504             l = wx.ALIGN_LEFT
   505             c = wx.ALIGN_CENTER 
   505             c = wx.ALIGN_CENTER
   506 
   506 
   507             #                      Num  Name    Class   Type    Init    Option   Doc
   507             #                      Num  Name    Class   Type    Init    Option   Doc
   508             self.ColSizes       = [40,  80,     70,     80,     80,     100,     160]
   508             self.ColSizes       = [40,  80,     70,     80,     80,     100,     160]
   509             self.ColAlignements = [c,   l,      l,      l,      l,      l,       l]
   509             self.ColAlignements = [c,   l,      l,      l,      l,      l,       l]
   510             
   510 
   511         self.ElementType = element_type
   511         self.ElementType = element_type
   512         self.BodyType = None
   512         self.BodyType = None
   513         
   513 
   514         for choice in self.FilterChoices:
   514         for choice in self.FilterChoices:
   515             self.ClassFilter.Append(_(choice))
   515             self.ClassFilter.Append(_(choice))
   516 
   516 
   517         reverse_transfer = {}
   517         reverse_transfer = {}
   518         for filter, choice in self.FilterChoiceTransfer.items():
   518         for filter, choice in self.FilterChoiceTransfer.items():
   524         self.VariablesGrid.SetButtons({"Add": self.AddButton,
   524         self.VariablesGrid.SetButtons({"Add": self.AddButton,
   525                                        "Delete": self.DeleteButton,
   525                                        "Delete": self.DeleteButton,
   526                                        "Up": self.UpButton,
   526                                        "Up": self.UpButton,
   527                                        "Down": self.DownButton})
   527                                        "Down": self.DownButton})
   528         self.VariablesGrid.SetEditable(not self.Debug)
   528         self.VariablesGrid.SetEditable(not self.Debug)
   529         
   529 
   530         def _AddVariable(new_row):
   530         def _AddVariable(new_row):
   531             if new_row > 0:
   531             if new_row > 0:
   532                 row_content = self.Values[new_row - 1].copy()
   532                 row_content = self.Values[new_row - 1].copy()
   533                 
   533 
   534                 result = VARIABLE_NAME_SUFFIX_MODEL.search(row_content.Name)
   534                 result = VARIABLE_NAME_SUFFIX_MODEL.search(row_content.Name)
   535                 if result is not None:
   535                 if result is not None:
   536                     name = row_content.Name[:result.start(1)]
   536                     name = row_content.Name[:result.start(1)]
   537                     suffix = result.group(1)
   537                     suffix = result.group(1)
   538                     if suffix != "":
   538                     if suffix != "":
   544                     start_idx = 0
   544                     start_idx = 0
   545             else:
   545             else:
   546                 row_content = None
   546                 row_content = None
   547                 start_idx = 0
   547                 start_idx = 0
   548                 name = "LocalVar"
   548                 name = "LocalVar"
   549                 
   549 
   550             if row_content is not None and row_content.Edit: 
   550             if row_content is not None and row_content.Edit:
   551                 row_content = self.Values[new_row - 1].copy()
   551                 row_content = self.Values[new_row - 1].copy()
   552             else:
   552             else:
   553                 row_content = self.DefaultValue.copy()
   553                 row_content = self.DefaultValue.copy()
   554                 if self.Filter in self.DefaultTypes:
   554                 if self.Filter in self.DefaultTypes:
   555                     row_content.Class = self.DefaultTypes[self.Filter]
   555                     row_content.Class = self.DefaultTypes[self.Filter]
   556                 else:
   556                 else:
   557                     row_content.Class = self.Filter
   557                     row_content.Class = self.Filter
   558             
   558 
   559             row_content.Name = self.Controler.GenerateNewName(
   559             row_content.Name = self.Controler.GenerateNewName(
   560                     self.TagName, None, name + "%d", start_idx)
   560                     self.TagName, None, name + "%d", start_idx)
   561             
   561 
   562             if self.Filter == "All" and len(self.Values) > 0:
   562             if self.Filter == "All" and len(self.Values) > 0:
   563                 self.Values.insert(new_row, row_content)
   563                 self.Values.insert(new_row, row_content)
   564             else:
   564             else:
   565                 self.Values.append(row_content)
   565                 self.Values.append(row_content)
   566                 new_row = self.Table.GetNumberRows()
   566                 new_row = self.Table.GetNumberRows()
   567             self.SaveValues()
   567             self.SaveValues()
   568             self.RefreshValues()
   568             self.RefreshValues()
   569             return new_row
   569             return new_row
   570         setattr(self.VariablesGrid, "_AddRow", _AddVariable)
   570         setattr(self.VariablesGrid, "_AddRow", _AddVariable)
   571         
   571 
   572         def _DeleteVariable(row):
   572         def _DeleteVariable(row):
   573             if self.Table.GetValueByName(row, "Edit"):
   573             if self.Table.GetValueByName(row, "Edit"):
   574                 self.Values.remove(self.Table.GetRow(row))
   574                 self.Values.remove(self.Table.GetRow(row))
   575                 self.SaveValues()
   575                 self.SaveValues()
   576                 if self.ElementType == "resource":
   576                 if self.ElementType == "resource":
   577                     self.ParentWindow.RefreshView(variablepanel = False)
   577                     self.ParentWindow.RefreshView(variablepanel = False)
   578                 self.RefreshValues()
   578                 self.RefreshValues()
   579         setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
   579         setattr(self.VariablesGrid, "_DeleteRow", _DeleteVariable)
   580             
   580 
   581         def _MoveVariable(row, move):
   581         def _MoveVariable(row, move):
   582             if self.Filter == "All":
   582             if self.Filter == "All":
   583                 new_row = max(0, min(row + move, len(self.Values) - 1))
   583                 new_row = max(0, min(row + move, len(self.Values) - 1))
   584                 if new_row != row:
   584                 if new_row != row:
   585                     self.Values.insert(new_row, self.Values.pop(row))
   585                     self.Values.insert(new_row, self.Values.pop(row))
   586                     self.SaveValues()
   586                     self.SaveValues()
   587                     self.RefreshValues()
   587                     self.RefreshValues()
   588                 return new_row
   588                 return new_row
   589             return row
   589             return row
   590         setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
   590         setattr(self.VariablesGrid, "_MoveRow", _MoveVariable)
   591         
   591 
   592         def _RefreshButtons():
   592         def _RefreshButtons():
   593             if self:
   593             if self:
   594                 table_length = len(self.Table.data)
   594                 table_length = len(self.Table.data)
   595                 row_class = None
   595                 row_class = None
   596                 row_edit = True
   596                 row_edit = True
   601                 self.AddButton.Enable(not self.Debug)
   601                 self.AddButton.Enable(not self.Debug)
   602                 self.DeleteButton.Enable(not self.Debug and (table_length > 0 and row_edit))
   602                 self.DeleteButton.Enable(not self.Debug and (table_length > 0 and row_edit))
   603                 self.UpButton.Enable(not self.Debug and (table_length > 0 and row > 0 and self.Filter == "All"))
   603                 self.UpButton.Enable(not self.Debug and (table_length > 0 and row > 0 and self.Filter == "All"))
   604                 self.DownButton.Enable(not self.Debug and (table_length > 0 and row < table_length - 1 and self.Filter == "All"))
   604                 self.DownButton.Enable(not self.Debug and (table_length > 0 and row < table_length - 1 and self.Filter == "All"))
   605         setattr(self.VariablesGrid, "RefreshButtons", _RefreshButtons)
   605         setattr(self.VariablesGrid, "RefreshButtons", _RefreshButtons)
   606         
   606 
   607         self.VariablesGrid.SetRowLabelSize(0)
   607         self.VariablesGrid.SetRowLabelSize(0)
   608         for col in range(self.Table.GetNumberCols()):
   608         for col in range(self.Table.GetNumberCols()):
   609             attr = wx.grid.GridCellAttr()
   609             attr = wx.grid.GridCellAttr()
   610             attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
   610             attr.SetAlignment(self.ColAlignements[col], wx.ALIGN_CENTRE)
   611             self.VariablesGrid.SetColAttr(col, attr)
   611             self.VariablesGrid.SetColAttr(col, attr)
   612             self.VariablesGrid.SetColMinimalWidth(col, self.ColSizes[col])
   612             self.VariablesGrid.SetColMinimalWidth(col, self.ColSizes[col])
   613             self.VariablesGrid.AutoSizeColumn(col, False)
   613             self.VariablesGrid.AutoSizeColumn(col, False)
   614     
   614 
   615     def __del__(self):
   615     def __del__(self):
   616         self.RefreshHighlightsTimer.Stop()
   616         self.RefreshHighlightsTimer.Stop()
   617     
   617 
   618     def SetTagName(self, tagname):
   618     def SetTagName(self, tagname):
   619         self.TagName = tagname
   619         self.TagName = tagname
   620         self.BodyType = self.Controler.GetEditedElementBodyType(self.TagName)
   620         self.BodyType = self.Controler.GetEditedElementBodyType(self.TagName)
   621     
   621 
   622     def GetTagName(self):
   622     def GetTagName(self):
   623         return self.TagName
   623         return self.TagName
   624     
   624 
   625     def IsFunctionBlockType(self, name):
   625     def IsFunctionBlockType(self, name):
   626         if (isinstance(name, TupleType) or 
   626         if (isinstance(name, TupleType) or
   627             self.ElementType != "function" and self.BodyType in ["ST", "IL"]):
   627             self.ElementType != "function" and self.BodyType in ["ST", "IL"]):
   628             return False
   628             return False
   629         else:
   629         else:
   630             return self.Controler.GetBlockType(name, debug=self.Debug) is not None
   630             return self.Controler.GetBlockType(name, debug=self.Debug) is not None
   631     
   631 
   632     def RefreshView(self):
   632     def RefreshView(self):
   633         self.PouNames = self.Controler.GetProjectPouNames(self.Debug)
   633         self.PouNames = self.Controler.GetProjectPouNames(self.Debug)
   634         returnType = None
   634         returnType = None
   635         description = None
   635         description = None
   636         
   636 
   637         words = self.TagName.split("::")
   637         words = self.TagName.split("::")
   638         if self.ElementType == "config":
   638         if self.ElementType == "config":
   639             self.Values = self.Controler.GetConfigurationGlobalVars(words[1], self.Debug)
   639             self.Values = self.Controler.GetConfigurationGlobalVars(words[1], self.Debug)
   640         elif self.ElementType == "resource":
   640         elif self.ElementType == "resource":
   641             self.Values = self.Controler.GetConfigurationResourceGlobalVars(words[1], words[2], self.Debug)
   641             self.Values = self.Controler.GetConfigurationResourceGlobalVars(words[1], words[2], self.Debug)
   645                 for data_type in self.Controler.GetDataTypes(self.TagName, debug=self.Debug):
   645                 for data_type in self.Controler.GetDataTypes(self.TagName, debug=self.Debug):
   646                     self.ReturnType.Append(data_type)
   646                     self.ReturnType.Append(data_type)
   647                 returnType = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, debug=self.Debug)
   647                 returnType = self.Controler.GetEditedElementInterfaceReturnType(self.TagName, debug=self.Debug)
   648             description = self.Controler.GetPouDescription(words[1])
   648             description = self.Controler.GetPouDescription(words[1])
   649             self.Values = self.Controler.GetEditedElementInterfaceVars(self.TagName, debug=self.Debug)
   649             self.Values = self.Controler.GetEditedElementInterfaceVars(self.TagName, debug=self.Debug)
   650         
   650 
   651         if returnType is not None:
   651         if returnType is not None:
   652             self.ReturnType.SetStringSelection(returnType)
   652             self.ReturnType.SetStringSelection(returnType)
   653             self.ReturnType.Enable(not self.Debug)
   653             self.ReturnType.Enable(not self.Debug)
   654             self.ReturnTypeLabel.Show()
   654             self.ReturnTypeLabel.Show()
   655             self.ReturnType.Show()
   655             self.ReturnType.Show()
   656         else:
   656         else:
   657             self.ReturnType.Enable(False)
   657             self.ReturnType.Enable(False)
   658             self.ReturnTypeLabel.Hide()
   658             self.ReturnTypeLabel.Hide()
   659             self.ReturnType.Hide()
   659             self.ReturnType.Hide()
   660         
   660 
   661         if description is not None:
   661         if description is not None:
   662             self.Description.SetValue(description)
   662             self.Description.SetValue(description)
   663             self.Description.Enable(not self.Debug)
   663             self.Description.Enable(not self.Debug)
   664             self.DescriptionLabel.Show()
   664             self.DescriptionLabel.Show()
   665             self.Description.Show()
   665             self.Description.Show()
   666         else:
   666         else:
   667             self.Description.Enable(False)
   667             self.Description.Enable(False)
   668             self.DescriptionLabel.Hide()
   668             self.DescriptionLabel.Hide()
   669             self.Description.Hide()
   669             self.Description.Hide()
   670         
   670 
   671         self.RefreshValues()
   671         self.RefreshValues()
   672         self.VariablesGrid.RefreshButtons()
   672         self.VariablesGrid.RefreshButtons()
   673         self.MainSizer.Layout()
   673         self.MainSizer.Layout()
   674     
   674 
   675     def OnReturnTypeChanged(self, event):
   675     def OnReturnTypeChanged(self, event):
   676         words = self.TagName.split("::")
   676         words = self.TagName.split("::")
   677         self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())
   677         self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())
   678         self.Controler.BufferProject()
   678         self.Controler.BufferProject()
   679         self.ParentWindow.RefreshView(variablepanel = False)
   679         self.ParentWindow.RefreshView(variablepanel = False)
   680         self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   680         self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   681         event.Skip()
   681         event.Skip()
   682     
   682 
   683     def OnDescriptionChanged(self, event):
   683     def OnDescriptionChanged(self, event):
   684         words = self.TagName.split("::")
   684         words = self.TagName.split("::")
   685         old_description = self.Controler.GetPouDescription(words[1])
   685         old_description = self.Controler.GetPouDescription(words[1])
   686         new_description = self.Description.GetValue()
   686         new_description = self.Description.GetValue()
   687         if new_description != old_description:
   687         if new_description != old_description:
   688             self.Controler.SetPouDescription(words[1], new_description)
   688             self.Controler.SetPouDescription(words[1], new_description)
   689             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   689             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   690         event.Skip()
   690         event.Skip()
   691     
   691 
   692     def OnClassFilter(self, event):
   692     def OnClassFilter(self, event):
   693         self.Filter = self.FilterChoiceTransfer[VARIABLE_CHOICES_DICT[self.ClassFilter.GetStringSelection()]]
   693         self.Filter = self.FilterChoiceTransfer[VARIABLE_CHOICES_DICT[self.ClassFilter.GetStringSelection()]]
   694         self.RefreshTypeList()
   694         self.RefreshTypeList()
   695         self.RefreshValues()
   695         self.RefreshValues()
   696         self.VariablesGrid.RefreshButtons()
   696         self.VariablesGrid.RefreshButtons()
   709     def OnVariablesGridCellChange(self, event):
   709     def OnVariablesGridCellChange(self, event):
   710         row, col = event.GetRow(), event.GetCol()
   710         row, col = event.GetRow(), event.GetCol()
   711         colname = self.Table.GetColLabelValue(col, False)
   711         colname = self.Table.GetColLabelValue(col, False)
   712         value = self.Table.GetValue(row, col)
   712         value = self.Table.GetValue(row, col)
   713         message = None
   713         message = None
   714         
   714 
   715         if colname == "Name" and value != "":
   715         if colname == "Name" and value != "":
   716             if not TestIdentifier(value):
   716             if not TestIdentifier(value):
   717                 message = _("\"%s\" is not a valid identifier!") % value
   717                 message = _("\"%s\" is not a valid identifier!") % value
   718             elif value.upper() in IEC_KEYWORDS:
   718             elif value.upper() in IEC_KEYWORDS:
   719                 message = _("\"%s\" is a keyword. It can't be used!") % value
   719                 message = _("\"%s\" is a keyword. It can't be used!") % value
   733             self.SaveValues()
   733             self.SaveValues()
   734             if colname == "Class":
   734             if colname == "Class":
   735                 wx.CallAfter(self.ParentWindow.RefreshView, False)
   735                 wx.CallAfter(self.ParentWindow.RefreshView, False)
   736             elif colname == "Location":
   736             elif colname == "Location":
   737                 wx.CallAfter(self.ParentWindow.RefreshView)
   737                 wx.CallAfter(self.ParentWindow.RefreshView)
   738             
   738 
   739         if message is not None:
   739         if message is not None:
   740             dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
   740             dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
   741             dialog.ShowModal()
   741             dialog.ShowModal()
   742             dialog.Destroy()
   742             dialog.Destroy()
   743             event.Veto()
   743             event.Veto()
   744         else:
   744         else:
   745             event.Skip()
   745             event.Skip()
   746     
   746 
   747     def OnVariablesGridEditorShown(self, event):
   747     def OnVariablesGridEditorShown(self, event):
   748         row, col = event.GetRow(), event.GetCol() 
   748         row, col = event.GetRow(), event.GetCol()
   749 
   749 
   750         label_value = self.Table.GetColLabelValue(col, False)
   750         label_value = self.Table.GetColLabelValue(col, False)
   751         if label_value == "Type":
   751         if label_value == "Type":
   752             type_menu = wx.Menu(title='')   # the root menu
   752             type_menu = wx.Menu(title='')   # the root menu
   753 
   753 
   767                 new_id = wx.NewId()
   767                 new_id = wx.NewId()
   768                 AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   768                 AppendMenu(datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   769                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   769                 self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   770 
   770 
   771             type_menu.AppendMenu(wx.NewId(), _("User Data Types"), datatype_menu)
   771             type_menu.AppendMenu(wx.NewId(), _("User Data Types"), datatype_menu)
   772             
   772 
   773             for category in self.Controler.GetConfNodeDataTypes():
   773             for category in self.Controler.GetConfNodeDataTypes():
   774                
   774 
   775                if len(category["list"]) > 0:
   775                if len(category["list"]) > 0:
   776                    # build a submenu containing confnode types
   776                    # build a submenu containing confnode types
   777                    confnode_datatype_menu = wx.Menu(title='')
   777                    confnode_datatype_menu = wx.Menu(title='')
   778                    for datatype in category["list"]:
   778                    for datatype in category["list"]:
   779                        new_id = wx.NewId()
   779                        new_id = wx.NewId()
   780                        AppendMenu(confnode_datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   780                        AppendMenu(confnode_datatype_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=datatype)
   781                        self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   781                        self.Bind(wx.EVT_MENU, self.GetVariableTypeFunction(datatype), id=new_id)
   782                    
   782 
   783                    type_menu.AppendMenu(wx.NewId(), category["name"], confnode_datatype_menu)
   783                    type_menu.AppendMenu(wx.NewId(), category["name"], confnode_datatype_menu)
   784 
   784 
   785             # build a submenu containing function block types
   785             # build a submenu containing function block types
   786             bodytype = self.Controler.GetEditedElementBodyType(self.TagName)
   786             bodytype = self.Controler.GetEditedElementBodyType(self.TagName)
   787             pouname, poutype = self.Controler.GetEditedElementType(self.TagName)
   787             pouname, poutype = self.Controler.GetEditedElementType(self.TagName)
   788             classtype = self.Table.GetValueByName(row, "Class")
   788             classtype = self.Table.GetValueByName(row, "Class")
   789             
   789 
   790             new_id = wx.NewId()
   790             new_id = wx.NewId()
   791             AppendMenu(type_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Array"))
   791             AppendMenu(type_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Array"))
   792             self.Bind(wx.EVT_MENU, self.VariableArrayTypeFunction, id=new_id)
   792             self.Bind(wx.EVT_MENU, self.VariableArrayTypeFunction, id=new_id)
   793             
   793 
   794             if classtype in ["Input", "Output", "InOut", "External", "Global"] or \
   794             if classtype in ["Input", "Output", "InOut", "External", "Global"] or \
   795             poutype != "function" and bodytype in ["ST", "IL"]:
   795             poutype != "function" and bodytype in ["ST", "IL"]:
   796                 functionblock_menu = wx.Menu(title='')
   796                 functionblock_menu = wx.Menu(title='')
   797                 fbtypes = self.Controler.GetFunctionBlockTypes(self.TagName)
   797                 fbtypes = self.Controler.GetFunctionBlockTypes(self.TagName)
   798                 for functionblock_type in fbtypes:
   798                 for functionblock_type in fbtypes:
   810             self.VariablesGrid.PopupMenuXY(type_menu, corner_x, corner_y)
   810             self.VariablesGrid.PopupMenuXY(type_menu, corner_x, corner_y)
   811             type_menu.Destroy()
   811             type_menu.Destroy()
   812             event.Veto()
   812             event.Veto()
   813         else:
   813         else:
   814             event.Skip()
   814             event.Skip()
   815     
   815 
   816     def GetVariableTypeFunction(self, base_type):
   816     def GetVariableTypeFunction(self, base_type):
   817         def VariableTypeFunction(event):
   817         def VariableTypeFunction(event):
   818             row = self.VariablesGrid.GetGridCursorRow()
   818             row = self.VariablesGrid.GetGridCursorRow()
   819             self.Table.SetValueByName(row, "Type", base_type)
   819             self.Table.SetValueByName(row, "Type", base_type)
   820             self.Table.ResetView(self.VariablesGrid)
   820             self.Table.ResetView(self.VariablesGrid)
   821             self.SaveValues(False)
   821             self.SaveValues(False)
   822             self.ParentWindow.RefreshView(variablepanel = False)
   822             self.ParentWindow.RefreshView(variablepanel = False)
   823             self.Controler.BufferProject()
   823             self.Controler.BufferProject()
   824             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   824             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   825         return VariableTypeFunction
   825         return VariableTypeFunction
   826     
   826 
   827     def VariableArrayTypeFunction(self, event):
   827     def VariableArrayTypeFunction(self, event):
   828         row = self.VariablesGrid.GetGridCursorRow()
   828         row = self.VariablesGrid.GetGridCursorRow()
   829         dialog = ArrayTypeDialog(self, 
   829         dialog = ArrayTypeDialog(self,
   830                                  self.Controler.GetDataTypes(self.TagName), 
   830                                  self.Controler.GetDataTypes(self.TagName),
   831                                  self.Table.GetValueByName(row, "Type"))
   831                                  self.Table.GetValueByName(row, "Type"))
   832         if dialog.ShowModal() == wx.ID_OK:
   832         if dialog.ShowModal() == wx.ID_OK:
   833             self.Table.SetValueByName(row, "Type", dialog.GetValue())
   833             self.Table.SetValueByName(row, "Type", dialog.GetValue())
   834             self.Table.ResetView(self.VariablesGrid)
   834             self.Table.ResetView(self.VariablesGrid)
   835             self.SaveValues(False)
   835             self.SaveValues(False)
   836             self.ParentWindow.RefreshView(variablepanel = False)
   836             self.ParentWindow.RefreshView(variablepanel = False)
   837             self.Controler.BufferProject()
   837             self.Controler.BufferProject()
   838             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   838             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   839         dialog.Destroy()
   839         dialog.Destroy()
   840     
   840 
   841     def OnVariablesGridCellLeftClick(self, event):
   841     def OnVariablesGridCellLeftClick(self, event):
   842         row = event.GetRow()
   842         row = event.GetRow()
   843         if not self.Debug and (event.GetCol() == 0 and self.Table.GetValueByName(row, "Edit")):
   843         if not self.Debug and (event.GetCol() == 0 and self.Table.GetValueByName(row, "Edit")):
   844             var_name = self.Table.GetValueByName(row, "Name")
   844             var_name = self.Table.GetValueByName(row, "Name")
   845             var_class = self.Table.GetValueByName(row, "Class")
   845             var_class = self.Table.GetValueByName(row, "Class")
   847             data = wx.TextDataObject(str((var_name, var_class, var_type, self.TagName)))
   847             data = wx.TextDataObject(str((var_name, var_class, var_type, self.TagName)))
   848             dragSource = wx.DropSource(self.VariablesGrid)
   848             dragSource = wx.DropSource(self.VariablesGrid)
   849             dragSource.SetData(data)
   849             dragSource.SetData(data)
   850             dragSource.DoDragDrop()
   850             dragSource.DoDragDrop()
   851         event.Skip()
   851         event.Skip()
   852     
   852 
   853     def RefreshValues(self):
   853     def RefreshValues(self):
   854         data = []
   854         data = []
   855         for num, variable in enumerate(self.Values):
   855         for num, variable in enumerate(self.Values):
   856             if variable.Class in self.ClassList:
   856             if variable.Class in self.ClassList:
   857                 variable.Number = num + 1
   857                 variable.Number = num + 1
   858                 data.append(variable)
   858                 data.append(variable)
   859         self.Table.SetData(data)
   859         self.Table.SetData(data)
   860         self.Table.ResetView(self.VariablesGrid)
   860         self.Table.ResetView(self.VariablesGrid)
   861             
   861 
   862     def SaveValues(self, buffer = True):
   862     def SaveValues(self, buffer = True):
   863         words = self.TagName.split("::")
   863         words = self.TagName.split("::")
   864         if self.ElementType == "config":
   864         if self.ElementType == "config":
   865             self.Controler.SetConfigurationGlobalVars(words[1], self.Values)
   865             self.Controler.SetConfigurationGlobalVars(words[1], self.Values)
   866         elif self.ElementType == "resource":
   866         elif self.ElementType == "resource":
   869             if self.ReturnType.IsEnabled():
   869             if self.ReturnType.IsEnabled():
   870                 self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())
   870                 self.Controler.SetPouInterfaceReturnType(words[1], self.ReturnType.GetStringSelection())
   871             self.Controler.SetPouInterfaceVars(words[1], self.Values)
   871             self.Controler.SetPouInterfaceVars(words[1], self.Values)
   872         if buffer:
   872         if buffer:
   873             self.Controler.BufferProject()
   873             self.Controler.BufferProject()
   874             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)            
   874             self.ParentWindow._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES, POUINSTANCEVARIABLESPANEL, LIBRARYTREE)
   875 
   875 
   876 #-------------------------------------------------------------------------------
   876 #-------------------------------------------------------------------------------
   877 #                        Highlights showing functions
   877 #                        Highlights showing functions
   878 #-------------------------------------------------------------------------------
   878 #-------------------------------------------------------------------------------
   879 
   879