Fixed variable panel in CodeFileEditor
authorLaurent Bessard
Wed, 15 May 2013 22:14:12 +0200
changeset 1146 510d1ea1f6c1
parent 1144 21475ee0e688
child 1147 71db4592beb2
Fixed variable panel in CodeFileEditor
CodeFileTreeNode.py
ProjectController.py
editors/CodeFileEditor.py
--- a/CodeFileTreeNode.py	Wed May 15 17:13:49 2013 +0900
+++ b/CodeFileTreeNode.py	Wed May 15 22:14:12 2013 +0200
@@ -90,6 +90,12 @@
     def GetDataTypes(self, basetypes = False):
         return self.GetCTRoot().GetDataTypes(basetypes=basetypes)
 
+    def GenerateNewName(self, format, start_idx):
+        return self.GetCTRoot().GenerateNewName(
+            None, None, format, start_idx,
+            dict([(var.getname(), None) 
+                  for var in self.CodeFile.variables.getvariable()]))
+
     def SetVariables(self, variables):
         self.CodeFile.variables.setvariable([])
         for var in variables:
--- a/ProjectController.py	Wed May 15 17:13:49 2013 +0900
+++ b/ProjectController.py	Wed May 15 22:14:12 2013 +0200
@@ -1182,7 +1182,10 @@
                 self.TracedIECPath = []
                 self._connector.SetTraceVariablesList([])
             self.IECdebug_lock.release()
-
+    
+    def IsPLCStarted(self):
+        return self.previous_plcstate == "Started"
+     
     def ReArmDebugRegisterTimer(self):
         if self.DebugTimer is not None:
             self.DebugTimer.cancel()
@@ -1190,7 +1193,7 @@
         # Prevent to call RegisterDebugVarToConnector when PLC is not started
         # If an output location var is forced it's leads to segmentation fault in runtime
         # Links between PLC located variables and real variables are not ready
-        if self.previous_plcstate == "Started":
+        if self.IsPLCStarted():
             # Timer to prevent rapid-fire when registering many variables
             # use wx.CallAfter use keep using same thread. TODO : use wx.Timer instead
             self.DebugTimer=Timer(0.5,wx.CallAfter,args = [self.RegisterDebugVarToConnector])
--- a/editors/CodeFileEditor.py	Wed May 15 17:13:49 2013 +0900
+++ b/editors/CodeFileEditor.py	Wed May 15 22:14:12 2013 +0200
@@ -6,10 +6,12 @@
 import wx.lib.buttons
 
 from plcopen.plcopen import TestTextElement
+from plcopen.structures import TestIdentifier, IEC_KEYWORDS
 from controls import CustomGrid, CustomTable
 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
 from util.BitmapLibrary import GetBitmap
 from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos, NAVIGATION_KEYS
+from controls.VariablePanel import VARIABLE_NAME_SUFFIX_MODEL
 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
 
 [STC_CODE_ERROR, STC_CODE_SEARCH_RESULT, 
@@ -365,8 +367,10 @@
             self.BraceBadLight(braceAtCaret)
         else:
             self.BraceHighlight(braceAtCaret, braceOpposite)
-            
-        self.ParentWindow.SetCopyBuffer(self.GetSelectedText(), True)
+        
+        selected_text = self.GetSelectedText()
+        if selected_text:
+            self.ParentWindow.SetCopyBuffer(selected_text, True)
         event.Skip()
 
     def OnMarginClick(self, event):
@@ -648,7 +652,7 @@
         self.ParentWindow = window
         self.Controler = controler
         
-        self.VariablesDefaultValue = {"Name" : "", "Type" : "", "Initial": ""}
+        self.VariablesDefaultValue = {"Name" : "", "Type" : "INT", "Initial": ""}
         self.Table = VariablesTable(self, [], ["#", "Name", "Type", "Initial"])
         self.ColAlignements = [wx.ALIGN_RIGHT, wx.ALIGN_LEFT, wx.ALIGN_LEFT, wx.ALIGN_LEFT]
         self.ColSizes = [40, 200, 150, 150]
@@ -659,7 +663,24 @@
                                        "Down": self.DownVariableButton})
         
         def _AddVariable(new_row):
-            self.Table.InsertRow(new_row, self.VariablesDefaultValue.copy())
+            if new_row > 0:
+                row_content = self.Table.data[new_row - 1].copy()
+                result = VARIABLE_NAME_SUFFIX_MODEL.search(row_content["Name"])
+                if result is not None:
+                    name = row_content["Name"][:result.start(1)]
+                    suffix = result.group(1)
+                    if suffix != "":
+                        start_idx = int(suffix)
+                    else:
+                        start_idx = 0
+                else:
+                    name = row_content["Name"]
+                    start_idx = 0
+                row_content["Name"] = self.Controler.GenerateNewName(
+                        name + "%d", start_idx)
+            else:
+                row_content = self.VariablesDefaultValue.copy()
+            self.Table.InsertRow(new_row, row_content)
             self.RefreshModel()
             self.RefreshView()
             return new_row
@@ -708,9 +729,34 @@
         return self.ParentWindow.GetPanelBestSize()
     
     def OnVariablesGridCellChange(self, event):
-        self.RefreshModel()
-        wx.CallAfter(self.RefreshView)
-        event.Skip()
+        row, col = event.GetRow(), event.GetCol()
+        colname = self.Table.GetColLabelValue(col, False)
+        value = self.Table.GetValue(row, col)
+        message = None
+        
+        if colname == "Name" and value != "":
+            if not TestIdentifier(value):
+                message = _("\"%s\" is not a valid identifier!") % value
+            elif value.upper() in IEC_KEYWORDS:
+                message = _("\"%s\" is a keyword. It can't be used!") % value
+            elif value.upper() in [var["Name"].upper() 
+                                   for var_row, var in enumerate(self.Table.data) 
+                                   if var_row != row]:
+                message = _("A variable with \"%s\" as name already exists!") % value
+            else:
+                self.RefreshModel()
+                wx.CallAfter(self.RefreshView)
+        else:
+            self.RefreshModel()
+            wx.CallAfter(self.RefreshView)
+        
+        if message is not None:
+            dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR)
+            dialog.ShowModal()
+            dialog.Destroy()
+            event.Veto()
+        else:
+            event.Skip()
 
     def OnVariablesGridEditorShown(self, event):
         row, col = event.GetRow(), event.GetCol()