# HG changeset patch
# User Laurent Bessard
# Date 1369340573 -7200
# Node ID a506e4de8f84c64cb8fa6eaf36c562341191777a
# Parent  074e46cdedbcafd07e2cc9c3f823ba9390e52c2c
Add support for Drag'n dropping located variables to function block creating global located variable in configuration and external variable in function block

diff -r 074e46cdedbc -r a506e4de8f84 IDEFrame.py
--- a/IDEFrame.py	Thu May 23 20:39:10 2013 +0200
+++ b/IDEFrame.py	Thu May 23 22:22:53 2013 +0200
@@ -1576,7 +1576,7 @@
                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames() if name != old_name]:
                         message = _("\"%s\" pou already exists!")%new_name
                         abort = True
-                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
+                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariableNames()]:
                         messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
                         if messageDialog.ShowModal() == wx.ID_NO:
                             abort = True
@@ -1590,7 +1590,7 @@
                 elif item_infos["type"] == ITEM_TRANSITION:
                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
                         message = _("A POU named \"%s\" already exists!")%new_name
-                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]:
+                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariableNames(pou_name) if name != old_name]:
                         message = _("A variable with \"%s\" as name already exists in this pou!")%new_name
                     else:
                         words = item_infos["tagname"].split("::")
@@ -1601,7 +1601,7 @@
                 elif item_infos["type"] == ITEM_ACTION:
                     if new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouNames()]:
                         message = _("A POU named \"%s\" already exists!")%new_name
-                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables(pou_name) if name != old_name]:
+                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariableNames(pou_name) if name != old_name]:
                         message = _("A variable with \"%s\" as name already exists in this pou!")%new_name
                     else:
                         words = item_infos["tagname"].split("::")
@@ -1618,7 +1618,7 @@
                         if messageDialog.ShowModal() == wx.ID_NO:
                             abort = True
                         messageDialog.Destroy()
-                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
+                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariableNames()]:
                         messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
                         if messageDialog.ShowModal() == wx.ID_NO:
                             abort = True
@@ -1637,7 +1637,7 @@
                         if messageDialog.ShowModal() == wx.ID_NO:
                             abort = True
                         messageDialog.Destroy()
-                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariables()]:
+                    elif new_name.upper() in [name.upper() for name in self.Controler.GetProjectPouVariableNames()]:
                         messageDialog = wx.MessageDialog(self, _("A POU has an element named \"%s\". This could cause a conflict. Do you wish to continue?")%new_name, _("Error"), wx.YES_NO|wx.ICON_QUESTION)
                         if messageDialog.ShowModal() == wx.ID_NO:
                             abort = True
@@ -2263,7 +2263,7 @@
         def OnAddPouMenu(event):
             dialog = PouDialog(self, pou_type)
             dialog.SetPouNames(self.Controler.GetProjectPouNames())
-            dialog.SetPouElementNames(self.Controler.GetProjectPouVariables())
+            dialog.SetPouElementNames(self.Controler.GetProjectPouVariableNames())
             dialog.SetValues({"pouName": self.Controler.GenerateNewName(None, None, "%s%%d" % pou_type)})
             if dialog.ShowModal() == wx.ID_OK:
                 values = dialog.GetValues()
@@ -2278,7 +2278,7 @@
         def OnAddTransitionMenu(event):
             dialog = PouTransitionDialog(self)
             dialog.SetPouNames(self.Controler.GetProjectPouNames())
-            dialog.SetPouElementNames(self.Controler.GetProjectPouVariables(pou_name))
+            dialog.SetPouElementNames(self.Controler.GetProjectPouVariableNames(pou_name))
             dialog.SetValues({"transitionName": self.Controler.GenerateNewName(None, None, "transition%d")})
             if dialog.ShowModal() == wx.ID_OK: 
                 values = dialog.GetValues()
@@ -2293,7 +2293,7 @@
         def OnAddActionMenu(event):
             dialog = PouActionDialog(self)
             dialog.SetPouNames(self.Controler.GetProjectPouNames())
-            dialog.SetPouElementNames(self.Controler.GetProjectPouVariables(pou_name))
+            dialog.SetPouElementNames(self.Controler.GetProjectPouVariableNames(pou_name))
             dialog.SetValues({"actionName": self.Controler.GenerateNewName(None, None, "action%d")})
             if dialog.ShowModal() == wx.ID_OK:
                 values = dialog.GetValues()
diff -r 074e46cdedbc -r a506e4de8f84 PLCControler.py
--- a/PLCControler.py	Thu May 23 20:39:10 2013 +0200
+++ b/PLCControler.py	Thu May 23 22:22:53 2013 +0200
@@ -266,8 +266,8 @@
             return [config.getname() for config in project.getconfigurations()]
         return []
     
-    # Return project pou variables
-    def GetProjectPouVariables(self, pou_name = None, debug = False):
+    # Return project pou variable names
+    def GetProjectPouVariableNames(self, pou_name = None, debug = False):
         variables = []
         project = self.GetProject(debug)
         if project is not None:
@@ -1261,6 +1261,16 @@
             tempvar["Documentation"] = ""
 
         return tempvar
+    
+    # Add a global var to configuration to configuration
+    def AddConfigurationGlobalVar(self, config_name, type, var_name, 
+                                           location="", description=""):
+        if self.Project is not None:
+            # Found the configuration corresponding to name
+            configuration = self.Project.getconfiguration(config_name)
+            if configuration is not None:
+                # Set configuration global vars
+                configuration.addglobalVar(type, var_name, location, description)
 
     # Replace the configuration globalvars by those given
     def SetConfigurationGlobalVars(self, name, vars):
@@ -1289,6 +1299,20 @@
                         vars.append(tempvar)
         return vars
 
+    # Return configuration variable names
+    def GetConfigurationVariableNames(self, config_name = None, debug = False):
+        variables = []
+        project = self.GetProject(debug)
+        if project is not None:
+            for configuration in self.Project.getconfigurations():
+                if config_name is None or config_name == configuration.getname():
+                    variables.extend(
+                        [var.getname() for var in reduce(
+                            lambda x, y: x + y, [varlist.getvariable() 
+                                for varlist in configuration.globalVars],
+                            [])])
+        return variables
+
     # Replace the resource globalvars by those given
     def SetConfigurationResourceGlobalVars(self, config_name, name, vars):
         if self.Project is not None:
@@ -1316,6 +1340,23 @@
                         vars.append(tempvar)
         return vars
     
+    # Return resource variable names
+    def GetConfigurationResourceVariableNames(self, 
+                config_name = None, resource_name = None, debug = False):
+        variables = []
+        project = self.GetProject(debug)
+        if project is not None:
+            for configuration in self.Project.getconfigurations():
+                if config_name is None or config_name == configuration.getname():
+                    for resource in configuration.getresource():
+                        if resource_name is None or resource.getname() == resource_name:
+                            variables.extend(
+                                [var.getname() for var in reduce(
+                                    lambda x, y: x + y, [varlist.getvariable() 
+                                        for varlist in resource.globalVars],
+                                    [])])
+        return variables
+    
     # Recursively generate element name tree for a structured variable
     def GenerateVarTree(self, typename, debug = False):
         project = self.GetProject(debug)
@@ -2076,7 +2117,13 @@
     def GetEditedElementVariables(self, tagname, debug = False):
         words = tagname.split("::")
         if words[0] in ["P","T","A"]:
-            return self.GetProjectPouVariables(words[1], debug)
+            return self.GetProjectPouVariableNames(words[1], debug)
+        elif words[0] in ["C", "R"]:
+            names = self.GetConfigurationVariableNames(words[1], debug)
+            if words[0] == "R":
+                names.extend(self.GetConfigurationResourceVariableNames(
+                    words[1], words[2], debug))
+            return names
         return []
 
     def GetEditedElementCopy(self, tagname, debug = False):
diff -r 074e46cdedbc -r a506e4de8f84 controls/VariablePanel.py
--- a/controls/VariablePanel.py	Thu May 23 20:39:10 2013 +0200
+++ b/controls/VariablePanel.py	Thu May 23 22:22:53 2013 +0200
@@ -300,24 +300,59 @@
                         self.ParentWindow.SaveValues()
             elif (element_type not in ["config", "resource", "function"] and values[1] == "Global" and 
                   self.ParentWindow.Filter in ["All", "Interface", "External"] or
-                  element_type in ["config", "resource", "program"] and values[1] == "location"):
+                  element_type != "function" and values[1] == "location"):
                 if values[1] == "location":
                     var_name = values[3]
                 else:
                     var_name = values[0]
                 tagname = self.ParentWindow.GetTagName()
-                if var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetProjectPouNames(self.ParentWindow.Debug)]:
+                if var_name.upper() in [name.upper() 
+                        for name in self.ParentWindow.Controler.\
+                            GetProjectPouNames(self.ParentWindow.Debug)]:
                     message = _("\"%s\" pou already exists!")%var_name
-                elif not var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
+                elif not var_name.upper() in [name.upper() 
+                        for name in self.ParentWindow.Controler.\
+                            GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
                     var_infos = self.ParentWindow.DefaultValue.copy()
                     var_infos["Name"] = var_name
                     var_infos["Type"] = values[2]
                     if values[1] == "location":
-                        if element_type == "program":
-                            var_infos["Class"] = "Local"
+                        location = values[0]
+                        if not location.startswith("%"):
+                            dialog = wx.SingleChoiceDialog(self.ParentWindow.ParentWindow.ParentWindow, 
+                                  _("Select a variable class:"), _("Variable class"), 
+                                  ["Input", "Output", "Memory"], 
+                                  wx.DEFAULT_DIALOG_STYLE|wx.OK|wx.CANCEL)
+                            if dialog.ShowModal() == wx.ID_OK:
+                                selected = dialog.GetSelection()
+                            else:
+                                selected = None
+                            dialog.Destroy()
+                            if selected is None:
+                                return
+                            if selected == 0:
+                                location = "%I" + location
+                            elif selected == 1:
+                                location = "%Q" + location
+                            else:
+                                location = "%M" + location
+                        if element_type == "functionBlock":
+                            configs = self.ParentWindow.Controler.GetProjectConfigNames(
+                                                                self.ParentWindow.Debug)
+                            if len(configs) == 0:
+                                return
+                            if not var_name.upper() in [name.upper() 
+                                for name in self.ParentWindow.Controler.\
+                                    GetConfigurationVariableNames(configs[0])]:
+                                self.ParentWindow.Controler.AddConfigurationGlobalVar(
+                                    configs[0], values[2], var_name, location, "")
+                            var_infos["Class"] = "External"
                         else:
-                            var_infos["Class"] = "Global"
-                        var_infos["Location"] = values[0]
+                            if element_type == "program":
+                                var_infos["Class"] = "Local"
+                            else:
+                                var_infos["Class"] = "Global"
+                            var_infos["Location"] = location
                     else:
                         var_infos["Class"] = "External"
                     var_infos["Number"] = len(self.ParentWindow.Values)
diff -r 074e46cdedbc -r a506e4de8f84 plcopen/plcopen.py
--- a/plcopen/plcopen.py	Thu May 23 20:39:10 2013 +0200
+++ b/plcopen/plcopen.py	Thu May 23 22:22:53 2013 +0200
@@ -855,6 +855,35 @@
 
 cls = PLCOpenClasses.get("configurations_configuration", None)
 if cls:
+    
+    def addglobalVar(self, type, name, location="", description=""):
+        globalvars = self.getglobalVars()
+        if len(globalvars) == 0:
+            globalvars.append(PLCOpenClasses["varList"]())
+        var = PLCOpenClasses["varListPlain_variable"]()
+        var.setname(name)
+        var_type = PLCOpenClasses["dataType"]()
+        if type in [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]:
+            if type == "STRING":
+                var_type.setcontent({"name" : "string", "value" : PLCOpenClasses["elementaryTypes_string"]()})
+            elif type == "WSTRING":
+                var_type.setcontent({"name" : "wstring", "value" : PLCOpenClasses["elementaryTypes_wstring"]()})
+            else:
+                var_type.setcontent({"name" : type, "value" : None})
+        else:
+            derived_type = PLCOpenClasses["derivedTypes_derived"]()
+            derived_type.setname(type)
+            var_type.setcontent({"name" : "derived", "value" : derived_type})
+        var.settype(var_type)
+        if location != "":
+            var.setaddress(location)
+        if description != "":
+            ft = PLCOpenClasses["formattedText"]()
+            ft.settext(description)
+            var.setdocumentation(ft)
+        globalvars[-1].appendvariable(var)
+    setattr(cls, "addglobalVar", addglobalVar)
+    
     def updateElementName(self, old_name, new_name):
         _updateConfigurationResourceElementName(self, old_name, new_name)
         for resource in self.getresource():