plugins/svgui/svgui.py
changeset 370 ee802ef00ca5
parent 369 bd54d41a7573
child 371 b7cb57a2da08
equal deleted inserted replaced
369:bd54d41a7573 370:ee802ef00ca5
     1 import os, shutil, sys
       
     2 base_folder = os.path.split(sys.path[0])[0]
       
     3 sys.path.append(os.path.join(base_folder, "wxsvg", "SVGUIEditor"))
       
     4 sys.path.append(os.path.join(base_folder, "plcopeneditor", "graphics"))
       
     5 
       
     6 import wx, subprocess
       
     7 
       
     8 from SVGUIGenerator import *
       
     9 from SVGUIControler import *
       
    10 from SVGUIEditor import *
       
    11 from FBD_Objects import *
       
    12 from PLCGenerator import PLCGenException
       
    13 
       
    14 from wxPopen import ProcessLogger
       
    15 from wx.wxsvg import SVGDocument
       
    16 from docutils import *
       
    17 
       
    18 [ID_SVGUIEDITORFBDPANEL, 
       
    19 ] = [wx.NewId() for _init_ctrls in range(1)]
       
    20 
       
    21 SVGUIFB_Types = {ITEM_CONTAINER : "Container",
       
    22                  ITEM_BUTTON : "Button", 
       
    23                  ITEM_TEXT : "TextCtrl", 
       
    24                  ITEM_SCROLLBAR : "ScrollBar", 
       
    25                  ITEM_ROTATING : "RotatingCtrl", 
       
    26                  ITEM_NOTEBOOK : "NoteBook", 
       
    27                  ITEM_TRANSFORM : "Transform"}
       
    28 
       
    29 class _SVGUIEditor(SVGUIEditor):
       
    30     """
       
    31     This Class add IEC specific features to the SVGUIEditor :
       
    32         - FDB preview
       
    33         - FBD begin drag 
       
    34     """
       
    35     
       
    36     def _init_coll_EditorGridSizer_Items(self, parent):
       
    37         SVGUIEditor._init_coll_EditorGridSizer_Items(self, parent)
       
    38         parent.AddWindow(self.FBDPanel, 0, border=0, flag=wx.GROW)
       
    39     
       
    40     def _init_ctrls(self, prnt):
       
    41         SVGUIEditor._init_ctrls(self, prnt, False)
       
    42         
       
    43         self.FBDPanel = wx.Panel(id=ID_SVGUIEDITORFBDPANEL, 
       
    44                   name='FBDPanel', parent=self.EditorPanel, pos=wx.Point(0, 0),
       
    45                   size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL|wx.SIMPLE_BORDER)
       
    46         self.FBDPanel.SetBackgroundColour(wx.WHITE)
       
    47         self.FBDPanel.Bind(wx.EVT_LEFT_DOWN, self.OnFBDPanelClick)
       
    48         self.FBDPanel.Bind(wx.EVT_PAINT, self.OnPaintFBDPanel)
       
    49         
       
    50         setattr(self.FBDPanel, "GetScaling", lambda: None) 
       
    51         setattr(self.FBDPanel, "IsOfType", self.IsOfType) 
       
    52         setattr(self.FBDPanel, "GetBlockType", self.GetBlockType) 
       
    53         
       
    54         self._init_sizers()
       
    55     
       
    56     def __init__(self, parent, controler = None, fileOpen = None):
       
    57         SVGUIEditor.__init__(self, parent, controler, fileOpen)
       
    58         
       
    59         self.FBDBlock = None
       
    60     
       
    61     def IsOfType(self, type, reference):
       
    62         return self.Controler.GetPlugRoot().IsOfType(type, reference)
       
    63     
       
    64     def GetBlockType(self, type, inputs = None):
       
    65         return self.Controler.GetPlugRoot().GetBlockType(type, inputs)
       
    66     
       
    67     def RefreshView(self, select_id = None):
       
    68         SVGUIEditor.RefreshView(self, select_id)
       
    69         self.FBDPanel.Refresh()
       
    70     
       
    71     def OnPaintFBDPanel(self,event):
       
    72         dc = wx.ClientDC(self.FBDPanel)
       
    73         dc.Clear()
       
    74         selected = self.GetSelected()
       
    75         if selected is not None:
       
    76             selected_type = self.Controler.GetElementType(selected)
       
    77             if selected_type is not None:
       
    78                 self.FBDBlock = FBD_Block(parent=self.FBDPanel,type=SVGUIFB_Types[selected_type],name=self.Controler.GetElementName(selected))
       
    79                 width, height = self.FBDBlock.GetMinSize()
       
    80                 self.FBDBlock.SetSize(width,height)
       
    81                 clientsize = self.FBDPanel.GetClientSize()
       
    82                 x = (clientsize.width - width) / 2
       
    83                 y = (clientsize.height - height) / 2
       
    84                 self.FBDBlock.SetPosition(x, y)
       
    85                 self.FBDBlock.Draw(dc)
       
    86         else:
       
    87             self.FBDBlock = None
       
    88         event.Skip()
       
    89         
       
    90     def OnFBDPanelClick(self, event):
       
    91         if self.FBDBlock:
       
    92             data = wx.TextDataObject(str((self.FBDBlock.GetType(), "functionBlock", self.FBDBlock.GetName())))
       
    93             DropSrc = wx.DropSource(self.FBDPanel)
       
    94             DropSrc.SetData(data)
       
    95             DropSrc.DoDragDrop()
       
    96         event.Skip()
       
    97     
       
    98     def OnInterfaceTreeItemSelected(self, event):
       
    99         self.FBDPanel.Refresh()
       
   100         SVGUIEditor.OnInterfaceTreeItemSelected(self, event)
       
   101     
       
   102     def OnGenerate(self,event):
       
   103         self.SaveProject()
       
   104         self.Controler.PlugGenerate_C(sys.path[0],(0,0,4,5),None)
       
   105         event.Skip()    
       
   106     
       
   107 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L",
       
   108     "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L",
       
   109     "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"}
       
   110 
       
   111 CTYPECONVERSION = {"BOOL" : "IEC_BOOL", "UINT" : "IEC_UINT", "STRING" : "IEC_STRING", "REAL" : "IEC_REAL"}
       
   112 CPRINTTYPECONVERSION = {"BOOL" : "d", "UINT" : "d", "STRING" : "s", "REAL" : "f"}
       
   113 
       
   114 class RootClass(SVGUIControler):
       
   115 
       
   116     def __init__(self):
       
   117         SVGUIControler.__init__(self)
       
   118         filepath = os.path.join(self.PlugPath(), "gui.xml")
       
   119         
       
   120         if os.path.isfile(filepath):
       
   121             svgfile = os.path.join(self.PlugPath(), "gui.svg")
       
   122             if os.path.isfile(svgfile):
       
   123                 self.SvgFilepath = svgfile
       
   124             self.OpenXMLFile(filepath)
       
   125         else:
       
   126             self.CreateNewInterface()
       
   127             self.SetFilePath(filepath)
       
   128 
       
   129     def GetElementIdFromName(self, name):
       
   130         element = self.GetElementByName(name)
       
   131         if element is not None:
       
   132             return element.getid()
       
   133         return None
       
   134 
       
   135     _View = None
       
   136     def _OpenView(self):
       
   137         if not self._View:
       
   138             def _onclose():
       
   139                 self._View = None
       
   140             def _onsave():
       
   141                 self.GetPlugRoot().SaveProject()
       
   142             self._View = _SVGUIEditor(self.GetPlugRoot().AppFrame, self)
       
   143             self._View._onclose = _onclose
       
   144             self._View._onsave = _onsave
       
   145             self._View.Show()
       
   146 
       
   147     def _ImportSVG(self):
       
   148         if not self._View:
       
   149             dialog = wx.FileDialog(self.GetPlugRoot().AppFrame, "Choose a SVG file", os.getcwd(), "",  "SVG files (*.svg)|*.svg|All files|*.*", wx.OPEN)
       
   150             if dialog.ShowModal() == wx.ID_OK:
       
   151                 svgpath = dialog.GetPath()
       
   152                 if os.path.isfile(svgpath):
       
   153                     shutil.copy(svgpath, os.path.join(self.PlugPath(), "gui.svg"))
       
   154                 else:
       
   155                     self.logger.write_error("No such SVG file: %s\n"%svgpath)
       
   156             dialog.Destroy()
       
   157 
       
   158     def _ImportXML(self):
       
   159         if not self._View:
       
   160             dialog = wx.FileDialog(self.GetPlugRoot().AppFrame, "Choose a XML file", os.getcwd(), "",  "XML files (*.xml)|*.xml|All files|*.*", wx.OPEN)
       
   161             if dialog.ShowModal() == wx.ID_OK:
       
   162                 xmlpath = dialog.GetPath()
       
   163                 if os.path.isfile(xmlpath):
       
   164                     shutil.copy(xmlpath, os.path.join(self.PlugPath(), "gui.xml"))
       
   165                 else:
       
   166                     self.logger.write_error("No such XML file: %s\n"%xmlpath)
       
   167             dialog.Destroy()
       
   168 
       
   169     def _StartInkscape(self):
       
   170         svgfile = os.path.join(self.PlugPath(), "gui.svg")		
       
   171         if not os.path.isfile(svgfile):
       
   172             svgfile = None
       
   173         open_svg(svgfile)
       
   174 
       
   175     PluginMethods = [
       
   176         {"bitmap" : os.path.join("images","HMIEditor"),
       
   177          "name" : "HMI Editor",
       
   178          "tooltip" : "HMI Editor",
       
   179          "method" : "_OpenView"},
       
   180         {"bitmap" : os.path.join("images","ImportSVG"),
       
   181          "name" : "Import SVG",
       
   182          "tooltip" : "Import SVG",
       
   183          "method" : "_ImportSVG"},
       
   184         {"bitmap" : os.path.join("images","ImportDEF"),
       
   185          "name" : "Import XML",
       
   186          "tooltip" : "Import XML",
       
   187          "method" : "_ImportXML"},
       
   188          {"bitmap" : os.path.join("images","ImportSVG"),
       
   189          "name" : "Inkscape",
       
   190          "tooltip" : "Create HMI",
       
   191          "method" : "_StartInkscape"},
       
   192     ]
       
   193     
       
   194     def OnPlugSave(self):
       
   195         self.SaveXMLFile(os.path.join(self.PlugPath(), "gui.xml"))
       
   196         return True
       
   197     
       
   198     def PlugGenerate_C(self, buildpath, locations):
       
   199         progname = "SVGUI_%s"%"_".join(map(str, self.GetCurrentLocation()))
       
   200         
       
   201         doc = SVGDocument(self.GetSVGFilePath())
       
   202         root_element = doc.GetRootElement()
       
   203         window_size = (int(float(root_element.GetAttribute("width"))),
       
   204                        int(float(root_element.GetAttribute("height"))))
       
   205 
       
   206 #        svgfilepath = self.GetSVGFilePath()
       
   207 #        xmlfilepath = self.GetFilePath()
       
   208 #        shutil.copy(svgfilepath, buildpath)
       
   209 #        shutil.copy(xmlfilepath, buildpath)
       
   210         
       
   211         SVGFilePath = self.GetSVGFilePath()
       
   212         SVGFileBaseName = os.path.split(SVGFilePath)[1]
       
   213         FilePath = self.GetFilePath()
       
   214         FileBaseName = os.path.split(FilePath)[1]
       
   215         
       
   216         generator = _SVGUICGenerator(self, self.GetElementsByType(), 
       
   217                                      os.path.split(self.GetSVGFilePath())[1], 
       
   218                                      os.path.split(self.GetFilePath())[1], 
       
   219                                      self.GetCurrentLocation())
       
   220         generator.GenerateProgram(window_size, buildpath, progname)
       
   221         Gen_C_file = os.path.join(buildpath, progname+".cpp" )
       
   222         
       
   223         if wx.Platform == '__WXMSW__':
       
   224             cxx_flags = "-I..\\lib\\wx\\include\\msw-unicode-release-2.8 -I..\\include\\wx-2.8 -I..\\..\\matiec\\lib -DWXUSINGDLL -D__WXMSW__ -mthreads"
       
   225             libs = "\"..\\lib\\libwxsvg.a\" \"..\\lib\\libwxsvg_agg.a\" \"..\\lib\\libagg.a\" \"..\\lib\\libaggplatformwin32.a\" \"..\\lib\\libaggfontwin32tt.a\" -L..\\lib -mwindows -mthreads -Wl,--subsystem,windows -mwindows -lwx_mswu_richtext-2.8 -lwx_mswu_aui-2.8 -lwx_mswu_xrc-2.8 -lwx_mswu_qa-2.8 -lwx_mswu_html-2.8 -lwx_mswu_adv-2.8 -lwx_mswu_core-2.8 -lwx_baseu_xml-2.8 -lwx_baseu_net-2.8 -lwx_baseu-2.8"
       
   226         else:
       
   227             status, result, err_result = ProcessLogger(self.logger, "wx-config --cxxflags", no_stdout=True).spin()
       
   228             if status:
       
   229                 self.logger.write_error("Unable to get wx cxxflags\n")
       
   230             cxx_flags = result.strip() + " -I../matiec/lib"
       
   231             
       
   232             status, result, err_result = ProcessLogger(self.logger, "wx-config --libs", no_stdout=True).spin()
       
   233             if status:
       
   234                 self.logger.write_error("Unable to get wx libs\n")
       
   235             libs = result.strip() + " -lwxsvg"
       
   236         
       
   237         return [(Gen_C_file, cxx_flags)],libs,True,(SVGFileBaseName, file(SVGFilePath, "rb")), (FileBaseName, file(FilePath, "rb"))
       
   238     
       
   239     def BlockTypesFactory(self):
       
   240         
       
   241         SVGUIBlock_Types = []
       
   242         
       
   243         def GetSVGUIBlockType(type):
       
   244             for category in SVGUIBlock_Types:
       
   245                 for blocktype in category["list"]:
       
   246                     if blocktype["name"] == type:
       
   247                         return blocktype
       
   248         setattr(self, "GetSVGUIBlockType", GetSVGUIBlockType)
       
   249         
       
   250         def generate_svgui_block(generator, block, body, link, order=False):
       
   251             name = block.getinstanceName()
       
   252             block_id = self.GetElementIdFromName(name)
       
   253             if block_id == None:
       
   254                 raise PLCGenException, "Undefined SVGUI Block \"%s\""%name
       
   255             type = block.gettypeName()
       
   256             block_infos = GetSVGUIBlockType(type)
       
   257             current_location = ".".join(map(str, self.GetCurrentLocation()))
       
   258             if not generator.ComputedBlocks.get(block, False) and not order:
       
   259                 generator.ComputedBlocks[block] = True
       
   260                 for num, variable in enumerate(block.inputVariables.getvariable()):
       
   261                     connections = variable.connectionPointIn.getconnections()
       
   262                     if connections is not None:
       
   263                         input_info = (generator.TagName, "block", block.getlocalId(), "input", num)
       
   264                         parameter = "%sQ%s%s.%d.%d"%("%", TYPECONVERSION[block_infos["inputs"][num][1]], current_location, block_id, num+1)
       
   265                         value = generator.ComputeExpression(body, connections)
       
   266                         generator.Program += [(generator.CurrentIndent, ()),
       
   267                                               (parameter, input_info),
       
   268                                               (" := ", ())]
       
   269                         generator.Program += generator.ExtractModifier(variable, value, input_info)
       
   270                         generator.Program += [(";\n", ())]
       
   271             if link:
       
   272                 connectionPoint = link.getposition()[-1]
       
   273                 for num, variable in enumerate(block.outputVariables.getvariable()):
       
   274                     blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY()
       
   275                     output_info = (generator.TagName, "block", block.getlocalId(), "output", num)
       
   276                     parameter = "%sI%s%s.%d.%d"%("%", TYPECONVERSION[block_infos["outputs"][num][1]], current_location, block_id, num+1)
       
   277                     if block.getx() + blockPointx == connectionPoint.getx() and block.gety() + blockPointy == connectionPoint.gety():
       
   278                         return generator.ExtractModifier(variable, [(parameter, output_info)], output_info)
       
   279                 raise PLCGenException, "No corresponding output variable found on SVGUI Block \"%s\""%name
       
   280             else:
       
   281                 return None
       
   282 
       
   283         def initialise_block(type, name, block = None):
       
   284             block_id = self.GetElementIdFromName(name)
       
   285             if block_id == None:
       
   286                 raise PLCGenException, "Undefined SVGUI Block \"%s\""%name
       
   287             block_infos = GetSVGUIBlockType(type)
       
   288             current_location = ".".join(map(str, self.GetCurrentLocation()))
       
   289             variables = []
       
   290             if block is not None:
       
   291                 input_variables = block.inputVariables.getvariable()
       
   292                 output_variables = block.outputVariables.getvariable()
       
   293             else:
       
   294                 input_variables = None
       
   295                 output_variables = None
       
   296             for num, (input_name, input_type, input_modifier) in enumerate(block_infos["inputs"]):
       
   297                 if input_variables is not None and num < len(input_variables):
       
   298                     connections = input_variables[num].connectionPointIn.getconnections()
       
   299                 if input_variables is None or connections and len(connections) == 1:
       
   300                     variables.append((input_type, None, "%sQ%s%s.%d.%d"%("%", TYPECONVERSION[input_type], current_location, block_id, num+1), None))
       
   301             for num, (output_name, output_type, output_modifier) in enumerate(block_infos["outputs"]):
       
   302                 variables.append((output_type, None, "%sI%s%s.%d.%d"%("%", TYPECONVERSION[input_type], current_location, block_id, num+1), None))
       
   303             return variables
       
   304 
       
   305         SVGUIBlock_Types.extend([{"name" : "SVGUI function blocks", "list" :
       
   306                 [{"name" : "Container", "type" : "functionBlock", "extensible" : False, 
       
   307                     "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none")], 
       
   308                     "outputs" : [],
       
   309                     "comment" : "SVGUI Container",
       
   310                     "generate" : generate_svgui_block, "initialise" : initialise_block},
       
   311                 {"name" : "Button", "type" : "functionBlock", "extensible" : False, 
       
   312                     "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("Value","BOOL","none")], 
       
   313                     "outputs" : [("State","BOOL","none")],
       
   314                     "comment" : "SVGUI Button",
       
   315                     "generate" : generate_svgui_block, "initialise" : initialise_block},
       
   316                 {"name" : "TextCtrl", "type" : "functionBlock", "extensible" : False, 
       
   317                     "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetText","STRING","none")], 
       
   318                     "outputs" : [("Text","STRING","none")],
       
   319                     "comment" : "SVGUI Text Control",
       
   320                     "generate" : generate_svgui_block, "initialise" : initialise_block},
       
   321                 {"name" : "ScrollBar", "type" : "functionBlock", "extensible" : False, 
       
   322                     "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetThumb","UINT","none"),("SetRange","UINT","none"),("SetPosition","UINT","none")], 
       
   323                     "outputs" : [("Position","UINT","none")],
       
   324                     "comment" : "SVGUI ScrollBar",
       
   325                     "generate" : generate_svgui_block, "initialise" : initialise_block},
       
   326                 {"name" : "NoteBook", "type" : "functionBlock", "extensible" : False, 
       
   327                     "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetSelected","BOOL","none")], 
       
   328                     "outputs" : [("Selected","UINT","none")],
       
   329                     "comment" : "SVGUI Notebook",
       
   330                     "generate" : generate_svgui_block, "initialise" : initialise_block},
       
   331                 {"name" : "RotatingCtrl", "type" : "functionBlock", "extensible" : False, 
       
   332                     "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetAngle","REAL","none")], 
       
   333                     "outputs" : [("Angle","REAL","none")],
       
   334                     "comment" : "SVGUI Rotating Control",
       
   335                     "generate" : generate_svgui_block, "initialise" : initialise_block},
       
   336                 {"name" : "Transform", "type" : "functionBlock", "extensible" : False, 
       
   337                     "inputs" : [("Show","BOOL","none"),("Enable","BOOL","none"),("SetX","REAL","none"),("SetY","REAL","none"),("SetXScale","REAL","none"),("SetYScale","REAL","none"),("SetAngle","REAL","none")], 
       
   338                     "outputs" : [("X","REAL","none"),("Y","REAL","none")],
       
   339                     "comment" : "SVGUI Transform",
       
   340                     "generate" : generate_svgui_block, "initialise" : initialise_block},
       
   341                ]}
       
   342         ])
       
   343 
       
   344         return SVGUIBlock_Types
       
   345 
       
   346 
       
   347 class _SVGUICGenerator(SVGUICGenerator):
       
   348 
       
   349     def __init__(self, controler, elements, svgfile, xmlfile, current_location):
       
   350         SVGUICGenerator.__init__(self, elements, svgfile, xmlfile)
       
   351         
       
   352         self.CurrentLocation = current_location
       
   353         self.Controler = controler
       
   354 
       
   355     def GenerateProgramHeadersPublicVars(self):
       
   356         text = """
       
   357     void OnPlcOutEvent(wxEvent& event);
       
   358 
       
   359     void Retrieve();
       
   360     void Publish();
       
   361     void Initialize();
       
   362 """
       
   363 #        text += "    void Print();\n"
       
   364         return text
       
   365     
       
   366     def GenerateIECVars(self):
       
   367         text = ""
       
   368         for element in self.Elements:
       
   369             text += "STATE_TYPE out_state_%d;\n"%element.getid()
       
   370             text += "STATE_TYPE in_state_%d;\n"%element.getid()
       
   371         text +="\n"
       
   372         current_location = "_".join(map(str, self.CurrentLocation))
       
   373         #Declaration des variables
       
   374         for element in self.Elements:
       
   375             block_infos = self.Controler.GetSVGUIBlockType(SVGUIFB_Types[GetElementType(element)])
       
   376             block_id = element.getid()
       
   377             for i, input in enumerate(block_infos["inputs"]):
       
   378                 element_c_type = CTYPECONVERSION[input[1]]
       
   379                 variable = "__Q%s%s_%d_%d"%(TYPECONVERSION[input[1]], current_location, block_id, i + 1)
       
   380                 text += "%s beremiz%s;\n"%(element_c_type, variable)
       
   381                 text += "%s* %s = &beremiz%s;\n"%(element_c_type, variable, variable)
       
   382                 text += "%s _copy%s;\n"%(element_c_type, variable)
       
   383             for i, output in enumerate(block_infos["outputs"]):
       
   384                 element_c_type = CTYPECONVERSION[output[1]]
       
   385                 variable = "__I%s%s_%d_%d"%(TYPECONVERSION[output[1]], current_location, block_id, i + 1)
       
   386                 text += "%s beremiz%s;\n"%(element_c_type, variable)
       
   387                 text += "%s* %s = &beremiz%s;\n"%(element_c_type, variable, variable)
       
   388                 text += "%s _copy%s;\n"%(element_c_type, variable)
       
   389             text +="\n"
       
   390         return text
       
   391     
       
   392     def GenerateGlobalVarsAndFuncs(self, size):
       
   393         text = """#include "iec_types.h"
       
   394 #ifdef __WXMSW__
       
   395 #define COMPARE_AND_SWAP_VAL(Destination, comparand, exchange) InterlockedCompareExchange(Destination, exchange, comparand)
       
   396 #define THREAD_RETURN_TYPE DWORD WINAPI
       
   397 #define STATE_TYPE long int
       
   398 #else
       
   399 #define COMPARE_AND_SWAP_VAL(Destination, comparand, exchange) __sync_val_compare_and_swap(Destination, comparand, exchange)
       
   400 #define THREAD_RETURN_TYPE void*
       
   401 #define STATE_TYPE volatile int
       
   402 #endif
       
   403 
       
   404 """
       
   405         
       
   406         text += self.GenerateIECVars()
       
   407         
       
   408         text += """IMPLEMENT_APP_NO_MAIN(SVGViewApp);
       
   409 SVGViewApp *myapp = NULL;
       
   410 wxSemaphore MyInitSem;
       
   411 
       
   412 #ifdef __WXMSW__
       
   413 HANDLE wxMainLoop;
       
   414 DWORD wxMainLoopId;
       
   415 #else
       
   416 pthread_t wxMainLoop;
       
   417 #endif
       
   418 
       
   419 """
       
   420 
       
   421         text += """int myargc = 0;
       
   422 char** myargv = NULL;
       
   423         
       
   424 #define UNCHANGED 1
       
   425 #define PLC_BUSY 2
       
   426 #define CHANGED 3
       
   427 #define GUI_BUSY 4
       
   428 #ifdef __WXMSW__
       
   429 #else
       
   430 #endif
       
   431 
       
   432 bool refresh = false;
       
   433 bool refreshing = false;
       
   434 
       
   435 THREAD_RETURN_TYPE InitWxEntry(void* args)
       
   436 {
       
   437   wxEntry(myargc,myargv);
       
   438   myapp = NULL;
       
   439   MyInitSem.Post();
       
   440   return 0;
       
   441 }
       
   442 
       
   443 """
       
   444 
       
   445         text += """
       
   446 bool SVGViewApp::OnInit()
       
   447 {
       
   448   #ifndef __WXMSW__
       
   449     setlocale(LC_NUMERIC, "C");
       
   450   #endif
       
   451 """
       
   452         
       
   453         text += """  frame = new MainFrame(NULL, wxT("Program"),wxDefaultPosition, wxSize(%d, %d));
       
   454   frame->Show();
       
   455   myapp = this;
       
   456 """%size
       
   457         text += """  return true;
       
   458 }
       
   459 
       
   460 extern "C" {
       
   461 
       
   462 int __init_%(location)s(int argc, char** argv)
       
   463 {
       
   464   myargc = argc;
       
   465   myargv = argv;
       
   466 #ifdef __WXMSW__
       
   467   wxMainLoop = CreateThread(NULL, 0, InitWxEntry, 0, 0, &wxMainLoopId);
       
   468 #else
       
   469   pthread_create(&wxMainLoop, NULL, InitWxEntry, NULL);
       
   470 #endif
       
   471   MyInitSem.Wait();
       
   472   return 0;
       
   473 }
       
   474 
       
   475 void __cleanup_%(location)s()
       
   476 {
       
   477   if(myapp){
       
   478       wxCloseEvent event(wxEVT_CLOSE_WINDOW);
       
   479       myapp->frame->AddPendingEvent(event);
       
   480       myapp = NULL;
       
   481   }
       
   482   MyInitSem.Wait();
       
   483 }
       
   484 
       
   485 void __retrieve_%(location)s()
       
   486 {
       
   487   if(myapp){
       
   488     myapp->frame->m_svgCtrl->Retrieve();
       
   489   }        
       
   490 }
       
   491 
       
   492 void __publish_%(location)s()
       
   493 {
       
   494   if(myapp){
       
   495     myapp->frame->m_svgCtrl->Publish();
       
   496   }
       
   497 }
       
   498 
       
   499 }
       
   500 
       
   501 IEC_STRING wxStringToIEC_STRING(wxString s)
       
   502 {
       
   503   IEC_STRING res = {0,""};
       
   504   int i;
       
   505   for(i = 0; i<s.Length() && i<STR_MAX_LEN; i++)
       
   506     res.body[i] = s.GetChar(i);
       
   507   res.len = i;
       
   508   return res;
       
   509 }
       
   510 
       
   511 """%{"location" : "_".join(map(str, self.CurrentLocation))}
       
   512         
       
   513         return text
       
   514     
       
   515     def GenerateProgramEventTable(self):
       
   516         text = """BEGIN_DECLARE_EVENT_TYPES()
       
   517 DECLARE_LOCAL_EVENT_TYPE( EVT_PLC, wxNewEventType() )
       
   518 END_DECLARE_EVENT_TYPES()
       
   519          
       
   520 DEFINE_LOCAL_EVENT_TYPE( EVT_PLC )
       
   521 
       
   522 """     
       
   523         #Event Table Declaration
       
   524         text += "BEGIN_EVENT_TABLE(Program, SVGUIWindow)\n"
       
   525         for element in self.Elements:
       
   526             element_type = GetElementType(element)
       
   527             element_name = element.getname()
       
   528             if element_type == ITEM_BUTTON:
       
   529                 text += "  EVT_BUTTON (SVGUIID(\"%s\"), Program::On%sClick)\n"%(element_name, element_name)
       
   530             elif element_type in [ITEM_SCROLLBAR, ITEM_ROTATING, ITEM_TRANSFORM]:
       
   531                 text += "  EVT_COMMAND_SCROLL_THUMBTRACK (SVGUIID(\"%s\"), Program::On%sChanging)\n"%(element_name, element_name)
       
   532             elif element_type == ITEM_NOTEBOOK:
       
   533                 text += "  EVT_NOTEBOOK_PAGE_CHANGED (SVGUIID(\"%s\"), Program::On%sTabChanged)\n"%(element_name, element_name)
       
   534         text += "  EVT_CUSTOM(EVT_PLC, wxID_ANY, Program::OnPlcOutEvent)\n"
       
   535         text += "END_EVENT_TABLE()\n\n"
       
   536         return text
       
   537     
       
   538     def GenerateProgramInitFrame(self):
       
   539         text = """MainFrame::MainFrame(wxWindow *parent, const wxString& title, const wxPoint& pos,const wxSize& size, long style): wxFrame(parent, wxID_ANY, title, pos, size, style)
       
   540 {
       
   541   wxFileName svgfilepath(wxTheApp->argv[1], wxT("%s"));
       
   542   wxFileName xmlfilepath(wxTheApp->argv[1], wxT("%s"));
       
   543 
       
   544   m_svgCtrl = new Program(this);
       
   545   if (m_svgCtrl->LoadFiles(svgfilepath.GetFullPath(), xmlfilepath.GetFullPath()))
       
   546   {
       
   547     Show(true);
       
   548     m_svgCtrl->SetFocus();
       
   549     m_svgCtrl->SetFitToFrame(true);
       
   550     m_svgCtrl->InitScrollBars();
       
   551     m_svgCtrl->Initialize();
       
   552     m_svgCtrl->Update();
       
   553   }
       
   554   else
       
   555   {
       
   556     printf("Error while opening SVGUI files\\n");
       
   557   }
       
   558 }
       
   559 
       
   560 
       
   561 """%(self.SVGFilePath, self.XMLFilePath)
       
   562 
       
   563         return text
       
   564     
       
   565     def GenerateProgramInitProgram(self):
       
   566         text = "Program::Program(wxWindow* parent):SVGUIWindow(parent)\n{\n"
       
   567         for element in self.Elements:
       
   568             text += "    out_state_%d = UNCHANGED;\n"%element.getid()
       
   569             text += "    in_state_%d = UNCHANGED;\n"%element.getid()
       
   570         text += "}\n\n"
       
   571         return text
       
   572     
       
   573     def GenerateProgramEventFunctions(self):
       
   574         text = ""
       
   575         current_location = "_".join(map(str, self.CurrentLocation))
       
   576         for element in self.Elements:
       
   577             element_type = GetElementType(element)
       
   578             element_lock = """
       
   579   if (COMPARE_AND_SWAP_VAL(&in_state_%d, CHANGED, GUI_BUSY) == CHANGED ||
       
   580       COMPARE_AND_SWAP_VAL(&in_state_%d, UNCHANGED, GUI_BUSY) == UNCHANGED) {
       
   581 """%(element.getid(), element.getid())
       
   582             element_unlock = """
       
   583     COMPARE_AND_SWAP_VAL(&in_state_%d, GUI_BUSY, CHANGED);
       
   584     event.Skip();
       
   585   }else{
       
   586       /* re post event for idle */
       
   587       AddPendingEvent(event);
       
   588   }
       
   589 }
       
   590 
       
   591 """%element.getid()
       
   592             element_name = element.getname()
       
   593                 
       
   594             if element_type == ITEM_BUTTON:
       
   595                 text += """void Program::On%sClick(wxCommandEvent& event)
       
   596 {
       
   597   SVGUIButton* button = (SVGUIButton*)GetElementByName(wxT("%s"));\n"""%(element_name, element_name)
       
   598                 text += element_lock
       
   599                 text += "    _copy__IX%s_%d_1 = button->GetToggle();\n"%(current_location, element.getid())
       
   600                 text += element_unlock
       
   601             elif element_type == ITEM_ROTATING:
       
   602                 text += """void Program::On%sChanging(wxScrollEvent& event)
       
   603 {
       
   604   SVGUIRotatingCtrl* rotating = (SVGUIRotatingCtrl*)GetElementByName(wxT("%s"));
       
   605 """%(element_name, element_name)
       
   606                 text += element_lock
       
   607                 text += "    _copy__ID%s_%d_1 = rotating->GetAngle();\n"%(current_location, element.getid())
       
   608                 text += element_unlock
       
   609             elif element_type == ITEM_NOTEBOOK:
       
   610                 text += """void Program::On%sTabChanged(wxNotebookEvent& event)
       
   611 {
       
   612   SVGUINoteBook* notebook = (SVGUINoteBook*)GetElementByName(wxT("%s"));
       
   613 """%(element_name, element_name)
       
   614                 text += element_lock
       
   615                 text += "    _copy__IB%s_%d_1 = notebook->GetCurrentPage();\n"%(current_location, element.getid())
       
   616                 text += element_unlock
       
   617             elif element_type == ITEM_TRANSFORM:
       
   618                 text += """void Program::On%sChanging(wxScrollEvent& event)
       
   619 {
       
   620   SVGUITransform* transform = (SVGUITransform*)GetElementByName(wxT("%s"));
       
   621 """%(element_name, element_name)
       
   622                 text += element_lock
       
   623                 text += "    _copy__ID%s_%d_1 = transform->GetX();\n"%(current_location, element.getid())
       
   624                 text += "    _copy__ID%s_%d_2 = transform->GetY();\n"%(current_location, element.getid())
       
   625                 text += element_unlock
       
   626         
       
   627         text += "/* OnPlcOutEvent update GUI with provided IEC __Q* PLC output variables */\n"
       
   628         text += """void Program::OnPlcOutEvent(wxEvent& event)
       
   629 {
       
   630   SVGUIElement* element;
       
   631   
       
   632   refreshing = true;
       
   633 
       
   634 
       
   635 """
       
   636         for element in self.Elements:
       
   637             element_type = GetElementType(element)
       
   638             texts = {"location" : current_location, "id" : element.getid()}
       
   639             
       
   640             text += """  if (COMPARE_AND_SWAP_VAL(&out_state_%(id)d, CHANGED, GUI_BUSY) == CHANGED)
       
   641   {
       
   642     element = (SVGUIElement*)GetElementById(wxT("%(id)d"));
       
   643             
       
   644     if (_copy__QX%(location)s_%(id)d_1 != element->IsVisible()) {
       
   645       if (_copy__QX%(location)s_%(id)d_1)
       
   646         element->Show();
       
   647       else
       
   648         element->Hide();
       
   649     }
       
   650     if (_copy__QX%(location)s_%(id)d_2 != element->IsEnabled()) {
       
   651       if (_copy__QX%(location)s_%(id)d_2)
       
   652         element->Enable();
       
   653       else
       
   654         element->Disable();
       
   655     }
       
   656 """%texts
       
   657             if element_type == ITEM_BUTTON:
       
   658                 text += """    if (_copy__QX%(location)s_%(id)d_3 != ((SVGUIButton*)element)->GetToggle())
       
   659       ((SVGUIButton*)element)->SetToggle(_copy__QX%(location)s_%(id)d_3);
       
   660 """%texts
       
   661             elif element_type == ITEM_TEXT:
       
   662                 text += """    if (((SVGUITextCtrl*)element)->GetValue().compare(_copy__QX%(location)s_%(id)d_3))
       
   663     {
       
   664       wxString str = wxString::FromAscii(_copy__QB%(location)s_%(id)d_3);
       
   665       ((SVGUITextCtrl*)element)->SetText(str);
       
   666     }
       
   667 """%texts
       
   668             elif  element_type == ITEM_SCROLLBAR:
       
   669                 text += """    if (_copy__QW%(location)s_%(id)d_3 != ((SVGUIScrollBar*)element)->GetThumbPosition() ||
       
   670         _copy__QW%(location)s_%(id)d_4 != ((SVGUIScrollBar*)element)->GetThumbSize() ||
       
   671         _copy__QW%(location)s_%(id)d_5 != ((SVGUIScrollBar*)element)->GetRange())
       
   672       ((SVGUIScrollBar*)element)->Init_ScrollBar(_copy__QW%(location)s_%(id)d_3, _copy__QW%(location)s_%(id)d_4, _copy__QW%(location)s_%(id)d_5);
       
   673 """%texts
       
   674             elif element_type == ITEM_ROTATING:
       
   675                 text += """    if (_copy__QD%(location)s_%(id)d_3 != ((SVGUIRotatingCtrl*)element)->GetAngle())
       
   676       ((SVGUIRotatingCtrl*)element)->SetAngle(_copy__QD%(location)s_%(id)d_3);
       
   677 """%texts
       
   678             elif element_type == ITEM_NOTEBOOK:
       
   679                 text += """    if (_copy__QB%(location)s_%(id)d_3 != ((SVGUINoteBook*)element)->GetCurrentPage())
       
   680       ((SVGUINoteBook*)element)->SetCurrentPage(_copy__QB%(location)s_%(id)d_3);
       
   681 """%texts
       
   682             elif element_type == ITEM_TRANSFORM:
       
   683                 text += """    if (_copy__QD%(location)s_%(id)d_3 != ((SVGUITransform*)element)->GetX() ||
       
   684         _copy__QD%(location)s_%(id)d_4 != ((SVGUITransform*)element)->GetY())
       
   685       ((SVGUITransform*)element)->Move(_copy__QD%(location)s_%(id)d_3, _copy__QD%(location)s_%(id)d_4);
       
   686     if (_copy__QD%(location)s_%(id)d_5 != ((SVGUITransform*)element)->GetXScale() ||
       
   687         _copy__QD%(location)s_%(id)d_6 != ((SVGUITransform*)element)->GetYScale())
       
   688       ((SVGUITransform*)element)->Scale(_copy__QD%(location)s_%(id)d_5, _copy__QD%(location)s_%(id)d_6);
       
   689     if (_copy__QD%(location)s_%(id)d_7 != ((SVGUITransform*)element)->GetAngle())
       
   690       ((SVGUITransform*)element)->Rotate(_copy__QD%(location)s_%(id)d_7);
       
   691 """%texts
       
   692             text += "    COMPARE_AND_SWAP_VAL(&out_state_%(id)d, GUI_BUSY, UNCHANGED);\n  }\n"%texts
       
   693             
       
   694         text += """
       
   695 
       
   696   refreshing = false;
       
   697 
       
   698   event.Skip();
       
   699 }
       
   700 
       
   701 """
       
   702         return text
       
   703     
       
   704     def GenerateProgramPrivateFunctions(self):
       
   705         current_location = "_".join(map(str, self.CurrentLocation))
       
   706         
       
   707         text = "void Program::Retrieve()\n{\n"
       
   708         for element in self.Elements:
       
   709             element_type = GetElementType(element)
       
   710             texts = {"location" : current_location, "id" : element.getid()}
       
   711             block_infos = self.Controler.GetSVGUIBlockType(SVGUIFB_Types[GetElementType(element)])
       
   712             if len(block_infos["outputs"]) > 0:
       
   713                 text += """  if (COMPARE_AND_SWAP_VAL(&in_state_%(id)d, CHANGED, PLC_BUSY) == CHANGED) {
       
   714 """%texts
       
   715                 for i, output in enumerate(block_infos["outputs"]):
       
   716                     texts["type"] = TYPECONVERSION[output[1]]
       
   717                     texts["pin"] = i + 1
       
   718                     
       
   719                     variable = "__I%(type)s%(location)s_%(id)d_%(pin)d"%texts
       
   720                     text +="    beremiz%s = _copy%s;\n"%(variable, variable)
       
   721                 
       
   722                 text += """    COMPARE_AND_SWAP_VAL(&in_state_%(id)d, PLC_BUSY, UNCHANGED);
       
   723   }
       
   724 """%texts
       
   725         text += "}\n\n" 
       
   726 
       
   727         text += "void Program::Publish()\n{\n  STATE_TYPE new_state;\n\n"
       
   728         for element in self.Elements:
       
   729             element_type = GetElementType(element)
       
   730             texts = {"location" : current_location, "id" : element.getid()}
       
   731             block_infos = self.Controler.GetSVGUIBlockType(SVGUIFB_Types[GetElementType(element)])
       
   732             
       
   733             text += """  if ((new_state = COMPARE_AND_SWAP_VAL(&out_state_%(id)d, UNCHANGED, PLC_BUSY)) == UNCHANGED ||
       
   734        (new_state = COMPARE_AND_SWAP_VAL(&out_state_%(id)d, CHANGED, PLC_BUSY)) == CHANGED) {
       
   735 """%texts
       
   736             for i, input in enumerate(block_infos["inputs"]):
       
   737                 texts["type"] = TYPECONVERSION[input[1]]
       
   738                 texts["pin"] = i + 1
       
   739                 variable = "__Q%(type)s%(location)s_%(id)d_%(pin)d"%texts
       
   740                 text += "    if (_copy%s != beremiz%s) {\n"%(variable, variable)
       
   741                 text += "      _copy%s = beremiz%s;\n"%(variable, variable)
       
   742                 text += "      new_state = CHANGED;\n    }\n"%texts
       
   743             text += """    COMPARE_AND_SWAP_VAL(&out_state_%(id)d, PLC_BUSY, new_state);
       
   744     refresh |= new_state == CHANGED;
       
   745   }
       
   746 """%texts
       
   747         
       
   748         text += """  /* Replace this with determinist signal if called from RT */
       
   749   if (refresh && !refreshing) {
       
   750     wxCommandEvent event( EVT_PLC );
       
   751     AddPendingEvent(event);
       
   752     refresh = false;
       
   753   }
       
   754 };
       
   755 
       
   756 """
       
   757 
       
   758         text += """void Program::Initialize()
       
   759 {
       
   760   SVGUIElement* element;
       
   761 """
       
   762         for element in self.Elements:
       
   763             element_type = GetElementType(element)
       
   764             texts = {"location" : current_location, "id" : element.getid()}
       
   765             
       
   766             text += """
       
   767   element = (SVGUIElement*)GetElementById(wxT("%(id)d"));
       
   768   beremiz__QX%(location)s_%(id)d_1 = _copy__QX%(location)s_%(id)d_1 = element->IsVisible();
       
   769   beremiz__QX%(location)s_%(id)d_2 = _copy__QX%(location)s_%(id)d_2 = element->IsEnabled();
       
   770 """%texts
       
   771             if element_type == ITEM_BUTTON:
       
   772                 text += "  beremiz__QX%(location)s_%(id)d_3 = _copy__QX%(location)s_%(id)d_3 = ((SVGUIButton*)element)->GetToggle();\n"%texts
       
   773                 text += "  beremiz__IX%(location)s_%(id)d_1 = _copy__IX%(location)s_%(id)d_1 = ((SVGUIButton*)element)->GetToggle();\n"%texts
       
   774             elif element_type == ITEM_TEXT:
       
   775                 text += "  beremiz__QB%(location)s_%(id)d_3 = _copy__QB%(location)s_%(id)d_3 = ((SVGUITextCtrl*)element)->GetValue();\n"%texts
       
   776                 text += "  beremiz__IB%(location)s_%(id)d_1 = _copy__IB%(location)s_%(id)d_1 = ((SVGUITextCtrl*)element)->GetValue();\n"%texts
       
   777             elif element_type == ITEM_SCROLLBAR:
       
   778                 text += "  beremiz__QW%(location)s_%(id)d_3 = _copy__QW%(location)s_%(id)d_3 = ((SVGUIScrollBar*)element)->GetThumbSize();\n"%texts
       
   779                 text += "  beremiz__QW%(location)s_%(id)d_4 = _copy__QW%(location)s_%(id)d_4 = ((SVGUIScrollBar*)element)->GetRange();\n"%texts
       
   780                 text += "  beremiz__QW%(location)s_%(id)d_5 = _copy__QW%(location)s_%(id)d_5 = ((SVGUIScrollBar*)element)->GetThumbPosition();\n"%texts
       
   781                 text += "  beremiz__IW%(location)s_%(id)d_1 = _copy__IW%(location)s_%(id)d_1 = ((SVGUIScrollBar*)element)->GetThumbPosition();\n"%texts
       
   782             elif element_type == ITEM_ROTATING:
       
   783                 text += "  beremiz__QD%(location)s_%(id)d_3 = _copy__QD%(location)s_%(id)d_3 = ((SVGUIRotatingCtrl*)element)->GetAngle();\n"%texts
       
   784                 text += "  beremiz__ID%(location)s_%(id)d_1 = _copy__ID%(location)s_%(id)d_1 = ((SVGUIRotatingCtrl*)element)->GetAngle();\n"%texts
       
   785             elif element_type == ITEM_NOTEBOOK:
       
   786                 text += "  beremiz__QB%(location)s_%(id)d_3 = _copy__QB%(location)s_%(id)d_3 = ((SVGUINoteBook*)element)->GetCurrentPage();\n"%texts
       
   787                 text += "  beremiz__IB%(location)s_%(id)d_1 = _copy__IB%(location)s_%(id)d_1 = ((SVGUINoteBook*)element)->GetCurrentPage();\n"%texts
       
   788             elif element_type == ITEM_TRANSFORM:
       
   789                 text += "  beremiz__QD%(location)s_%(id)d_3 = _copy__QD%(location)s_%(id)d_3 = ((SVGUITransform*)element)->GetX();\n"%texts
       
   790                 text += "  beremiz__QD%(location)s_%(id)d_4 = _copy__QD%(location)s_%(id)d_4 = ((SVGUITransform*)element)->GetY();\n"%texts
       
   791                 text += "  beremiz__QD%(location)s_%(id)d_5 = _copy__QD%(location)s_%(id)d_5 = ((SVGUITransform*)element)->GetXScale();\n"%texts
       
   792                 text += "  beremiz__QD%(location)s_%(id)d_6 = _copy__QD%(location)s_%(id)d_6 = ((SVGUITransform*)element)->GetYScale();\n"%texts
       
   793                 text += "  beremiz__QD%(location)s_%(id)d_7 = _copy__QD%(location)s_%(id)d_7 = ((SVGUITransform*)element)->GetAngle();\n"%texts
       
   794                 text += "  beremiz__ID%(location)s_%(id)d_1 = _copy__ID%(location)s_%(id)d_1 = ((SVGUITransform*)element)->GetX();\n"%texts
       
   795                 text += "  beremiz__ID%(location)s_%(id)d_2 = _copy__ID%(location)s_%(id)d_2 = ((SVGUITransform*)element)->GetY();\n"%texts
       
   796         
       
   797         text += "\n  MyInitSem.Post();\n}\n\n"
       
   798         return text