Adding auto-completion into ST and IL Editors
authorlbessard
Wed, 11 Apr 2007 17:26:07 +0200
changeset 8 7ceec5c40d77
parent 7 f1691e685c49
child 9 b29105e29081
Adding auto-completion into ST and IL Editors
Adding support for multiple coil on a rung into LD Editor
LDViewer.py
PLCOpenEditor.py
Viewer.py
graphics/LD_Objects.py
--- a/LDViewer.py	Tue Apr 10 18:02:40 2007 +0200
+++ b/LDViewer.py	Wed Apr 11 17:26:07 2007 +0200
@@ -562,8 +562,6 @@
         elif self.SelectedElement not in self.Elements:
             elements = self.SelectedElement.GetElements()
             for element in elements:
-                if isinstance(element, (LD_PowerRail, LD_Coil)):
-                    return
                 blocks.append(element)
         if len(blocks) > 0:
             blocks_infos = []
@@ -861,27 +859,77 @@
         self.RefreshRungs(new_bbox.height - old_bbox.height, rungindex + 1)
         self.SelectedElement = None
 
+    def RecursiveDeletion(self, element, rung):
+        connectors = element.GetConnectors()
+        input_wires = [wire for wire, handle in connectors["input"].GetWires()]
+        left_elements = [wire.EndConnected for wire in input_wires]
+        rung.SelectElement(element)
+        element.Clean()
+        for wire in input_wires:
+            wire.Clean()
+            self.Wires.remove(wire)
+            self.Elements.remove(wire)
+            rung.SelectElement(wire)
+        self.Blocks.remove(element)
+        self.Elements.remove(element)
+        self.Controler.RemoveCurrentElementEditingInstance(element.GetId())
+        for left_element in left_elements:
+            block = left_element.GetParentBlock()
+            if len(left_element.GetWires()) == 0:
+                self.RecursiveDeletion(block, rung)
+            else:
+                self.RefreshPosition(block)
+
     def DeleteCoil(self, coil):
         rungindex = self.FindRung(coil)
         rung = self.Rungs[rungindex]
-        bbox = rung.GetBoundingBox()
+        old_bbox = rung.GetBoundingBox()
+        nbcoils = 0
         for element in rung.GetElements():
-            if element in self.Wires:
-                element.Clean()
-                self.Wires.remove(element)
-                self.Elements.remove(element)
-        for element in rung.GetElements():
-            if element in self.Blocks:
-                self.Controler.RemoveCurrentElementEditingInstance(element.GetId())
-                self.Blocks.remove(element)
-                self.Elements.remove(element)
-        self.Controler.RemoveCurrentElementEditingInstance(self.Comments[rungindex].GetId())
-        self.Elements.remove(self.Comments[rungindex])
-        self.Comments.pop(rungindex)
-        self.Rungs.pop(rungindex)
-        if rungindex < len(self.Rungs):
-            next_bbox = self.Rungs[rungindex].GetBoundingBox()
-            self.RefreshRungs(bbox.y - next_bbox.y, rungindex)
+            if isinstance(element, LD_Coil):
+                nbcoils += 1
+        if nbcoils > 1:
+            connectors = coil.GetConnectors()
+            output_wires = [wire for wire, handle in connectors["output"].GetWires()]
+            right_elements = [wire.StartConnected for wire in output_wires]
+            for wire in output_wires:
+                wire.Clean()
+                self.Wires.remove(wire)
+                self.Elements.remove(wire)
+                rung.SelectElement(wire)
+            for right_element in right_elements:
+                right_block = right_element.GetParentBlock()
+                if isinstance(right_block, LD_PowerRail):
+                    if len(right_element.GetWires()) == 0:
+                        index = right_block.GetConnectorIndex(right_element)
+                        right_block.DeleteConnector(index)
+                        powerrail_connectors = right_block.GetConnectors()
+                        for connector in powerrail_connectors:
+                            for wire, handle in connector.GetWires():
+                                block = wire.EndConnected.GetParentBlock()
+                                endpoint = wire.EndConnected.GetPosition(False)
+                                startpoint = connector.GetPosition(False)
+                                block.Move(0, startpoint.y - endpoint.y)
+                                self.RefreshPosition(block)
+            self.RecursiveDeletion(coil, rung)
+        else:
+            for element in rung.GetElements():
+                if element in self.Wires:
+                    element.Clean()
+                    self.Wires.remove(element)
+                    self.Elements.remove(element)
+            for element in rung.GetElements():
+                if element in self.Blocks:
+                    self.Controler.RemoveCurrentElementEditingInstance(element.GetId())
+                    self.Blocks.remove(element)
+                    self.Elements.remove(element)
+            self.Controler.RemoveCurrentElementEditingInstance(self.Comments[rungindex].GetId())
+            self.Elements.remove(self.Comments[rungindex])
+            self.Comments.pop(rungindex)
+            self.Rungs.pop(rungindex)
+            if rungindex < len(self.Rungs):
+                next_bbox = self.Rungs[rungindex].GetBoundingBox()
+                self.RefreshRungs(old_bbox.y - next_bbox.y, rungindex)
         self.SelectedElement = None
 
     def DeleteWire(self, wire):
@@ -940,7 +988,7 @@
 #                        Refresh element position functions
 #-------------------------------------------------------------------------------
 
-    def RefreshPosition(self, element):
+    def RefreshPosition(self, element, recursive=True):
         if isinstance(element, LD_PowerRail) and element.GetType() == LEFTRAIL:
             element.RefreshModel()
             return
@@ -949,6 +997,10 @@
         output_connectors = []
         if isinstance(element, LD_PowerRail) and element.GetType() == RIGHTRAIL:
             input_connectors = connectors
+            for i, connector in enumerate(input_connectors):
+                for j, (wire, handle) in enumerate(connector.GetWires()):
+                    block = wire.EndConnected.GetParentBlock()
+                    self.RefreshPosition(block, False)
         else:
             if "inputs" in connectors:
                 input_connectors = connectors["inputs"]
@@ -977,6 +1029,7 @@
             interval += LD_WIRE_SIZE
         movex = minx + interval - position[0]
         element.Move(movex, 0)
+        position = element.GetPosition()
         for i, connector in enumerate(input_connectors):
             startpoint = connector.GetPosition(False)
             previous_blocks = []
@@ -986,6 +1039,11 @@
                 middlepoint = minx + LD_WIRE_SIZE
             for j, (wire, handle) in enumerate(connector.GetWires()):
                 block = wire.EndConnected.GetParentBlock()
+                if isinstance(element, LD_PowerRail):
+                    pos = block.GetPosition()
+                    size = leftblock.GetSize()
+                    movex = position[0] - LD_WIRE_SIZE - size[0] - pos[0]
+                    block.Move(movex, 0)
                 endpoint = wire.EndConnected.GetPosition(False)
                 if j == 0:
                     if not onlyone[i] and wire.EndConnected.GetWireIndex(wire) > 0:
@@ -1002,7 +1060,14 @@
                               wxPoint(endmiddlepoint, endpoint.y), endpoint]
                 else:
                     if startpoint.y + offset != endpoint.y:
-                        if isinstance(block, LD_PowerRail):
+                        if isinstance(element, LD_PowerRail):
+                            diff = (startpoint.y - endpoint.y) / LD_LINE_SIZE
+                            for k in xrange(abs(diff)):
+                                if diff < 0:
+                                    element.DeleteConnector(i - 1 - k)
+                                else:
+                                    element.InsertConnector(i + k, False)
+                        elif isinstance(block, LD_PowerRail):
                             index = block.GetConnectorIndex(wire.EndConnected)
                             if index:
                                 diff = (startpoint.y - endpoint.y) / LD_LINE_SIZE
@@ -1013,7 +1078,7 @@
                                         block.InsertConnector(index + k, False)
                         else:
                             block.Move(0, startpoint.y + offset - endpoint.y)
-                            self.RefreshPosition(block)
+                            self.RefreshPosition(block, False)
                         endpoint = wire.EndConnected.GetPosition(False)
                     if not onlyone[i]:
                         points = [startpoint, wxPoint(middlepoint, startpoint.y),
@@ -1024,9 +1089,10 @@
                 previous_blocks.append(block)
                 ExtractNextBlocks(block, block_list)
         element.RefreshModel(False)
-        for connector in output_connectors:
-            for wire, handle in connector.GetWires():
-                self.RefreshPosition(wire.StartConnected.GetParentBlock())
+        if recursive:
+            for connector in output_connectors:
+                for wire, handle in connector.GetWires():
+                    self.RefreshPosition(wire.StartConnected.GetParentBlock())
     
     def RefreshRungs(self, movey, fromidx):
         if movey != 0:
--- a/PLCOpenEditor.py	Tue Apr 10 18:02:40 2007 +0200
+++ b/PLCOpenEditor.py	Wed Apr 11 17:26:07 2007 +0200
@@ -439,7 +439,7 @@
             self.EditMenu.FindItemByPosition(8).Enable(False)
             self.EditMenu.FindItemByPosition(9).Enable(False)
         bodytype = self.Controler.GetCurrentElementEditingBodyType()
-        if bodytype in ["LD","ST"]:
+        if bodytype in ["IL","ST"]:
             self.EditMenu.FindItemByPosition(4).Enable(True)
             self.EditMenu.FindItemByPosition(5).Enable(True)
             self.EditMenu.FindItemByPosition(6).Enable(True)
@@ -896,6 +896,7 @@
                     new_window = SFC_Viewer(self.TabsOpened, self, self.Controler)
                 elif language in ["IL", "ST"]:
                     new_window = TextViewer(self.TabsOpened, self, self.Controler)
+                    new_window.SetTextSyntax(language)
                     if language == "IL":
                         new_window.SetKeywords(IL_KEYWORDS)
                     else:
--- a/Viewer.py	Tue Apr 10 18:02:40 2007 +0200
+++ b/Viewer.py	Wed Apr 11 17:26:07 2007 +0200
@@ -885,11 +885,16 @@
         self.Functions = []
         self.Jumps = []
         self.TextChanged = False
+        self.TextSyntax = "ST"
         
         self.Controler = controler
 
         EVT_KEY_DOWN(self, self.OnKeyDown)
         EVT_STC_STYLENEEDED(self, wxID_TEXTVIEWER, self.OnStyleNeeded)
+        EVT_KILL_FOCUS(self, self.OnKillFocus)
+    
+    def SetTextSyntax(self, syntax):
+        self.TextSyntax = syntax
     
     def SetKeywords(self, keywords):
         self.Keywords = [keyword.upper() for keyword in keywords]
@@ -1046,27 +1051,47 @@
             self.CallTipCancel()
         key = event.KeyCode()
 
+        # Code completion
         if key == WXK_SPACE and event.ControlDown():
-            pos = self.GetCurrentPos()
-
-            # Tips
-            if event.ShiftDown():
-                self.CallTipSetBackground("yellow")
-                self.CallTipShow(pos, 'Here will be some help.')
             
-            # Code completion
+            line = self.GetCurrentLine()
+            if line == 0:
+                start_pos = 0
             else:
-                kw = [key for key in self.Keywords]
-                
-                kw.sort()  # Python sorts are case sensitive
-                self.AutoCompSetIgnoreCase(False)  # so this needs to match
-
-                self.AutoCompShow(0, " ".join(kw))
+                start_pos = self.GetLineEndPosition(line - 1) + 1
+            end_pos = self.GetCurrentPos()
+
+            lineText = self.GetTextRange(start_pos, end_pos).replace("\t", " ")
+            words = lineText.split(" ")
+            words = [word for i, word in enumerate(words) if word != '' or i == len(words) - 1]
+                        
+            kw = []
+            
+            if self.TextSyntax == "IL":
+                if len(words) == 1:
+                    kw = self.Keywords
+                elif len(words) == 2:
+                    if words[0].upper() in ["CAL", "CALC", "CALNC"]:
+                        kw = self.Functions
+                    elif words[0].upper() in ["JMP", "JMPC", "JMPNC"]:
+                        kw = self.Jumps
+                    else:
+                        kw = self.Variables
+            else:
+                kw = self.Keywords + self.Variables + self.Functions
+            if len(kw) > 0:
+                kw.sort()
+                self.AutoCompSetIgnoreCase(True)
+                self.AutoCompShow(len(words[-1]), " ".join(kw))
         else:
             self.TextChanged = False
             wxCallAfter(self.RefreshModel)
             event.Skip()
 
+    def OnKillFocus(self, event):
+        self.AutoCompCancel()
+        event.Skip()
+
 
 #-------------------------------------------------------------------------------
 #                            Resource Editor class
--- a/graphics/LD_Objects.py	Tue Apr 10 18:02:40 2007 +0200
+++ b/graphics/LD_Objects.py	Wed Apr 11 17:26:07 2007 +0200
@@ -136,7 +136,8 @@
     # Refresh the position of wires connected to power rail
     def RefreshConnected(self, exclude = []):
         for connector in self.Connectors:
-            connector.MoveConnected(exclude)
+            if connector:
+                connector.MoveConnected(exclude)
     
     # Returns the power rail connector that starts with the point given if it exists 
     def GetConnector(self, position):