wxglade_hmi/wxglade_hmi.py
author Laurent Bessard
Mon, 03 Jun 2013 11:52:13 +0200
changeset 1213 599e43ec921b
parent 1163 32599dcf311f
child 1256 02a710c7b5ed
permissions -rw-r--r--
Fixed bug when scroll in and out using wheel mouse in graph, range of data displayed could be out of bounds of whole data stored range
import wx
import os, sys, shutil
from xml.dom import minidom

from py_ext import PythonFileCTNMixin

class WxGladeHMI(PythonFileCTNMixin):

    ConfNodeMethods = [
        {"bitmap" : "editWXGLADE",
         "name" : _("WXGLADE GUI"),
         "tooltip" : _("Edit a WxWidgets GUI with WXGlade"),
         "method" : "_editWXGLADE"},
    ]

    def GetIconName(self):
        return "wxGlade"

    def ConfNodePath(self):
        return os.path.join(os.path.dirname(__file__))

    def _getWXGLADEpath(self, project_path=None):
        if project_path is None:
            project_path = self.CTNPath()
        # define name for wxGlade gui file
        return os.path.join(project_path, "hmi.wxg")

    def launch_wxglade(self, options, wait=False):
        from wxglade import __file__ as fileName
        path = os.path.dirname(fileName)
        glade = os.path.join(path, 'wxglade.py')
        if wx.Platform == '__WXMSW__':
            glade = "\"%s\""%glade
        mode = {False:os.P_NOWAIT, True:os.P_WAIT}[wait]
        os.spawnv(mode, sys.executable, ["\"%s\""%sys.executable] + [glade] + options)

    def OnCTNSave(self, from_project_path=None):
        if from_project_path is not None:
            shutil.copyfile(self._getWXGLADEpath(from_project_path),
                            self._getWXGLADEpath())
        return PythonFileCTNMixin.OnCTNSave(self, from_project_path)

    def CTNGenerate_C(self, buildpath, locations):
        
        hmi_frames = []
        
        wxgfile_path=self._getWXGLADEpath()
        if os.path.exists(wxgfile_path):
            wxgfile = open(wxgfile_path, 'r')
            wxgtree = minidom.parse(wxgfile)
            wxgfile.close()
            
            for node in wxgtree.childNodes[1].childNodes:
                if node.nodeType == wxgtree.ELEMENT_NODE:
                    hmi_frames.append({
                        "name" : node.getAttribute("name"),
                        "class" : node.getAttribute("class"),
                        "handlers" : [
                            hnode.firstChild.data for hnode in 
                            node.getElementsByTagName("handler")]})
                    
            hmipyfile_path=os.path.join(self._getBuildPath(), "hmi.py")
            if wx.Platform == '__WXMSW__':
                wxgfile_path = "\"%s\""%wxgfile_path
                wxghmipyfile_path = "\"%s\""%hmipyfile_path
            else:
                wxghmipyfile_path = hmipyfile_path
            self.launch_wxglade(['-o', wxghmipyfile_path, '-g', 'python', wxgfile_path], wait=True)
            
            hmipyfile = open(hmipyfile_path, 'r')
            define_hmi = hmipyfile.read().decode('utf-8')
            hmipyfile.close()
        
        declare_hmi = "\n".join(["%(name)s = None\n" % x + 
                          "\n".join(["%(class)s.%(h)s = %(h)s"%
                            dict(x,h=h) for h in x['handlers']])
                                for x in hmi_frames])
        global_hmi = "global %s\n"%",".join(
            [x["name"] for x in hmi_frames]) 
        init_hmi = "\n".join(["""\
def OnCloseFrame(evt):
    wx.MessageBox(_("Please stop PLC to close"))

%(name)s = %(class)s(None)
%(name)s.Bind(wx.EVT_CLOSE, OnCloseFrame)
%(name)s.Show()
""" % x for x in hmi_frames])
        cleanup_hmi = "\n".join(
            ["if %(name)s is not None: %(name)s.Destroy()" % x 
                for x in hmi_frames])
        
        self.PreSectionsTexts = {
            "globals":define_hmi,
            "start":global_hmi,
            "stop":global_hmi + cleanup_hmi
        }
        self.PostSectionsTexts = {
            "globals":declare_hmi,
            "start":init_hmi,
        }

        return PythonFileCTNMixin.CTNGenerate_C(self, buildpath, locations)

    def _editWXGLADE(self):
        wxg_filename = self._getWXGLADEpath()
        open_wxglade = True
        if not self.GetCTRoot().CheckProjectPathPerm():
            dialog = wx.MessageDialog(self.GetCTRoot().AppFrame,
                                      _("You don't have write permissions.\nOpen wxGlade anyway ?"),
                                      _("Open wxGlade"),
                                      wx.YES_NO|wx.ICON_QUESTION)
            open_wxglade = dialog.ShowModal() == wx.ID_YES
            dialog.Destroy()
        if open_wxglade:
            if not os.path.exists(wxg_filename):
                hmi_name = self.BaseParams.getName()
                open(wxg_filename,"w").write("""<?xml version="1.0"?>
    <application path="" name="" class="" option="0" language="python" top_window="%(name)s" encoding="UTF-8" use_gettext="0" overwrite="0" use_new_namespace="1" for_version="2.8" is_template="0">
        <object class="%(class)s" name="%(name)s" base="EditFrame">
            <style>wxDEFAULT_FRAME_STYLE</style>
            <title>frame_1</title>
            <object class="wxBoxSizer" name="sizer_1" base="EditBoxSizer">
                <orient>wxVERTICAL</orient>
            <object class="sizerslot" />
        </object>
        </object>
    </application>
    """ % {"name": hmi_name, "class": "Class_%s" % hmi_name})
            if wx.Platform == '__WXMSW__':
                wxg_filename = "\"%s\""%wxg_filename
            self.launch_wxglade([wxg_filename])