PLCControler.py
changeset 384 ed27a676d5c9
parent 383 25ffba02b6a8
child 385 373635372b93
--- a/PLCControler.py	Fri Jul 24 10:47:35 2009 +0200
+++ b/PLCControler.py	Fri Jul 24 11:07:33 2009 +0200
@@ -1580,6 +1580,148 @@
             return self.GetProjectPouVariables(words[1], debug)
         return []
 
+    def GetEditedElementCopy(self, tagname, debug = False):
+        element = self.GetEditedElement(tagname, debug)
+        if element is not None:
+            name = element.__class__.__name__
+            return element.generateXMLText(name.split("_")[-1], 0)
+        return ""
+        
+    def GetEditedElementInstancesCopy(self, tagname, blocks_id = None, wires = None, debug = False):
+        element = self.GetEditedElement(tagname, debug)
+        text = ""
+        if element is not None:
+            wires = dict([(wire, True) for wire in wires if wire[0] in blocks_id and wire[1] in blocks_id])
+            for id in blocks_id:
+                instance = element.getinstance(id)
+                if instance is not None:
+                    instance_copy = self.Copy(instance)
+                    instance_copy.filterConnections(wires)
+                    name = instance_copy.__class__.__name__
+                    text += instance_copy.generateXMLText(name.split("_")[-1], 0)
+        return text
+    
+    def GenerateNewName(self, tagname, name, format, exclude={}, debug=False):
+        names = exclude.copy()
+        names.update(dict([(varname.upper(), True) for varname in self.GetEditedElementVariables(tagname, debug)]))
+        element = self.GetEditedElement(tagname, debug)
+        if element is not None:
+            for instance in element.getinstances():
+                if isinstance(instance, (plcopen.sfcObjects_step, plcopen.commonObjects_connector, plcopen.commonObjects_continuation)):
+                    names[instance.getname()] = True
+        i = 1
+        while names.get(name.upper(), False):
+            name = (format%i)
+            i += 1
+        return name
+    
+    CheckPasteCompatibility = {"SFC": lambda name: True,
+                               "LD": lambda name: not name.startswith("sfcObjects"),
+                               "FBD": lambda name: name.startswith("fbdObjects") or name.startswith("commonObjects")}
+    
+    def PasteEditedElementInstances(self, tagname, text, new_pos, middle=False, debug=False):
+        element = self.GetEditedElement(tagname, debug)
+        element_name, element_type = self.GetEditedElementType(tagname, debug)
+        if element is not None:
+            bodytype = element.getbodyType()
+            
+            # Get edited element type scaling
+            scaling = None
+            project = self.GetProject(debug)
+            if project is not None:
+                properties = project.getcontentHeader()
+                scaling = properties["scaling"][bodytype]
+            
+            # Get ids already by all the instances in edited element
+            used_id = dict([(instance.getlocalId(), True) for instance in element.getinstances()])
+            new_id = {}
+            
+            text = "<paste>%s</paste>"%text
+            
+            try:
+                tree = minidom.parseString(text)
+            except:
+                return _("Invalid plcopen element(s)!!!")
+            instances = []
+            exclude = {}
+            for root in tree.childNodes:
+                if root.nodeType == tree.ELEMENT_NODE and root.nodeName == "paste":
+                    for child in root.childNodes:
+                        if child.nodeType == tree.ELEMENT_NODE:
+                            classname = plcopen.ElementNameToClass[child.nodeName]
+                            if not self.CheckPasteCompatibility[bodytype](classname):
+                                return _("\"%s\" element can't be paste here!!!")%child.nodeName
+                            classobj = getattr(plcopen, classname, None)
+                            if classobj is not None:
+                                instance = classobj()
+                                instance.loadXMLTree(child)
+                                if child.nodeName == "block":
+                                    blockname = instance.getinstanceName()
+                                    if blockname is not None:
+                                        blocktype = instance.gettypeName()
+                                        if element_type == "function":
+                                            return _("FunctionBlock \"%s\" can't be paste in a Function!!!")%blocktype
+                                        blockname = self.GenerateNewName(tagname, blockname, "Block%d", debug=debug)
+                                        exclude[blockname] = True
+                                        instance.setinstanceName(blockname)
+                                        self.AddEditedElementPouVar(tagname, blocktype, blockname)
+                                elif child.nodeName == "step":
+                                    stepname = self.GenerateNewName(tagname, instance.getname(), "Step%d", exclude, debug)
+                                    exclude[stepname] = True
+                                    instance.setname(stepname)
+                                localid = instance.getlocalId()
+                                if not used_id.has_key(localid):
+                                    new_id[localid] = True
+                                instances.append((child.nodeName, instance))
+            
+            if len(instances) == 0:
+                return _("Invalid plcopen element(s)!!!")
+            
+            idx = 1
+            translate_id = {}
+            bbox = plcopen.rect()
+            for name, instance in instances:
+                localId = instance.getlocalId()
+                bbox.union(instance.getBoundingBox())
+                if used_id.has_key(localId):
+                    while used_id.has_key(idx) or new_id.has_key(idx):
+                        idx += 1
+                    new_id[idx] = True
+                    instance.setlocalId(idx)
+                    translate_id[localId] = idx
+            
+            x, y, width, height = bbox.bounding_box()
+            if middle:
+                new_pos[0] -= width / 2
+                new_pos[1] -= height / 2
+            else:
+                new_pos = map(lambda x: x + 30, new_pos)
+            if scaling[0] != 0 and scaling[1] != 0:
+                min_pos = map(lambda x: 30 / x, scaling)
+                minx = round(min_pos[0])
+                if int(min_pos[0]) == round(min_pos[0]):
+                    minx += 1
+                miny = round(min_pos[1])
+                if int(min_pos[1]) == round(min_pos[1]):
+                    miny += 1
+                minx *= scaling[0]
+                miny *= scaling[1]
+                new_pos = (max(minx, round(new_pos[0] / scaling[0]) * scaling[0]),
+                           max(miny, round(new_pos[1] / scaling[1]) * scaling[1]))
+            else:
+                new_pos = (max(30, new_pos[0]), max(30, new_pos[1]))
+            diff = (new_pos[0] - x, new_pos[1] - y)
+            
+            connections = {}
+            for name, instance in instances:
+                connections.update(instance.updateConnectionsId(translate_id))
+                if getattr(instance, "setexecutionOrderId", None) is not None:
+                    instance.setexecutionOrderId(0)
+                instance.translate(*diff)
+                element.addinstance(name, instance)
+            
+            return new_id, connections
+                
     # Return the current pou editing informations
     def GetEditedElementInstanceInfos(self, tagname, id = None, exclude = [], debug = False):
         infos = {}