plugins/c_ext/c_ext.py
author etisserant
Mon, 17 Sep 2007 18:04:13 +0200
changeset 45 00acf2162135
parent 31 33b38700d0db
child 47 fd45c291fed0
permissions -rw-r--r--
Now, C extension plugin do handle multiple files
import wx
import wx.stc as stc
import os, sys, shutil
from CppSTC import CppSTC
from plugger import PlugTemplate
import tempfile

class _Cfile:
    XSD = """<?xml version="1.0" encoding="ISO-8859-1" ?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <xsd:element name="C_Extension">
        <xsd:complexType>
          <xsd:attribute name="C_Files" type="xsd:string" use="required" default="myfile.c"/>
          <xsd:attribute name="CFLAGS" type="xsd:string" use="required"/>
          <xsd:attribute name="LDFLAGS" type="xsd:string" use="required"/>
        </xsd:complexType>
      </xsd:element>
    </xsd:schema>
    """
    def __init__(self):
        self.CheckCFilesExist()
        
    def CheckCFilesExist(self):
        for CFile in self.CFileNames():
            if not os.path.isfile(CFile):
                f = open(CFile, 'w')
                f.write("/*Empty*/")
                f.close()

    def CFileBaseNames(self):
        """
        Returns list of C files base names, out of C_Extension.C_Files, coma separated list
        """
        return map(str.strip,str(self.C_Extension.getC_Files()).split(','))

    def CFileName(self, fn):
        return os.path.join(self.PlugPath(),fn)

    def CFileNames(self):
        """
        Returns list of full C files paths, out of C_Extension.C_Files, coma separated list
        """
        return map(self.CFileName, self.CFileBaseNames())

    def SetParamsAttribute(self, path, value, logger):
        """
        Take actions if C_Files changed
        """
        # Get a C files list before changes
        oldnames = self.CFileNames()
        # Apply changes
        res = PlugTemplate.SetParamsAttribute(self, path, value, logger)
        # If changes was about C files,
        if path == "C_Extension.C_Files":
            # Create files if did not exist
            self.CheckCFilesExist()
            # Get new list
            newnames = self.CFileNames()
            # Move unused files into trash (temporary directory)
            for oldfile in oldnames:
                if oldfile not in newnames:
                    # define new "trash" name
                    trashname = os.path.join(tempfile.gettempdir(),os.path.basename(oldfile))
                    # move the file
                    shutil.move(oldfile, trashname)
                    # warn user
                    logger.write_warning("\"%s\" moved to \"%s\"\n"%(oldfile, trashname))
            return value, False
        return res

    _Views = {}
    def _OpenView(self, logger):
        lst = self.CFileBaseNames()

        dlg = wx.MultiChoiceDialog( self.GetPlugRoot().AppFrame, 
                                   "Pick some fruit from\nthis list",
                                   "wx.MultiChoiceDialog", lst)

        if (dlg.ShowModal() == wx.ID_OK):
            selections = dlg.GetSelections()
            for selected in [lst[x] for x in selections]:
                if selected not in self._Views:
                    # keep track of selected name as static for later close
                    def _onclose(evt, sel = selected):
                        self.SaveCView(sel)
                        self._Views.pop(sel)
                        evt.Skip()
                    New_View = wx.Frame(self.GetPlugRoot().AppFrame,-1)
                    New_View.Bind(wx.EVT_CLOSE, _onclose)
                    ed = CppSTC(New_View, wx.NewId())
                    ed.SetText(open(self.CFileName(selected)).read())
                    ed.EmptyUndoBuffer()
                    ed.Colourise(0, -1)
                    ed.SetMarginType(1, stc.STC_MARGIN_NUMBER)
                    ed.SetMarginWidth(1, 25)
                    New_View.ed = ed
                    New_View.Show()
                    self._Views[selected] = New_View

        dlg.Destroy()
        

    PluginMethods = [("Edit C File",_OpenView), ("Import C File",_OpenView)]

    def SaveCView(self, name):
        f = open(self.CFileName(name),'w')
        f.write(self._Views[name].ed.GetText())
        f.close()
        
    def OnPlugSave(self):
        for name in self._Views:
            self.SaveCView(name)
        return True

    def PlugGenerate_C(self, buildpath, locations, logger):
        """
        Generate C code
        @param current_location: Tupple containing plugin IEC location : %I0.0.4.5 => (0,0,4,5)
        @param locations: List of complete variables locations \
            [{"IEC_TYPE" : the IEC type (i.e. "INT", "STRING", ...)
            "NAME" : name of the variable (generally "__IW0_1_2" style)
            "DIR" : direction "Q","I" or "M"
            "SIZE" : size "X", "B", "W", "D", "L"
            "LOC" : tuple of interger for IEC location (0,1,2,...)
            }, ...]
        @return: [(C_file_name, CFLAGS),...] , LDFLAGS_TO_APPEND
        """
        current_location = self.GetCurrentLocation()
        # define a unique name for the generated C file
        location_str = "_".join(map(lambda x:str(x), current_location))
        res = []
        for CFile in self.CFileBaseNames():
            Gen_Cfile_path = os.path.join(buildpath, location_str + "_" + os.path.splitext(CFile)[0] + "_CFile.c" )
            f = open(Gen_Cfile_path,'w')
            f.write("/* Header generated by Beremiz c_ext plugin */\n")
            f.write("#include \"iec_std_lib.h\"\n")
            f.write("#define EXT_C_INIT __init_%s\n"%location_str)
            f.write("#define EXT_C_CLEANUP __init_%s\n"%location_str)
            f.write("#define EXT_C_PUBLISH __init_%s\n"%location_str)
            f.write("#define EXT_C_RETRIVE __init_%s\n"%location_str)
            for loc in locations:
                f.write(loc["IEC_TYPE"]+" "+loc["NAME"]+";\n")
            f.write("/* End of header generated by Beremiz c_ext plugin */\n\n")
            src_file = open(self.CFileName(CFile),'r')
            f.write(src_file.read())
            src_file.close()
            f.close()
            res.append((Gen_Cfile_path,str(self.C_Extension.getCFLAGS())))
        return res,str(self.C_Extension.getLDFLAGS())
    
class RootClass:

    PlugChildsTypes = [("C_File",_Cfile)]
    
    def PlugGenerate_C(self, buildpath, locations, logger):
        return [],""