lbessard@0: #!/usr/bin/env python lbessard@0: # -*- coding: utf-8 -*- lbessard@0: lbessard@3: #This file is part of Beremiz, a Integrated Development Environment for lbessard@3: #programming IEC 61131-3 automates supporting plcopen standard and CanFestival. lbessard@0: # lbessard@3: #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD lbessard@0: # lbessard@0: #See COPYING file for copyrights details. lbessard@0: # lbessard@0: #This library is free software; you can redistribute it and/or lbessard@0: #modify it under the terms of the GNU General Public lbessard@0: #License as published by the Free Software Foundation; either lbessard@0: #version 2.1 of the License, or (at your option) any later version. lbessard@0: # lbessard@0: #This library is distributed in the hope that it will be useful, lbessard@0: #but WITHOUT ANY WARRANTY; without even the implied warranty of lbessard@0: #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU lbessard@3: #General Public License for more details. lbessard@0: # lbessard@0: #You should have received a copy of the GNU General Public lbessard@0: #License along with this library; if not, write to the Free Software lbessard@0: #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA lbessard@0: etisserant@13: __version__ = "$Revision$" etisserant@13: lbessard@0: import wx lbessard@65: import wx.lib.buttons lbessard@5: lbessard@17: import types lbessard@0: etisserant@48: import time etisserant@48: lbessard@1: import os, re, platform, sys, time, traceback, getopt, commands etisserant@20: lbessard@17: from plugger import PluginsRoot lbessard@0: etisserant@48: from wxPopen import wxPopen3 etisserant@48: lbessard@97: SCROLLBAR_UNIT = 10 lbessard@97: WINDOW_COLOUR = wx.Colour(240,240,240) lbessard@97: lbessard@97: if wx.Platform == '__WXMSW__': lbessard@97: faces = { 'times': 'Times New Roman', lbessard@97: 'mono' : 'Courier New', lbessard@97: 'helv' : 'Arial', lbessard@97: 'other': 'Comic Sans MS', lbessard@98: 'size' : 16, lbessard@97: } lbessard@97: else: lbessard@97: faces = { 'times': 'Times', lbessard@97: 'mono' : 'Courier', lbessard@97: 'helv' : 'Helvetica', lbessard@97: 'other': 'new century schoolbook', lbessard@97: 'size' : 18, lbessard@97: } lbessard@97: lbessard@72: CWD = os.path.split(os.path.realpath(__file__))[0] lbessard@72: lbessard@97: gen_mini_GetBackgroundBrush = lambda obj:lambda dc: wx.Brush(obj.faceDnClr, wx.SOLID) lbessard@97: gen_mini_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenBitmapTextButton._GetLabelSize(obj)[:-1] + (False,)) lbessard@98: gen_textbutton_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenButton._GetLabelSize(obj)[:-1] + (False,)) lbessard@98: lbessard@98: def GenerateEmptyBitmap(width, height): lbessard@98: bitmap = wx.EmptyBitmap(width, height) lbessard@97: dc = wx.MemoryDC(bitmap) lbessard@97: dc.SetPen(wx.Pen(WINDOW_COLOUR)) lbessard@97: dc.SetBrush(wx.Brush(WINDOW_COLOUR)) lbessard@98: dc.DrawRectangle(0, 0, width, height) lbessard@97: return bitmap lbessard@97: lbessard@1: class LogPseudoFile: lbessard@1: """ Base class for file like objects to facilitate StdOut for the Shell.""" lbessard@1: def __init__(self, output = None): etisserant@7: self.red_white = wx.TextAttr("RED", "WHITE") etisserant@7: self.red_yellow = wx.TextAttr("RED", "YELLOW") etisserant@7: self.black_white = wx.TextAttr("BLACK", "WHITE") etisserant@7: self.default_style = None lbessard@1: self.output = output lbessard@1: lbessard@1: def writelines(self, l): lbessard@1: map(self.write, l) lbessard@1: etisserant@22: def write(self, s, style = None): lbessard@101: if not style : style=self.black_white etisserant@22: if self.default_style != style: etisserant@22: self.output.SetDefaultStyle(style) etisserant@22: self.default_style = style etisserant@7: self.output.AppendText(s) etisserant@7: etisserant@7: def write_warning(self, s): etisserant@22: self.write(s,self.red_white) etisserant@7: etisserant@7: def write_error(self, s): etisserant@22: self.write(s,self.red_yellow) lbessard@1: lbessard@1: def flush(self): lbessard@1: self.output.SetValue("") lbessard@1: lbessard@1: def isatty(self): lbessard@1: return false lbessard@1: etisserant@48: def LogCommand(self, Command, sz_limit = 100, no_stdout=False): etisserant@48: self.errlen = 0 etisserant@48: self.exitcode = None etisserant@48: self.outdata = "" etisserant@48: self.errdata = "" etisserant@48: etisserant@48: def output(v): etisserant@48: self.outdata += v etisserant@48: if not no_stdout: etisserant@48: self.write(v) etisserant@48: etisserant@48: def errors(v): etisserant@48: self.errdata += v etisserant@48: self.errlen += 1 etisserant@48: if self.errlen > sz_limit: etisserant@48: p.kill() etisserant@48: self.write_warning(v) etisserant@48: etisserant@48: def fin(pid,ecode): etisserant@48: self.exitcode = ecode etisserant@48: if self.exitcode != 0: etisserant@49: self.write(Command + "\n") etisserant@49: self.write_warning("exited with status %d (pid %d)\n"%(ecode,pid)) etisserant@48: etisserant@48: def spin(p): etisserant@48: while not p.finished: etisserant@48: wx.Yield() etisserant@48: time.sleep(0.01) etisserant@48: etisserant@48: input = [] etisserant@48: p = wxPopen3(Command, input, output, errors, fin, self.output) etisserant@89: if p.pid: etisserant@89: spin(p) etisserant@48: etisserant@48: return (self.exitcode, self.outdata, self.errdata) etisserant@20: lbessard@17: [ID_BEREMIZ, ID_BEREMIZMAINSPLITTER, lbessard@97: ID_BEREMIZPLCCONFIG, ID_BEREMIZLOGCONSOLE, lbessard@97: ] = [wx.NewId() for _init_ctrls in range(4)] lbessard@0: lbessard@4: [ID_BEREMIZFILEMENUITEMS0, ID_BEREMIZFILEMENUITEMS1, lbessard@4: ID_BEREMIZFILEMENUITEMS2, ID_BEREMIZFILEMENUITEMS3, lbessard@4: ID_BEREMIZFILEMENUITEMS5, ID_BEREMIZFILEMENUITEMS7, lbessard@0: ] = [wx.NewId() for _init_coll_FileMenu_Items in range(6)] lbessard@0: lbessard@4: [ID_BEREMIZEDITMENUITEMS0, ID_BEREMIZEDITMENUITEMS2, lbessard@4: ID_BEREMIZEDITMENUITEMS3, lbessard@0: ] = [wx.NewId() for _init_coll_EditMenu_Items in range(3)] lbessard@0: lbessard@4: [ID_BEREMIZRUNMENUITEMS0, ID_BEREMIZRUNMENUITEMS2, lbessard@4: ID_BEREMIZRUNMENUITEMS3, ID_BEREMIZRUNMENUITEMS5, lbessard@0: ] = [wx.NewId() for _init_coll_EditMenu_Items in range(4)] lbessard@0: lbessard@4: [ID_BEREMIZHELPMENUITEMS0, ID_BEREMIZHELPMENUITEMS1, lbessard@0: ] = [wx.NewId() for _init_coll_HelpMenu_Items in range(2)] lbessard@0: lbessard@0: class Beremiz(wx.Frame): lbessard@0: lbessard@0: def _init_coll_FileMenu_Items(self, parent): lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS0, lbessard@0: kind=wx.ITEM_NORMAL, text=u'New\tCTRL+N') lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS1, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Open\tCTRL+O') lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS2, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Save\tCTRL+S') lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS3, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Close Project') lbessard@0: parent.AppendSeparator() lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS5, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Properties') lbessard@0: parent.AppendSeparator() lbessard@4: parent.Append(help='', id=ID_BEREMIZFILEMENUITEMS7, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Quit\tCTRL+Q') lbessard@0: self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS0) lbessard@0: self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS1) lbessard@0: self.Bind(wx.EVT_MENU, self.OnSaveProjectMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS2) lbessard@0: self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS3) lbessard@0: self.Bind(wx.EVT_MENU, self.OnPropertiesMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS5) lbessard@0: self.Bind(wx.EVT_MENU, self.OnQuitMenu, lbessard@4: id=ID_BEREMIZFILEMENUITEMS7) lbessard@0: lbessard@0: def _init_coll_EditMenu_Items(self, parent): lbessard@4: parent.Append(help='', id=ID_BEREMIZEDITMENUITEMS0, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Edit PLC\tCTRL+R') lbessard@0: parent.AppendSeparator() lbessard@4: parent.Append(help='', id=ID_BEREMIZEDITMENUITEMS2, lbessard@17: kind=wx.ITEM_NORMAL, text=u'Add Plugin') lbessard@4: parent.Append(help='', id=ID_BEREMIZEDITMENUITEMS3, lbessard@17: kind=wx.ITEM_NORMAL, text=u'Delete Plugin') lbessard@0: self.Bind(wx.EVT_MENU, self.OnEditPLCMenu, lbessard@4: id=ID_BEREMIZEDITMENUITEMS0) lbessard@17: self.Bind(wx.EVT_MENU, self.OnAddMenu, lbessard@4: id=ID_BEREMIZEDITMENUITEMS2) lbessard@17: self.Bind(wx.EVT_MENU, self.OnDeleteMenu, lbessard@4: id=ID_BEREMIZEDITMENUITEMS3) lbessard@0: lbessard@0: def _init_coll_RunMenu_Items(self, parent): lbessard@4: parent.Append(help='', id=ID_BEREMIZRUNMENUITEMS0, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Build\tCTRL+R') lbessard@0: parent.AppendSeparator() lbessard@4: parent.Append(help='', id=ID_BEREMIZRUNMENUITEMS2, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Simulate') lbessard@4: parent.Append(help='', id=ID_BEREMIZRUNMENUITEMS3, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Run') lbessard@0: parent.AppendSeparator() lbessard@4: parent.Append(help='', id=ID_BEREMIZRUNMENUITEMS5, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Save Log') lbessard@1: self.Bind(wx.EVT_MENU, self.OnBuildMenu, lbessard@4: id=ID_BEREMIZRUNMENUITEMS0) lbessard@0: self.Bind(wx.EVT_MENU, self.OnSimulateMenu, lbessard@4: id=ID_BEREMIZRUNMENUITEMS2) lbessard@0: self.Bind(wx.EVT_MENU, self.OnRunMenu, lbessard@4: id=ID_BEREMIZRUNMENUITEMS3) lbessard@0: self.Bind(wx.EVT_MENU, self.OnSaveLogMenu, lbessard@4: id=ID_BEREMIZRUNMENUITEMS5) lbessard@0: lbessard@0: def _init_coll_HelpMenu_Items(self, parent): lbessard@4: parent.Append(help='', id=ID_BEREMIZHELPMENUITEMS0, lbessard@0: kind=wx.ITEM_NORMAL, text=u'Beremiz\tF1') lbessard@4: parent.Append(help='', id=ID_BEREMIZHELPMENUITEMS1, lbessard@0: kind=wx.ITEM_NORMAL, text=u'About') lbessard@0: self.Bind(wx.EVT_MENU, self.OnBeremizMenu, lbessard@4: id=ID_BEREMIZHELPMENUITEMS0) lbessard@0: self.Bind(wx.EVT_MENU, self.OnAboutMenu, lbessard@4: id=ID_BEREMIZHELPMENUITEMS1) lbessard@0: lbessard@0: def _init_coll_menuBar1_Menus(self, parent): lbessard@0: parent.Append(menu=self.FileMenu, title=u'File') etisserant@28: #parent.Append(menu=self.EditMenu, title=u'Edit') etisserant@28: #parent.Append(menu=self.RunMenu, title=u'Run') lbessard@0: parent.Append(menu=self.HelpMenu, title=u'Help') lbessard@0: lbessard@0: def _init_utils(self): lbessard@0: self.menuBar1 = wx.MenuBar() lbessard@0: self.FileMenu = wx.Menu(title=u'') etisserant@28: #self.EditMenu = wx.Menu(title=u'') etisserant@28: #self.RunMenu = wx.Menu(title=u'') lbessard@0: self.HelpMenu = wx.Menu(title=u'') lbessard@0: lbessard@0: self._init_coll_menuBar1_Menus(self.menuBar1) lbessard@0: self._init_coll_FileMenu_Items(self.FileMenu) etisserant@28: #self._init_coll_EditMenu_Items(self.EditMenu) etisserant@28: #self._init_coll_RunMenu_Items(self.RunMenu) lbessard@0: self._init_coll_HelpMenu_Items(self.HelpMenu) lbessard@0: lbessard@97: def _init_coll_PLCConfigMainSizer_Items(self, parent): lbessard@97: parent.AddSizer(self.PLCParamsSizer, 0, border=10, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) lbessard@97: parent.AddSizer(self.PluginTreeSizer, 0, border=10, flag=wx.BOTTOM|wx.LEFT|wx.RIGHT) lbessard@97: lbessard@97: def _init_coll_PLCConfigMainSizer_Growables(self, parent): lbessard@67: parent.AddGrowableCol(0) lbessard@67: parent.AddGrowableRow(1) lbessard@67: lbessard@97: def _init_coll_PluginTreeSizer_Growables(self, parent): lbessard@17: parent.AddGrowableCol(0) lbessard@97: parent.AddGrowableCol(1) lbessard@0: lbessard@0: def _init_sizers(self): lbessard@97: self.PLCConfigMainSizer = wx.FlexGridSizer(cols=1, hgap=2, rows=2, vgap=2) lbessard@97: self.PLCParamsSizer = wx.BoxSizer(wx.VERTICAL) lbessard@99: self.PluginTreeSizer = wx.FlexGridSizer(cols=3, hgap=0, rows=0, vgap=2) lbessard@97: lbessard@97: self._init_coll_PLCConfigMainSizer_Items(self.PLCConfigMainSizer) lbessard@97: self._init_coll_PLCConfigMainSizer_Growables(self.PLCConfigMainSizer) lbessard@97: self._init_coll_PluginTreeSizer_Growables(self.PluginTreeSizer) lbessard@97: lbessard@97: self.PLCConfig.SetSizer(self.PLCConfigMainSizer) lbessard@97: lbessard@0: def _init_ctrls(self, prnt): lbessard@4: wx.Frame.__init__(self, id=ID_BEREMIZ, name=u'Beremiz', lbessard@17: parent=prnt, pos=wx.Point(0, 0), size=wx.Size(1000, 600), lbessard@25: style=wx.DEFAULT_FRAME_STYLE|wx.CLIP_CHILDREN, title=u'Beremiz') lbessard@0: self._init_utils() lbessard@17: self.SetClientSize(wx.Size(1000, 600)) lbessard@0: self.SetMenuBar(self.menuBar1) lbessard@62: self.Bind(wx.EVT_ACTIVATE, self.OnFrameActivated) lbessard@0: lbessard@71: if wx.VERSION < (2, 8, 0): lbessard@71: self.MainSplitter = wx.SplitterWindow(id=ID_BEREMIZMAINSPLITTER, lbessard@71: name='MainSplitter', parent=self, point=wx.Point(0, 0), lbessard@71: size=wx.Size(0, 0), style=wx.SP_3D) lbessard@71: self.MainSplitter.SetNeedUpdating(True) lbessard@71: self.MainSplitter.SetMinimumPaneSize(1) lbessard@71: lbessard@97: parent = self.MainSplitter lbessard@97: else: lbessard@97: parent = self lbessard@97: lbessard@97: self.PLCConfig = wx.ScrolledWindow(id=ID_BEREMIZPLCCONFIG, lbessard@97: name='PLCConfig', parent=parent, pos=wx.Point(0, 0), lbessard@97: size=wx.Size(-1, -1), style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL) lbessard@97: self.PLCConfig.SetBackgroundColour(wx.WHITE) lbessard@97: self.PLCConfig.Bind(wx.EVT_SIZE, self.OnMoveWindow) lbessard@97: lbessard@97: self.LogConsole = wx.TextCtrl(id=ID_BEREMIZLOGCONSOLE, value='', lbessard@97: name='LogConsole', parent=parent, pos=wx.Point(0, 0), lbessard@71: size=wx.Size(0, 0), style=wx.TE_MULTILINE|wx.TE_RICH2) lbessard@97: lbessard@97: if wx.VERSION < (2, 8, 0): lbessard@97: self.MainSplitter.SplitHorizontally(self.PLCConfig, self.LogConsole, -250) lbessard@97: lbessard@71: else: lbessard@82: self.AUIManager = wx.aui.AuiManager(self) lbessard@82: self.AUIManager.SetDockSizeConstraint(0.5, 0.5) lbessard@97: lbessard@97: self.AUIManager.AddPane(self.PLCConfig, wx.aui.AuiPaneInfo().CenterPane()) lbessard@97: lbessard@97: self.AUIManager.AddPane(self.LogConsole, wx.aui.AuiPaneInfo(). lbessard@97: Caption("Log Console").Bottom().Layer(1). lbessard@97: BestSize(wx.Size(800, 200)).CloseButton(False)) lbessard@82: lbessard@71: self.AUIManager.Update() etisserant@13: lbessard@97: self._init_sizers() lbessard@97: etisserant@13: def __init__(self, parent, projectOpen): lbessard@0: self._init_ctrls(parent) lbessard@0: lbessard@17: self.Log = LogPseudoFile(self.LogConsole) lbessard@17: etisserant@20: self.PluginRoot = PluginsRoot(self) lbessard@82: self.DisableEvents = False lbessard@17: lbessard@97: self.PluginInfos = {} lbessard@97: lbessard@17: if projectOpen: etisserant@24: self.PluginRoot.LoadProject(projectOpen, self.Log) lbessard@97: self.RefreshPLCParams() lbessard@17: self.RefreshPluginTree() lbessard@82: lbessard@0: self.RefreshMainMenu() lbessard@62: lbessard@97: def OnMoveWindow(self, event): lbessard@97: self.GetBestSize() lbessard@97: self.RefreshScrollBars() lbessard@97: event.Skip() lbessard@97: lbessard@62: def OnFrameActivated(self, event): lbessard@62: if not event.GetActive(): lbessard@62: self.PluginRoot.RefreshPluginsBlockLists() lbessard@62: lbessard@0: def RefreshMainMenu(self): lbessard@0: if self.menuBar1: lbessard@17: if self.PluginRoot.HasProjectOpened(): lbessard@42: ## self.menuBar1.EnableTop(1, True) lbessard@42: ## self.menuBar1.EnableTop(2, True) lbessard@17: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS2, True) lbessard@17: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS3, True) lbessard@17: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS5, True) lbessard@17: else: lbessard@42: ## self.menuBar1.EnableTop(1, False) lbessard@42: ## self.menuBar1.EnableTop(2, False) lbessard@4: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS2, False) lbessard@4: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS3, False) lbessard@4: self.FileMenu.Enable(ID_BEREMIZFILEMENUITEMS5, False) lbessard@17: lbessard@97: def RefreshScrollBars(self): lbessard@97: xstart, ystart = self.PLCConfig.GetViewStart() lbessard@97: window_size = self.PLCConfig.GetClientSize() lbessard@97: sizer = self.PLCConfig.GetSizer() lbessard@97: if sizer: lbessard@97: maxx, maxy = sizer.GetMinSize() lbessard@97: self.PLCConfig.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, lbessard@101: maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, xstart, ystart) lbessard@97: lbessard@97: def RefreshPLCParams(self): lbessard@97: self.ClearSizer(self.PLCParamsSizer) lbessard@97: lbessard@97: if self.PluginRoot.HasProjectOpened(): lbessard@97: plcwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1)) lbessard@97: plcwindow.SetBackgroundColour(WINDOW_COLOUR) lbessard@97: self.PLCParamsSizer.AddWindow(plcwindow, 0, border=0, flag=wx.GROW) lbessard@97: lbessard@98: plcwindowsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@97: plcwindow.SetSizer(plcwindowsizer) lbessard@97: lbessard@97: st = wx.StaticText(plcwindow, -1) lbessard@98: st.SetFont(wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"])) lbessard@98: st.SetLabel(self.PluginRoot.GetProjectName()) lbessard@98: plcwindowsizer.AddWindow(st, 0, border=5, flag=wx.ALL|wx.ALIGN_CENTER) lbessard@98: lbessard@98: plcwindowmainsizer = wx.BoxSizer(wx.VERTICAL) lbessard@98: plcwindowsizer.AddSizer(plcwindowmainsizer, 0, border=5, flag=wx.ALL) lbessard@98: lbessard@98: plcwindowbuttonsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@98: plcwindowmainsizer.AddSizer(plcwindowbuttonsizer, 0, border=0, flag=wx.ALIGN_CENTER) lbessard@98: lbessard@98: msizer = self.GenerateMethodButtonSizer(self.PluginRoot, plcwindow) lbessard@98: plcwindowbuttonsizer.AddSizer(msizer, 0, border=0, flag=wx.GROW) lbessard@97: lbessard@97: paramswindow = wx.Panel(plcwindow, -1, size=wx.Size(-1, -1)) lbessard@97: paramswindow.SetBackgroundColour(WINDOW_COLOUR) lbessard@98: plcwindowbuttonsizer.AddWindow(paramswindow, 0, border=0, flag=0) lbessard@97: lbessard@97: psizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@97: paramswindow.SetSizer(psizer) lbessard@97: lbessard@97: plugin_infos = self.PluginRoot.GetParamsAttributes() lbessard@97: self.RefreshSizerElement(paramswindow, psizer, self.PluginRoot, plugin_infos, None, False) lbessard@97: lbessard@97: paramswindow.Hide() lbessard@97: lbessard@97: minimizebutton_id = wx.NewId() lbessard@97: minimizebutton = wx.lib.buttons.GenBitmapToggleButton(id=minimizebutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'Maximize.png')), lbessard@97: name='MinimizeButton', parent=plcwindow, pos=wx.Point(0, 0), lbessard@97: size=wx.Size(24, 24), style=wx.NO_BORDER) lbessard@97: minimizebutton.GetBackgroundBrush = gen_mini_GetBackgroundBrush(minimizebutton) lbessard@97: minimizebutton.SetBackgroundColour(wx.Colour(208, 208, 208)) lbessard@97: minimizebutton.labelDelta = 0 lbessard@97: minimizebutton.SetBezelWidth(0) lbessard@97: minimizebutton.SetUseFocusIndicator(False) lbessard@97: minimizebutton.SetBitmapSelected(wx.Bitmap(os.path.join(CWD, 'images', 'Minimize.png'))) lbessard@99: plcwindowbuttonsizer.AddWindow(minimizebutton, 0, border=5, flag=wx.ALL) lbessard@99: lbessard@99: if len(self.PluginRoot.PlugChildsTypes) > 0: lbessard@99: addsizer = self.GenerateAddButtonSizer(self.PluginRoot, plcwindow) lbessard@99: plcwindowbuttonsizer.AddSizer(addsizer, 0, border=0, flag=0) lbessard@99: else: lbessard@99: addsizer = None lbessard@99: lbessard@97: def togglewindow(event): lbessard@97: if minimizebutton.GetToggle(): lbessard@97: paramswindow.Show() lbessard@97: msizer.SetCols(1) lbessard@99: if addsizer is not None: lbessard@99: addsizer.SetCols(1) lbessard@97: else: lbessard@97: paramswindow.Hide() lbessard@97: msizer.SetCols(len(self.PluginRoot.PluginMethods)) lbessard@99: if addsizer is not None: lbessard@99: addsizer.SetCols(len(self.PluginRoot.PlugChildsTypes)) lbessard@97: self.PLCConfigMainSizer.Layout() lbessard@97: self.RefreshScrollBars() lbessard@97: event.Skip() lbessard@97: minimizebutton.Bind(wx.EVT_BUTTON, togglewindow, id=minimizebutton_id) lbessard@101: lbessard@101: self.PLCConfigMainSizer.Layout() lbessard@101: self.RefreshScrollBars() lbessard@99: lbessard@99: def GenerateAddButtonSizer(self, plugin, parent, horizontal = True): lbessard@99: if horizontal: lbessard@99: addsizer = wx.FlexGridSizer(cols=len(plugin.PluginMethods)) lbessard@99: else: lbessard@99: addsizer = wx.FlexGridSizer(cols=1) lbessard@98: for name, XSDClass in plugin.PlugChildsTypes: lbessard@98: addbutton_id = wx.NewId() lbessard@98: addbutton = wx.lib.buttons.GenButton(id=addbutton_id, label="Add %s"%name, lbessard@98: name='AddBusButton', parent=parent, pos=wx.Point(0, 0), lbessard@98: style=wx.NO_BORDER) lbessard@98: font = addbutton.GetFont() lbessard@98: font.SetUnderlined(True) lbessard@98: addbutton.SetFont(font) lbessard@98: addbutton._GetLabelSize = gen_textbutton_GetLabelSize(addbutton) lbessard@98: addbutton.SetForegroundColour(wx.BLUE) lbessard@98: addbutton.SetToolTipString("Add a %s plugin to this one"%name) lbessard@98: addbutton.Bind(wx.EVT_BUTTON, self._GetAddPluginFunction(name, plugin), id=addbutton_id) lbessard@99: addsizer.AddWindow(addbutton, 0, border=0, flag=0) lbessard@98: return addsizer lbessard@98: lbessard@98: def GenerateMethodButtonSizer(self, plugin, parent, horizontal = True): lbessard@98: if horizontal: lbessard@98: msizer = wx.FlexGridSizer(cols=len(plugin.PluginMethods)) lbessard@98: else: lbessard@98: msizer = wx.FlexGridSizer(cols=1) lbessard@98: for plugin_method in plugin.PluginMethods: lbessard@98: if "method" in plugin_method: lbessard@98: id = wx.NewId() lbessard@98: button = wx.lib.buttons.GenBitmapTextButton(id=id, parent=parent, lbessard@98: bitmap=wx.Bitmap(os.path.join(CWD, "%s24x24.png"%plugin_method.get("bitmap", os.path.join("images", "Unknown")))), label=plugin_method["name"], lbessard@98: name=plugin_method["name"], pos=wx.DefaultPosition, style=wx.NO_BORDER) lbessard@98: button.SetToolTipString(plugin_method["tooltip"]) lbessard@98: button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(plugin, plugin_method["method"]), id=id) lbessard@98: #hack to force size to mini lbessard@98: button._GetLabelSize = gen_mini_GetLabelSize(button) lbessard@98: #button._GetLabelSize = lambda :(-1,-1,False) lbessard@98: msizer.AddWindow(button, 0, border=0, flag=0) lbessard@98: return msizer lbessard@97: lbessard@17: def RefreshPluginTree(self): lbessard@97: self.ClearSizer(self.PluginTreeSizer) lbessard@97: if self.PluginRoot.HasProjectOpened(): lbessard@97: index = [0] lbessard@97: for child in self.PluginRoot.IECSortedChilds(): lbessard@97: self.GenerateTreeBranch(child, index) lbessard@97: if not self.PluginInfos[child]["expanded"]: lbessard@97: self.CollapsePlugin(child) lbessard@97: self.PLCConfigMainSizer.Layout() lbessard@97: self.RefreshScrollBars() lbessard@97: lbessard@97: def ExpandPlugin(self, plugin, force = False): lbessard@97: for child in self.PluginInfos[plugin]["children"]: lbessard@97: self.PluginTreeSizer.Show(self.PluginInfos[child]["left"]) lbessard@99: self.PluginTreeSizer.Show(self.PluginInfos[child]["middle"]) lbessard@97: self.PluginTreeSizer.Show(self.PluginInfos[child]["right"]) lbessard@97: if force or not self.PluginInfos[child]["expanded"]: lbessard@97: self.ExpandPlugin(child, force) lbessard@97: if force: lbessard@97: self.PluginInfos[child]["expanded"] = True lbessard@97: lbessard@97: def CollapsePlugin(self, plugin, force = False): lbessard@97: for child in self.PluginInfos[plugin]["children"]: lbessard@97: self.PluginTreeSizer.Hide(self.PluginInfos[child]["left"]) lbessard@99: self.PluginTreeSizer.Hide(self.PluginInfos[child]["middle"]) lbessard@97: self.PluginTreeSizer.Hide(self.PluginInfos[child]["right"]) lbessard@97: if force or self.PluginInfos[child]["expanded"]: lbessard@97: self.CollapsePlugin(child, force) lbessard@97: if force: lbessard@97: self.PluginInfos[child]["expanded"] = False lbessard@97: lbessard@97: def GenerateTreeBranch(self, plugin, index): lbessard@97: leftwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1)) lbessard@97: leftwindow.SetBackgroundColour(WINDOW_COLOUR) lbessard@97: lbessard@97: if plugin not in self.PluginInfos: lbessard@99: self.PluginInfos[plugin] = {"expanded" : False, "left_visible" : False, "middle_visible" : False} lbessard@97: lbessard@97: self.PluginInfos[plugin]["children"] = plugin.IECSortedChilds() lbessard@97: lbessard@97: self.PluginTreeSizer.AddWindow(leftwindow, 0, border=0, flag=wx.GROW) lbessard@97: lbessard@97: leftwindowsizer = wx.FlexGridSizer(cols=1, rows=2) lbessard@97: leftwindowsizer.AddGrowableCol(0) lbessard@97: leftwindowsizer.AddGrowableRow(1) lbessard@97: leftwindow.SetSizer(leftwindowsizer) lbessard@97: lbessard@97: leftbuttonmainsizer = wx.FlexGridSizer(cols=3, rows=1) lbessard@97: leftbuttonmainsizer.AddGrowableCol(0) lbessard@98: leftwindowsizer.AddSizer(leftbuttonmainsizer, 0, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.TOP) lbessard@97: lbessard@97: leftbuttonsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@97: leftbuttonmainsizer.AddSizer(leftbuttonsizer, 0, border=15, flag=wx.GROW|wx.RIGHT) lbessard@97: lbessard@97: ieccsizer = wx.BoxSizer(wx.VERTICAL) lbessard@97: leftbuttonsizer.AddSizer(ieccsizer, 0, border=15, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) lbessard@97: lbessard@97: plugin_IECChannel = plugin.BaseParams.getIEC_Channel() lbessard@97: lbessard@97: if plugin_IECChannel > 0: lbessard@98: ieccdownbutton_id = wx.NewId() lbessard@98: ieccdownbutton = wx.lib.buttons.GenBitmapButton(id=ieccdownbutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'IECCDown.png')), lbessard@98: name='IECCDownButton', parent=leftwindow, pos=wx.Point(0, 0), lbessard@98: size=wx.Size(16, 16), style=wx.NO_BORDER) lbessard@97: ieccdownbutton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(plugin, plugin_IECChannel - 1), id=ieccdownbutton_id) lbessard@98: ieccsizer.AddWindow(ieccdownbutton, 0, border=0, flag=wx.ALIGN_CENTER) lbessard@97: else: lbessard@98: staticbitmap = wx.StaticBitmap(id=-1, bitmap=GenerateEmptyBitmap(16, 16), lbessard@98: name="staticBitmap", parent=leftwindow, lbessard@98: pos=wx.Point(0, 0), size=wx.Size(16, 16), style=0) lbessard@98: ieccsizer.AddWindow(staticbitmap, 0, border=0, flag=wx.ALIGN_CENTER) lbessard@97: lbessard@97: st = wx.StaticText(leftwindow, -1) lbessard@97: st.SetFont(wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"])) lbessard@97: st.SetLabel(plugin.GetFullIEC_Channel()) lbessard@97: ieccsizer.AddWindow(st, 0, border=0, flag=0) lbessard@97: lbessard@97: ieccupbutton_id = wx.NewId() lbessard@97: ieccupbutton = wx.lib.buttons.GenBitmapTextButton(id=ieccupbutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'IECCUp.png')), lbessard@97: name='IECCUpButton', parent=leftwindow, pos=wx.Point(0, 0), lbessard@97: size=wx.Size(16, 16), style=wx.NO_BORDER) lbessard@97: ieccupbutton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(plugin, plugin_IECChannel + 1), id=ieccupbutton_id) lbessard@97: ieccsizer.AddWindow(ieccupbutton, 0, border=0, flag=wx.ALIGN_CENTER) lbessard@97: lbessard@97: if len(self.PluginInfos[plugin]["children"]) > 0: lbessard@97: expandbutton_id = wx.NewId() lbessard@97: expandbutton = wx.lib.buttons.GenBitmapToggleButton(id=expandbutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'plus.png')), lbessard@97: name='ExpandButton', parent=leftwindow, pos=wx.Point(0, 0), lbessard@97: size=wx.Size(13, 13), style=wx.NO_BORDER) lbessard@97: expandbutton.labelDelta = 0 lbessard@97: expandbutton.SetBezelWidth(0) lbessard@97: expandbutton.SetUseFocusIndicator(False) lbessard@97: expandbutton.SetBitmapSelected(wx.Bitmap(os.path.join(CWD, 'images', 'minus.png'))) lbessard@97: expandbutton.SetToggle(self.PluginInfos[plugin]["expanded"]) lbessard@97: lbessard@97: def togglebutton(event): lbessard@97: if expandbutton.GetToggle(): lbessard@97: self.ExpandPlugin(plugin) etisserant@89: else: lbessard@97: self.CollapsePlugin(plugin) lbessard@97: self.PluginInfos[plugin]["expanded"] = expandbutton.GetToggle() lbessard@97: self.PLCConfigMainSizer.Layout() lbessard@97: self.RefreshScrollBars() lbessard@97: event.Skip() lbessard@97: expandbutton.Bind(wx.EVT_BUTTON, togglebutton, id=expandbutton_id) lbessard@97: leftbuttonsizer.AddWindow(expandbutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) lbessard@97: lbessard@97: tc_id = wx.NewId() lbessard@97: tc = wx.TextCtrl(leftwindow, tc_id, size=wx.Size(150, 35), style=wx.TE_PROCESS_ENTER|wx.NO_BORDER) lbessard@97: tc.SetFont(wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, wx.BOLD, faceName = faces["helv"])) lbessard@97: tc.SetValue(plugin.MandatoryParams[1].getName()) lbessard@97: tc.Bind(wx.EVT_TEXT_ENTER, self.GetTextCtrlCallBackFunction(tc, plugin, "BaseParams.Name"), id=tc_id) lbessard@97: leftbuttonsizer.AddWindow(tc, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) lbessard@97: lbessard@97: enablebutton_id = wx.NewId() lbessard@99: enablebutton = wx.lib.buttons.GenBitmapToggleButton(id=enablebutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'Disabled.png')), lbessard@99: name='EnableButton', parent=leftwindow, pos=wx.Point(0, 0), style=wx.NO_BORDER) lbessard@99: enablebutton.SetToolTipString("Enable/Disable this plugin") lbessard@97: enablebutton.GetBackgroundBrush = gen_mini_GetBackgroundBrush(enablebutton) lbessard@97: enablebutton.SetBackgroundColour(wx.Colour(208, 208, 208)) lbessard@97: enablebutton.labelDelta = 0 lbessard@97: enablebutton.SetBezelWidth(0) lbessard@97: enablebutton.SetUseFocusIndicator(False) lbessard@97: enablebutton.SetBitmapSelected(wx.Bitmap(os.path.join(CWD, 'images', 'Enabled.png'))) lbessard@97: enablebutton.SetToggle(plugin.MandatoryParams[1].getEnabled()) lbessard@97: def toggleenablebutton(event): lbessard@97: res, StructChanged = plugin.SetParamsAttribute("BaseParams.Enabled", enablebutton.GetToggle(), self.Log) lbessard@97: if StructChanged: wx.CallAfter(self.RefreshPluginTree) lbessard@97: enablebutton.SetToggle(res) lbessard@97: event.Skip() lbessard@97: enablebutton.Bind(wx.EVT_BUTTON, toggleenablebutton, id=enablebutton_id) lbessard@97: leftbuttonsizer.AddWindow(enablebutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) lbessard@97: lbessard@97: leftminimizebutton_id = wx.NewId() lbessard@97: leftminimizebutton = wx.lib.buttons.GenBitmapToggleButton(id=leftminimizebutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'Maximize.png')), lbessard@97: name='MinimizeButton', parent=leftwindow, pos=wx.Point(0, 0), lbessard@97: size=wx.Size(24, 24), style=wx.NO_BORDER) lbessard@97: leftminimizebutton.GetBackgroundBrush = gen_mini_GetBackgroundBrush(leftminimizebutton) lbessard@97: leftminimizebutton.SetBackgroundColour(wx.Colour(208, 208, 208)) lbessard@97: leftminimizebutton.labelDelta = 0 lbessard@97: leftminimizebutton.SetBezelWidth(0) lbessard@97: leftminimizebutton.SetUseFocusIndicator(False) lbessard@97: leftminimizebutton.SetBitmapSelected(wx.Bitmap(os.path.join(CWD, 'images', 'Minimize.png'))) lbessard@97: leftminimizebutton.SetToggle(self.PluginInfos[plugin]["left_visible"]) lbessard@97: def toggleleftwindow(event): lbessard@97: if leftminimizebutton.GetToggle(): lbessard@97: leftwindowsizer.Show(1) lbessard@97: else: lbessard@97: leftwindowsizer.Hide(1) lbessard@97: self.PluginInfos[plugin]["left_visible"] = leftminimizebutton.GetToggle() lbessard@97: self.PLCConfigMainSizer.Layout() lbessard@97: self.RefreshScrollBars() lbessard@97: event.Skip() lbessard@97: leftminimizebutton.Bind(wx.EVT_BUTTON, toggleleftwindow, id=leftminimizebutton_id) lbessard@97: leftbuttonmainsizer.AddWindow(leftminimizebutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER) lbessard@97: lbessard@97: deletebutton_id = wx.NewId() lbessard@97: deletebutton = wx.lib.buttons.GenBitmapButton(id=deletebutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'Delete24x24.png')), lbessard@97: name='DeleteBusButton', parent=leftwindow, pos=wx.Point(0, 0), lbessard@97: size=wx.Size(24, 24), style=wx.NO_BORDER) lbessard@97: deletebutton.SetToolTipString("Delete this plugin") lbessard@97: deletebutton.Bind(wx.EVT_BUTTON, self.GetDeleteButtonFunction(plugin), id=deletebutton_id) lbessard@97: leftbuttonmainsizer.AddWindow(deletebutton, 0, border=5, flag=wx.RIGHT|wx.ALIGN_CENTER) lbessard@97: lbessard@98: locations = plugin.GetLocations() lbessard@98: lb = wx.ListBox(leftwindow, -1, size=wx.Size(-1, max(1, min(len(locations), 4)) * 25), style=wx.NO_BORDER) lbessard@98: for location in locations: lbessard@97: lb.Append(location["NAME"].replace("__", "%").replace("_", ".")) lbessard@97: if not self.PluginInfos[plugin]["left_visible"]: lbessard@97: lb.Hide() lbessard@98: self.PluginInfos[plugin]["variable_list"] = lb lbessard@99: leftwindowsizer.AddWindow(lb, 0, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) lbessard@99: lbessard@99: middlewindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1)) lbessard@99: middlewindow.SetBackgroundColour(wx.Colour(240,240,240)) lbessard@99: lbessard@99: self.PluginTreeSizer.AddWindow(middlewindow, 0, border=0, flag=wx.GROW) lbessard@99: lbessard@99: middlewindowmainsizer = wx.BoxSizer(wx.VERTICAL) lbessard@99: middlewindow.SetSizer(middlewindowmainsizer) lbessard@99: lbessard@99: middlewindowsizer = wx.FlexGridSizer(cols=2, rows=1) lbessard@99: middlewindowsizer.AddGrowableCol(1) lbessard@99: middlewindowsizer.AddGrowableRow(0) lbessard@99: middlewindowmainsizer.AddSizer(middlewindowsizer, 0, border=17, flag=wx.TOP|wx.GROW) lbessard@99: lbessard@99: msizer = self.GenerateMethodButtonSizer(plugin, middlewindow, not self.PluginInfos[plugin]["middle_visible"]) lbessard@99: middlewindowsizer.AddSizer(msizer, 0, border=0, flag=wx.GROW) lbessard@99: lbessard@99: middleparamssizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@99: middlewindowsizer.AddSizer(middleparamssizer, 0, border=0, flag=wx.ALIGN_RIGHT) lbessard@99: lbessard@99: paramswindow = wx.Panel(middlewindow, -1, size=wx.Size(-1, -1)) lbessard@99: paramswindow.SetBackgroundColour(WINDOW_COLOUR) lbessard@99: lbessard@99: psizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@99: paramswindow.SetSizer(psizer) lbessard@99: lbessard@99: middleparamssizer.AddWindow(paramswindow, 0, border=5, flag=wx.ALL) lbessard@99: lbessard@99: plugin_infos = plugin.GetParamsAttributes() lbessard@99: self.RefreshSizerElement(paramswindow, psizer, plugin, plugin_infos, None, False) lbessard@99: lbessard@99: if not self.PluginInfos[plugin]["middle_visible"]: lbessard@99: paramswindow.Hide() lbessard@99: lbessard@99: middleminimizebutton_id = wx.NewId() lbessard@99: middleminimizebutton = wx.lib.buttons.GenBitmapToggleButton(id=middleminimizebutton_id, bitmap=wx.Bitmap(os.path.join(CWD, 'images', 'Maximize.png')), lbessard@99: name='MinimizeButton', parent=middlewindow, pos=wx.Point(0, 0), lbessard@99: size=wx.Size(24, 24), style=wx.NO_BORDER) lbessard@99: middleminimizebutton.GetBackgroundBrush = gen_mini_GetBackgroundBrush(middleminimizebutton) lbessard@99: middleminimizebutton.SetBackgroundColour(wx.Colour(208, 208, 208)) lbessard@99: middleminimizebutton.labelDelta = 0 lbessard@99: middleminimizebutton.SetBezelWidth(0) lbessard@99: middleminimizebutton.SetUseFocusIndicator(False) lbessard@99: middleminimizebutton.SetBitmapSelected(wx.Bitmap(os.path.join(CWD, 'images', 'Minimize.png'))) lbessard@99: middleminimizebutton.SetToggle(self.PluginInfos[plugin]["middle_visible"]) lbessard@99: middleparamssizer.AddWindow(middleminimizebutton, 0, border=5, flag=wx.ALL) lbessard@99: lbessard@97: rightwindow = wx.Panel(self.PLCConfig, -1, size=wx.Size(-1, -1)) lbessard@97: rightwindow.SetBackgroundColour(wx.Colour(240,240,240)) lbessard@97: lbessard@97: self.PluginTreeSizer.AddWindow(rightwindow, 0, border=0, flag=wx.GROW) lbessard@97: lbessard@99: rightsizer = wx.BoxSizer(wx.VERTICAL) lbessard@99: rightwindow.SetSizer(rightsizer) lbessard@99: lbessard@99: rightmainsizer = wx.BoxSizer(wx.VERTICAL) lbessard@99: rightsizer.AddSizer(rightmainsizer, 0, border=5, flag=wx.ALL) lbessard@99: lbessard@99: if len(plugin.PlugChildsTypes) > 0: lbessard@99: addsizer = self.GenerateAddButtonSizer(plugin, rightwindow) lbessard@99: rightmainsizer.AddSizer(addsizer, 0, border=12, flag=wx.TOP) lbessard@99: else: lbessard@99: addsizer = None lbessard@99: lbessard@99: def togglemiddlerightwindow(event): lbessard@99: if middleminimizebutton.GetToggle(): lbessard@99: middleparamssizer.Show(0) lbessard@97: msizer.SetCols(1) lbessard@99: if addsizer is not None: lbessard@99: addsizer.SetCols(1) lbessard@97: else: lbessard@99: middleparamssizer.Hide(0) lbessard@97: msizer.SetCols(len(plugin.PluginMethods)) lbessard@99: if addsizer is not None: lbessard@99: addsizer.SetCols(len(plugin.PlugChildsTypes)) lbessard@99: self.PluginInfos[plugin]["middle_visible"] = middleminimizebutton.GetToggle() lbessard@97: self.PLCConfigMainSizer.Layout() lbessard@97: self.RefreshScrollBars() lbessard@84: event.Skip() lbessard@99: middleminimizebutton.Bind(wx.EVT_BUTTON, togglemiddlerightwindow, id=middleminimizebutton_id) lbessard@99: lbessard@97: self.PluginInfos[plugin]["left"] = index[0] lbessard@99: self.PluginInfos[plugin]["middle"] = index[0] + 1 lbessard@99: self.PluginInfos[plugin]["right"] = index[0] + 2 lbessard@99: index[0] += 3 lbessard@97: for child in self.PluginInfos[plugin]["children"]: lbessard@97: self.GenerateTreeBranch(child, index) lbessard@97: if not self.PluginInfos[child]["expanded"]: lbessard@97: self.CollapsePlugin(child) lbessard@97: lbessard@98: def RefreshVariableLists(self): lbessard@98: for plugin, infos in self.PluginInfos.items(): lbessard@98: locations = plugin.GetLocations() lbessard@98: infos["variable_list"].SetSize(wx.Size(-1, max(1, min(len(locations), 4)) * 25)) lbessard@98: infos["variable_list"].Clear() lbessard@98: for location in locations: lbessard@98: infos["variable_list"].Append(location["NAME"].replace("__", "%").replace("_", ".")) lbessard@98: self.PLCConfigMainSizer.Layout() lbessard@98: self.RefreshScrollBars() lbessard@98: lbessard@97: def GetItemChannelChangedFunction(self, plugin, value): lbessard@82: def OnPluginTreeItemChannelChanged(event): lbessard@97: res, StructChanged = plugin.SetParamsAttribute("BaseParams.IEC_Channel", value, self.Log) lbessard@97: wx.CallAfter(self.RefreshPluginTree) lbessard@82: event.Skip() lbessard@82: return OnPluginTreeItemChannelChanged lbessard@82: lbessard@97: def _GetAddPluginFunction(self, name, plugin): lbessard@17: def OnPluginMenu(event): lbessard@98: wx.CallAfter(self.AddPlugin, name, plugin) lbessard@17: event.Skip() lbessard@17: return OnPluginMenu lbessard@17: lbessard@17: def OnPluginTreeRightUp(self, event): lbessard@17: plugin = self.GetSelectedPlugin() lbessard@17: if plugin: lbessard@17: main_menu = wx.Menu(title='') lbessard@17: if len(plugin.PlugChildsTypes) > 0: lbessard@17: plugin_menu = wx.Menu(title='') lbessard@82: for name, XSDClass in plugin.PlugChildsTypes: lbessard@17: new_id = wx.NewId() lbessard@17: plugin_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=name) lbessard@17: self.Bind(wx.EVT_MENU, self._GetAddPluginFunction(name), id=new_id) lbessard@17: main_menu.AppendMenu(-1, "Add", plugin_menu, '') lbessard@17: new_id = wx.NewId() lbessard@17: main_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text="Delete") lbessard@17: self.Bind(wx.EVT_MENU, self.OnDeleteButton, id=new_id) lbessard@82: pos_x, pos_y = event.GetPosition() lbessard@82: self.PluginTree.PopupMenuXY(main_menu, pos_x, pos_y) lbessard@82: event.Skip() lbessard@82: lbessard@21: def GetButtonCallBackFunction(self, plugin, method): lbessard@21: def OnButtonClick(event): etisserant@105: getattr(plugin,method)(self.Log) lbessard@98: self.RefreshVariableLists() lbessard@21: event.Skip() lbessard@21: return OnButtonClick lbessard@21: lbessard@97: def GetChoiceCallBackFunction(self, choicectrl, plugin, path): lbessard@19: def OnChoiceChanged(event): lbessard@97: res, StructChanged = plugin.SetParamsAttribute(path, choicectrl.GetStringSelection(), self.Log) lbessard@97: if StructChanged: wx.CallAfter(self.RefreshPluginTree) lbessard@97: choicectrl.SetStringSelection(res) lbessard@19: event.Skip() lbessard@19: return OnChoiceChanged lbessard@19: lbessard@97: def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, plugin, path): lbessard@19: def OnChoiceContentChanged(event): lbessard@97: res, StructChanged = plugin.SetParamsAttribute(path, choicectrl.GetStringSelection(), self.Log) lbessard@97: if StructChanged: wx.CallAfter(self.RefreshPluginTree) lbessard@97: choicectrl.SetStringSelection(res) lbessard@97: infos = self.PluginRoot.GetParamsAttributes(path) lbessard@97: staticbox = staticboxsizer.GetStaticBox() lbessard@97: staticbox.SetLabel("%(name)s - %(value)s"%infos) lbessard@97: if wx.VERSION < (2, 8, 0): lbessard@97: self.ParamsPanel.Freeze() lbessard@97: self.RefreshSizerElement(self.ParamsPanel, staticboxsizer, infos["children"], "%s.%s"%(path, infos["name"]), selected=selected) lbessard@97: self.ParamsPanelMainSizer.Layout() lbessard@97: self.ParamsPanel.Thaw() lbessard@97: self.ParamsPanel.Refresh() lbessard@97: else: lbessard@97: wx.CallAfter(self.RefreshPluginTree) lbessard@19: event.Skip() lbessard@19: return OnChoiceContentChanged lbessard@19: lbessard@97: def GetTextCtrlCallBackFunction(self, textctrl, plugin, path): lbessard@19: def OnTextCtrlChanged(event): lbessard@97: res, StructChanged = plugin.SetParamsAttribute(path, textctrl.GetValue(), self.Log) lbessard@97: if StructChanged: wx.CallAfter(self.RefreshPluginTree) lbessard@97: textctrl.SetValue(res) lbessard@19: event.Skip() lbessard@19: return OnTextCtrlChanged lbessard@19: lbessard@97: def GetCheckBoxCallBackFunction(self, chkbx, plugin, path): lbessard@19: def OnCheckBoxChanged(event): lbessard@97: res, StructChanged = plugin.SetParamsAttribute(path, chkbx.IsChecked(), self.Log) lbessard@97: if StructChanged: wx.CallAfter(self.RefreshPluginTree) lbessard@97: chkbx.SetValue(res) lbessard@19: event.Skip() lbessard@19: return OnCheckBoxChanged lbessard@19: lbessard@19: def ClearSizer(self, sizer): lbessard@19: staticboxes = [] lbessard@19: for item in sizer.GetChildren(): lbessard@19: if item.IsSizer(): lbessard@19: item_sizer = item.GetSizer() lbessard@19: self.ClearSizer(item_sizer) lbessard@19: if isinstance(item_sizer, wx.StaticBoxSizer): lbessard@19: staticboxes.append(item_sizer.GetStaticBox()) lbessard@19: sizer.Clear(True) lbessard@19: for staticbox in staticboxes: lbessard@19: staticbox.Destroy() lbessard@19: lbessard@97: def RefreshSizerElement(self, parent, sizer, plugin, elements, path, clean = True): lbessard@25: if clean: lbessard@97: if wx.VERSION < (2, 8, 0): lbessard@97: self.ClearSizer(sizer) lbessard@97: else: lbessard@97: sizer.Clear(True) lbessard@19: first = True lbessard@19: for element_infos in elements: lbessard@19: if path: lbessard@19: element_path = "%s.%s"%(path, element_infos["name"]) lbessard@19: else: lbessard@19: element_path = element_infos["name"] lbessard@19: if isinstance(element_infos["type"], types.ListType): lbessard@19: boxsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@19: if first: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL) lbessard@19: else: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) lbessard@65: bitmappath = os.path.join("images", "%s.png"%element_infos["name"]) lbessard@65: if os.path.isfile(bitmappath): lbessard@65: staticbitmap = wx.StaticBitmap(id=-1, bitmap=wx.Bitmap(bitmappath), lbessard@82: name="%s_bitmap"%element_infos["name"], parent=parent, lbessard@65: pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) lbessard@65: boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) lbessard@97: else: lbessard@98: staticbitmap = wx.StaticBitmap(id=-1, bitmap=GenerateEmptyBitmap(24, 24), lbessard@97: name="%s_bitmap"%element_infos["name"], parent=parent, lbessard@97: pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) lbessard@97: boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) lbessard@19: statictext = wx.StaticText(id=-1, label="%s:"%element_infos["name"], lbessard@82: name="%s_label"%element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(100, 17), style=0) lbessard@67: boxsizer.AddWindow(statictext, 0, border=4, flag=wx.TOP) lbessard@19: id = wx.NewId() lbessard@82: choicectrl = wx.Choice(id=id, name=element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(150, 25), style=0) lbessard@19: boxsizer.AddWindow(choicectrl, 0, border=0, flag=0) lbessard@19: choicectrl.Append("") lbessard@19: if len(element_infos["type"]) > 0 and isinstance(element_infos["type"][0], types.TupleType): lbessard@19: for choice, xsdclass in element_infos["type"]: lbessard@19: choicectrl.Append(choice) lbessard@19: staticbox = wx.StaticBox(id=-1, label="%(name)s - %(value)s"%element_infos, lbessard@82: name='%s_staticbox'%element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0) lbessard@19: staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) lbessard@82: sizer.AddSizer(staticboxsizer, 0, border=5, flag=wx.GROW|wx.BOTTOM) lbessard@97: self.RefreshSizerElement(parent, staticboxsizer, plugin, element_infos["children"], element_path) lbessard@97: callback = self.GetChoiceContentCallBackFunction(choicectrl, staticboxsizer, plugin, element_path) lbessard@19: else: lbessard@19: for choice in element_infos["type"]: lbessard@19: choicectrl.Append(choice) lbessard@97: callback = self.GetChoiceCallBackFunction(choicectrl, plugin, element_path) etisserant@22: if element_infos["value"]: etisserant@22: choicectrl.SetStringSelection(element_infos["value"]) etisserant@28: choicectrl.Bind(wx.EVT_CHOICE, callback, id=id) lbessard@19: elif isinstance(element_infos["type"], types.DictType): lbessard@19: boxsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@19: if first: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL) lbessard@19: else: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) lbessard@65: bitmappath = os.path.join("images", "%s.png"%element_infos["name"]) lbessard@65: if os.path.isfile(bitmappath): lbessard@65: staticbitmap = wx.StaticBitmap(id=-1, bitmap=wx.Bitmap(bitmappath), lbessard@82: name="%s_bitmap"%element_infos["name"], parent=parent, lbessard@65: pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) lbessard@65: boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) lbessard@97: else: lbessard@98: staticbitmap = wx.StaticBitmap(id=-1, bitmap=GenerateEmptyBitmap(24, 24), lbessard@97: name="%s_bitmap"%element_infos["name"], parent=parent, lbessard@97: pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) lbessard@97: boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) lbessard@19: statictext = wx.StaticText(id=-1, label="%s:"%element_infos["name"], lbessard@82: name="%s_label"%element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(100, 17), style=0) lbessard@67: boxsizer.AddWindow(statictext, 0, border=4, flag=wx.TOP) lbessard@19: id = wx.NewId() etisserant@23: scmin = -(2**31) etisserant@23: scmax = 2**31-1 lbessard@19: if "min" in element_infos["type"]: etisserant@23: scmin = element_infos["type"]["min"] lbessard@19: if "max" in element_infos["type"]: etisserant@23: scmax = element_infos["type"]["max"] lbessard@82: spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=parent, etisserant@23: pos=wx.Point(0, 0), size=wx.Size(150, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) etisserant@23: spinctrl.SetRange(scmin,scmax) lbessard@19: boxsizer.AddWindow(spinctrl, 0, border=0, flag=0) etisserant@28: spinctrl.SetValue(element_infos["value"]) lbessard@97: spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, plugin, element_path), id=id) lbessard@19: elif element_infos["type"] == "element": lbessard@19: staticbox = wx.StaticBox(id=-1, label=element_infos["name"], lbessard@82: name='%s_staticbox'%element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0) lbessard@19: staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) lbessard@19: if first: lbessard@19: sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW|wx.TOP) lbessard@19: else: lbessard@19: sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW) lbessard@97: self.RefreshSizerElement(parent, staticboxsizer, plugin, element_infos["children"], element_path) lbessard@19: else: lbessard@19: boxsizer = wx.BoxSizer(wx.HORIZONTAL) lbessard@19: if first: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL) lbessard@19: else: lbessard@19: sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) lbessard@65: bitmappath = os.path.join("images", "%s.png"%element_infos["name"]) lbessard@65: if os.path.isfile(bitmappath): lbessard@65: staticbitmap = wx.StaticBitmap(id=-1, bitmap=wx.Bitmap(bitmappath), lbessard@82: name="%s_bitmap"%element_infos["name"], parent=parent, lbessard@65: pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) lbessard@65: boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) lbessard@97: else: lbessard@98: staticbitmap = wx.StaticBitmap(id=-1, bitmap=GenerateEmptyBitmap(24, 24), lbessard@97: name="%s_bitmap"%element_infos["name"], parent=parent, lbessard@97: pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) lbessard@97: boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) lbessard@97: lbessard@19: statictext = wx.StaticText(id=-1, label="%s:"%element_infos["name"], lbessard@82: name="%s_label"%element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(100, 17), style=0) lbessard@67: boxsizer.AddWindow(statictext, 0, border=4, flag=wx.TOP) lbessard@19: id = wx.NewId() lbessard@19: if element_infos["type"] == "boolean": lbessard@82: checkbox = wx.CheckBox(id=id, name=element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(17, 25), style=0) lbessard@19: boxsizer.AddWindow(checkbox, 0, border=0, flag=0) etisserant@28: checkbox.SetValue(element_infos["value"]) lbessard@97: checkbox.Bind(wx.EVT_CHECKBOX, self.GetCheckBoxCallBackFunction(checkbox, plugin, element_path), id=id) lbessard@19: elif element_infos["type"] in ["unsignedLong", "long","integer"]: etisserant@23: if element_infos["type"].startswith("unsigned"): etisserant@23: scmin = 0 etisserant@23: else: etisserant@23: scmin = -(2**31) etisserant@23: scmax = 2**31-1 lbessard@82: spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=parent, lbessard@19: pos=wx.Point(0, 0), size=wx.Size(150, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) etisserant@23: spinctrl.SetRange(scmin, scmax) lbessard@19: boxsizer.AddWindow(spinctrl, 0, border=0, flag=0) etisserant@28: spinctrl.SetValue(element_infos["value"]) lbessard@97: spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, plugin, element_path), id=id) lbessard@19: else: lbessard@82: textctrl = wx.TextCtrl(id=id, name=element_infos["name"], parent=parent, etisserant@28: pos=wx.Point(0, 0), size=wx.Size(150, 25), style=wx.TE_PROCESS_ENTER) lbessard@19: boxsizer.AddWindow(textctrl, 0, border=0, flag=0) lbessard@19: textctrl.SetValue(str(element_infos["value"])) lbessard@97: textctrl.Bind(wx.EVT_TEXT_ENTER, self.GetTextCtrlCallBackFunction(textctrl, plugin, element_path), id=id) lbessard@97: textctrl.Bind(wx.EVT_KILL_FOCUS, self.GetTextCtrlCallBackFunction(textctrl, plugin, element_path)) lbessard@19: first = False lbessard@19: lbessard@0: def OnNewProjectMenu(self, event): lbessard@17: defaultpath = self.PluginRoot.GetProjectPath() etisserant@22: if not defaultpath: lbessard@0: defaultpath = os.getcwd() lbessard@4: dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON) lbessard@4: if dialog.ShowModal() == wx.ID_OK: lbessard@0: projectpath = dialog.GetPath() lbessard@0: dialog.Destroy() etisserant@20: res = self.PluginRoot.NewProject(projectpath) etisserant@20: if not res : lbessard@97: self.RefreshPLCParams() etisserant@20: self.RefreshPluginTree() etisserant@20: self.RefreshMainMenu() lbessard@0: else: etisserant@20: message = wx.MessageDialog(self, res, "ERROR", wx.OK|wx.ICON_ERROR) lbessard@0: message.ShowModal() lbessard@0: message.Destroy() lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnOpenProjectMenu(self, event): lbessard@17: defaultpath = self.PluginRoot.GetProjectPath() etisserant@20: if not defaultpath: lbessard@0: defaultpath = os.getcwd() lbessard@4: dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON) lbessard@4: if dialog.ShowModal() == wx.ID_OK: lbessard@17: projectpath = dialog.GetPath() lbessard@17: if os.path.isdir(projectpath): etisserant@24: result = self.PluginRoot.LoadProject(projectpath, self.Log) lbessard@17: if not result: lbessard@97: self.RefreshPLCParams() lbessard@17: self.RefreshPluginTree() lbessard@17: self.RefreshMainMenu() lbessard@17: else: lbessard@17: message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR) lbessard@17: message.ShowModal() lbessard@17: message.Destroy() lbessard@17: else: lbessard@17: message = wx.MessageDialog(self, "\"%s\" folder is not a valid Beremiz project\n"%projectpath, "Error", wx.OK|wx.ICON_ERROR) lbessard@17: message.ShowModal() lbessard@17: message.Destroy() lbessard@0: dialog.Destroy() lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnCloseProjectMenu(self, event): lbessard@97: self.PluginInfos = {} lbessard@97: self.RefreshPLCParams() lbessard@82: self.RefreshPluginTree() lbessard@0: self.RefreshMainMenu() lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnSaveProjectMenu(self, event): lbessard@17: if self.PluginRoot.HasProjectOpened(): lbessard@17: self.PluginRoot.SaveProject() lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnPropertiesMenu(self, event): lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnQuitMenu(self, event): lbessard@0: self.Close() lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnEditPLCMenu(self, event): lbessard@0: self.EditPLC() lbessard@0: event.Skip() lbessard@0: lbessard@17: def OnAddMenu(self, event): lbessard@17: self.AddPlugin() lbessard@17: event.Skip() lbessard@17: lbessard@17: def OnDeleteMenu(self, event): lbessard@17: self.DeletePlugin() lbessard@0: event.Skip() lbessard@0: lbessard@1: def OnBuildMenu(self, event): etisserant@20: #self.BuildAutom() lbessard@1: event.Skip() lbessard@1: lbessard@0: def OnSimulateMenu(self, event): lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnRunMenu(self, event): lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnSaveLogMenu(self, event): lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnBeremizMenu(self, event): lbessard@0: event.Skip() lbessard@0: lbessard@0: def OnAboutMenu(self, event): lbessard@0: event.Skip() lbessard@17: lbessard@17: def OnAddButton(self, event): lbessard@17: PluginType = self.PluginChilds.GetStringSelection() lbessard@17: if PluginType != "": lbessard@17: self.AddPlugin(PluginType) lbessard@17: event.Skip() lbessard@17: lbessard@17: def OnDeleteButton(self, event): lbessard@17: self.DeletePlugin() lbessard@0: event.Skip() lbessard@0: lbessard@97: def GetAddButtonFunction(self, plugin, window): lbessard@82: def AddButtonFunction(event): lbessard@82: if plugin and len(plugin.PlugChildsTypes) > 0: lbessard@82: plugin_menu = wx.Menu(title='') lbessard@82: for name, XSDClass in plugin.PlugChildsTypes: lbessard@82: new_id = wx.NewId() lbessard@82: plugin_menu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=name) lbessard@97: self.Bind(wx.EVT_MENU, self._GetAddPluginFunction(name, plugin), id=new_id) lbessard@87: window_pos = window.GetPosition() lbessard@97: wx.CallAfter(self.PLCConfig.PopupMenu, plugin_menu) lbessard@82: event.Skip() lbessard@82: return AddButtonFunction lbessard@82: lbessard@97: def GetDeleteButtonFunction(self, plugin): lbessard@82: def DeleteButtonFunction(event): lbessard@97: wx.CallAfter(self.DeletePlugin, plugin) lbessard@82: event.Skip() lbessard@82: return DeleteButtonFunction lbessard@82: lbessard@97: def AddPlugin(self, PluginType, plugin): lbessard@17: dialog = wx.TextEntryDialog(self, "Please enter a name for plugin:", "Add Plugin", "", wx.OK|wx.CANCEL) lbessard@4: if dialog.ShowModal() == wx.ID_OK: lbessard@17: PluginName = dialog.GetValue() etisserant@28: plugin.PlugAddChild(PluginName, PluginType, self.Log) lbessard@17: self.RefreshPluginTree() lbessard@0: dialog.Destroy() lbessard@0: lbessard@97: def DeletePlugin(self, plugin): lbessard@72: dialog = wx.MessageDialog(self, "Really delete plugin ?", "Remove plugin", wx.YES_NO|wx.NO_DEFAULT) etisserant@50: if dialog.ShowModal() == wx.ID_YES: lbessard@97: self.PluginInfos.pop(plugin) etisserant@50: plugin.PlugRemove() etisserant@50: del plugin etisserant@50: self.RefreshPluginTree() etisserant@50: dialog.Destroy() etisserant@7: lbessard@0: #------------------------------------------------------------------------------- lbessard@0: # Exception Handler lbessard@0: #------------------------------------------------------------------------------- lbessard@0: lbessard@0: Max_Traceback_List_Size = 20 lbessard@0: lbessard@0: def Display_Exception_Dialog(e_type,e_value,e_tb): lbessard@0: trcbck_lst = [] lbessard@0: for i,line in enumerate(traceback.extract_tb(e_tb)): lbessard@0: trcbck = " " + str(i+1) + ". " lbessard@0: if line[0].find(os.getcwd()) == -1: lbessard@0: trcbck += "file : " + str(line[0]) + ", " lbessard@0: else: lbessard@0: trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ", " lbessard@0: trcbck += "line : " + str(line[1]) + ", " + "function : " + str(line[2]) lbessard@0: trcbck_lst.append(trcbck) lbessard@0: lbessard@0: # Allow clicking.... lbessard@0: cap = wx.Window_GetCapture() lbessard@0: if cap: lbessard@0: cap.ReleaseMouse() lbessard@0: lbessard@0: dlg = wx.SingleChoiceDialog(None, lbessard@0: """ lbessard@0: An error happens. lbessard@0: lbessard@0: Click on OK for saving an error report. lbessard@0: lbessard@0: Please contact LOLITech at: lbessard@0: +33 (0)3 29 52 95 67 lbessard@0: bugs_Beremiz@lolitech.fr lbessard@0: lbessard@0: lbessard@0: Error: lbessard@0: """ + lbessard@0: str(e_type) + " : " + str(e_value), lbessard@0: "Error", lbessard@0: trcbck_lst) lbessard@0: try: lbessard@0: res = (dlg.ShowModal() == wx.ID_OK) lbessard@0: finally: lbessard@0: dlg.Destroy() lbessard@0: lbessard@0: return res lbessard@0: lbessard@0: def Display_Error_Dialog(e_value): lbessard@0: message = wxMessageDialog(None, str(e_value), "Error", wxOK|wxICON_ERROR) lbessard@0: message.ShowModal() lbessard@0: message.Destroy() lbessard@0: lbessard@0: def get_last_traceback(tb): lbessard@0: while tb.tb_next: lbessard@0: tb = tb.tb_next lbessard@0: return tb lbessard@0: lbessard@0: lbessard@0: def format_namespace(d, indent=' '): lbessard@0: return '\n'.join(['%s%s: %s' % (indent, k, repr(v)[:10000]) for k, v in d.iteritems()]) lbessard@0: lbessard@0: lbessard@0: ignored_exceptions = [] # a problem with a line in a module is only reported once per session lbessard@0: lbessard@5: def AddExceptHook(path, app_version='[No version]'):#, ignored_exceptions=[]): lbessard@0: lbessard@0: def handle_exception(e_type, e_value, e_traceback): lbessard@0: traceback.print_exception(e_type, e_value, e_traceback) # this is very helpful when there's an exception in the rest of this func lbessard@0: last_tb = get_last_traceback(e_traceback) lbessard@0: ex = (last_tb.tb_frame.f_code.co_filename, last_tb.tb_frame.f_lineno) lbessard@0: if str(e_value).startswith("!!!"): lbessard@0: Display_Error_Dialog(e_value) lbessard@0: elif ex not in ignored_exceptions: lbessard@0: result = Display_Exception_Dialog(e_type,e_value,e_traceback) lbessard@0: if result: lbessard@0: ignored_exceptions.append(ex) lbessard@0: info = { lbessard@0: 'app-title' : wx.GetApp().GetAppName(), # app_title lbessard@0: 'app-version' : app_version, lbessard@0: 'wx-version' : wx.VERSION_STRING, lbessard@0: 'wx-platform' : wx.Platform, lbessard@0: 'python-version' : platform.python_version(), #sys.version.split()[0], lbessard@0: 'platform' : platform.platform(), lbessard@0: 'e-type' : e_type, lbessard@0: 'e-value' : e_value, lbessard@0: 'date' : time.ctime(), lbessard@0: 'cwd' : os.getcwd(), lbessard@0: } lbessard@0: if e_traceback: lbessard@0: info['traceback'] = ''.join(traceback.format_tb(e_traceback)) + '%s: %s' % (e_type, e_value) lbessard@0: last_tb = get_last_traceback(e_traceback) lbessard@0: exception_locals = last_tb.tb_frame.f_locals # the locals at the level of the stack trace where the exception actually occurred lbessard@0: info['locals'] = format_namespace(exception_locals) lbessard@0: if 'self' in exception_locals: lbessard@0: info['self'] = format_namespace(exception_locals['self'].__dict__) lbessard@0: lbessard@0: output = open(path+os.sep+"bug_report_"+info['date'].replace(':','-').replace(' ','_')+".txt",'w') lbessard@0: lst = info.keys() lbessard@0: lst.sort() lbessard@0: for a in lst: lbessard@0: output.write(a+":\n"+str(info[a])+"\n\n") lbessard@0: lbessard@0: #sys.excepthook = lambda *args: wx.CallAfter(handle_exception, *args) lbessard@0: sys.excepthook = handle_exception lbessard@0: lbessard@0: if __name__ == '__main__': etisserant@13: def usage(): etisserant@13: print "\nUsage of Beremiz.py :" etisserant@13: print "\n %s [Projectpath]\n"%sys.argv[0] etisserant@13: etisserant@13: try: etisserant@13: opts, args = getopt.getopt(sys.argv[1:], "h", ["help"]) etisserant@13: except getopt.GetoptError: etisserant@13: # print help information and exit: etisserant@13: usage() etisserant@13: sys.exit(2) etisserant@13: etisserant@13: for o, a in opts: etisserant@13: if o in ("-h", "--help"): etisserant@13: usage() etisserant@13: sys.exit() etisserant@13: etisserant@13: if len(args) > 1: etisserant@13: usage() etisserant@13: sys.exit() etisserant@13: elif len(args) == 1: etisserant@13: projectOpen = args[0] etisserant@13: else: etisserant@13: projectOpen = None etisserant@13: lbessard@5: app = wx.PySimpleApp() lbessard@5: wx.InitAllImageHandlers() lbessard@0: lbessard@0: # Install a exception handle for bug reports lbessard@5: AddExceptHook(os.getcwd(),__version__) lbessard@0: etisserant@13: frame = Beremiz(None, projectOpen) greg@103: greg@103: # Add beremiz's icon in top left corner of the frame greg@102: if wx.Platform == '__WXMSW__': greg@103: winicon = wx.Icon(os.path.join(CWD,"brz.ico"),wx.BITMAP_TYPE_ICO) greg@103: frame.SetIcon(winicon) greg@103: else: greg@103: linicon = wx.Icon(os.path.join(CWD,"brz.png"),wx.BITMAP_TYPE_PNG) greg@103: frame.SetIcon(linicon) greg@103: frame.Show() lbessard@0: app.MainLoop()