Adding support for automatically generate function blocks in interface when a block is added
authorlbessard
Thu, 09 Aug 2007 18:07:44 +0200
changeset 67 3a1b0afdaf84
parent 66 fd138fc77510
child 68 66308e07402c
Adding support for automatically generate function blocks in interface when a block is added
LDViewer.py
PLCControler.py
PLCOpenEditor.py
SFCViewer.py
Viewer.py
examples/example.xml
plcopen/plcopen.py
xmlclass/xmlclass.py
--- a/LDViewer.py	Thu Aug 09 18:06:54 2007 +0200
+++ b/LDViewer.py	Thu Aug 09 18:07:44 2007 +0200
@@ -179,9 +179,10 @@
         for i, rung in enumerate(self.Rungs):
             bbox = rung.GetBoundingBox()
             if i < len(self.RungComments):
-                pos = self.RungComments[i].GetPosition()
-                if pos[1] > bbox.y:
-                    self.RungComments.insert(i, None)
+                if self.RungComments[i]:
+                    pos = self.RungComments[i].GetPosition()
+                    if pos[1] > bbox.y:
+                        self.RungComments.insert(i, None)
             else:
                 self.RungComments.insert(i, None)
     
@@ -207,7 +208,8 @@
             for connector in element.GetConnectors():
                 for wire, num in connector.GetWires():
                     self.Rungs[rungs[0]].SelectElement(wire)
-            self.RefreshPosition(element)
+            if self.GetDrawingMode() != FREEDRAWING_MODE:
+                self.RefreshPosition(element)
         elif instance["type"] in ["contact", "coil"]:
             rungs = []
             for link in instance["connectors"]["input"]["links"]:
@@ -221,7 +223,8 @@
             self.Rungs[rungs[0]].SelectElement(element)
             for wire, num in element.GetConnectors()["input"].GetWires():
                 self.Rungs[rungs[0]].SelectElement(wire)
-            self.RefreshPosition(element)
+            if self.GetDrawingMode() != FREEDRAWING_MODE:
+                self.RefreshPosition(element)
         elif instance["type"] == "comment":
             element = self.FindElementById(instance["id"])
             pos = element.GetPosition()
--- a/PLCControler.py	Thu Aug 09 18:06:54 2007 +0200
+++ b/PLCControler.py	Thu Aug 09 18:07:44 2007 +0200
@@ -24,6 +24,7 @@
 
 from minixsv import pyxsval
 from xml.dom import minidom
+from types import StringType, UnicodeType
 import cPickle
 import os,sys,re
 from datetime import *
@@ -382,15 +383,15 @@
 
     def GenerateProgram(self, filepath):
         if self.Project:
-            try:
-                program = GenerateCurrentProgram(self.Project)
-                programfile = open(filepath, "w")
-                programfile.write(program)
-                programfile.close()
-                self.ProgramFilePath = filepath
-                return True
-            except:
-                pass
+            #try:
+            program = GenerateCurrentProgram(self.Project)
+            programfile = open(filepath, "w")
+            programfile.write(program)
+            programfile.close()
+            self.ProgramFilePath = filepath
+            return True
+            #except:
+            #    pass
         return False
 
 #-------------------------------------------------------------------------------
@@ -626,7 +627,12 @@
             tempvar = plcopen.varListPlain_variable()
             tempvar.setName(var["Name"])
             var_type = plcopen.dataType()
-            var_type.setValue(var["Type"])
+            if GetBlockType(var["Type"]) != None:
+                derived_type = plcopen.derived()
+                derived_type.setName(var["Type"])
+                var_type.setValue(derived_type)
+            else:
+                var_type.setValue(var["Type"])
             tempvar.setType(var_type)
             if var["Initial Value"] != "":
                 value = plcopen.value()
@@ -660,7 +666,12 @@
             # Extract variables from every varLists
             for varlist in configuration.getGlobalVars():
                 for var in varlist.getVariable():
-                    tempvar = {"Name":var.getName(),"Class":"Global","Type":var.getType().getValue()}
+                    tempvar = {"Name":var.getName(),"Class":"Global"}
+                    var_type = var.getType().getValue()
+                    if isinstance(var_type, (StringType, UnicodeType)):
+                        tempvar["Type"] = var_type
+                    else:
+                        tempvar["Type"] = var_type.getName()
                     initial = var.getInitialValue()
                     if initial:
                         tempvar["Initial Value"] = initial.getValue()
@@ -702,7 +713,12 @@
             # Extract variables from every varLists
             for varlist in resource.getGlobalVars():
                 for var in varlist.getVariable():
-                    tempvar = {"Name":var.getName(),"Class":"Global","Type":var.getType().getValue()}
+                    tempvar = {"Name":var.getName(),"Class":"Global"}
+                    var_type = var.getType().getValue()
+                    if isinstance(var_type, (StringType, UnicodeType)):
+                        tempvar["Type"] = var_type
+                    else:
+                        tempvar["Type"] = var_type.getName()
                     initial = var.getInitialValue()
                     if initial:
                         tempvar["Initial Value"] = initial.getValue()
@@ -737,7 +753,12 @@
             # Extract variables from every varLists
             for type, varlist in pou.getVars():
                 for var in varlist.getVariable():
-                    tempvar = {"Name":var.getName(),"Class":type,"Type":var.getType().getValue()}
+                    tempvar = {"Name":var.getName(),"Class":type}
+                    var_type = var.getType().getValue()
+                    if isinstance(var_type, (StringType, UnicodeType)):
+                        tempvar["Type"] = var_type
+                    else:
+                        tempvar["Type"] = var_type.getName()
                     initial = var.getInitialValue()
                     if initial:
                         tempvar["Initial Value"] = initial.getValue()
@@ -1418,10 +1439,24 @@
                     connection.setConnectionParameter(idx, None)
                 idx += 1
     
-    def AddCurrentElementEditingBlock(self, id):
+    def AddCurrentElementEditingBlock(self, id, blocktype, blockname = None):
         block = plcopen.block()
         block.setLocalId(id)
-        self.GetCurrentElementEditing().addInstance("block", block)
+        block.setTypeName(blocktype)
+        if blockname:
+            block.setInstanceName(blockname)
+        element = self.GetCurrentElementEditing()
+        blocktype_infos = GetBlockType(blocktype)
+        if blocktype_infos["type"] != "function":
+            if self.CurrentElementEditing != None:
+                name = self.ElementsOpened[self.CurrentElementEditing]
+                words = name.split("::")
+                if len(words) == 1:
+                    element.addPouVar(blocktype, blockname)
+                elif words[0] in ['T', 'A']:
+                    pou = self.Project.getPou(words[1])
+                    pou.addPouVar(blocktype, blockname)    
+        element.addInstance("block", block)
         self.RefreshPouUsingTree()
     
     def SetCurrentElementEditingBlockInfos(self, id, infos):
@@ -1888,7 +1923,21 @@
                 self.SetConnectionWires(actionBlock.connectionPointIn, value)
     
     def RemoveCurrentElementEditingInstance(self, id):
-        self.GetCurrentElementEditing().removeInstance(id)
+        element = self.GetCurrentElementEditing()
+        instance = element.getInstance(id)
+        if isinstance(instance, plcopen.block):
+            blocktype = instance.getTypeName()
+            blocktype_infos = GetBlockType(blocktype)
+            if blocktype_infos["type"] != "function":
+                if self.CurrentElementEditing != None:
+                    name = self.ElementsOpened[self.CurrentElementEditing]
+                    words = name.split("::")
+                    if len(words) == 1:
+                        element.removePouVar(blocktype, instance.getInstanceName())
+                    elif words[0] in ['T', 'A']:
+                        pou = self.Project.getPou(words[1])
+                        pou.removePouVar(blocktype, instance.getInstanceName())    
+        element.removeInstance(id)
         self.RefreshPouUsingTree()
 
     def GetCurrentResourceEditingVariables(self):
--- a/PLCOpenEditor.py	Thu Aug 09 18:06:54 2007 +0200
+++ b/PLCOpenEditor.py	Thu Aug 09 18:07:44 2007 +0200
@@ -412,7 +412,7 @@
         else:
             self.Controler = controler
         
-        if fileOpen:
+        if self.ModeSolo and fileOpen:
             self.Controler.OpenXMLFile(fileOpen)
             self.RefreshProjectTree()
         
@@ -485,6 +485,11 @@
                 self.EditMenu.FindItemByPosition(5).Enable(False)
             self.EditMenu.FindItemByPosition(6).Enable(False)
 
+    def RefreshEditor(self):
+        selected = self.TabsOpened.GetSelection()
+        if selected != -1:
+            self.TabsOpened.GetPage(selected).RefreshView()
+
     def ShowProperties(self):
         old_values = self.Controler.GetProjectProperties()
         dialog = ProjectDialog(self)
@@ -585,6 +590,10 @@
                     message = wx.MessageDialog(self, "Can't generate program to file %s!"%filepath, "Error", wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
+                else:
+                    message = wx.MessageDialog(self, "Program was successfully generated!", "Done", wx.OK|wx.ICON_INFORMATION)
+                    message.ShowModal()
+                    message.Destroy()
             else:
                 message = wx.MessageDialog(self, "%s is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
@@ -2434,7 +2443,7 @@
         self.RefreshValues()
         self.RefreshButtons()
         self.Viewer.RefreshView()
-        
+    
     def OnClassFilter(self, event):
         self.Filter = self.FilterChoiceTransfer[self.ClassFilter.GetStringSelection()]
         self.RefreshTypeList()
--- a/SFCViewer.py	Thu Aug 09 18:06:54 2007 +0200
+++ b/SFCViewer.py	Thu Aug 09 18:07:44 2007 +0200
@@ -325,6 +325,7 @@
                 self.Scroll(max(0, xpos - 1), ypos)
             elif self.SelectedElement:
                 self.SelectedElement.Move(-scaling[0], 0)
+                self.SelectedElement.RefreshModel()
                 self.RefreshBuffer()
                 self.RefreshScrollBars()
                 self.Refresh()
@@ -335,6 +336,7 @@
                 self.Scroll(min(xpos + 1, xmax), ypos)
             elif self.SelectedElement:
                 self.SelectedElement.Move(scaling[0], 0)
+                self.SelectedElement.RefreshModel()
                 self.RefreshBuffer()
                 self.RefreshScrollBars()
                 self.Refresh()
@@ -345,6 +347,7 @@
                 self.Scroll(xpos, max(0, ypos - 1))
             elif self.SelectedElement:
                 self.SelectedElement.Move(0, -scaling[1])
+                self.SelectedElement.RefreshModel()
                 self.RefreshBuffer()
                 self.RefreshScrollBars()
                 self.Refresh()
@@ -355,6 +358,7 @@
                 self.Scroll(xpos, min(ypos + 1, ymax))
             elif self.SelectedElement:
                 self.SelectedElement.Move(0, scaling[1])
+                self.SelectedElement.RefreshModel()
                 self.RefreshBuffer()
                 self.RefreshScrollBars()
                 self.Refresh()
--- a/Viewer.py	Thu Aug 09 18:06:54 2007 +0200
+++ b/Viewer.py	Thu Aug 09 18:07:44 2007 +0200
@@ -832,7 +832,7 @@
                 elif self.Mode == MODE_CONTACT:
                     wx.CallAfter(self.AddNewContact, bbox)
                 elif self.Mode == MODE_COIL:
-                    wx.CallAfter(self.AddNewContact, bbox)
+                    wx.CallAfter(self.AddNewCoil, bbox)
                 elif self.Mode == MODE_POWERRAIL:
                     wx.CallAfter(self.AddNewPowerRail, bbox)
                 elif self.Mode == MODE_INITIALSTEP:
@@ -948,6 +948,7 @@
                 self.Scroll(max(0, xpos - 1), ypos)
             elif self.SelectedElement:
                 self.SelectedElement.Move(-scaling[0], 0)
+                self.SelectedElement.RefreshModel()
                 self.RefreshBuffer()
                 self.RefreshScrollBars()
                 self.Refresh()
@@ -958,6 +959,7 @@
                 self.Scroll(min(xpos + 1, xmax), ypos)
             elif self.SelectedElement:
                 self.SelectedElement.Move(scaling[0], 0)
+                self.SelectedElement.RefreshModel()
                 self.RefreshBuffer()
                 self.RefreshScrollBars()
                 self.Refresh()
@@ -968,6 +970,7 @@
                 self.Scroll(xpos, max(0, ypos - 1))
             elif self.SelectedElement:
                 self.SelectedElement.Move(0, -scaling[1])
+                self.SelectedElement.RefreshModel()
                 self.RefreshBuffer()
                 self.RefreshScrollBars()
                 self.Refresh()
@@ -978,6 +981,7 @@
                 self.Scroll(xpos, min(ypos + 1, ymax))
             elif self.SelectedElement:
                 self.SelectedElement.Move(0, scaling[1])
+                self.SelectedElement.RefreshModel()
                 self.RefreshBuffer()
                 self.RefreshScrollBars()
                 self.Refresh()
@@ -1000,10 +1004,11 @@
             block.SetPosition(bbox.x, bbox.y)
             block.SetSize(values["width"], values["height"])
             self.AddBlock(block)
-            self.Controler.AddCurrentElementEditingBlock(id)
+            self.Controler.AddCurrentElementEditingBlock(id, values["type"], values.get("name", None))
             self.RefreshBlockModel(block)
             self.RefreshBuffer()
             self.RefreshScrollBars()
+            self.Parent.RefreshEditor()
             self.Refresh()
         dialog.Destroy()
     
@@ -1114,7 +1119,7 @@
             coil.SetSize(values["width"], values["height"])
             self.AddBlock(coil)
             self.Controler.AddCurrentElementEditingCoil(id)
-            self.RefreshCoilModel(contact)
+            self.RefreshCoilModel(coil)
             self.RefreshBuffer()
             self.RefreshScrollBars()
             self.Refresh()
@@ -1492,6 +1497,7 @@
         self.Controler.RemoveCurrentElementEditingInstance(block.GetId())
         for element in elements:
             element.RefreshModel()
+        wx.CallAfter(self.Parent.RefreshEditor)
 
     def DeleteVariable(self, variable):
         connectors = variable.GetConnectors()
--- a/examples/example.xml	Thu Aug 09 18:06:54 2007 +0200
+++ b/examples/example.xml	Thu Aug 09 18:07:44 2007 +0200
@@ -55,6 +55,13 @@
               </type>
             </variable>
           </outputVars>
+          <localVars>
+            <variable name="SR1">
+              <type>
+                <derived name="SR"/>
+              </type>
+            </variable>
+          </localVars>
         </interface>
         <body>
           <FBD>
@@ -78,15 +85,15 @@
                 <relPosition y="16" x="0"/>
                 <connection refLocalId="11" formalParameter="Q1">
                   <position y="198" x="587"/>
-                  <position y="198" x="517"/>
+                  <position y="198" x="523"/>
                 </connection>
               </connectionPointIn>
               <expression>OUT</expression>
             </outVariable>
-            <block localId="6" height="84" width="99" typeName="AND">
+            <block localId="6" height="84" width="99" instanceName="" typeName="AND">
               <position y="105" x="235"/>
               <inputVariables>
-                <variable formalParameter="" edge="rising">
+                <variable formalParameter="IN1" edge="rising">
                   <connectionPointIn>
                     <relPosition y="36" x="0"/>
                     <connection refLocalId="2">
@@ -97,7 +104,7 @@
                     </connection>
                   </connectionPointIn>
                 </variable>
-                <variable formalParameter="">
+                <variable formalParameter="IN2">
                   <connectionPointIn>
                     <relPosition y="68" x="0"/>
                     <connection refLocalId="3">
@@ -111,7 +118,7 @@
               </inputVariables>
               <inOutVariables/>
               <outputVariables>
-                <variable formalParameter="" negated="true">
+                <variable formalParameter="OUT" negated="true">
                   <connectionPointOut>
                     <relPosition y="36" x="99"/>
                   </connectionPointOut>
@@ -125,7 +132,7 @@
               </connectionPointOut>
               <expression>IN3</expression>
             </inVariable>
-            <block localId="8" height="87" width="99" typeName="OR">
+            <block localId="8" height="87" width="99" instanceName="" typeName="OR">
               <position y="246" x="235"/>
               <inputVariables>
                 <variable formalParameter="IN1" negated="true">
@@ -162,29 +169,29 @@
             </block>
             <comment localId="10" height="37" width="261">
               <position y="32" x="243"/>
-              <content>POU qui sert a tester PLCOpenEditor.</content>
+              <content><![CDATA[POU used for testing PLCOpenEditor.]]></content>
             </comment>
-            <block localId="11" height="91" width="97" instanceName="SR1" typeName="SR">
-              <position y="161" x="420"/>
+            <block localId="11" height="97" width="105" instanceName="SR1" typeName="SR">
+              <position y="159" x="418"/>
               <inputVariables>
                 <variable formalParameter="S1">
                   <connectionPointIn>
-                    <relPosition y="37" x="0"/>
+                    <relPosition y="39" x="0"/>
                     <connection refLocalId="6" formalParameter="OUT">
-                      <position y="198" x="420"/>
-                      <position y="198" x="369"/>
-                      <position y="141" x="369"/>
+                      <position y="198" x="418"/>
+                      <position y="198" x="376"/>
+                      <position y="141" x="376"/>
                       <position y="141" x="334"/>
                     </connection>
                   </connectionPointIn>
                 </variable>
                 <variable formalParameter="R">
                   <connectionPointIn>
-                    <relPosition y="72" x="0"/>
+                    <relPosition y="77" x="0"/>
                     <connection refLocalId="8" formalParameter="OUT">
-                      <position y="233" x="420"/>
-                      <position y="233" x="369"/>
-                      <position y="282" x="369"/>
+                      <position y="236" x="418"/>
+                      <position y="236" x="376"/>
+                      <position y="282" x="376"/>
                       <position y="282" x="334"/>
                     </connection>
                   </connectionPointIn>
@@ -194,7 +201,7 @@
               <outputVariables>
                 <variable formalParameter="Q1">
                   <connectionPointOut>
-                    <relPosition y="37" x="97"/>
+                    <relPosition y="39" x="105"/>
                   </connectionPointOut>
                 </variable>
               </outputVariables>
@@ -234,7 +241,7 @@
           <LD>
             <comment localId="1" height="40" width="600">
               <position y="10" x="10"/>
-              <content>Commentaire</content>
+              <content><![CDATA[Comment]]></content>
             </comment>
             <leftPowerRail localId="2" height="80" width="2">
               <position y="60" x="10"/>
@@ -385,6 +392,7 @@
         </interface>
         <body>
           <IL>
+<![CDATA[
      LD   Y1
      SUB  Y2     (* Substract Y2 from Y1 *)
      ST   Temp   (* Store Y1-Y2 in Temp *)
@@ -401,6 +409,7 @@
      S    ERROR  (* Set ERROR *)
      RET         (* Normal return *)
 ERR: RET         (* Error return, ENO not set *)
+]]>
           </IL>
         </body>
       </pou>
@@ -438,11 +447,13 @@
           <action name="ACT1">
             <body>
               <ST>
+<![CDATA[
 IF IN1 THEN
   IN2 := 1;
 ELSE
   IN3 := 1;
 END_IF;
+]]>
               </ST>
             </body>
           </action>
@@ -450,7 +461,156 @@
         <transitions>
           <transition name="TR1">
             <body>
-              <ST>:= AND(IN1, IN2, IN3);</ST>
+              <ST><![CDATA[:= AND(IN1, IN2, IN3);]]></ST>
+            </body>
+          </transition>
+          <transition name="TR2">
+            <body>
+              <FBD>
+                <block localId="1" height="82" width="107" typeName="AND">
+                  <position y="61" x="160"/>
+                  <inputVariables>
+                    <variable formalParameter="IN1">
+                      <connectionPointIn>
+                        <relPosition y="35" x="0"/>
+                        <connection refLocalId="2">
+                          <position y="96" x="160"/>
+                          <position y="96" x="120"/>
+                          <position y="72" x="120"/>
+                          <position y="72" x="81"/>
+                        </connection>
+                      </connectionPointIn>
+                    </variable>
+                    <variable formalParameter="IN2">
+                      <connectionPointIn>
+                        <relPosition y="66" x="0"/>
+                        <connection refLocalId="3">
+                          <position y="127" x="160"/>
+                          <position y="127" x="120"/>
+                          <position y="153" x="120"/>
+                          <position y="153" x="81"/>
+                        </connection>
+                      </connectionPointIn>
+                    </variable>
+                  </inputVariables>
+                  <inOutVariables/>
+                  <outputVariables>
+                    <variable formalParameter="OUT">
+                      <connectionPointOut>
+                        <relPosition y="35" x="107"/>
+                      </connectionPointOut>
+                    </variable>
+                  </outputVariables>
+                </block>
+                <inVariable localId="2" width="54" height="27">
+                  <position y="59" x="27"/>
+                  <connectionPointOut>
+                    <relPosition y="13" x="54"/>
+                  </connectionPointOut>
+                  <expression>IN1</expression>
+                </inVariable>
+                <inVariable localId="3" width="53" height="27">
+                  <position y="140" x="28"/>
+                  <connectionPointOut>
+                    <relPosition y="13" x="53"/>
+                  </connectionPointOut>
+                  <expression>IN2</expression>
+                </inVariable>
+                <outVariable localId="4" width="57" height="27">
+                  <position y="83" x="351"/>
+                  <connectionPointIn>
+                    <relPosition y="13" x="0"/>
+                    <connection refLocalId="1" formalParameter="OUT">
+                      <position y="96" x="351"/>
+                      <position y="96" x="267"/>
+                    </connection>
+                  </connectionPointIn>
+                  <expression>TR2</expression>
+                </outVariable>
+              </FBD>
+            </body>
+          </transition>
+          <transition name="TR3">
+            <body>
+              <LD>
+                <leftPowerRail localId="1" height="98" width="2">
+                  <position y="20" x="31"/>
+                  <connectionPointOut formalParameter="">
+                    <relPosition y="20" x="2"/>
+                  </connectionPointOut>
+                  <connectionPointOut formalParameter="">
+                    <relPosition y="64" x="2"/>
+                  </connectionPointOut>
+                </leftPowerRail>
+                <contact localId="2" width="21" height="15" edge="none" negated="false">
+                  <position y="32" x="72"/>
+                  <connectionPointIn>
+                    <relPosition y="8" x="0"/>
+                    <connection refLocalId="1">
+                      <position y="40" x="72"/>
+                      <position y="40" x="33"/>
+                    </connection>
+                  </connectionPointIn>
+                  <connectionPointOut>
+                    <relPosition y="8" x="21"/>
+                  </connectionPointOut>
+                  <variable>IN2</variable>
+                </contact>
+                <contact localId="3" width="21" height="15" edge="rising" negated="false">
+                  <position y="76" x="72"/>
+                  <connectionPointIn>
+                    <relPosition y="8" x="0"/>
+                    <connection refLocalId="1">
+                      <position y="84" x="72"/>
+                      <position y="84" x="33"/>
+                    </connection>
+                  </connectionPointIn>
+                  <connectionPointOut>
+                    <relPosition y="8" x="21"/>
+                  </connectionPointOut>
+                  <variable>IN5</variable>
+                </contact>
+                <coil localId="4" width="21" storage="none" height="15" negated="true">
+                  <position y="32" x="208"/>
+                  <connectionPointIn>
+                    <relPosition y="8" x="0"/>
+                    <connection refLocalId="2">
+                      <position y="40" x="208"/>
+                      <position y="40" x="93"/>
+                    </connection>
+                    <connection refLocalId="3">
+                      <position y="40" x="208"/>
+                      <position y="40" x="131"/>
+                      <position y="84" x="131"/>
+                      <position y="84" x="93"/>
+                    </connection>
+                  </connectionPointIn>
+                  <connectionPointOut>
+                    <relPosition y="8" x="21"/>
+                  </connectionPointOut>
+                  <variable>TR3</variable>
+                </coil>
+                <rightPowerRail localId="5" height="40" width="2">
+                  <position y="19" x="271"/>
+                  <connectionPointIn>
+                    <relPosition y="21" x="0"/>
+                    <connection refLocalId="4">
+                      <position y="40" x="271"/>
+                      <position y="40" x="229"/>
+                    </connection>
+                  </connectionPointIn>
+                </rightPowerRail>
+              </LD>
+            </body>
+          </transition>
+          <transition name="TR4">
+            <body>
+              <IL>
+<![CDATA[
+    LD  IN3
+    AND IN4
+]]>
+              </IL>
             </body>
           </transition>
         </transitions>
@@ -527,7 +687,7 @@
               </connectionPointOut>
               <condition>
                 <inline name="">
-                  <ST>IN2 AND IN3</ST>
+                  <ST><![CDATA[IN2 AND IN3]]></ST>
                 </inline>
               </condition>
             </transition>
@@ -557,9 +717,7 @@
                 <relPosition y="2" x="10"/>
               </connectionPointOut>
               <condition>
-                <inline name="">
-                  <ST>IN3</ST>
-                </inline>
+                <reference name="TR2"/>
               </condition>
             </transition>
             <step localId="8" height="27" width="48" initialStep="false" name="Step2">
@@ -588,9 +746,7 @@
                 <relPosition y="2" x="10"/>
               </connectionPointOut>
               <condition>
-                <inline name="">
-                  <ST>IN4</ST>
-                </inline>
+                <reference name="TR4"/>
               </condition>
             </transition>
             <step localId="10" height="27" width="48" initialStep="false" name="Step3">
@@ -622,9 +778,7 @@
                 <relPosition y="2" x="10"/>
               </connectionPointOut>
               <condition>
-                <inline name="">
-                  <ST>IN5</ST>
-                </inline>
+                <reference name="TR3"/>
               </condition>
             </transition>
             <jumpStep localId="12" height="13" width="12" targetName="Start">
@@ -664,7 +818,7 @@
               </connectionPointOut>
               <condition>
                 <inline name="">
-                  <ST>IN5</ST>
+                  <ST><![CDATA[IN5]]></ST>
                 </inline>
               </condition>
             </transition>
@@ -682,7 +836,7 @@
               </connectionPointOut>
               <condition>
                 <inline name="">
-                  <ST>IN5</ST>
+                  <ST><![CDATA[IN5]]></ST>
                 </inline>
               </condition>
             </transition>
@@ -733,7 +887,7 @@
               </action>
               <action qualifier="P">
                 <inline>
-                  <ST>IN2 := TRUE;</ST>
+                  <ST><![CDATA[IN2 := TRUE;]]></ST>
                 </inline>
               </action>
             </actionBlock>
@@ -838,6 +992,7 @@
         </interface>
         <body>
           <ST>
+<![CDATA[
 IF Collision THEN
   Speed := 0;
   Brakes := TRUE;
@@ -851,6 +1006,7 @@
 
   PumpSpeed := 10.0;
 END_IF;
+]]>
           </ST>
         </body>
       </pou>
--- a/plcopen/plcopen.py	Thu Aug 09 18:06:54 2007 +0200
+++ b/plcopen/plcopen.py	Thu Aug 09 18:07:44 2007 +0200
@@ -23,6 +23,7 @@
 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 from xmlclass import *
+from types import *
 import os, sys
 
 """
@@ -52,8 +53,8 @@
 GenerateClassesFromXSD(os.path.join(base_folder, "plcopen/TC6_XML_V10_B.xsd"))
 CreateClasses(PLCOpenClasses, PLCOpenTypes)
 
-if "dataType" in PLCOpenClasses:
-    cls = PLCOpenClasses["dataType"]
+cls = PLCOpenClasses.get("dataType", None)
+if cls:
     cls.value = None
     
     def getValue(self):
@@ -65,20 +66,28 @@
     setattr(cls, "setValue", setValue)
     
     def loadXMLTree(self, tree):
-        self.value = tree.childNodes[1].nodeName
+        node = tree.childNodes[1]
+        if node.nodeName == "derived":
+            self.value = PLCOpenClasses["derived"]()
+            self.value.loadXMLTree(node)
+        else:
+            self.value = node.nodeName
     setattr(cls, "loadXMLTree", loadXMLTree)
     
     def generateXMLText(self, name, indent, extras = {}):
         ind1, ind2 = getIndent(indent, name)
         text = ind1 + "<%s>\n"%name
-        ind3, ind4 = getIndent(indent + 1, self.value)
-        text += ind3 + "<%s/>\n"%self.value
+        if isinstance(self.value, (StringType, UnicodeType)):
+            ind3, ind4 = getIndent(indent + 1, self.value)
+            text += ind3 + "<%s/>\n"%self.value
+        else:
+            text += self.value.generateXMLText("derived", indent + 1)
         text += ind1 + "</%s>\n"%name
         return text
     setattr(cls, "generateXMLText", generateXMLText)
 
-if "formattedText" in PLCOpenClasses:
-    cls = PLCOpenClasses["formattedText"]
+cls = PLCOpenClasses.get("formattedText", None)
+if cls:
     cls.text = ""
     
     def getText(self):
@@ -98,12 +107,12 @@
     def generateXMLText(self, name, indent, extras = {}):
         ind1, ind2 = getIndent(indent, name)
         if len(self.text.splitlines()) > 1:
-            text = ind1 + "<%s>\n"%name
+            text = ind1 + "<%s>\n<![CDATA[\n"%name
             text += "%s\n"%self.text
-            text += ind1 + "</%s>\n"%name
+            text += "]]>\n" + ind1 + "</%s>\n"%name
             return text
         else:
-            return ind1 + "<%s>%s</%s>\n"%(name, self.text, name)
+            return ind1 + "<%s><![CDATA[%s]]></%s>\n"%(name, self.text, name)
     setattr(cls, "generateXMLText", generateXMLText)
     
     def updateElementName(self, old_name, new_name):
@@ -118,8 +127,8 @@
                 index = self.text.find(old_name, index + len(new_name))
     setattr(cls, "updateElementName", updateElementName)
     
-if "project" in PLCOpenClasses:
-    cls = PLCOpenClasses["project"]
+cls = PLCOpenClasses.get("project", None)
+if cls:
     cls.singleLineAttributes = False
     
     def getFileHeader(self):
@@ -252,20 +261,20 @@
             configuration.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
-PLCOpenClasses["project_fileHeader"].singleLineAttributes = False
-
-if "configurations_configuration" in PLCOpenClasses:
-    cls = PLCOpenClasses["configurations_configuration"]
-    
+cls = PLCOpenClasses.get("project_fileHeader", None)
+if cls:
+    cls.singleLineAttributes = False
+
+cls = PLCOpenClasses.get("configurations_configuration", None)
+if cls:
     def updateElementName(self, old_name, new_name):
         for resource in self.getResource():
             resource.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
 
-if "configuration_resource" in PLCOpenClasses:
-    cls = PLCOpenClasses["configuration_resource"]
-    
+cls = PLCOpenClasses.get("configuration_resource", None)
+if cls:
     def updateElementName(self, old_name, new_name):
         for instance in self.getPouInstance():
             instance.updateElementName(old_name, new_name)
@@ -273,9 +282,8 @@
             task.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
-if "resource_task" in PLCOpenClasses:
-    cls = PLCOpenClasses["resource_task"]
-    
+cls = PLCOpenClasses.get("resource_task", None)
+if cls:
     def updateElementName(self, old_name, new_name):
         if self.single == old_name:
             self.single = new_name
@@ -283,17 +291,15 @@
             instance.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
-if "pouInstance" in PLCOpenClasses:
-    cls = PLCOpenClasses["pouInstance"]
-    
+cls = PLCOpenClasses.get("pouInstance", None)
+if cls:
     def updateElementName(self, old_name, new_name):
         if self.type == old_name:
             self.type = new_name
     setattr(cls, "updateElementName", updateElementName)
 
-if "project_types" in PLCOpenClasses:
-    cls = PLCOpenClasses["project_types"]
-
+cls = PLCOpenClasses.get("project_types", None)
+if cls:
     def getPouElements(self):
         return self.pous.getPou()
     setattr(cls, "getPouElements", getPouElements)
@@ -375,9 +381,8 @@
     return self.body.getText()
 setattr(cls, "getText", getText)
 
-if "pous_pou" in PLCOpenClasses:
-    cls = PLCOpenClasses["pous_pou"]
-
+cls = PLCOpenClasses.get("pous_pou", None)
+if cls:
     setattr(cls, "setBodyType", setBodyType)
     setattr(cls, "getBodyType", getBodyType)
     setattr(cls, "addInstance", addInstance)
@@ -405,6 +410,35 @@
             self.interface.appendContent(VarTypes[vartype], varlist)
     setattr(cls, "setVars", setVars)
     
+    def addPouVar(self, type, name):
+        content = self.interface.getContent()
+        if len(content) == 0 or content[-1]["name"] != "localVars":
+            self.interface.appendContent("localVars", PLCOpenClasses["varList"]())
+        var = PLCOpenClasses["varListPlain_variable"]()
+        var.setName(name)
+        var_type = PLCOpenClasses["dataType"]()
+        derived_type = PLCOpenClasses["derived"]()
+        derived_type.setName(type)
+        var_type.setValue(derived_type)
+        var.setType(var_type)
+        content[-1]["value"].appendVariable(var)
+    setattr(cls, "addPouVar", addPouVar)
+    
+    def removePouVar(self, type, name):
+        content = self.interface.getContent()
+        for varlist in content:
+            variables = varlist["value"].getVariable()
+            for var in variables:
+                if var.getName() == name:
+                    var_type = var.getType().getValue()
+                    if isinstance(var_type, PLCOpenClasses["derived"]) and var_type.getName() == type:
+                        variables.remove(var)
+                        break
+            if len(varlist["value"].getVariable()) == 0:
+                content.remove(varlist)
+                break
+    setattr(cls, "removePouVar", removePouVar)
+        
     def addTransition(self, name, type):
         if not self.transitions:
             self.addTransitions()
@@ -489,9 +523,8 @@
             transition.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
-if "transitions_transition" in PLCOpenClasses:
-    cls = PLCOpenClasses["transitions_transition"]
-
+cls = PLCOpenClasses.get("transitions_transition", None)
+if cls:
     setattr(cls, "setBodyType", setBodyType)
     setattr(cls, "getBodyType", getBodyType)
     setattr(cls, "addInstance", addInstance)
@@ -507,9 +540,8 @@
         self.body.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
-if "actions_action" in PLCOpenClasses:
-    cls = PLCOpenClasses["actions_action"]
-
+cls = PLCOpenClasses.get("actions_action", None)
+if cls:
     setattr(cls, "setBodyType", setBodyType)
     setattr(cls, "getBodyType", getBodyType)
     setattr(cls, "addInstance", addInstance)
@@ -525,9 +557,8 @@
         self.body.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
-if "body" in PLCOpenClasses:
-    cls = PLCOpenClasses["body"]
-    
+cls = PLCOpenClasses.get("body", None)
+if cls:
     def appendContentInstance(self, name, instance):
         if self.content["name"] in ["LD","FBD","SFC"]:
             self.content["value"].appendContent(name, instance)
@@ -624,8 +655,8 @@
 def setY(self, y):
     self.position.setY(y)
 
-if "comment" in PLCOpenClasses:
-    cls = PLCOpenClasses["comment"]
+cls = PLCOpenClasses.get("comment", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -643,8 +674,8 @@
         self.content.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
-if "block" in PLCOpenClasses:
-    cls = PLCOpenClasses["block"]
+cls = PLCOpenClasses.get("block", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -655,9 +686,8 @@
             self.typeName = new_name
     setattr(cls, "updateElementName", updateElementName)
 
-if "inputVariables_variable" in PLCOpenClasses:
-    cls = PLCOpenClasses["inputVariables_variable"]
-
+cls = PLCOpenClasses.get("inputVariables_variable", None)
+if cls:
     def setConnectorEdge(self, edge):
         if not self.edge:
             self.edge = PLCOpenClasses["edgeModifierType"]()
@@ -670,9 +700,8 @@
         return None
     setattr(cls, "getConnectorEdge", getConnectorEdge)
 
-if "outputVariables_variable" in PLCOpenClasses:
-    cls = PLCOpenClasses["outputVariables_variable"]
-    
+cls = PLCOpenClasses.get("outputVariables_variable", None)
+if cls:
     def setConnectorEdge(self, edge):
         if not self.edge:
             self.edge = PLCOpenClasses["edgeModifierType"]()
@@ -685,8 +714,8 @@
         return None
     setattr(cls, "getConnectorEdge", getConnectorEdge)
 
-if "leftPowerRail" in PLCOpenClasses:
-    cls = PLCOpenClasses["leftPowerRail"]
+cls = PLCOpenClasses.get("leftPowerRail", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -696,8 +725,19 @@
         pass
     setattr(cls, "updateElementName", updateElementName)
 
-if "contact" in PLCOpenClasses:
-    cls = PLCOpenClasses["contact"]
+cls = PLCOpenClasses.get("rightPowerRail", None)
+if cls:
+    setattr(cls, "getX", getX)
+    setattr(cls, "getY", getY)
+    setattr(cls, "setX", setX)
+    setattr(cls, "setY", setY)
+    
+    def updateElementName(self, old_name, new_name):
+        pass
+    setattr(cls, "updateElementName", updateElementName)
+
+cls = PLCOpenClasses.get("contact", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -720,8 +760,8 @@
             self.variable = new_name
     setattr(cls, "updateElementName", updateElementName)
 
-if "coil" in PLCOpenClasses:
-    cls = PLCOpenClasses["coil"]
+cls = PLCOpenClasses.get("coil", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -744,30 +784,19 @@
             self.variable = new_name
     setattr(cls, "updateElementName", updateElementName)
 
-if "rightPowerRail" in PLCOpenClasses:
-    cls = PLCOpenClasses["rightPowerRail"]
-    setattr(cls, "getX", getX)
-    setattr(cls, "getY", getY)
-    setattr(cls, "setX", setX)
-    setattr(cls, "setY", setY)
-    
+cls = PLCOpenClasses.get("step", None)
+if cls:
+    setattr(cls, "getX", getX)
+    setattr(cls, "getY", getY)
+    setattr(cls, "setX", setX)
+    setattr(cls, "setY", setY)
+
     def updateElementName(self, old_name, new_name):
         pass
     setattr(cls, "updateElementName", updateElementName)
 
-if "step" in PLCOpenClasses:
-    cls = PLCOpenClasses["step"]
-    setattr(cls, "getX", getX)
-    setattr(cls, "getY", getY)
-    setattr(cls, "setX", setX)
-    setattr(cls, "setY", setY)
-
-    def updateElementName(self, old_name, new_name):
-        pass
-    setattr(cls, "updateElementName", updateElementName)
-
-if "transition" in PLCOpenClasses:
-    cls = PLCOpenClasses["transition"]
+cls = PLCOpenClasses.get("transition", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -891,8 +920,8 @@
     
     setattr(cls, "addConnection", addConnection)    
 
-if "selectionDivergence" in PLCOpenClasses:
-    cls = PLCOpenClasses["selectionDivergence"]
+cls = PLCOpenClasses.get("selectionDivergence", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -902,8 +931,8 @@
         pass
     setattr(cls, "updateElementName", updateElementName)
 
-if "selectionConvergence" in PLCOpenClasses:
-    cls = PLCOpenClasses["selectionConvergence"]
+cls = PLCOpenClasses.get("selectionConvergence", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -913,8 +942,8 @@
         pass
     setattr(cls, "updateElementName", updateElementName)
     
-if "simultaneousDivergence" in PLCOpenClasses:
-    cls = PLCOpenClasses["simultaneousDivergence"]
+cls = PLCOpenClasses.get("simultaneousDivergence", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -924,8 +953,8 @@
         pass
     setattr(cls, "updateElementName", updateElementName)
     
-if "simultaneousDivergence" in PLCOpenClasses:
-    cls = PLCOpenClasses["simultaneousConvergence"]
+cls = PLCOpenClasses.get("simultaneousConvergence", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -935,8 +964,8 @@
         pass
     setattr(cls, "updateElementName", updateElementName)
 
-if "jumpStep" in PLCOpenClasses:
-    cls = PLCOpenClasses["jumpStep"]
+cls = PLCOpenClasses.get("jumpStep", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -946,10 +975,8 @@
         pass
     setattr(cls, "updateElementName", updateElementName)
 
-
-if "actionBlock_action" in PLCOpenClasses:
-    cls = PLCOpenClasses["actionBlock_action"]
-    
+cls = PLCOpenClasses.get("actionBlock_action", None)
+if cls:
     def setQualifierValue(self, value):
         if self.qualifier:
             self.qualifier.setValue(value)
@@ -991,8 +1018,8 @@
             self.inline.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
-if "actionBlock" in PLCOpenClasses:
-    cls = PLCOpenClasses["actionBlock"]
+cls = PLCOpenClasses.get("actionBlock", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -1043,8 +1070,8 @@
             action.updateElementName(old_name, new_name)
     setattr(cls, "updateElementName", updateElementName)
 
-if "inVariable" in PLCOpenClasses:
-    cls = PLCOpenClasses["inVariable"]
+cls = PLCOpenClasses.get("inVariable", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -1067,8 +1094,8 @@
             self.expression = new_name
     setattr(cls, "updateElementName", updateElementName)
 
-if "outVariable" in PLCOpenClasses:
-    cls = PLCOpenClasses["outVariable"]
+cls = PLCOpenClasses.get("outVariable", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -1091,8 +1118,8 @@
             self.expression = new_name
     setattr(cls, "updateElementName", updateElementName)
 
-if "inOutVariable" in PLCOpenClasses:
-    cls = PLCOpenClasses["inOutVariable"]
+cls = PLCOpenClasses.get("inOutVariable", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -1127,8 +1154,8 @@
             self.expression = new_name
     setattr(cls, "updateElementName", updateElementName)
 
-if "continuation" in PLCOpenClasses:
-    cls = PLCOpenClasses["continuation"]
+cls = PLCOpenClasses.get("continuation", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -1138,8 +1165,8 @@
         pass
     setattr(cls, "updateElementName", updateElementName)
 
-if "connector" in PLCOpenClasses:
-    cls = PLCOpenClasses["connector"]
+cls = PLCOpenClasses.get("connector", None)
+if cls:
     setattr(cls, "getX", getX)
     setattr(cls, "getY", getY)
     setattr(cls, "setX", setX)
@@ -1149,9 +1176,8 @@
         pass
     setattr(cls, "updateElementName", updateElementName)
 
-if "connection" in PLCOpenClasses:
-    cls = PLCOpenClasses["connection"]
-    
+cls = PLCOpenClasses.get("connection", None)
+if cls:
     def setPoints(self, points):
         self.position = []
         for point in points:
@@ -1168,9 +1194,8 @@
         return points
     setattr(cls, "getPoints", getPoints)
 
-if "connectionPointIn" in PLCOpenClasses:
-    cls = PLCOpenClasses["connectionPointIn"]
-
+cls = PLCOpenClasses.get("connectionPointIn", None)
+if cls:
     def setRelPosition(self, x, y):
         self.relPosition = PLCOpenClasses["position"]()
         self.relPosition.setX(x)
@@ -1241,9 +1266,8 @@
         return None
     setattr(cls, "getConnectionParameter", getConnectionParameter)
 
-if "connectionPointOut" in PLCOpenClasses:
-    cls = PLCOpenClasses["connectionPointOut"]
-
+cls = PLCOpenClasses.get("connectionPointOut", None)
+if cls:
     def setRelPosition(self, x, y):
         self.relPosition = PLCOpenClasses["position"]()
         self.relPosition.setX(x)
@@ -1256,9 +1280,8 @@
         return self.relPosition
     setattr(cls, "getRelPosition", getRelPosition)
 
-if "value" in PLCOpenClasses:
-    cls = PLCOpenClasses["value"]
-    
+cls = PLCOpenClasses.get("value", None)
+if cls:
     def setValue(self, value):
         try:
             value = eval(value)
@@ -1287,9 +1310,8 @@
         return value
     setattr(cls, "getValue", getValue)
 
-if "value_arrayValue" in PLCOpenClasses:
-    cls = PLCOpenClasses["value_arrayValue"]
-    
+cls = PLCOpenClasses.get("value_arrayValue", None)
+if cls:
     def setValue(self, array):
         self.value = []
         for value in array:
@@ -1302,9 +1324,8 @@
         return [element.getValue() for element in self.value]
     setattr(cls, "getValue", getValue)
 
-if "value_structValue" in PLCOpenClasses:
-    cls = PLCOpenClasses["value_structValue"]
-    
+cls = PLCOpenClasses.get("value_structValue", None)
+if cls:
     def setValue(self, dict):
         self.value = []
         for name,value in dict.items():
--- a/xmlclass/xmlclass.py	Thu Aug 09 18:06:54 2007 +0200
+++ b/xmlclass/xmlclass.py	Thu Aug 09 18:07:44 2007 +0200
@@ -239,7 +239,11 @@
     if len(attr.childNodes) == 1:
         return attr.childNodes[0].data.encode()
     else:
-        return ""
+        text = ""
+        for node in attr.childNodes:
+            if node.nodeName != "#text":
+                text += node.data.encode()
+        return text
 
 """
 Funtion that returns the Python type and default value for a given type