etisserant@31: import wx etisserant@31: import wx.stc as stc etisserant@31: import os, sys, shutil etisserant@31: from CppSTC import CppSTC etisserant@31: from plugger import PlugTemplate etisserant@45: import tempfile etisserant@31: etisserant@31: class _Cfile: etisserant@31: XSD = """ etisserant@31: etisserant@45: etisserant@31: etisserant@45: etisserant@45: etisserant@45: etisserant@31: etisserant@31: etisserant@31: etisserant@31: """ etisserant@31: def __init__(self): etisserant@45: self.CheckCFilesExist() etisserant@45: etisserant@45: def CheckCFilesExist(self): etisserant@45: for CFile in self.CFileNames(): etisserant@45: if not os.path.isfile(CFile): etisserant@45: f = open(CFile, 'w') etisserant@45: f.write("/*Empty*/") etisserant@45: f.close() etisserant@31: etisserant@45: def CFileBaseNames(self): etisserant@45: """ etisserant@45: Returns list of C files base names, out of C_Extension.C_Files, coma separated list etisserant@45: """ etisserant@45: return map(str.strip,str(self.C_Extension.getC_Files()).split(',')) etisserant@45: etisserant@45: def CFileName(self, fn): etisserant@45: return os.path.join(self.PlugPath(),fn) etisserant@45: etisserant@45: def CFileNames(self): etisserant@45: """ etisserant@45: Returns list of full C files paths, out of C_Extension.C_Files, coma separated list etisserant@45: """ etisserant@45: return map(self.CFileName, self.CFileBaseNames()) etisserant@31: etisserant@31: def SetParamsAttribute(self, path, value, logger): etisserant@45: """ etisserant@45: Take actions if C_Files changed etisserant@45: """ etisserant@45: # Get a C files list before changes etisserant@45: oldnames = self.CFileNames() etisserant@45: # Apply changes etisserant@31: res = PlugTemplate.SetParamsAttribute(self, path, value, logger) etisserant@45: # If changes was about C files, etisserant@45: if path == "C_Extension.C_Files": etisserant@45: # Create files if did not exist etisserant@45: self.CheckCFilesExist() etisserant@45: # Get new list etisserant@45: newnames = self.CFileNames() etisserant@45: # Move unused files into trash (temporary directory) etisserant@45: for oldfile in oldnames: etisserant@45: if oldfile not in newnames: etisserant@45: # define new "trash" name etisserant@45: trashname = os.path.join(tempfile.gettempdir(),os.path.basename(oldfile)) etisserant@45: # move the file etisserant@45: shutil.move(oldfile, trashname) etisserant@45: # warn user etisserant@45: logger.write_warning("\"%s\" moved to \"%s\"\n"%(oldfile, trashname)) etisserant@31: return value, False etisserant@31: return res etisserant@31: etisserant@45: _Views = {} etisserant@31: def _OpenView(self, logger): etisserant@45: lst = self.CFileBaseNames() etisserant@31: etisserant@45: dlg = wx.MultiChoiceDialog( self.GetPlugRoot().AppFrame, etisserant@47: "Choose C files to Edit :", etisserant@47: "Edit", lst) etisserant@31: etisserant@45: if (dlg.ShowModal() == wx.ID_OK): etisserant@45: selections = dlg.GetSelections() etisserant@45: for selected in [lst[x] for x in selections]: etisserant@45: if selected not in self._Views: etisserant@45: # keep track of selected name as static for later close etisserant@45: def _onclose(evt, sel = selected): etisserant@45: self.SaveCView(sel) etisserant@45: self._Views.pop(sel) etisserant@45: evt.Skip() etisserant@47: New_View = wx.Frame(self.GetPlugRoot().AppFrame,-1,selected) etisserant@45: New_View.Bind(wx.EVT_CLOSE, _onclose) etisserant@45: ed = CppSTC(New_View, wx.NewId()) etisserant@45: ed.SetText(open(self.CFileName(selected)).read()) etisserant@45: ed.EmptyUndoBuffer() etisserant@45: ed.Colourise(0, -1) etisserant@45: ed.SetMarginType(1, stc.STC_MARGIN_NUMBER) etisserant@45: ed.SetMarginWidth(1, 25) etisserant@45: New_View.ed = ed etisserant@45: New_View.Show() etisserant@45: self._Views[selected] = New_View etisserant@31: etisserant@45: dlg.Destroy() etisserant@45: etisserant@45: lbessard@65: PluginMethods = [ lbessard@65: {"name" : "Edit C File", lbessard@65: "tooltip" : "Edit C File", lbessard@65: "method" : _OpenView}, lbessard@65: {"name" : "Import C File", lbessard@65: "tooltip" : "Import C File", lbessard@65: "method" : _OpenView} lbessard@65: ] etisserant@45: etisserant@45: def SaveCView(self, name): etisserant@45: f = open(self.CFileName(name),'w') etisserant@45: f.write(self._Views[name].ed.GetText()) etisserant@45: f.close() etisserant@45: etisserant@31: def OnPlugSave(self): etisserant@45: for name in self._Views: etisserant@45: self.SaveCView(name) etisserant@31: return True etisserant@31: etisserant@31: def PlugGenerate_C(self, buildpath, locations, logger): etisserant@31: """ etisserant@31: Generate C code etisserant@31: @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5) etisserant@31: @param locations: List of complete variables locations \ etisserant@31: [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...) etisserant@31: "NAME" : name of the variable (generally "__IW0_1_2" style) etisserant@31: "DIR" : direction "Q","I" or "M" etisserant@31: "SIZE" : size "X", "B", "W", "D", "L" etisserant@31: "LOC" : tuple of interger for IEC location (0,1,2,...) etisserant@31: }, ...] etisserant@31: @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND etisserant@31: """ etisserant@31: current_location = self.GetCurrentLocation() etisserant@31: # define a unique name for the generated C file etisserant@45: location_str = "_".join(map(lambda x:str(x), current_location)) etisserant@45: res = [] etisserant@45: for CFile in self.CFileBaseNames(): etisserant@49: Gen_Cfile_path = os.path.join(buildpath, "CFile_%s_%s.c"%(location_str, os.path.splitext(CFile)[0])) etisserant@45: f = open(Gen_Cfile_path,'w') etisserant@45: f.write("/* Header generated by Beremiz c_ext plugin */\n") etisserant@45: f.write("#include \"iec_std_lib.h\"\n") etisserant@45: f.write("#define EXT_C_INIT __init_%s\n"%location_str) etisserant@45: f.write("#define EXT_C_CLEANUP __init_%s\n"%location_str) etisserant@45: f.write("#define EXT_C_PUBLISH __init_%s\n"%location_str) etisserant@45: f.write("#define EXT_C_RETRIVE __init_%s\n"%location_str) etisserant@45: for loc in locations: etisserant@45: f.write(loc["IEC_TYPE"]+" "+loc["NAME"]+";\n") etisserant@45: f.write("/* End of header generated by Beremiz c_ext plugin */\n\n") etisserant@45: src_file = open(self.CFileName(CFile),'r') etisserant@45: f.write(src_file.read()) etisserant@45: src_file.close() etisserant@45: f.close() etisserant@45: res.append((Gen_Cfile_path,str(self.C_Extension.getCFLAGS()))) etisserant@55: return res,str(self.C_Extension.getLDFLAGS()),True etisserant@31: etisserant@31: class RootClass: etisserant@31: etisserant@31: PlugChildsTypes = [("C_File",_Cfile)] etisserant@31: etisserant@31: def PlugGenerate_C(self, buildpath, locations, logger): etisserant@55: return [],"",False etisserant@31: etisserant@31: