# HG changeset patch # User laurent # Date 1337587467 -7200 # Node ID 413946c04c87c865b78a8e9f088cd110f7a791de # Parent 7b421e08063696b4f86e455a5b39d81e4bd3dcf5 refactoring diff -r 7b421e080636 -r 413946c04c87 Beremiz.py --- a/Beremiz.py Mon May 21 02:49:53 2012 +0200 +++ b/Beremiz.py Mon May 21 10:04:27 2012 +0200 @@ -156,14 +156,14 @@ import cPickle from util.BrowseValuesLibraryDialog import BrowseValuesLibraryDialog import types, time, re, platform, time, traceback, commands -from ProjectController import ProjectController, MATIEC_ERROR_MODEL +from ProjectController import ProjectController, MATIEC_ERROR_MODEL, ITEM_CONFNODE from util.MiniTextControler import MiniTextControler from util.ProcessLogger import ProcessLogger from docutil import OpenHtmlFrame from PLCOpenEditor import IDEFrame, AppendMenu, TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU, PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE, SCALING, PAGETITLES from PLCOpenEditor import EditorPanel, Viewer, TextViewer, GraphicViewer, ResourceEditor, ConfigurationEditor, DataTypeEditor -from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY +from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY, ITEM_PROJECT, ITEM_RESOURCE SCROLLBAR_UNIT = 10 WINDOW_COLOUR = wx.Colour(240,240,240) @@ -452,6 +452,17 @@ (wx.ID_SAVEAS, "saveas.png", _(u'Save As...'), None), (wx.ID_PRINT, "print.png", _(u'Print'), None)]) + def _init_coll_AddMenu_Items(self, parent): + IDEFrame._init_coll_AddMenu_Items(self, parent, False) + new_id = wx.NewId() + AppendMenu(parent, help='', id=new_id, + kind=wx.ITEM_NORMAL, text=_(u'&Resource')) + for name, XSDClass, help in ProjectController.CTNChildrenTypes: + new_id = wx.NewId() + AppendMenu(parent, help='', id=new_id, + kind=wx.ITEM_NORMAL, text=help) + self.Bind(wx.EVT_MENU, self._GetAddConfNodeFunction(name), id=new_id) + def _init_coll_HelpMenu_Items(self, parent): parent.Append(help='', id=wx.ID_ABOUT, kind=wx.ITEM_NORMAL, text=_(u'About')) @@ -495,7 +506,7 @@ def OnMethod(evt): if obj.CTR is not None: obj.CTR.CallMethod('_'+meth) - wx.CallAfter(self.RefreshAll) + wx.CallAfter(self.RefreshStatusToolBar) return OnMethod newid = wx.NewId() self.Bind(wx.EVT_MENU, OnMethodGen(self,method), id=newid) @@ -510,8 +521,8 @@ self.PLCConfig.Bind(wx.EVT_LEFT_DOWN, self.OnPanelLeftDown) self.PLCConfig.Bind(wx.EVT_SIZE, self.OnMoveWindow) self.PLCConfig.Bind(wx.EVT_MOUSEWHEEL, self.OnPLCConfigScroll) - self.MainTabs["PLCConfig"] = (self.PLCConfig, _("Topology")) - self.BottomNoteBook.InsertPage(0, self.PLCConfig, _("Topology"), True) + #self.MainTabs["PLCConfig"] = (self.PLCConfig, _("Topology")) + #self.BottomNoteBook.InsertPage(0, self.PLCConfig, _("Topology"), True) self.LogConsole = wx.TextCtrl(id=ID_BEREMIZLOGCONSOLE, value='', name='LogConsole', parent=self.BottomNoteBook, pos=wx.Point(0, 0), @@ -520,9 +531,21 @@ self.MainTabs["LogConsole"] = (self.LogConsole, _("Log Console")) self.BottomNoteBook.AddPage(*self.MainTabs["LogConsole"]) self.BottomNoteBook.Split(self.BottomNoteBook.GetPageIndex(self.LogConsole), wx.RIGHT) + + StatusToolBar = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, + wx.TB_FLAT | wx.TB_NODIVIDER | wx.NO_BORDER) + StatusToolBar.SetToolBitmapSize(wx.Size(25, 25)) + StatusToolBar.Realize() + self.Panes["StatusToolBar"] = StatusToolBar + self.AUIManager.AddPane(StatusToolBar, wx.aui.AuiPaneInfo(). + Name("StatusToolBar").Caption(_("Status ToolBar")). + ToolbarPane().Top().Position(2). + LeftDockable(False).RightDockable(False)) self._init_beremiz_sizers() + self.AUIManager.Update() + def __init__(self, parent, projectOpen=None, buildpath=None, ctr=None, debug=True): IDEFrame.__init__(self, parent, debug) self.Log = LogPseudoFile(self.LogConsole,self.RiseLogConsole) @@ -553,6 +576,11 @@ ("VAR_LOCAL", LOCATION_VAR_MEMORY)]: self.LocationImageDict[itemtype]=self.LocationImageList.Add(wx.Bitmap(os.path.join(base_folder, "plcopeneditor", 'Images', '%s.png'%imgname))) + # Icons for other items + for imgname, itemtype in [ + ("Extension", ITEM_CONFNODE)]: + self.TreeImageDict[itemtype]=self.TreeImageList.Add(wx.Bitmap(os.path.join(CWD, 'images', '%s.png'%imgname))) + # Add beremiz's icon in top left corner of the frame self.SetIcon(wx.Icon(Bpath( "images", "brz.ico"), wx.BITMAP_TYPE_ICO)) @@ -567,10 +595,11 @@ result = self.CTR.LoadProject(projectOpen, buildpath) if not result: self.LibraryPanel.SetControler(self.Controler) + self.ProjectTree.Enable(True) self.PouInstanceVariablesPanel.SetController(self.Controler) self.RefreshConfigRecentProjects(os.path.abspath(projectOpen)) self._Refresh(PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) - self.RefreshAll() + self.RefreshStatusToolBar() else: self.ResetView() self.ShowErrorMessage(result) @@ -579,9 +608,10 @@ self.Controler = ctr if ctr is not None: self.LibraryPanel.SetControler(self.Controler) + self.ProjectTree.Enable(True) self.PouInstanceVariablesPanel.SetController(self.Controler) self._Refresh(PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) - self.RefreshAll() + self.RefreshStatusToolBar() if self.EnableDebug: self.DebugVariablePanel.SetDataProducer(self.CTR) @@ -589,6 +619,7 @@ self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU, DISPLAYMENU) self.RefreshConfNodeMenu() + self.RefreshStatusToolBar() self.LogConsole.SetFocus() def RiseLogConsole(self): @@ -823,6 +854,26 @@ if callback is not None: self.Bind(wx.EVT_MENU, callback, id=id) + def RefreshStatusToolBar(self): + StatusToolBar = self.Panes["StatusToolBar"] + StatusToolBar.ClearTools() + + if self.CTR is not None: + + for confnode_method in self.CTR.StatusMethods: + if "method" in confnode_method and confnode_method.get("shown",True): + id = wx.NewId() + StatusToolBar.AddSimpleTool(id, + wx.Bitmap(Bpath("images", "%s.png"%confnode_method.get("bitmap", "Unknown"))), + confnode_method["tooltip"]) + self.Bind(wx.EVT_MENU, self.GetMenuCallBackFunction(confnode_method["method"]), id=id) + + StatusToolBar.Realize() + self.AUIManager.GetPane("StatusToolBar").BestSize(StatusToolBar.GetBestSize()).Show() + else: + self.AUIManager.GetPane("StatusToolBar").Hide() + self.AUIManager.Update() + def RefreshConfNodeMenu(self): if self.CTR is not None: selected = self.TabsOpened.GetSelection() @@ -1420,7 +1471,7 @@ event.Skip() return OnConfNodeTreeItemChannelChanged - def _GetAddConfNodeFunction(self, name, confnode): + def _GetAddConfNodeFunction(self, name, confnode=None): def OnConfNodeMenu(event): wx.CallAfter(self.AddConfNode, name, confnode) return OnConfNodeMenu @@ -1437,6 +1488,19 @@ main_menu.Destroy() return AddConfNodeMenu + def GetMenuCallBackFunction(self, method): + """ Generate the callbackfunc for a given CTR method""" + def OnMenu(event): + # Disable button to prevent re-entrant call + event.GetEventObject().Disable() + # Call + getattr(self.CTR, method)() + # Re-enable button + event.GetEventObject().Enable() + # Trigger refresh on Idle + wx.CallAfter(self.RefreshStatusToolBar) + return OnMenu + def GetButtonCallBackFunction(self, confnode, method): """ Generate the callbackfunc for a given confnode method""" def OnButtonClick(event): @@ -1656,6 +1720,9 @@ textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, confnode, element_path)) first = False + def GetConfigEntry(self, entry_name, default): + return cPickle.loads(str(self.Config.Read(entry_name, cPickle.dumps(default)))) + def ResetView(self): IDEFrame.ResetView(self) self.ConfNodeInfos = {} @@ -1695,12 +1762,13 @@ self.CTR = ctr self.Controler = self.CTR self.LibraryPanel.SetControler(self.Controler) + self.ProjectTree.Enable(True) self.PouInstanceVariablesPanel.SetController(self.Controler) self.RefreshConfigRecentProjects(projectpath) if self.EnableDebug: self.DebugVariablePanel.SetDataProducer(self.CTR) self._Refresh(PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) - self.RefreshAll() + self.RefreshStatusToolBar() else: self.ResetView() self.ShowErrorMessage(result) @@ -1731,13 +1799,14 @@ result = self.CTR.LoadProject(projectpath) if not result: self.LibraryPanel.SetControler(self.Controler) + self.ProjectTree.Enable(True) self.PouInstanceVariablesPanel.SetController(self.Controler) self.RefreshConfigRecentProjects(projectpath) if self.EnableDebug: self.DebugVariablePanel.SetDataProducer(self.CTR) self.LoadProjectOrganization() self._Refresh(PROJECTTREE, POUINSTANCEVARIABLESPANEL, LIBRARYTREE) - self.RefreshAll() + self.RefreshStatusToolBar() else: self.ResetView() self.ShowErrorMessage(result) @@ -1752,18 +1821,16 @@ self.SaveProjectOrganization() self.ResetView() self._Refresh(TITLE, EDITORTOOLBAR, FILEMENU, EDITMENU) - self.RefreshAll() + self.RefreshStatusToolBar() def OnSaveProjectMenu(self, event): if self.CTR is not None: self.CTR.SaveProject() - self.RefreshAll() self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES) def OnSaveProjectAsMenu(self, event): if self.CTR is not None: self.CTR.SaveProjectAs() - self.RefreshAll() self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES) event.Skip() @@ -1784,6 +1851,71 @@ wx.CallAfter(self.RefreshConfNodeMenu) IDEFrame.OnPageClose(self, event) + def OnProjectTreeItemBeginEdit(self, event): + selected = event.GetItem() + if self.ProjectTree.GetPyData(selected)["type"] in ITEM_CONFNODE: + event.Veto() + else: + IDEFrame.OnProjectTreeItemBeginEdit(self, event) + + def OnProjectTreeRightUp(self, event): + if wx.Platform == '__WXMSW__': + item = event.GetItem() + else: + item, flags = self.ProjectTree.HitTest(wx.Point(event.GetX(), event.GetY())) + item_infos = self.ProjectTree.GetPyData(item) + + if item_infos["type"] == ITEM_CONFNODE: + confnode_menu = wx.Menu(title='') + + confnode = item_infos["confnode"] + if confnode is not None and len(confnode.CTNChildrenTypes) > 0: + for name, XSDClass, help in confnode.CTNChildrenTypes: + new_id = wx.NewId() + confnode_menu.Append(help=help, id=new_id, kind=wx.ITEM_NORMAL, text=name) + self.Bind(wx.EVT_MENU, self._GetAddConfNodeFunction(name, confnode), id=new_id) + + new_id = wx.NewId() + AppendMenu(confnode_menu, help='', id=new_id, kind=wx.ITEM_NORMAL, text=_("Delete")) + self.Bind(wx.EVT_MENU, self.GetDeleteButtonFunction(confnode), id=new_id) + + self.PopupMenu(confnode_menu) + confnode_menu.Destroy() + + event.Skip() + else: + IDEFrame.OnProjectTreeRightUp(self, event) + + def OnProjectTreeItemActivated(self, event): + selected = event.GetItem() + name = self.ProjectTree.GetItemText(selected) + item_infos = self.ProjectTree.GetPyData(selected) + if item_infos["type"] == ITEM_CONFNODE: + item_infos["confnode"]._OpenView() + event.Skip() + elif item_infos["type"] == ITEM_PROJECT: + self.CTR._OpenView() + else: + IDEFrame.OnProjectTreeItemActivated(self, event) + + def SelectProjectTreeItem(self, tagname): + if self.ProjectTree is not None: + root = self.ProjectTree.GetRootItem() + if root.IsOk(): + words = tagname.split("::") + if len(words) == 1: + if tagname == "Project": + self.SelectedItem = root + self.ProjectTree.SelectItem(root) + wx.CallAfter(self.ResetSelectedItem) + else: + return self.RecursiveProjectTreeItemSelection(root, + [(word, ITEM_CONFNODE) for word in tagname.split(".")]) + elif words[0] == "R": + return self.RecursiveProjectTreeItemSelection(root, [(words[2], ITEM_RESOURCE)]) + else: + IDEFrame.SelectProjectTreeItem(self, tagname) + def GetAddButtonFunction(self, confnode, window): def AddButtonFunction(event): if confnode and len(confnode.CTNChildrenTypes) > 0: @@ -1803,14 +1935,17 @@ event.Skip() return DeleteButtonFunction - def AddConfNode(self, ConfNodeType, confnode): + def AddConfNode(self, ConfNodeType, confnode=None): if self.CTR.CheckProjectPathPerm(): dialog = wx.TextEntryDialog(self, _("Please enter a name for confnode:"), _("Add ConfNode"), "", wx.OK|wx.CANCEL) if dialog.ShowModal() == wx.ID_OK: ConfNodeName = dialog.GetValue() - confnode.CTNAddChild(ConfNodeName, ConfNodeType) + if confnode is not None: + confnode.CTNAddChild(ConfNodeName, ConfNodeType) + else: + self.CTR.CTNAddChild(ConfNodeName, ConfNodeType) self.CTR.RefreshConfNodesBlockLists() - self._Refresh(TITLE, FILEMENU) + self._Refresh(TITLE, FILEMENU, PROJECTTREE) self.RefreshConfNodeTree() dialog.Destroy() @@ -1822,7 +1957,7 @@ confnode.CTNRemove() del confnode self.CTR.RefreshConfNodesBlockLists() - self._Refresh(TITLE, FILEMENU) + self._Refresh(TITLE, FILEMENU, PROJECTTREE) self.RefreshConfNodeTree() dialog.Destroy() diff -r 7b421e080636 -r 413946c04c87 ConfTreeNodeEditor.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ConfTreeNodeEditor.py Mon May 21 10:04:27 2012 +0200 @@ -0,0 +1,536 @@ + +import os +import types + +import wx +import wx.lib.buttons + +from controls import EditorPanel + +from PLCOpenEditor import TITLE, FILEMENU, PROJECTTREE, PAGETITLES + +from util import opjimg +from util.TextCtrlAutoComplete import TextCtrlAutoComplete +from util.BrowseValuesLibraryDialog import BrowseValuesLibraryDialog + +if wx.Platform == '__WXMSW__': + faces = { 'times': 'Times New Roman', + 'mono' : 'Courier New', + 'helv' : 'Arial', + 'other': 'Comic Sans MS', + 'size' : 16, + } +else: + faces = { 'times': 'Times', + 'mono' : 'Courier', + 'helv' : 'Helvetica', + 'other': 'new century schoolbook', + 'size' : 18, + } + +SCROLLBAR_UNIT = 10 +WINDOW_COLOUR = wx.Colour(240,240,240) + +CWD = os.path.split(os.path.realpath(__file__))[0] + +def Bpath(*args): + return os.path.join(CWD,*args) + +# Some helpers to tweak GenBitmapTextButtons +# TODO: declare customized classes instead. +gen_mini_GetBackgroundBrush = lambda obj:lambda dc: wx.Brush(obj.GetParent().GetBackgroundColour(), wx.SOLID) +gen_textbutton_GetLabelSize = lambda obj:lambda:(wx.lib.buttons.GenButton._GetLabelSize(obj)[:-1] + (False,)) + +def make_genbitmaptogglebutton_flat(button): + button.GetBackgroundBrush = gen_mini_GetBackgroundBrush(button) + button.labelDelta = 0 + button.SetBezelWidth(0) + button.SetUseFocusIndicator(False) + +# Patch wx.lib.imageutils so that gray is supported on alpha images +import wx.lib.imageutils +from wx.lib.imageutils import grayOut as old_grayOut +def grayOut(anImage): + if anImage.HasAlpha(): + AlphaData = anImage.GetAlphaData() + else : + AlphaData = None + + old_grayOut(anImage) + + if AlphaData is not None: + anImage.SetAlphaData(AlphaData) + +wx.lib.imageutils.grayOut = grayOut + +class GenBitmapTextButton(wx.lib.buttons.GenBitmapTextButton): + def _GetLabelSize(self): + """ used internally """ + w, h = self.GetTextExtent(self.GetLabel()) + if not self.bmpLabel: + return w, h, False # if there isn't a bitmap use the size of the text + + w_bmp = self.bmpLabel.GetWidth()+2 + h_bmp = self.bmpLabel.GetHeight()+2 + height = h + h_bmp + if w_bmp > w: + width = w_bmp + else: + width = w + return width, height, False + + def DrawLabel(self, dc, width, height, dw=0, dy=0): + bmp = self.bmpLabel + if bmp != None: # if the bitmap is used + if self.bmpDisabled and not self.IsEnabled(): + bmp = self.bmpDisabled + if self.bmpFocus and self.hasFocus: + bmp = self.bmpFocus + if self.bmpSelected and not self.up: + bmp = self.bmpSelected + bw,bh = bmp.GetWidth(), bmp.GetHeight() + if not self.up: + dw = dy = self.labelDelta + hasMask = bmp.GetMask() != None + else: + bw = bh = 0 # no bitmap -> size is zero + + dc.SetFont(self.GetFont()) + if self.IsEnabled(): + dc.SetTextForeground(self.GetForegroundColour()) + else: + dc.SetTextForeground(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) + + label = self.GetLabel() + tw, th = dc.GetTextExtent(label) # size of text + if not self.up: + dw = dy = self.labelDelta + + pos_x = (width-bw)/2+dw # adjust for bitmap and text to centre + pos_y = (height-bh-th)/2+dy + if bmp !=None: + dc.DrawBitmap(bmp, pos_x, pos_y, hasMask) # draw bitmap if available + pos_x = (width-tw)/2+dw # adjust for bitmap and text to centre + pos_y += bh + 2 + + dc.DrawText(label, pos_x, pos_y) # draw the text + + +class GenStaticBitmap(wx.lib.statbmp.GenStaticBitmap): + """ Customized GenStaticBitmap, fix transparency redraw bug on wx2.8/win32, + and accept image name as __init__ parameter, fail silently if file do not exist""" + def __init__(self, parent, ID, bitmapname, + pos = wx.DefaultPosition, size = wx.DefaultSize, + style = 0, + name = "genstatbmp"): + + bitmappath = Bpath( "images", bitmapname) + if os.path.isfile(bitmappath): + bitmap = wx.Bitmap(bitmappath) + else: + bitmap = None + wx.lib.statbmp.GenStaticBitmap.__init__(self, parent, ID, bitmap, + pos, size, + style, + name) + + def OnPaint(self, event): + dc = wx.PaintDC(self) + colour = self.GetParent().GetBackgroundColour() + dc.SetPen(wx.Pen(colour)) + dc.SetBrush(wx.Brush(colour )) + dc.DrawRectangle(0, 0, *dc.GetSizeTuple()) + if self._bitmap: + dc.DrawBitmap(self._bitmap, 0, 0, True) + +class ConfTreeNodeEditor(EditorPanel): + + HAS_BASE_PARAMS = True + + def _init_ConfNodeEditor(self, prnt): + self.ConfNodeEditor = None + + def _init_Editor(self, prnt): + self.Editor = wx.SplitterWindow(id=self.ID, name='EditorSplitter', parent=prnt, + size=wx.Size(0, 0), style=wx.SUNKEN_BORDER|wx.SP_3D) + self.SetNeedUpdating(True) + self.SetMinimumPaneSize(1) + + self.ParamsEditor = wx.ScrolledWindow(self.Editor, -1, size=wx.Size(-1, -1), + style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL) + self.ParamsEditor.SetBackgroundColour(WINDOW_COLOUR) + self.ParamsEditor.Bind(wx.EVT_SIZE, self.OnWindowResize) + self.ParamsEditor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel) + + # Variable allowing disabling of ParamsEditor scroll when Popup shown + self.ScrollingEnabled = True + + self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) + self.ParamsEditorSizer.AddGrowableCol(0) + self.ParamsEditorSizer.AddGrowableRow(1) + + self.ParamsEditor.SetSizer(self.ParamsEditorSizer) + + baseparamseditor_sizer = wx.BoxSizer(wx.HORIZONTAL) + self.ParamsEditorSizer.AddSizer(baseparamseditor_sizer, 0, border=5, + flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.TOP) + + self.FullIECChannel = wx.StaticText(self.ParamsEditor, -1) + self.FullIECChannel.SetFont( + wx.Font(faces["size"], wx.DEFAULT, wx.NORMAL, + wx.BOLD, faceName = faces["helv"])) + baseparamseditor_sizer.AddWindow(self.FullIECChannel, 0, border=0, flag=wx.ALIGN_CENTER_VERTICAL) + + updownsizer = wx.BoxSizer(wx.VERTICAL) + baseparamseditor_sizer.AddSizer(updownsizer, 0, border=5, + flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL) + + ieccdownbutton_id = wx.NewId() + self.IECCDownButton = wx.lib.buttons.GenBitmapButton( + id=ieccdownbutton_id, bitmap=wx.Bitmap(opjimg('IECCDown')), + name='IECDownButton', parent=self.ParamsEditor, pos=wx.Point(0, 0), + size=wx.Size(16, 16), style=wx.NO_BORDER) + self.IECCDownButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(-1), + id=ieccdownbutton_id) + updownsizer.AddWindow(self.IECCDownButton, 0, border=0, flag=wx.ALIGN_LEFT) + + ieccupbutton_id = wx.NewId() + self.IECCUpButton = wx.lib.buttons.GenBitmapTextButton( + id=ieccupbutton_id, bitmap=wx.Bitmap(opjimg('IECCUp')), + name='IECUpButton', parent=self.ParamsEditor, pos=wx.Point(0, 0), + size=wx.Size(16, 16), style=wx.NO_BORDER) + self.IECCUpButton.Bind(wx.EVT_BUTTON, self.GetItemChannelChangedFunction(1), + id=ieccupbutton_id) + updownsizer.AddWindow(self.IECCUpButton, 0, border=0, flag=wx.ALIGN_LEFT) + + self.RefreshIECChannelControlsState() + + confnodename_id = wx.NewId() + self.ConfNodeName = wx.TextCtrl( + self.ParamsEditor, confnodename_id, + size=wx.Size(150, 25), style=wx.NO_BORDER) + self.ConfNodeName.SetFont( + wx.Font(faces["size"] * 0.75, wx.DEFAULT, wx.NORMAL, + wx.BOLD, faceName = faces["helv"])) + self.ConfNodeName.ChangeValue(self.Controler.MandatoryParams[1].getName()) + self.ConfNodeName.Bind(wx.EVT_TEXT, + self.GetTextCtrlCallBackFunction(self.ConfNodeName, "BaseParams.Name"), + id=confnodename_id) + baseparamseditor_sizer.AddWindow(self.ConfNodeName, 0, border=5, flag=wx.LEFT|wx.RIGHT|wx.ALIGN_CENTER_VERTICAL) + + buttons_sizer = self.GenerateMethodButtonSizer() + baseparamseditor_sizer.AddSizer(buttons_sizer, 0, border=0, flag=wx.ALIGN_CENTER) + + self.ConfNodeParamsSizer = wx.BoxSizer(wx.VERTICAL) + self.ParamsEditorSizer.AddSizer(self.ConfNodeParamsSizer, 0, border=5, + flag=wx.LEFT|wx.RIGHT|wx.BOTTOM) + + self.RefreshConfNodeParamsSizer() + + self._init_ConfNodeEditor(self.Editor) + + if self.ConfNodeEditor is not None: + min_size = self.ParamsEditorSizer.GetMinSize() + self.Editor.SplitHorizontally(self.ParamsEditor, + self.ConfNodeEditor, + min(min_size.height, 200)) + else: + self.Editor.Initialize(self.ParamsEditor) + + def __init__(self, parent, tagname, controler, window): + EditorPanel.__init__(self, parent, tagname, window, controler) + + self.SetIcon(wx.Bitmap(self.Controler.GetIconPath(), wx.BITMAP_TYPE_PNG)) + + def __del__(self): + self.Controler.OnCloseEditor(self) + + def GetTagName(self): + return self.Controler.CTNFullName() + + def GetTitle(self): + fullname = self.Controler.CTNFullName() + if self.Controler.CTNTestModified(): + return "~%s~" % fullname + return fullname + + def HasNoModel(self): + return False + + def EnableScrolling(self, enable): + self.ScrollingEnabled = enable + + def RefreshIECChannelControlsState(self): + self.FullIECChannel.SetLabel(self.Controler.GetFullIEC_Channel()) + self.IECCDownButton.Enable(self.Controler.BaseParams.getIEC_Channel() > 0) + + def RefreshConfNodeParamsSizer(self): + self.Freeze() + self.ConfNodeParamsSizer.Clear(True) + + confnode_infos = self.Controler.GetParamsAttributes() + if len(confnode_infos) > 0: + self.GenerateSizerElements(self.ConfNodeParamsSizer, confnode_infos, None, False) + + self.ParamsEditorSizer.Layout() + self.Thaw() + + def GenerateMethodButtonSizer(self): + normal_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, faceName = faces["helv"]) + mouseover_bt_font=wx.Font(faces["size"] / 3, wx.DEFAULT, wx.NORMAL, wx.NORMAL, underline=True, faceName = faces["helv"]) + + msizer = wx.BoxSizer(wx.HORIZONTAL) + + for confnode_method in self.Controler.ConfNodeMethods: + if "method" in confnode_method and confnode_method.get("shown",True): + id = wx.NewId() + label = confnode_method["name"] + button = GenBitmapTextButton(id=id, parent=self.ParamsEditor, + bitmap=wx.Bitmap(Bpath("images", "%s.png"%confnode_method.get("bitmap", "Unknown"))), label=label, + name=label, pos=wx.DefaultPosition, style=wx.NO_BORDER) + button.SetFont(normal_bt_font) + button.SetToolTipString(confnode_method["tooltip"]) + button.Bind(wx.EVT_BUTTON, self.GetButtonCallBackFunction(confnode_method["method"]), id=id) + # a fancy underline on mouseover + def setFontStyle(b, s): + def fn(event): + b.SetFont(s) + b.Refresh() + event.Skip() + return fn + button.Bind(wx.EVT_ENTER_WINDOW, setFontStyle(button, mouseover_bt_font)) + button.Bind(wx.EVT_LEAVE_WINDOW, setFontStyle(button, normal_bt_font)) + #hack to force size to mini + if not confnode_method.get("enabled",True): + button.Disable() + msizer.AddWindow(button, 0, border=0, flag=wx.ALIGN_CENTER) + return msizer + + def GenerateSizerElements(self, sizer, elements, path, clean = True): + if clean: + sizer.Clear(True) + first = True + for element_infos in elements: + if path: + element_path = "%s.%s"%(path, element_infos["name"]) + else: + element_path = element_infos["name"] + if element_infos["type"] == "element": + label = element_infos["name"] + staticbox = wx.StaticBox(id=-1, label=_(label), + name='%s_staticbox'%element_infos["name"], parent=self.ParamsEditor, + pos=wx.Point(0, 0), size=wx.Size(10, 0), style=0) + staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) + if first: + sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW|wx.TOP) + else: + sizer.AddSizer(staticboxsizer, 0, border=0, flag=wx.GROW) + self.GenerateSizerElements(staticboxsizer, element_infos["children"], element_path) + else: + boxsizer = wx.FlexGridSizer(cols=3, rows=1) + boxsizer.AddGrowableCol(1) + if first: + sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.ALL) + else: + sizer.AddSizer(boxsizer, 0, border=5, flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.BOTTOM) + staticbitmap = GenStaticBitmap(ID=-1, bitmapname="%s.png"%element_infos["name"], + name="%s_bitmap"%element_infos["name"], parent=self.ParamsEditor, + pos=wx.Point(0, 0), size=wx.Size(24, 24), style=0) + boxsizer.AddWindow(staticbitmap, 0, border=5, flag=wx.RIGHT) + label = element_infos["name"] + statictext = wx.StaticText(id=-1, label="%s:"%_(label), + name="%s_label"%element_infos["name"], parent=self.ParamsEditor, + pos=wx.Point(0, 0), size=wx.DefaultSize, style=0) + boxsizer.AddWindow(statictext, 0, border=5, flag=wx.ALIGN_CENTER_VERTICAL|wx.RIGHT) + id = wx.NewId() + if isinstance(element_infos["type"], types.ListType): + if isinstance(element_infos["value"], types.TupleType): + browse_boxsizer = wx.BoxSizer(wx.HORIZONTAL) + boxsizer.AddSizer(browse_boxsizer, 0, border=0, flag=0) + + textctrl = wx.TextCtrl(id=id, name=element_infos["name"], parent=self.ParamsEditor, + pos=wx.Point(0, 0), size=wx.Size(275, 25), style=wx.TE_READONLY) + if element_infos["value"] is not None: + textctrl.SetValue(element_infos["value"][0]) + value_infos = element_infos["value"][1] + else: + value_infos = None + browse_boxsizer.AddWindow(textctrl, 0, border=0, flag=0) + button_id = wx.NewId() + button = wx.Button(id=button_id, name="browse_%s" % element_infos["name"], parent=self.ParamsEditor, + label="...", pos=wx.Point(0, 0), size=wx.Size(25, 25)) + browse_boxsizer.AddWindow(button, 0, border=0, flag=0) + button.Bind(wx.EVT_BUTTON, + self.GetBrowseCallBackFunction(element_infos["name"], textctrl, element_infos["type"], + value_infos, element_path), + id=button_id) + else: + combobox = wx.ComboBox(id=id, name=element_infos["name"], parent=self.ParamsEditor, + pos=wx.Point(0, 0), size=wx.Size(300, 28), style=wx.CB_READONLY) + boxsizer.AddWindow(combobox, 0, border=0, flag=0) + if element_infos["use"] == "optional": + combobox.Append("") + if len(element_infos["type"]) > 0 and isinstance(element_infos["type"][0], types.TupleType): + for choice, xsdclass in element_infos["type"]: + combobox.Append(choice) + name = element_infos["name"] + value = element_infos["value"] + staticbox = wx.StaticBox(id=-1, label="%s - %s"%(_(name), _(value)), + name='%s_staticbox'%element_infos["name"], parent=self.ParamsEditor, + pos=wx.Point(0, 0), size=wx.Size(10, 0), style=0) + staticboxsizer = wx.StaticBoxSizer(staticbox, wx.VERTICAL) + sizer.AddSizer(staticboxsizer, 0, border=5, flag=wx.GROW|wx.BOTTOM) + self.GenerateSizerElements(staticboxsizer, element_infos["children"], element_path) + callback = self.GetChoiceContentCallBackFunction(combobox, staticboxsizer, element_path) + else: + for choice in element_infos["type"]: + combobox.Append(choice) + callback = self.GetChoiceCallBackFunction(combobox, element_path) + if element_infos["value"] is None: + combobox.SetStringSelection("") + else: + combobox.SetStringSelection(element_infos["value"]) + combobox.Bind(wx.EVT_COMBOBOX, callback, id=id) + elif isinstance(element_infos["type"], types.DictType): + scmin = -(2**31) + scmax = 2**31-1 + if "min" in element_infos["type"]: + scmin = element_infos["type"]["min"] + if "max" in element_infos["type"]: + scmax = element_infos["type"]["max"] + spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=self.ParamsEditor, + pos=wx.Point(0, 0), size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) + spinctrl.SetRange(scmin,scmax) + boxsizer.AddWindow(spinctrl, 0, border=0, flag=0) + if element_infos["value"] is not None: + spinctrl.SetValue(element_infos["value"]) + spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, element_path), id=id) + else: + if element_infos["type"] == "boolean": + checkbox = wx.CheckBox(id=id, name=element_infos["name"], parent=self.ParamsEditor, + pos=wx.Point(0, 0), size=wx.Size(17, 25), style=0) + boxsizer.AddWindow(checkbox, 0, border=0, flag=0) + if element_infos["value"] is not None: + checkbox.SetValue(element_infos["value"]) + checkbox.Bind(wx.EVT_CHECKBOX, self.GetCheckBoxCallBackFunction(checkbox, element_path), id=id) + elif element_infos["type"] in ["unsignedLong", "long","integer"]: + if element_infos["type"].startswith("unsigned"): + scmin = 0 + else: + scmin = -(2**31) + scmax = 2**31-1 + spinctrl = wx.SpinCtrl(id=id, name=element_infos["name"], parent=self.ParamsEditor, + pos=wx.Point(0, 0), size=wx.Size(300, 25), style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT) + spinctrl.SetRange(scmin, scmax) + boxsizer.AddWindow(spinctrl, 0, border=0, flag=0) + if element_infos["value"] is not None: + spinctrl.SetValue(element_infos["value"]) + spinctrl.Bind(wx.EVT_SPINCTRL, self.GetTextCtrlCallBackFunction(spinctrl, element_path), id=id) + else: + choices = self.ParentWindow.GetConfigEntry(element_path, [""]) + textctrl = TextCtrlAutoComplete(id=id, + name=element_infos["name"], + parent=self.ParamsEditor, + appframe=self, + choices=choices, + element_path=element_path, + pos=wx.Point(0, 0), + size=wx.Size(300, 25), + style=0) + + boxsizer.AddWindow(textctrl, 0, border=0, flag=0) + if element_infos["value"] is not None: + textctrl.ChangeValue(str(element_infos["value"])) + textctrl.Bind(wx.EVT_TEXT, self.GetTextCtrlCallBackFunction(textctrl, element_path)) + first = False + + + def GetItemChannelChangedFunction(self, dir): + def OnConfNodeTreeItemChannelChanged(event): + confnode_IECChannel = self.Controler.BaseParams.getIEC_Channel() + res = self.SetConfNodeParamsAttribute("BaseParams.IEC_Channel", confnode_IECChannel + dir) + wx.CallAfter(self.RefreshIECChannelControlsState) + wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE) + wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName()) + event.Skip() + return OnConfNodeTreeItemChannelChanged + + def SetConfNodeParamsAttribute(self, *args, **kwargs): + res, StructChanged = self.Controler.SetParamsAttribute(*args, **kwargs) + if StructChanged: + wx.CallAfter(self.RefreshConfNodeParamsSizer) + wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU) + return res + + def GetButtonCallBackFunction(self, method): + """ Generate the callbackfunc for a given confnode method""" + def OnButtonClick(event): + # Disable button to prevent re-entrant call + event.GetEventObject().Disable() + # Call + getattr(self.Controler,method)() + # Re-enable button + event.GetEventObject().Enable() + + event.Skip() + return OnButtonClick + + def GetChoiceCallBackFunction(self, choicectrl, path): + def OnChoiceChanged(event): + res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection()) + choicectrl.SetStringSelection(res) + event.Skip() + return OnChoiceChanged + + def GetChoiceContentCallBackFunction(self, choicectrl, staticboxsizer, path): + def OnChoiceContentChanged(event): + res = self.SetConfNodeParamsAttribute(path, choicectrl.GetStringSelection()) + event.Skip() + return OnChoiceContentChanged + + def GetTextCtrlCallBackFunction(self, textctrl, path): + def OnTextCtrlChanged(event): + res = self.SetConfNodeParamsAttribute(path, textctrl.GetValue()) + if res != textctrl.GetValue(): + textctrl.ChangeValue(res) + if textctrl == self.ConfNodeName: + wx.CallAfter(self.ParentWindow._Refresh, TITLE, FILEMENU, PROJECTTREE, PAGETITLES) + wx.CallAfter(self.ParentWindow.SelectProjectTreeItem, self.GetTagName()) + event.Skip() + return OnTextCtrlChanged + + def GetCheckBoxCallBackFunction(self, chkbx, path): + def OnCheckBoxChanged(event): + res = self.SetConfNodeParamsAttribute(path, chkbx.IsChecked()) + chkbx.SetValue(res) + event.Skip() + return OnCheckBoxChanged + + def GetBrowseCallBackFunction(self, name, textctrl, library, value_infos, path): + infos = [value_infos] + def OnBrowseButton(event): + dialog = BrowseValuesLibraryDialog(self, name, library, infos[0]) + if dialog.ShowModal() == wx.ID_OK: + value, value_infos = self.SetConfNodeParamsAttribute(path, dialog.GetValueInfos()) + textctrl.ChangeValue(value) + infos[0] = value_infos + dialog.Destroy() + event.Skip() + return OnBrowseButton + + def OnWindowResize(self, event): + self.GetBestSize() + xstart, ystart = self.ParamsEditor.GetViewStart() + window_size = self.ParamsEditor.GetClientSize() + maxx, maxy = self.ParamsEditorSizer.GetMinSize() + posx = max(0, min(xstart, (maxx - window_size[0]) / SCROLLBAR_UNIT)) + posy = max(0, min(ystart, (maxy - window_size[1]) / SCROLLBAR_UNIT)) + self.ParamsEditor.Scroll(posx, posy) + self.ParamsEditor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, + maxx / SCROLLBAR_UNIT, maxy / SCROLLBAR_UNIT, posx, posy) + event.Skip() + + def OnMouseWheel(self, event): + if self.ScrollingEnabled: + event.Skip() + diff -r 7b421e080636 -r 413946c04c87 ConfigTreeNode.py --- a/ConfigTreeNode.py Mon May 21 02:49:53 2012 +0200 +++ b/ConfigTreeNode.py Mon May 21 10:04:27 2012 +0200 @@ -12,7 +12,7 @@ from xml.dom import minidom from xmlclass import GenerateClassesFromXSDstring -from util import opjimg, GetClassImporter +from util import GetClassImporter from PLCControler import PLCControler, LOCATION_CONFNODE @@ -40,7 +40,8 @@ ConfNodeMethods = [] LibraryControler = None EditorType = None - + IconPath = None + def _AddParamsMembers(self): self.CTNParams = None if self.XSD: @@ -572,22 +573,3 @@ self.GetCTRoot().logger.write_error(_("Could not add child \"%s\", type %s :\n%s\n")%(pname, ptype, str(exc))) self.GetCTRoot().logger.write_error(traceback.format_exc()) - def EnableMethod(self, method, value): - for d in self.ConfNodeMethods: - if d["method"]==method: - d["enabled"]=value - return True - return False - - def ShowMethod(self, method, value): - for d in self.ConfNodeMethods: - if d["method"]==method: - d["shown"]=value - return True - return False - - def CallMethod(self, method): - for d in self.ConfNodeMethods: - if d["method"]==method and d.get("enabled", True) and d.get("shown", True): - getattr(self, method)() - diff -r 7b421e080636 -r 413946c04c87 ProjectController.py --- a/ProjectController.py Mon May 21 02:49:53 2012 +0200 +++ b/ProjectController.py Mon May 21 10:04:27 2012 +0200 @@ -16,13 +16,14 @@ import connectors from util import MiniTextControler, opjimg, CheckPathPerm, GetClassImporter from util.ProcessLogger import ProcessLogger -from PLCControler import PLCControler -from PLCOpenEditor import ProjectDialog +from PLCControler import PLCControler +from PLCOpenEditor import CWD from TextViewer import TextViewer from plcopen.structures import IEC_KEYWORDS from targets.typemapping import DebugTypesSize from util.discovery import DiscoveryDialog from ConfigTreeNode import ConfigTreeNode +from ProjectNodeEditor import ProjectNodeEditor base_folder = os.path.split(sys.path[0])[0] @@ -31,6 +32,8 @@ DEBUG_RETRIES_WARN = 3 DEBUG_RETRIES_REREGISTER = 4 +ITEM_CONFNODE = 25 + class ProjectController(ConfigTreeNode, PLCControler): """ This class define Root object of the confnode tree. @@ -73,7 +76,8 @@ """ - + EditorType = ProjectNodeEditor + def __init__(self, frame, logger): PLCControler.__init__(self) @@ -99,6 +103,7 @@ # Keep track of the confnode type name self.CTNType = "Beremiz" self.Children = {} + self._View = None # After __init__ root confnode is not valid self.ProjectPath = None self._setBuildPath(None) @@ -121,7 +126,7 @@ if self.DebugTimer: self.DebugTimer.cancel() self.KillDebugThread() - + def SetAppFrame(self, frame, logger): self.AppFrame = frame self.logger = logger @@ -143,6 +148,9 @@ self.logger = logger + def CTNName(self): + return "Project" + def CTNTestModified(self): return self.ChangesToSave or not self.ProjectIsSaved() @@ -173,6 +181,9 @@ def GetProjectName(self): return os.path.split(self.ProjectPath)[1] + def GetIconPath(self): + return os.path.join(CWD, "Images", "PROJECT.png") + def GetDefaultTargetName(self): if wx.Platform == '__WXMSW__': return "Win32" @@ -212,9 +223,9 @@ dialog.Destroy() if answer == wx.ID_YES: if self.SaveProjectAs(): - self.AppFrame.RefreshAll() self.AppFrame.RefreshTitle() self.AppFrame.RefreshFileMenu() + self.AppFrame.RefreshPageTitles() return True return False @@ -228,17 +239,16 @@ if not os.path.isdir(ProjectPath) or len(os.listdir(ProjectPath)) > 0: return _("Chosen folder isn't empty. You can't use it for a new project!") - dialog = ProjectDialog(self.AppFrame) - if dialog.ShowModal() == wx.ID_OK: - values = dialog.GetValues() - values["creationDateTime"] = datetime(*localtime()[:6]) - dialog.Destroy() - else: - dialog.Destroy() - return _("Project not created") - # Create PLCOpen program - self.CreateNewProject(values) + self.CreateNewProject( + {"projectName": _("Unnamed"), + "productName": _("Unnamed"), + "productVersion": _("1"), + "companyName": _("Unknown"), + "creationDateTime": datetime(*localtime()[:6])}) + self.ProjectAddConfiguration("config") + self.ProjectAddConfigurationResource("config", "resource1") + # Change XSD into class members self._AddParamsMembers() self.Children = {} @@ -290,6 +300,32 @@ return None + def RecursiveConfNodeInfos(self, confnode): + values = [] + for CTNChild in confnode.IECSortedChildren(): + values.append( + {"name": "%s: %s" % (CTNChild.GetFullIEC_Channel(), + CTNChild.CTNName()), + "type": ITEM_CONFNODE, + "confnode": CTNChild, + "icon": CTNChild.GetIconPath(), + "values": self.RecursiveConfNodeInfos(CTNChild)}) + return values + + def GetProjectInfos(self): + infos = PLCControler.GetProjectInfos(self) + configurations = infos["values"].pop(-1) + resources = None + for config_infos in configurations["values"]: + if resources is None: + resources = config_infos["values"][0] + else: + resources["values"].extend(config_infos["values"][0]["values"]) + if resources is not None: + infos["values"].append(resources) + infos["values"].extend(self.RecursiveConfNodeInfos(self)) + return infos + def CloseProject(self): self.ClearChildren() self.ResetAppFrame(None) @@ -906,7 +942,7 @@ return IEC_code_viewer elif name == "IEC raw code": - controler = MiniTextControler(self._getIECrawcodepath()) + controler = MiniTextControler.MiniTextControler(self._getIECrawcodepath()) IEC_raw_code_viewer = TextViewer(self.AppFrame.TabsOpened, "", None, controler, instancepath=name) #IEC_raw_code_viewer.Enable(False) IEC_raw_code_viewer.SetTextSyntax("ALL") @@ -918,7 +954,8 @@ return IEC_raw_code_viewer - return None + else: + return ConfigTreeNode._OpenView(self, name) def _Clean(self): if os.path.isdir(os.path.join(self._getBuildPath())): @@ -971,7 +1008,7 @@ {"Broken": self.logger.write_error, None: lambda x: None}.get( self.previous_plcstate, self.logger.write)(_("PLC is %s\n")%status) - self.AppFrame.RefreshAll() + self.AppFrame.RefreshStatusToolBar() def RegisterDebugVarToConnector(self): self.DebugTimer=None @@ -1339,7 +1376,7 @@ wx.CallAfter(self.UpdateMethodsFromPLCStatus) - ConfNodeMethods = [ + StatusMethods = [ {"bitmap" : "Build", "name" : _("Build"), "tooltip" : _("Build project into build folder"), @@ -1378,8 +1415,31 @@ "shown" : False, "tooltip" : _("Show IEC code generated by PLCGenerator"), "method" : "_showIECcode"}, + ] + + ConfNodeMethods = [ {"bitmap" : "editIECrawcode", "name" : _("Raw IEC code"), "tooltip" : _("Edit raw IEC code added to code generated by PLCGenerator"), "method" : "_editIECrawcode"}, ] + + + def EnableMethod(self, method, value): + for d in self.StatusMethods: + if d["method"]==method: + d["enabled"]=value + return True + return False + + def ShowMethod(self, method, value): + for d in self.StatusMethods: + if d["method"]==method: + d["shown"]=value + return True + return False + + def CallMethod(self, method): + for d in self.StatusMethods: + if d["method"]==method and d.get("enabled", True) and d.get("shown", True): + getattr(self, method)() diff -r 7b421e080636 -r 413946c04c87 ProjectNodeEditor.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ProjectNodeEditor.py Mon May 21 10:04:27 2012 +0200 @@ -0,0 +1,54 @@ + +import wx + +from ConfTreeNodeEditor import ConfTreeNodeEditor, WINDOW_COLOUR + +class ProjectNodeEditor(ConfTreeNodeEditor): + + VARIABLE_PANEL_TYPE = "config" + + def _init_Editor(self, prnt): + self.Editor = wx.ScrolledWindow(prnt, -1, size=wx.Size(-1, -1), + style=wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER|wx.HSCROLL|wx.VSCROLL) + self.Editor.SetBackgroundColour(WINDOW_COLOUR) + self.ParamsEditor = self.Editor + + # Variable allowing disabling of Editor scroll when Popup shown + self.ScrollingEnabled = True + + self.ParamsEditorSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=2, vgap=5) + self.ParamsEditorSizer.AddGrowableCol(0) + self.ParamsEditorSizer.AddGrowableRow(1) + + self.Editor.SetSizer(self.ParamsEditorSizer) + + + buttons_sizer = self.GenerateMethodButtonSizer() + self.ParamsEditorSizer.AddSizer(buttons_sizer, 0, border=5, + flag=wx.GROW|wx.LEFT|wx.RIGHT|wx.TOP) + + self.ConfNodeParamsSizer = wx.BoxSizer(wx.VERTICAL) + self.ParamsEditorSizer.AddSizer(self.ConfNodeParamsSizer, 0, border=5, + flag=wx.LEFT|wx.RIGHT|wx.BOTTOM) + + self.RefreshConfNodeParamsSizer() + + def __init__(self, parent, controler, window): + configuration = controler.GetProjectMainConfigurationName() + if configuration is not None: + tagname = controler.ComputeConfigurationName(configuration) + else: + tagname = "" + + ConfTreeNodeEditor.__init__(self, parent, tagname, controler, window) + + def GetTagName(self): + return self.Controler.CTNName() + + def GetTitle(self): + fullname = self.Controler.CTNName() + if self.Controler.CTNTestModified(): + return "~%s~" % fullname + return fullname + + \ No newline at end of file diff -r 7b421e080636 -r 413946c04c87 c_ext/CFileEditor.py --- a/c_ext/CFileEditor.py Mon May 21 02:49:53 2012 +0200 +++ b/c_ext/CFileEditor.py Mon May 21 10:04:27 2012 +0200 @@ -6,7 +6,8 @@ import wx.lib.buttons from util import opjimg -from controls import CustomGrid, CustomTable, EditorPanel +from controls import CustomGrid, CustomTable +from ConfTreeNodeEditor import ConfTreeNodeEditor if wx.Platform == '__WXMSW__': faces = { 'times': 'Times New Roman', @@ -776,10 +777,10 @@ ID_CFILEEDITORCFILETREE, ID_CFILEEDITORPARTSOPENED, ] = [wx.NewId() for _init_ctrls in range(4)] -class CFileEditor(EditorPanel): - - def _init_Editor(self, prnt): - self.Editor = wx.Panel(id=ID_CFILEEDITOR, parent=prnt, pos=wx.Point(0, 0), +class CFileEditor(ConfTreeNodeEditor): + + def _init_ConfNodeEditor(self, prnt): + self.ConfNodeEditor = wx.Panel(id=ID_CFILEEDITOR, parent=prnt, pos=wx.Point(0, 0), size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL) self.Panels = {} @@ -790,41 +791,31 @@ button_id = wx.NewId() button = FoldPanelCaption(id=button_id, name='FoldPanelCaption_%s' % name, label=name, bitmap=wx.Bitmap(opjimg("CollapsedIconData")), - parent=self.Editor, pos=wx.Point(0, 0), + parent=self.ConfNodeEditor, pos=wx.Point(0, 0), size=wx.Size(0, 20), style=wx.NO_BORDER|wx.ALIGN_LEFT) button.SetBitmapSelected(wx.Bitmap(opjimg("ExpandedIconData"))) button.Bind(wx.EVT_BUTTON, self.GenPanelButtonCallback(name), id=button_id) self.MainSizer.AddWindow(button, 0, border=0, flag=wx.TOP|wx.GROW) if panel_class == VariablesEditor: - panel = VariablesEditor(self.Editor, self.ParentWindow, self.Controler) - else: - panel = panel_class(self.Editor, name, self.ParentWindow, self.Controler) + panel = VariablesEditor(self.ConfNodeEditor, self.ParentWindow, self.Controler) + else: + panel = panel_class(self.ConfNodeEditor, name, self.ParentWindow, self.Controler) self.MainSizer.AddWindow(panel, 0, border=0, flag=wx.BOTTOM|wx.GROW) panel.Hide() self.Panels[name] = {"button": button, "panel": panel, "expanded": False, "row": 2 * idx + 1} - self.Spacer = wx.Panel(self.Editor, -1) + self.Spacer = wx.Panel(self.ConfNodeEditor, -1) self.SpacerExpanded = True self.MainSizer.AddWindow(self.Spacer, 0, border=0, flag=wx.GROW) self.MainSizer.AddGrowableRow(2 * len(CFILE_PARTS)) - self.Editor.SetSizer(self.MainSizer) - + self.ConfNodeEditor.SetSizer(self.MainSizer) + def __init__(self, parent, controler, window): - EditorPanel.__init__(self, parent, "", window, controler) - self.SetIcon(wx.Bitmap(opjimg("Cfile"))) - - def __del__(self): - self.Controler.OnCloseEditor(self) - - def GetTitle(self): - fullname = self.Controler.CTNFullName() - if not self.Controler.CFileIsSaved(): - return "~%s~" % fullname - return fullname + ConfTreeNodeEditor.__init__(self, parent, "", controler, window) def GetBufferState(self): return self.Controler.GetBufferState() @@ -837,9 +828,6 @@ self.Controler.LoadNext() self.RefreshView() - def HasNoModel(self): - return False - def RefreshView(self): for infos in self.Panels.itervalues(): infos["panel"].RefreshView() diff -r 7b421e080636 -r 413946c04c87 c_ext/c_ext.py --- a/c_ext/c_ext.py Mon May 21 02:49:53 2012 +0200 +++ b/c_ext/c_ext.py Mon May 21 10:04:27 2012 +0200 @@ -4,6 +4,7 @@ from xmlclass import * +from util import opjimg from CFileEditor import CFileEditor from PLCControler import UndoBuffer, LOCATION_CONFNODE, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT @@ -43,6 +44,9 @@ self.CreateCFileBuffer(False) self.OnCTNSave() + def GetIconPath(self): + return opjimg("Cfile") + def CFileName(self): return os.path.join(self.CTNPath(), "cfile.xml") @@ -138,13 +142,6 @@ return self.CFile.publishFunction.gettext() return "" - ConfNodeMethods = [ - {"bitmap" : "EditCfile", - "name" : _("Edit C File"), - "tooltip" : _("Edit C File"), - "method" : "_OpenView"}, - ] - def CTNTestModified(self): return self.ChangesToSave or not self.CFileIsSaved() diff -r 7b421e080636 -r 413946c04c87 canfestival/NetworkEditor.py --- a/canfestival/NetworkEditor.py Mon May 21 02:49:53 2012 +0200 +++ b/canfestival/NetworkEditor.py Mon May 21 10:04:27 2012 +0200 @@ -1,6 +1,3 @@ -import os, sys -base_folder = os.path.split(sys.path[0])[0] -CanFestivalPath = os.path.join(base_folder, "CanFestival-3") import wx @@ -56,7 +53,7 @@ EditorPanel.__init__(self, parent, "", window, controler) NetworkEditorTemplate.__init__(self, controler, window, False) - img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage() + img = wx.Bitmap(controler.GetIconPath(), wx.BITMAP_TYPE_PNG).ConvertToImage() self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16))) self.RefreshNetworkNodes() diff -r 7b421e080636 -r 413946c04c87 canfestival/SlaveEditor.py --- a/canfestival/SlaveEditor.py Mon May 21 02:49:53 2012 +0200 +++ b/canfestival/SlaveEditor.py Mon May 21 10:04:27 2012 +0200 @@ -1,6 +1,3 @@ -import os, sys -base_folder = os.path.split(sys.path[0])[0] -CanFestivalPath = os.path.join(base_folder, "CanFestival-3") import wx @@ -28,7 +25,7 @@ EditorPanel.__init__(self, parent, "", window, controler) NodeEditorTemplate.__init__(self, controler, window, False) - img = wx.Bitmap(os.path.join(CanFestivalPath, "objdictgen", "networkedit.png"), wx.BITMAP_TYPE_PNG).ConvertToImage() + img = wx.Bitmap(controler.GetIconPath(), wx.BITMAP_TYPE_PNG).ConvertToImage() self.SetIcon(wx.BitmapFromImage(img.Rescale(16, 16))) def __del__(self): diff -r 7b421e080636 -r 413946c04c87 canfestival/canfestival.py --- a/canfestival/canfestival.py Mon May 21 02:49:53 2012 +0200 +++ b/canfestival/canfestival.py Mon May 21 10:04:27 2012 +0200 @@ -64,6 +64,7 @@ """ % DEFAULT_SETTINGS EditorType = SlaveEditor + IconPath = os.path.join(CanFestivalPath, "objdictgen", "networkedit.png") def __init__(self): # TODO change netname when name change @@ -215,6 +216,7 @@ """ % DEFAULT_SETTINGS EditorType = NetworkEditor + IconPath = os.path.join(CanFestivalPath, "objdictgen", "networkedit.png") def __init__(self): manager = NodeManager() diff -r 7b421e080636 -r 413946c04c87 images/Extension.png Binary file images/Extension.png has changed diff -r 7b421e080636 -r 413946c04c87 images/Pyfile.png Binary file images/Pyfile.png has changed diff -r 7b421e080636 -r 413946c04c87 images/SVGUI.png Binary file images/SVGUI.png has changed diff -r 7b421e080636 -r 413946c04c87 images/icons.svg --- a/images/icons.svg Mon May 21 02:49:53 2012 +0200 +++ b/images/icons.svg Mon May 21 10:04:27 2012 +0200 @@ -31,8 +31,8 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %% Cfile %% + sodipodi:role="line">%% Extension Cfile Pyfile wxGlade SVGUI %% + + + + + Py + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wx + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 7b421e080636 -r 413946c04c87 images/wxGlade.png Binary file images/wxGlade.png has changed diff -r 7b421e080636 -r 413946c04c87 py_ext/PythonEditor.py --- a/py_ext/PythonEditor.py Mon May 21 02:49:53 2012 +0200 +++ b/py_ext/PythonEditor.py Mon May 21 10:04:27 2012 +0200 @@ -1,10 +1,9 @@ -import wx, wx.grid -import wx.stc as stc +import wx +import wx.grid +import wx.stc as stc import keyword -from util import opjimg - -from controls import EditorPanel +from ConfTreeNodeEditor import ConfTreeNodeEditor if wx.Platform == '__WXMSW__': faces = { 'times': 'Times New Roman', @@ -55,197 +54,186 @@ else: return None -class PythonEditor(EditorPanel): +class PythonEditor(ConfTreeNodeEditor): fold_symbols = 3 - def _init_Editor(self, prnt): - self.Editor = stc.StyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt, + def _init_ConfNodeEditor(self, prnt): + self.ConfNodeEditor = stc.StyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt, name="TextViewer", pos=wx.DefaultPosition, size=wx.DefaultSize, style=0) - self.Editor.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN) - self.Editor.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT) - - self.Editor.SetLexer(stc.STC_LEX_PYTHON) - self.Editor.SetKeyWords(0, " ".join(keyword.kwlist)) - - self.Editor.SetProperty("fold", "1") - self.Editor.SetProperty("tab.timmy.whinge.level", "1") - self.Editor.SetMargins(0,0) - - self.Editor.SetViewWhiteSpace(False) - - self.Editor.SetEdgeMode(stc.STC_EDGE_BACKGROUND) - self.Editor.SetEdgeColumn(78) + self.ConfNodeEditor.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN) + self.ConfNodeEditor.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT) + + self.ConfNodeEditor.SetLexer(stc.STC_LEX_PYTHON) + self.ConfNodeEditor.SetKeyWords(0, " ".join(keyword.kwlist)) + + self.ConfNodeEditor.SetProperty("fold", "1") + self.ConfNodeEditor.SetProperty("tab.timmy.whinge.level", "1") + self.ConfNodeEditor.SetMargins(0,0) + + self.ConfNodeEditor.SetViewWhiteSpace(False) + + self.ConfNodeEditor.SetEdgeMode(stc.STC_EDGE_BACKGROUND) + self.ConfNodeEditor.SetEdgeColumn(78) # Set up the numbers in the margin for margin #1 - self.Editor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER) + self.ConfNodeEditor.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER) # Reasonable value for, say, 4-5 digits using a mono font (40 pix) - self.Editor.SetMarginWidth(1, 40) + self.ConfNodeEditor.SetMarginWidth(1, 40) # Setup a margin to hold fold markers - self.Editor.SetMarginType(2, stc.STC_MARGIN_SYMBOL) - self.Editor.SetMarginMask(2, stc.STC_MASK_FOLDERS) - self.Editor.SetMarginSensitive(2, True) - self.Editor.SetMarginWidth(2, 12) + self.ConfNodeEditor.SetMarginType(2, stc.STC_MARGIN_SYMBOL) + self.ConfNodeEditor.SetMarginMask(2, stc.STC_MASK_FOLDERS) + self.ConfNodeEditor.SetMarginSensitive(2, True) + self.ConfNodeEditor.SetMarginWidth(2, 12) if self.fold_symbols == 0: # Arrow pointing right for contracted folders, arrow pointing down for expanded - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") elif self.fold_symbols == 1: # Plus for contracted folders, minus for expanded - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") elif self.fold_symbols == 2: # Like a flattened tree control using circular headers and curved joins - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040") elif self.fold_symbols == 3: # Like a flattened tree control using square headers - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080") - self.Editor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080") - - - self.Editor.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI) - self.Editor.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick) - self.Editor.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed) + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080") + self.ConfNodeEditor.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080") + + + self.ConfNodeEditor.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI) + self.ConfNodeEditor.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick) + self.ConfNodeEditor.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed) # Global default style if wx.Platform == '__WXMSW__': - self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New') + self.ConfNodeEditor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New') elif wx.Platform == '__WXMAC__': # TODO: if this looks fine on Linux too, remove the Mac-specific case # and use this whenever OS != MSW. - self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Monaco') + self.ConfNodeEditor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Monaco') else: defsize = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT).GetPointSize() - self.Editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize) + self.ConfNodeEditor.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier,size:%d'%defsize) # Clear styles and revert to default. - self.Editor.StyleClearAll() + self.ConfNodeEditor.StyleClearAll() # Following style specs only indicate differences from default. # The rest remains unchanged. # Line numbers in margin - self.Editor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2') # Highlighted brace - self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00') # Unmatched brace - self.Editor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000') # Indentation guide - self.Editor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD") + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD") # Python styles - self.Editor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000') # Comments - self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0') - self.Editor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0') # Numbers - self.Editor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080') # Strings and characters - self.Editor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080') - self.Editor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080') # Keywords - self.Editor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold') # Triple quotes - self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA') - self.Editor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA') # Class names - self.Editor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold') # Function names - self.Editor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold') # Operators - self.Editor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold') # Identifiers. I leave this as not bold because everything seems # to be an identifier if it doesn't match the above criterae - self.Editor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000') + self.ConfNodeEditor.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000') # Caret color - self.Editor.SetCaretForeground("BLUE") + self.ConfNodeEditor.SetCaretForeground("BLUE") # Selection background - self.Editor.SetSelBackground(1, '#66CCFF') - - self.Editor.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)) - self.Editor.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)) + self.ConfNodeEditor.SetSelBackground(1, '#66CCFF') + + self.ConfNodeEditor.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)) + self.ConfNodeEditor.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)) # register some images for use in the AutoComplete box. #self.RegisterImage(1, images.getSmilesBitmap()) - self.Editor.RegisterImage(1, + self.ConfNodeEditor.RegisterImage(1, wx.ArtProvider.GetBitmap(wx.ART_DELETE, size=(16,16))) - self.Editor.RegisterImage(2, + self.ConfNodeEditor.RegisterImage(2, wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16))) - self.Editor.RegisterImage(3, + self.ConfNodeEditor.RegisterImage(3, wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16))) # Indentation and tab stuff - self.Editor.SetIndent(4) # Proscribed indent size for wx - self.Editor.SetIndentationGuides(True) # Show indent guides - self.Editor.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space - self.Editor.SetTabIndents(True) # Tab key indents - self.Editor.SetTabWidth(4) # Proscribed tab size for wx - self.Editor.SetUseTabs(False) # Use spaces rather than tabs, or + self.ConfNodeEditor.SetIndent(4) # Proscribed indent size for wx + self.ConfNodeEditor.SetIndentationGuides(True) # Show indent guides + self.ConfNodeEditor.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space + self.ConfNodeEditor.SetTabIndents(True) # Tab key indents + self.ConfNodeEditor.SetTabWidth(4) # Proscribed tab size for wx + self.ConfNodeEditor.SetUseTabs(False) # Use spaces rather than tabs, or # TabTimmy will complain! # White space - self.Editor.SetViewWhiteSpace(False) # Don't view white space + self.ConfNodeEditor.SetViewWhiteSpace(False) # Don't view white space # EOL: Since we are loading/saving ourselves, and the # strings will always have \n's in them, set the STC to # edit them that way. - self.Editor.SetEOLMode(wx.stc.STC_EOL_LF) - self.Editor.SetViewEOL(False) + self.ConfNodeEditor.SetEOLMode(wx.stc.STC_EOL_LF) + self.ConfNodeEditor.SetViewEOL(False) # No right-edge mode indicator - self.Editor.SetEdgeMode(stc.STC_EDGE_NONE) - - self.Editor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE) - - self.Editor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR) - self.Editor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) - self.Editor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR) + self.ConfNodeEditor.SetEdgeMode(stc.STC_EDGE_NONE) + + self.ConfNodeEditor.SetModEventMask(wx.stc.STC_MOD_BEFOREINSERT|wx.stc.STC_MOD_BEFOREDELETE) + + self.ConfNodeEditor.Bind(wx.stc.EVT_STC_DO_DROP, self.OnDoDrop, id=ID_PYTHONEDITOR) + self.ConfNodeEditor.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) + self.ConfNodeEditor.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModification, id=ID_PYTHONEDITOR) def __init__(self, parent, controler, window): - EditorPanel.__init__(self, parent, "", window, controler) + ConfTreeNodeEditor.__init__(self, parent, "", controler, window) self.DisableEvents = False self.CurrentAction = None - - self.SetIcon(wx.Bitmap(opjimg("Cfile"))) - - def __del__(self): - self.Controler.OnCloseEditor(self) - - def GetTitle(self): - fullname = self.Controler.CTNFullName() - if not self.Controler.PythonIsSaved(): - return "~%s~" % fullname - return fullname def GetBufferState(self): return self.Controler.GetBufferState() @@ -258,9 +246,6 @@ self.Controler.LoadNext() self.RefreshView() - def HasNoModel(self): - return False - def OnModification(self, event): if not self.DisableEvents: mod_type = event.GetModificationType() @@ -313,50 +298,43 @@ def RefreshView(self): self.ResetBuffer() self.DisableEvents = True - old_cursor_pos = self.Editor.GetCurrentPos() - old_text = self.Editor.GetText() + old_cursor_pos = self.ConfNodeEditor.GetCurrentPos() + old_text = self.ConfNodeEditor.GetText() new_text = self.Controler.GetPythonCode() - self.Editor.SetText(new_text) + self.ConfNodeEditor.SetText(new_text) new_cursor_pos = GetCursorPos(old_text, new_text) if new_cursor_pos != None: - self.Editor.GotoPos(new_cursor_pos) - else: - self.Editor.GotoPos(old_cursor_pos) - self.Editor.ScrollToColumn(0) - self.Editor.EmptyUndoBuffer() + self.ConfNodeEditor.GotoPos(new_cursor_pos) + else: + self.ConfNodeEditor.GotoPos(old_cursor_pos) + self.ConfNodeEditor.ScrollToColumn(0) + self.ConfNodeEditor.EmptyUndoBuffer() self.DisableEvents = False - self.Editor.Colourise(0, -1) + self.ConfNodeEditor.Colourise(0, -1) def RefreshModel(self): - self.Controler.SetPythonCode(self.Editor.GetText()) + self.Controler.SetPythonCode(self.ConfNodeEditor.GetText()) def OnKeyPressed(self, event): - if self.Editor.CallTipActive(): - self.Editor.CallTipCancel() + if self.ConfNodeEditor.CallTipActive(): + self.ConfNodeEditor.CallTipCancel() key = event.GetKeyCode() if key == 32 and event.ControlDown(): - pos = self.Editor.GetCurrentPos() - - # Tips - if event.ShiftDown(): - pass -## self.CallTipSetBackground("yellow") -## self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n' -## 'show some suff, maybe parameters..\n\n' -## 'fubar(param1, param2)') + pos = self.ConfNodeEditor.GetCurrentPos() + # Code completion - else: - self.Editor.AutoCompSetIgnoreCase(False) # so this needs to match + if not event.ShiftDown(): + self.ConfNodeEditor.AutoCompSetIgnoreCase(False) # so this needs to match # Images are specified with a appended "?type" - self.Editor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist])) + self.ConfNodeEditor.AutoCompShow(0, " ".join([word + "?1" for word in keyword.kwlist])) else: event.Skip() def OnKillFocus(self, event): - self.Editor.AutoCompCancel() + self.ConfNodeEditor.AutoCompCancel() event.Skip() def OnUpdateUI(self, evt): @@ -364,11 +342,11 @@ braceAtCaret = -1 braceOpposite = -1 charBefore = None - caretPos = self.Editor.GetCurrentPos() + caretPos = self.ConfNodeEditor.GetCurrentPos() if caretPos > 0: - charBefore = self.Editor.GetCharAt(caretPos - 1) - styleBefore = self.Editor.GetStyleAt(caretPos - 1) + charBefore = self.ConfNodeEditor.GetCharAt(caretPos - 1) + styleBefore = self.ConfNodeEditor.GetStyleAt(caretPos - 1) # check before if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR: @@ -376,24 +354,19 @@ # check after if braceAtCaret < 0: - charAfter = self.Editor.GetCharAt(caretPos) - styleAfter = self.Editor.GetStyleAt(caretPos) + charAfter = self.ConfNodeEditor.GetCharAt(caretPos) + styleAfter = self.ConfNodeEditor.GetStyleAt(caretPos) if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR: braceAtCaret = caretPos if braceAtCaret >= 0: - braceOpposite = self.Editor.BraceMatch(braceAtCaret) + braceOpposite = self.ConfNodeEditor.BraceMatch(braceAtCaret) if braceAtCaret != -1 and braceOpposite == -1: - self.Editor.BraceBadLight(braceAtCaret) - else: - self.Editor.BraceHighlight(braceAtCaret, braceOpposite) - #pt = self.Editor.PointFromPosition(braceOpposite) - #self.Editor.Refresh(True, wxRect(pt.x, pt.y, 5,5)) - #print pt - #self.Editor.Refresh(False) - + self.ConfNodeEditor.BraceBadLight(braceAtCaret) + else: + self.ConfNodeEditor.BraceHighlight(braceAtCaret, braceOpposite) def OnMarginClick(self, evt): # fold and unfold as needed @@ -401,83 +374,83 @@ if evt.GetShift() and evt.GetControl(): self.FoldAll() else: - lineClicked = self.Editor.LineFromPosition(evt.GetPosition()) - - if self.Editor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG: + lineClicked = self.ConfNodeEditor.LineFromPosition(evt.GetPosition()) + + if self.ConfNodeEditor.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG: if evt.GetShift(): - self.Editor.SetFoldExpanded(lineClicked, True) + self.ConfNodeEditor.SetFoldExpanded(lineClicked, True) self.Expand(lineClicked, True, True, 1) elif evt.GetControl(): - if self.Editor.GetFoldExpanded(lineClicked): - self.Editor.SetFoldExpanded(lineClicked, False) + if self.ConfNodeEditor.GetFoldExpanded(lineClicked): + self.ConfNodeEditor.SetFoldExpanded(lineClicked, False) self.Expand(lineClicked, False, True, 0) else: - self.Editor.SetFoldExpanded(lineClicked, True) + self.ConfNodeEditor.SetFoldExpanded(lineClicked, True) self.Expand(lineClicked, True, True, 100) else: - self.Editor.ToggleFold(lineClicked) + self.ConfNodeEditor.ToggleFold(lineClicked) def FoldAll(self): - lineCount = self.Editor.GetLineCount() + lineCount = self.ConfNodeEditor.GetLineCount() expanding = True # find out if we are folding or unfolding for lineNum in range(lineCount): - if self.Editor.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG: - expanding = not self.Editor.GetFoldExpanded(lineNum) + if self.ConfNodeEditor.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG: + expanding = not self.ConfNodeEditor.GetFoldExpanded(lineNum) break lineNum = 0 while lineNum < lineCount: - level = self.Editor.GetFoldLevel(lineNum) + level = self.ConfNodeEditor.GetFoldLevel(lineNum) if level & stc.STC_FOLDLEVELHEADERFLAG and \ (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE: if expanding: - self.Editor.SetFoldExpanded(lineNum, True) + self.ConfNodeEditor.SetFoldExpanded(lineNum, True) lineNum = self.Expand(lineNum, True) lineNum = lineNum - 1 else: - lastChild = self.Editor.GetLastChild(lineNum, -1) - self.Editor.SetFoldExpanded(lineNum, False) + lastChild = self.ConfNodeEditor.GetLastChild(lineNum, -1) + self.ConfNodeEditor.SetFoldExpanded(lineNum, False) if lastChild > lineNum: - self.Editor.HideLines(lineNum+1, lastChild) + self.ConfNodeEditor.HideLines(lineNum+1, lastChild) lineNum = lineNum + 1 def Expand(self, line, doExpand, force=False, visLevels=0, level=-1): - lastChild = self.Editor.GetLastChild(line, level) + lastChild = self.ConfNodeEditor.GetLastChild(line, level) line = line + 1 while line <= lastChild: if force: if visLevels > 0: - self.Editor.ShowLines(line, line) + self.ConfNodeEditor.ShowLines(line, line) else: - self.Editor.HideLines(line, line) + self.ConfNodeEditor.HideLines(line, line) else: if doExpand: - self.Editor.ShowLines(line, line) + self.ConfNodeEditor.ShowLines(line, line) if level == -1: - level = self.Editor.GetFoldLevel(line) + level = self.ConfNodeEditor.GetFoldLevel(line) if level & stc.STC_FOLDLEVELHEADERFLAG: if force: if visLevels > 1: - self.Editor.SetFoldExpanded(line, True) + self.ConfNodeEditor.SetFoldExpanded(line, True) else: - self.Editor.SetFoldExpanded(line, False) + self.ConfNodeEditor.SetFoldExpanded(line, False) line = self.Expand(line, doExpand, force, visLevels-1) else: - if doExpand and self.Editor.GetFoldExpanded(line): + if doExpand and self.ConfNodeEditor.GetFoldExpanded(line): line = self.Expand(line, True, force, visLevels-1) else: line = self.Expand(line, False, force, visLevels-1) @@ -489,18 +462,18 @@ def Cut(self): self.ResetBuffer() self.DisableEvents = True - self.Editor.CmdKeyExecute(wx.stc.STC_CMD_CUT) + self.ConfNodeEditor.CmdKeyExecute(wx.stc.STC_CMD_CUT) self.DisableEvents = False self.RefreshModel() self.RefreshBuffer() def Copy(self): - self.Editor.CmdKeyExecute(wx.stc.STC_CMD_COPY) + self.ConfNodeEditor.CmdKeyExecute(wx.stc.STC_CMD_COPY) def Paste(self): self.ResetBuffer() self.DisableEvents = True - self.Editor.CmdKeyExecute(wx.stc.STC_CMD_PASTE) + self.ConfNodeEditor.CmdKeyExecute(wx.stc.STC_CMD_PASTE) self.DisableEvents = False self.RefreshModel() self.RefreshBuffer() diff -r 7b421e080636 -r 413946c04c87 py_ext/PythonFileCTNMixin.py --- a/py_ext/PythonFileCTNMixin.py Mon May 21 02:49:53 2012 +0200 +++ b/py_ext/PythonFileCTNMixin.py Mon May 21 10:04:27 2012 +0200 @@ -14,13 +14,6 @@ def __init__(self): - self.ConfNodeMethods.insert(0, - {"bitmap" : "editPYTHONcode", - "name" : _("Edit Python File"), - "tooltip" : _("Edit Python File"), - "method" : "_OpenView"}, - ) - filepath = self.PythonFileName() self.PythonCode = PythonClasses["Python"]() diff -r 7b421e080636 -r 413946c04c87 py_ext/py_ext.py --- a/py_ext/py_ext.py Mon May 21 02:49:53 2012 +0200 +++ b/py_ext/py_ext.py Mon May 21 10:04:27 2012 +0200 @@ -1,6 +1,7 @@ import os from POULibrary import POULibrary from PythonFileCTNMixin import PythonFileCTNMixin +from util import opjimg class PythonLibrary(POULibrary): def GetLibraryPath(self): @@ -29,6 +30,10 @@ return (["py_ext"], [(Gen_Pythonfile_path, IECCFLAGS)], True), "" class PythonFile(PythonFileCTNMixin): + + def GetIconPath(self): + return opjimg("Pyfile") + def CTNGenerate_C(self, buildpath, locations): current_location = self.GetCurrentLocation() # define a unique name for the generated C file