plcopen/plcopen.py
changeset 384 ed27a676d5c9
parent 383 25ffba02b6a8
child 387 fcae4e40f296
--- a/plcopen/plcopen.py	Fri Jul 24 10:47:35 2009 +0200
+++ b/plcopen/plcopen.py	Fri Jul 24 11:07:33 2009 +0200
@@ -45,8 +45,54 @@
 QualifierList = {"N" : False, "R" : False, "S" : False, "L" : True, "D" : True, 
     "P" : False, "P0" : False, "P1" : False, "SD" : True, "DS" : True, "SL" : True}
 
+
+def _init_and_compare(function, v1, v2):
+    if v1 is None:
+        return v2
+    if v2 is not None:
+        return function(v1, v2)
+    return v1
+
+"""
+Helper class for bounding_box calculation 
+"""
+class rect:
+    
+    def __init__(self, x=None, y=None, width=None, height=None):
+        self.x_min = x
+        self.x_max = None
+        self.y_min = y
+        self.y_max = None
+        if width is not None and x is not None:
+            self.x_max = x + width
+        if height is not None and y is not None:
+            self.y_max = y + height
+    
+    def update(self, x, y):
+        self.x_min = _init_and_compare(min, self.x_min, x)
+        self.x_max = _init_and_compare(max, self.x_max, x)
+        self.y_min = _init_and_compare(min, self.y_min, y)
+        self.y_max = _init_and_compare(max, self.y_max, y)
+        
+    def union(self, rect):
+        self.x_min = _init_and_compare(min, self.x_min, rect.x_min)
+        self.x_max = _init_and_compare(max, self.x_max, rect.x_max)
+        self.y_min = _init_and_compare(min, self.y_min, rect.y_min)
+        self.y_max = _init_and_compare(max, self.y_max, rect.y_max)
+    
+    def bounding_box(self):
+        width = height = None
+        if self.x_min is not None and self.x_max is not None:
+            width = self.x_max - self.x_min
+        if self.y_min is not None and self.y_max is not None:
+            height = self.y_max - self.y_min
+        return self.x_min, self.y_min, width, height
+            
+
 PLCOpenClasses = GenerateClassesFromXSD(os.path.join(os.path.split(__file__)[0], "TC6_XML_V10_B.xsd"))
 
+ElementNameToClass = {}
+
 cls = PLCOpenClasses.get("formattedText", None)
 if cls:
     def updateElementName(self, old_name, new_name):
@@ -1223,10 +1269,120 @@
 def sety(self, y):
     self.position.sety(y)
 
+def _getBoundingBox(self):
+    return rect(self.getx(), self.gety(), self.getwidth(), self.getheight())
+
+def _getConnectionsBoundingBox(connectionPointIn):
+    bbox = rect()
+    connections = connectionPointIn.getconnections()
+    if connections is not None:
+        for connection in connections:
+            for x, y in connection.getpoints():
+                bbox.update(x, y)
+    return bbox
+
+def _getBoundingBoxSingle(self):
+    bbox = _getBoundingBox(self)
+    if self.connectionPointIn is not None:
+        bbox.union(_getConnectionsBoundingBox(self.connectionPointIn))
+    return bbox
+
+def _getBoundingBoxMultiple(self):
+    bbox = _getBoundingBox(self)
+    for connectionPointIn in self.getconnectionPointIn():
+        bbox.union(_getConnectionsBoundingBox(connectionPointIn))
+    return bbox
+
+def _filterConnections(connectionPointIn, localId, connections):
+    in_connections = connectionPointIn.getconnections()
+    if in_connections is not None:
+        to_delete = []
+        for i, connection in enumerate(in_connections):
+            connected = connection.getrefLocalId()
+            if not connections.has_key((localId, connected)) and \
+               not connections.has_key((connected, localId)):
+                to_delete.append(i)
+        to_delete.reverse()
+        for i in to_delete:
+            connectionPointIn.removeconnection(i)
+
+def _filterConnectionsSingle(self, connections):
+    if self.connectionPointIn is not None:
+        _filterConnections(self.connectionPointIn, self.localId, connections)
+
+def _filterConnectionsMultiple(self, connections):
+    for connectionPointIn in self.getconnectionPointIn():
+        _filterConnections(connectionPointIn, self.localId, connections)
+
+def _getconnectionsdefinition(instance, connections_end):
+    id = instance.getlocalId()
+    return dict([((id, end), True) for end in connections_end])
+
+def _updateConnectionsId(connectionPointIn, translation):
+    connections_end = []
+    connections = connectionPointIn.getconnections()
+    if connections is not None:
+        for connection in connections:
+            refLocalId = connection.getrefLocalId()
+            new_reflocalId = translation.get(refLocalId, refLocalId)
+            connection.setrefLocalId(new_reflocalId)
+            connections_end.append(new_reflocalId)
+    return connections_end
+
+def _updateConnectionsIdSingle(self, translation):
+    connections_end = []
+    if self.connectionPointIn is not None:
+        connections_end = _updateConnectionsId(self.connectionPointIn, translation)
+    return _getconnectionsdefinition(self, connections_end)
+
+def _updateConnectionsIdMultiple(self, translation):
+    connections_end = []
+    for connectionPointIn in self.getconnectionPointIn():
+        connections_end.extend(_updateConnectionsId(connectionPointIn, translation))
+    return _getconnectionsdefinition(self, connections_end)
+
+def _translate(self, dx, dy):
+    self.setx(self.getx() + dx)
+    self.sety(self.gety() + dy)
+    
+def _translateConnections(connectionPointIn, dx, dy):
+    connections = connectionPointIn.getconnections()
+    if connections is not None:
+        for connection in connections:
+            for position in connection.getposition():
+                position.setx(position.getx() + dx)
+                position.sety(position.gety() + dy)
+
+def _translateSingle(self, dx, dy):
+    _translate(self, dx, dy)
+    if self.connectionPointIn is not None:
+        _translateConnections(self.connectionPointIn, dx, dy)
+
+def _translateMultiple(self, dx, dy):
+    _translate(self, dx, dy)
+    for connectionPointIn in self.getconnectionPointIn():
+        _translateConnections(connectionPointIn, dx, dy)
+
 def _updateElementName(self, old_name, new_name):
     pass
 
+_connectionsFunctions = {
+    "bbox": {"none": _getBoundingBox,
+             "single": _getBoundingBoxSingle,
+             "multiple": _getBoundingBoxMultiple},
+    "translate": {"none": _translate,
+               "single": _translateSingle,
+               "multiple": _translateMultiple},
+    "filter": {"none": lambda self, connections: None,
+               "single": _filterConnectionsSingle,
+               "multiple": _filterConnectionsMultiple},
+    "update": {"none": lambda self, translation: None,
+               "single": _updateConnectionsIdSingle,
+               "multiple": _updateConnectionsIdMultiple}
+}
+
 def _initElementClass(name, classname, connectionPointInType="none"):
+    ElementNameToClass[name] = classname
     cls = PLCOpenClasses.get(classname, None)
     if cls:
         setattr(cls, "getx", getx)
@@ -1234,6 +1390,10 @@
         setattr(cls, "setx", setx)
         setattr(cls, "sety", sety)
         setattr(cls, "updateElementName", _updateElementName)
+        setattr(cls, "getBoundingBox", _connectionsFunctions["bbox"][connectionPointInType])
+        setattr(cls, "translate", _connectionsFunctions["translate"][connectionPointInType])
+        setattr(cls, "filterConnections", _connectionsFunctions["filter"][connectionPointInType])
+        setattr(cls, "updateConnectionsId", _connectionsFunctions["update"][connectionPointInType])
     return cls
 
 def _getexecutionOrder(instance, specific_values):
@@ -1414,6 +1574,24 @@
             self.typeName = new_name
     setattr(cls, "updateElementName", updateElementName)
 
+    def filterConnections(self, connections):
+        for input in self.inputVariables.getvariable():
+            _filterConnections(input.connectionPointIn, self.localId, connections)
+    setattr(cls, "filterConnections", filterConnections)
+
+    def updateConnectionsId(self, translation):
+        connections_end = []
+        for input in self.inputVariables.getvariable():
+            connections_end.extend(_updateConnectionsId(input.connectionPointIn, translation))
+        return _getconnectionsdefinition(self, connections_end)
+    setattr(cls, "updateConnectionsId", updateConnectionsId)
+
+    def translate(self, dx, dy):
+        _translate(self, dx, dy)
+        for input in self.inputVariables.getvariable():
+            _translateConnections(input.connectionPointIn, dx, dy)
+    setattr(cls, "translate", translate)
+
 cls = _initElementClass("leftPowerRail", "ldObjects_leftPowerRail")
 if cls:
     setattr(cls, "getinfos", _getpowerrailinfosFunction("leftPowerRail"))