Adding support for searching pattern in datatype elements
authorlaurent
Wed, 12 Oct 2011 23:47:48 +0200
changeset 576 3f2024f30553
parent 575 a7c706b9492e
child 577 9dbb79722fbc
Adding support for searching pattern in datatype elements
DataTypeEditor.py
SearchResultPanel.py
plcopen/plcopen.py
--- a/DataTypeEditor.py	Wed Oct 12 15:08:47 2011 +0200
+++ b/DataTypeEditor.py	Wed Oct 12 23:47:48 2011 +0200
@@ -57,7 +57,7 @@
         self.data = data
         self.old_value = None
         self.colnames = colnames
-        self.Errors = {}
+        self.Highlights = {}
         self.Parent = parent
         # XXX
         # we need to store the row length and collength to
@@ -148,6 +148,7 @@
         """
         
         for row in range(self.GetNumberRows()):
+            row_highlights = self.Highlights.get(row, {})
             for col in range(self.GetNumberCols()):
                 editor = None
                 renderer = None
@@ -168,13 +169,14 @@
                 grid.SetCellEditor(row, col, editor)
                 grid.SetCellRenderer(row, col, renderer)
                 
-                if self.Errors.has_key(row) and self.Errors[row][0] == colname.lower():
-                    grid.SetCellBackgroundColour(row, col, wx.Colour(255, 255, 0))
-                    grid.SetCellTextColour(row, col, wx.RED)
-                    grid.MakeCellVisible(row, col)
-                else:
-                    grid.SetCellTextColour(row, col, wx.BLACK)
-                    grid.SetCellBackgroundColour(row, col, wx.WHITE)
+                highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1]
+                grid.SetCellBackgroundColour(row, col, highlight_colours[0])
+                grid.SetCellTextColour(row, col, highlight_colours[1])
+            if wx.Platform == '__WXMSW__':
+                grid.SetRowMinimalHeight(row, 20)
+            else:
+                grid.SetRowMinimalHeight(row, 28)
+            grid.AutoSizeRow(row, False)
     
     def SetData(self, data):
         self.data = data
@@ -202,11 +204,25 @@
         self.data = []
         self.editors = []
 
-    def AddError(self, infos):
-        self.Errors[infos[0]] = infos[1:]
-
-    def ClearErrors(self):
-        self.Errors = {}
+    def AddHighlight(self, infos, highlight_type):
+        row_highlights = self.Highlights.setdefault(infos[0], {})
+        if infos[1] == "initial":
+            col_highlights = row_highlights.setdefault("initial value", [])
+        else:
+            col_highlights = row_highlights.setdefault(infos[1], [])
+        col_highlights.append(highlight_type)
+
+    def ClearHighlights(self, highlight_type=None):
+        if highlight_type is None:
+            self.Highlights = {}
+        else:
+            for row, row_highlights in self.Highlights.iteritems():
+                row_items = row_highlights.items()
+                for col, col_highlights in row_items:
+                    if highlight_type in col_highlights:
+                        col_highlights.remove(highlight_type)
+                    if len(col_highlights) == 0:
+                        row_highlights.pop(col)
 
 #-------------------------------------------------------------------------------
 #                          Datatype Editor class
@@ -383,6 +399,7 @@
         self.DirectlyBaseType = wx.ComboBox(id=ID_DATATYPEEDITORDIRECTLYBASETYPE, 
               name='DirectlyBaseType', parent=self.DirectlyPanel, pos=wx.Point(0, 0),
               size=wx.Size(0, 28), style=wx.CB_READONLY)
+        self.DirectlyBaseType.SetBackgroundColour(wx.BLUE)
         self.Bind(wx.EVT_COMBOBOX, self.OnInfosChanged, id=ID_DATATYPEEDITORDIRECTLYBASETYPE)
 
         self.staticText3 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT3,
@@ -407,6 +424,7 @@
         self.SubrangeBaseType = wx.ComboBox(id=ID_DATATYPEEDITORSUBRANGEBASETYPE, 
               name='SubrangeBaseType', parent=self.SubrangePanel, pos=wx.Point(0, 0),
               size=wx.Size(0, 28), style=wx.CB_READONLY)
+        self.SubrangeBaseType.SetBackgroundColour(wx.BLUE)
         self.Bind(wx.EVT_COMBOBOX, self.OnSubrangeBaseTypeChanged, id=ID_DATATYPEEDITORSUBRANGEBASETYPE)
 
         self.staticText5 = wx.StaticText(id=ID_DATATYPEEDITORSTATICTEXT5,
@@ -590,6 +608,20 @@
         self.Controler = controler
         self.TagName = tagname
         
+        self.HighlightControls = {
+            ("Directly", "base"): self.DirectlyBaseType,
+            ("Directly", "initial"): self.DirectlyInitialValue,
+            ("Subrange", "base"): self.SubrangeBaseType,
+            ("Subrange", "lower"): self.SubrangeMinimum,
+            ("Subrange", "upper"): self.SubrangeMaximum,
+            ("Subrange", "initial"): self.SubrangeInitialValue,
+            ("Enumerated", "value"): self.EnumeratedValues,
+            ("Enumerated", "initial"): self.EnumeratedInitialValue,
+            ("Array", "initial"): self.ArrayInitialValue,
+            ("Array", "base"): self.ArrayBaseType,
+            ("Array", "range"): self.ArrayDimensions,
+        }
+        
         self.RefreshHighlightsTimer = wx.Timer(self, -1)
         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
         
@@ -655,9 +687,9 @@
                 self.ArrayInitialValue.SetValue(type_infos["initial"])
             elif type_infos["type"] == "Structure":
                 self.StructureElementsTable.SetData(type_infos["elements"])
-                self.StructureElementsTable.ResetView(self.StructureElementsGrid)
             self.RefreshDisplayedInfos()
-        self.ShowErrors()
+        self.ShowHighlights()
+        self.StructureElementsTable.ResetView(self.StructureElementsGrid)
         self.Initializing = False
 
     def RefreshScaling(self, refresh=True):
@@ -940,50 +972,41 @@
             self.Highlights = []
         else:
             self.Highlights = [(infos, start, end, highlight) for (infos, start, end, highlight) in self.Highlights if highlight != highlight_type]
+        for control in self.HighlightControls.itervalues():
+            if isinstance(control, (wx.ComboBox, wx.SpinCtrl)):
+                control.SetBackgroundColour(wx.NullColour)
+                control.SetForegroundColour(wx.NullColour)
+            elif isinstance(control, wx.TextCtrl):
+                value = control.GetValue()
+                control.SetStyle(0, len(value), wx.TextAttr(wx.NullColour))
+            elif isinstance(control, wx.gizmos.EditableListBox):
+                listctrl = control.GetListCtrl()
+                for i in xrange(listctrl.GetItemCount()):
+                    listctrl.SetItemBackgroundColour(i, wx.NullColour)
+                    listctrl.SetItemTextColour(i, wx.NullColour)
+        self.StructureElementsTable.ClearHighlights(highlight_type)
         self.RefreshView()
 
     def AddHighlight(self, infos, start, end ,highlight_type):
         self.Highlights.append((infos, start, end, highlight_type))
         self.RefreshHighlightsTimer.Start(int(REFRESH_HIGHLIGHT_PERIOD * 1000), oneShot=True)
 
-    def ShowErrors(self):
+    def ShowHighlights(self):
         type_infos = self.Controler.GetDataTypeInfos(self.TagName)
         for infos, start, end, highlight_type in self.Highlights:
-            if infos[0] == "base":
-                if type_infos["type"] == "Directly":
-                    self.DirectlyBaseType.SetBackgroundColour(highlight_type[0])
-                    self.DirectlyBaseType.SetForegroundColour(highlight_type[1])
-                elif type_infos["type"] == "Subrange":
-                    self.SubrangeBaseType.SetBackgroundColour(highlight_type[0])
-                    self.SubrangeBaseType.SetForegroundColour(highlight_type[1])
-                elif type_infos["type"] == "Array":
-                    self.ArrayBaseType.SetBackgroundColour(highlight_type[0])
-                    self.ArrayBaseType.SetForegroundColour(highlight_type[1])
-            elif infos[0] == "lower":
-                self.SubrangeMinimum.SetBackgroundColour(highlight_type[0])
-                self.SubrangeMaximum.SetForegroundColour(highlight_type[1])
-            elif infos[0] == "upper":
-                self.SubrangeMinimum.SetBackgroundColour(highlight_type[0])
-                self.SubrangeMaximum.SetForegroundColour(highlight_type[1])
-            elif infos[0] == "value":
-                listctrl = self.EnumeratedValues.GetListCtrl()
-                listctrl.SetItemBackgroundColour(infos[1], highlight_type[0])
-                listctrl.SetItemTextColour(infos[1], highlight_type[1])
-                listctrl.Select(listctrl.FocusedItem, False)
-            elif infos[0] == "range":
-                listctrl = self.EnumeratedValues.GetListCtrl()
-                listctrl.SetItemBackgroundColour(infos[1], highlight_type[0])
-                listctrl.SetItemTextColour(infos[1], highlight_type[1])
-                listctrl.SetStringSelection("")
-            elif infos[0] == "initial":
-                if type_infos["type"] == "Directly":
-                    self.DirectlyInitialValue.SetStyle(start[1], end[1] + 1, wx.TextAttr(highlight_type[1], highlight_type[0]))
-                elif type_infos["type"] == "Subrange":
-                    self.SubrangeInitialValue.SetBackgroundColour(highlight_type[0])
-                    self.SubrangeInitialValue.SetForegroundColour(highlight_type[1])
-                elif type_infos["type"] == "Enumerated":
-                    self.EnumeratedInitialValue.SetBackgroundColour(highlight_type[0])
-                    self.EnumeratedInitialValue.SetForegroundColour(highlight_type[1])
-                elif type_infos["type"] == "Array":
-                    self.ArrayInitialValue.SetStyle(start[1], end[1] + 1, wx.TextAttr(highlight_type[1], highlight_type[0]))
-
+            if infos[0] == "struct":
+                self.StructureElementsTable.AddHighlight(infos[1:], highlight_type)
+            else:
+                control = self.HighlightControls.get((type_infos["type"], infos[0]), None)
+                if control is not None:
+                    if isinstance(control, (wx.ComboBox, wx.SpinCtrl)):
+                        control.SetBackgroundColour(highlight_type[0])
+                        control.SetForegroundColour(highlight_type[1])
+                    elif isinstance(control, wx.TextCtrl):
+                        control.SetStyle(start[1], end[1] + 1, wx.TextAttr(highlight_type[1], highlight_type[0]))
+                    elif isinstance(control, wx.gizmos.EditableListBox):
+                        listctrl = control.GetListCtrl()
+                        listctrl.SetItemBackgroundColour(infos[1], highlight_type[0])
+                        listctrl.SetItemTextColour(infos[1], highlight_type[1])
+                        listctrl.Select(listctrl.FocusedItem, False)
+
--- a/SearchResultPanel.py	Wed Oct 12 15:08:47 2011 +0200
+++ b/SearchResultPanel.py	Wed Oct 12 23:47:48 2011 +0200
@@ -32,8 +32,12 @@
 CWD = os.path.split(os.path.realpath(__file__))[0]
 
 def GenerateName(infos):
-    if infos[0] in ["input", "output"]:
+    if infos[0] in ["input", "output", "value"]:
         return "%s %d:" % (infos[0], infos[1])
+    elif infos[0] == "range":
+        return "%s %d %s" % (infos[0], infos[1], infos[2])
+    elif infos[0] == "struct":
+        return "element %d %s" % (infos[1], infos[2])
     return "%s:" % infos[0]
 
 #-------------------------------------------------------------------------------
@@ -191,17 +195,21 @@
                 
                 children = element_infos.setdefault("children", [])
                 for infos, start, end, text in results:
-                    child_type = infos[1]
-                    if child_type == "body":
-                        child_name = "body"
-                        if element_type == ITEM_TRANSITION:
-                            child_type = self.ParentWindow.Controler.GetTransitionBodyType(words[1], words[2])
-                        elif element_type == ITEM_ACTION:
-                            child_type = self.ParentWindow.Controler.GetActionBodyType(words[1], words[2])
+                    if element_type == ITEM_DATATYPE:
+                        child_name = GenerateName(infos[1:])
+                        child_type = element_type
+                    else:
+                        child_type = infos[1]
+                        if child_type == "body":
+                            child_name = "body"
+                            if element_type == ITEM_TRANSITION:
+                                child_type = self.ParentWindow.Controler.GetTransitionBodyType(words[1], words[2])
+                            elif element_type == ITEM_ACTION:
+                                child_type = self.ParentWindow.Controler.GetActionBodyType(words[1], words[2])
+                            else:
+                                child_type = self.ParentWindow.Controler.GetPouBodyType(words[1])
                         else:
-                            child_type = self.ParentWindow.Controler.GetPouBodyType(words[1])
-                    else:
-                        child_name = GenerateName(infos[3:])
+                            child_name = GenerateName(infos[3:])
                     child_infos = {"name": child_name,
                                    "type": child_type,
                                    "data": (infos, start, end ,None),
--- a/plcopen/plcopen.py	Wed Oct 12 15:08:47 2011 +0200
+++ b/plcopen/plcopen.py	Wed Oct 12 23:47:48 2011 +0200
@@ -353,18 +353,7 @@
 
     def updateElementName(self, old_name, new_name):
         for datatype in self.types.getdataTypeElements():
-            datatype_content = datatype.baseType.getcontent()
-            if datatype_content["name"] == "derived" and datatype_content["value"].getname() == old_name:
-                datatype_content["value"].setname(new_name)
-            elif datatype_content["name"] in ["array", "subrangeSigned", "subrangeUnsigned"]:
-                basetype_content = datatype_content["value"].baseType.getcontent()
-                if basetype_content["name"] == "derived" and basetype_content["value"].getname() == old_name:
-                    basetype_content["value"].setname(new_name)
-            elif datatype_content["name"] == "struct":
-                for element in datatype_content["value"].getvariable():
-                    element_type = element.type.getcontent()
-                    if element_type["name"] == "derived" and element_type["value"].getname() == old_name:
-                        element_type["value"].setname(new_name)
+            datatype.updateElementName(old_name, new_name)
         for pou in self.types.getpouElements():
             pou.updateElementName(old_name, new_name)
         for configuration in self.instances.configurations.getconfiguration():
@@ -823,9 +812,7 @@
                     variables.pop(i)
 
 def _SearchInConfigurationResource(self, criteria, parent_infos=[]):
-    search_result = []
-    for result in TestTextElement(self.getname(), criteria):
-        search_result.append((tuple(parent_infos + ["name"]),) + result)
+    search_result = _Search([("name", self.getname())], criteria, parent_infos)
     var_number = 0
     for varlist in self.getglobalVars():
         variable_type = searchResultVarTypes.get("globalVars", "var_local")
@@ -1097,14 +1084,103 @@
     def Search(self, criteria, parent_infos=[]):
         search_result = []
         filter = criteria["filter"]
-        #if filter == "all" or "datatype" in filter:
-        #    for datatype in self.dataTypes.getdataType():
-        #        search_result.extend(datatype.Search(criteria, parent_infos))
+        for datatype in self.dataTypes.getdataType():
+            search_result.extend(datatype.Search(criteria, parent_infos))
         for pou in self.pous.getpou():
             search_result.extend(pou.Search(criteria, parent_infos))
         return search_result
     setattr(cls, "Search", Search)
 
+def _updateBaseTypeElementName(self, old_name, new_name):
+    self.baseType.updateElementName(old_name, new_name)
+
+cls = PLCOpenClasses.get("dataTypes_dataType", None)
+if cls:
+    setattr(cls, "updateElementName", _updateBaseTypeElementName)
+    
+    def Search(self, criteria, parent_infos=[]):
+        search_result = []
+        filter = criteria["filter"]
+        if filter == "all" or "datatype" in filter:
+            parent_infos = parent_infos + ["D::%s" % self.getname()]
+            search_result.extend(_Search([("name", self.getname())], criteria, parent_infos))
+            search_result.extend(self.baseType.Search(criteria, parent_infos))
+            if self.initialValue is not None:
+                search_result.extend(_Search([("initial", self.initialValue.getvalue())], criteria, parent_infos))
+        return search_result
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("dataType", None)
+if cls:
+    
+    def updateElementName(self, old_name, new_name):
+        if self.content["name"] in ["derived", "array", "subrangeSigned", "subrangeUnsigned"]:
+            self.content["value"].updateElementName(old_name, new_name)
+        elif self.content["name"] == "struct":
+            for element in datatype_content["value"].getvariable():
+                element_type = element.type.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def Search(self, criteria, parent_infos=[]):
+        search_result = []
+        if self.content["name"] in ["derived", "array", "enum", "subrangeSigned", "subrangeUnsigned"]:
+            search_result.extend(self.content["value"].Search(criteria, parent_infos))
+        elif self.content["name"] == "struct":
+            for i, element in enumerate(self.content["value"].getvariable()):
+                search_result.extend(element.Search(criteria, parent_infos + ["struct", i]))
+        else:
+            basetype = self.content["name"]
+            if basetype in ["string", "wstring"]:
+                basetype = basetype.upper()
+            search_result.extend(_Search([("base", basetype)], criteria, parent_infos))
+        return search_result
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("derivedTypes_array", None)
+if cls:
+    setattr(cls, "updateElementName", _updateBaseTypeElementName)
+    
+    def Search(self, criteria, parent_infos=[]):
+        search_result = self.baseType.Search(criteria, parent_infos)
+        for i, dimension in enumerate(self.getdimension()):
+            search_result.extend(_Search([("lower", dimension.getlower()),
+                                          ("upper", dimension.getupper())],
+                                         criteria, parent_infos + ["range", i]))
+        return search_result
+    setattr(cls, "Search", Search)
+
+def _SearchInSubrange(self, criteria, parent_infos=[]):
+    search_result = self.baseType.Search(criteria, parent_infos)
+    search_result.extend(_Search([("lower", self.range.getlower()),
+                                  ("upper", self.range.getupper())],
+                                 criteria, parent_infos))
+    return search_result
+
+cls = PLCOpenClasses.get("derivedTypes_subrangeSigned", None)
+if cls:
+    setattr(cls, "updateElementName", _updateBaseTypeElementName)
+    setattr(cls, "Search", _SearchInSubrange)
+
+cls = PLCOpenClasses.get("derivedTypes_subrangeUnsigned", None)
+if cls:
+    setattr(cls, "updateElementName", _updateBaseTypeElementName)
+    setattr(cls, "Search", _SearchInSubrange)
+
+cls = PLCOpenClasses.get("derivedTypes_enum", None)
+if cls:
+    
+    def updateElementName(self, old_name, new_name):
+        pass
+    setattr(cls, "updateElementName", updateElementName)
+    
+    def Search(self, criteria, parent_infos=[]):
+        search_result = []
+        for i, value in enumerate(self.values.getvalue()):
+            for result in TestTextElement(value.getname(), criteria):
+                search_result.append((tuple(parent_infos + ["value", i]),) + result)
+        return search_result
+    setattr(cls, "Search", Search)
+
 cls = PLCOpenClasses.get("pous_pou", None)
 if cls:
     
@@ -1433,8 +1509,7 @@
         filter = criteria["filter"]
         if filter == "all" or self.getpouType() in filter:
             parent_infos = parent_infos + ["P::%s" % self.getname()]
-            for result in TestTextElement(self.getname(), criteria):
-                search_result.append((tuple(parent_infos + ["name"]),) + result)
+            search_result.extend(_Search([("name", self.getname())], criteria, parent_infos))
             if self.interface is not None:
                 var_number = 0
                 for content in self.interface.getcontent():