#---------------------------------------------------------------------- # Name: Palette.py # Purpose: Main frame containing palette for visual frame design # # Author: Riaan Booysen # # Created: 1999 # RCS-ID: $Id: Palette.py,v 1.38 2005/05/06 14:00:05 riaan Exp $ # Copyright: (c) 1999 - 2005 Riaan Booysen # Licence: GPL #---------------------------------------------------------------------- #Boa:Frame:BoaFrame print 'importing Palette' import os, sys import wx import PaletteMapping, PaletteStore import Help, Preferences, Utils, Plugins from Preferences import IS, flatTools import wx.lib.buttons currentMouseOverTip = '' [wxID_BOAFRAME, wxID_BOAFRAMEPALETTE, wxID_BOAFRAMETOOLBAR, ] = [wx.NewId() for _init_ctrls in range(3)] [wxID_BOAFRAMETOOLBARTOOLS0, wxID_BOAFRAMETOOLBARTOOLS1, ] = [wx.NewId() for _init_coll_toolBar_Tools in range(2)] class BoaFrame(wx.Frame, Utils.FrameRestorerMixin): paletteIcon = 'Images/Icons/Boa.ico' def _init_coll_toolBar_Tools(self, parent): # generated method, don't edit parent.AddTool(bitmap=IS.load('Images/Shared/Inspector.png'), id=wxID_BOAFRAMETOOLBARTOOLS0, isToggle=False, longHelpString='', pushedBitmap=wx.NullBitmap, shortHelpString='Brings the Inspector to the front') parent.AddTool(bitmap=IS.load('Images/Shared/Editor.png'), id=wxID_BOAFRAMETOOLBARTOOLS1, isToggle=False, longHelpString='', pushedBitmap=wx.NullBitmap, shortHelpString='Brings the Editor to the front') self.Bind(wx.EVT_TOOL, self.OnInspectorToolClick, id=wxID_BOAFRAMETOOLBARTOOLS0) self.Bind(wx.EVT_TOOL, self.OnEditorToolClick, id=wxID_BOAFRAMETOOLBARTOOLS1) parent.Realize() def _init_ctrls(self, prnt): # generated method, don't edit wx.Frame.__init__(self, #style=wx.SYSTEM_MENU | wx.RESIZE_BORDER | wx.CAPTION | wx.MINIMIZE_BOX, id=wxID_BOAFRAME, name='', parent=prnt, pos=wx.Point(116, 275), size=wx.Size(645, 74), style=wx.DEFAULT_FRAME_STYLE& ~wx.MAXIMIZE_BOX, title=self.frameTitle) self.SetClientSize(wx.Size(637, 47)) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.Bind(wx.EVT_ICONIZE, self.OnBoaframeIconize) self.toolBar = wx.ToolBar(id=wxID_BOAFRAMETOOLBAR, name='toolBar', parent=self, pos=wx.Point(0, 0), size=wx.Size(637, 24), style=wx.TB_HORIZONTAL | wx.NO_BORDER | Preferences.flatTools) self.SetToolBar(self.toolBar) self.palette = wx.Notebook(id=wxID_BOAFRAMEPALETTE, name='palette', parent=self, pos=wx.Point(0, 24), size=wx.Size(637, 23), style=0) self._init_coll_toolBar_Tools(self.toolBar) def __init__(self, parent, id, app): self.frameTitle = 'Boa Constructor - Python IDE & wxPython GUI Builder' self.frameTitle = Preferences.paletteTitle self._init_ctrls(parent) self.winConfOption = 'palette' self.loadDims() self.paletteStyle = Preferences.paletteStyle if self.paletteStyle == 'menu': self.menuBar = wx.MenuBar() self.SetMenuBar(self.menuBar) self.palette.Show(False) self.app = app self.destroying = False self.widgetSet = {} self.SetIcon(IS.load(self.paletteIcon)) self.browser = None self.toolBar.AddSeparator() self.componentSB = ComponentSelection(self) if Preferences.showFrameTestButton: self.toolBar.AddSeparator() self.addTool('Images/Shared/CustomHelp', 'Test', 'Test', self.OnTest) # Add main helpbuttons defined in the config file conf = Utils.createAndReadConfig('Explorer') self.paletteHelpItems = eval(conf.get('help', 'palettehelp'), {}) self.toolBar.AddSeparator() self.addTool('Images/Shared/Help', 'Boa or selected component help', 'Show help', self.OnHelpToolClick) self.addTool('Images/Shared/wxWinHelp', 'wxPython help', 'Show help', self.OnWxWinHelpToolClick) self.addTool('Images/Shared/PythonHelp', 'Python help', 'Show help', self.OnPythonHelpToolClick) # Add additional helpbuttons if defined in the config file customHelpItems = eval(conf.get('help', 'customhelp'), {}) self.customHelpItems = {} for caption, helpFile in customHelpItems.items(): mID = wx.NewId() self.toolBar.AddTool(mID, IS.load('Images/Shared/CustomHelp.png'), shortHelpString = caption) self.Bind(wx.EVT_TOOL, self.OnCustomHelpToolClick, id=mID) self.customHelpItems[mID] = (caption, helpFile) if wx.Platform == '__WXGTK__': self.toolBar.AddSeparator() self.addTool('Images/Shared/CloseWindow', 'Exit', '', self.OnCloseClick) self.toolBar.Realize() self.palettePages = [] self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE)) def initPalette(self, inspector, editor): self.inspector = inspector self.editor = editor transpSF = '' if Preferences.paletteStyle == 'menu': mb = self.menuBar else: mb = None # XXX Set these from class if not hasattr(sys, 'cyclops'): # 'New' page palettePage = NewPalettePage(self.palette, 'New', 'Images/Palette/'+transpSF, self, self.widgetSet, self) for modelName in PaletteStore.paletteLists['New']: palettePage.addButton2(modelName, PaletteStore.newControllers[modelName], wx.lib.buttons.GenBitmapButton) if mb: mb.Append(menu = palettePage.menu, title = 'New') self.palettePages.append(palettePage) # Normal control pages for palette in PaletteMapping.palette: palettePage = PalettePage(self.palette, palette[0], 'Images/Palette/'+transpSF, self, self.widgetSet, self.componentSB, self) palettePage.addToggleBitmaps(palette[2], None, None) self.palettePages.append(palettePage) if mb: mb.Append(menu = palettePage.menu, title = palette[0]) # Dialog page if PaletteMapping.dialogPalette[2]: self.dialogPalettePage = PanelPalettePage(self.palette, PaletteMapping.dialogPalette[0], 'Images/Palette/'+transpSF, self, self.widgetSet, self.componentSB, self) for dialog in PaletteMapping.dialogPalette[2]: self.dialogPalettePage.addButton( PaletteMapping.compInfo[dialog][0], dialog, PaletteMapping.compInfo[dialog][1], self.OnDialogPaletteClick, None, None, wx.lib.buttons.GenBitmapButton) self.palettePages.append(self.dialogPalettePage) if mb: mb.Append(menu = self.dialogPalettePage.menu, title = 'Dialogs') # Zope page if Plugins.transportInstalled('ZopeLib.ZopeExplorer'): self.zopePalettePage = ZopePalettePage(self.palette, PaletteMapping.zopePalette[0], 'Images/Palette/'+transpSF, self, self.widgetSet, self.componentSB, self) self.zopePalettePage.addToggleBitmaps( PaletteMapping.zopePalette[2], None, None) self.palettePages.append(self.zopePalettePage) if mb: mb.Append(menu = self.zopePalettePage.menu, title = 'Zope') else: palettePage = None # Prototype for composites # Composites are very much not thought out right now, but basically # reflects Frames in Delphi 5. A D5 frame is a composite component # for reuse of common control combinations. In implementation it's # very much like Delphi's form inheritance, i.e. by changing the parent # all children will be updated. # Current thoughts on implementation in Boa: # To centralise, I like the idea of storing initialisations in a # sepatate file and using 'import' to load controls into a frame. ## self.composites = CompositeListCtrlPalPage(self.palette, -1, style=wx.LC_SMALL_ICON) ## self.palette.AddPage(self.composites, 'Composites') ## self.composites.InsertStringItem(0, 'OK / Cancel buttons') ## self.composites.InsertStringItem(0, 'Tabbed dialog') ## self.composites.InsertStringItem(0, 'Name/Value') ## self.composites.Enable(False) # Prototype for templates # Templates is a real simple idea, instead of starting from a blank # frame, start from a previously saved frame in the templates directory ## self.templates = TemplateListCtrlPalPage(self.palette, -1, style=wx.LC_SMALL_ICON) ## self.palette.AddPage(self.templates, 'Templates') ## self.templates.InsertStringItem(0, 'Menu/Toolbar/StatusBar') ## self.templates.InsertStringItem(0, 'Wizard') ## self.templates.Enable(False) def setDefaultDimensions(self): self.SetDimensions(0, Preferences.topMenuHeight, Preferences.screenWidth - Preferences.windowManagerSide * 2, Preferences.paletteHeight) def addTool(self, filename, text, help, func, toggle = False): mID = wx.NewId() self.toolBar.AddTool(mID, IS.load(filename+'.png'), shortHelpString = text, isToggle = toggle) self.Bind(wx.EVT_TOOL, func, id=mID) return mID def OnInspectorToolClick(self, event): self.inspector.restore() def OnEditorToolClick(self, event): self.editor.restore() def OnHelpToolClick(self, event): if self.componentSB.selection: Help.showCtrlHelp(self.componentSB.selection[1].__name__) else: Help.showMainHelp(self.paletteHelpItems['boa']) def OnWxWinHelpToolClick(self, event): Help.showMainHelp(self.paletteHelpItems['wx']) def OnPythonHelpToolClick(self, event): Help.showMainHelp(self.paletteHelpItems['python']) def OnCustomHelpToolClick(self, event): caption, helpFile = self.customHelpItems[event.GetId()] Help.showHelp(helpFile) def OnFileExit(self, event): self.Close() def OnDialogPaletteClick(self, event): cls, cmp = self.dialogPalettePage.widgets[event.GetId()][1:] self.editor.addNewDialog(cls, cmp) def OnZopePaletteClick(self, event): cls, cmp = self.zopePalettePage.widgets[event.GetId()][1:] def OnComposeClick(self, event): pass def OnInheritClick(self, event): pass def OnCloseClick(self, event): self.Close() def OnCloseWindow(self, event): self.destroying = True try: if hasattr(self, 'editor') and self.editor: self.editor.destroying = True self.editor.Close() if not self.destroying: return if hasattr(self, 'inspector'): self.inspector.destroying = True self.inspector.Close() if hasattr(self, 'app'): self.app = None Help.delHelp() self.palette.Hide() for page in self.palettePages: page.destroy() finally: if not self.destroying: self.editor.destroying = False self.inspector.destroying = False else: self.Destroy() event.Skip() app =wx.GetApp() if hasattr(app, 'tbicon'): app.tbicon.Destroy() def OnUncheckComponent(self, event): self.componentSB.selectNone() def OnTest(self, event): import Tests Tests.test_wxFrame(self) def OnCreateNew(self, name, controller): self.editor.addNewPage(name, controller) def Iconize(self, iconize): if Help._hc: frm = Help._hc.GetFrame() if frm: frm.Iconize(iconize) wx.Frame.Iconize(self, iconize) def OnBoaframeIconize(self, event): self.SetFocus() if Help._hc: frm = Help._hc.GetFrame() if frm: frm.Iconize(True) event.Skip() class ComponentSelection: """ Controls the selection of the palette and access to associated palette mapping structures. Accessed by the Designer """ def __init__(self, palette): wID = wx.NewId() self.selComp = wx.CheckBox(palette.toolBar, wID, ' (Nothing selected)', size =wx.Size(160, 20)) self.selComp.Enable(False) self.selComp.Bind(wx.EVT_CHECKBOX, palette.OnUncheckComponent, id=wID) palette.toolBar.AddControl(self.selComp) cId = palette.addTool('Images/Shared/Compose', 'Compose', ' ', palette.OnComposeClick, toggle = True) iId = palette.addTool('Images/Shared/Inherit', 'Inherit', ' ', palette.OnInheritClick, toggle = True) palette.toolBar.ToggleTool(cId, True) palette.toolBar.EnableTool(cId, False) palette.toolBar.EnableTool(iId, False) self.selection = None self.prevPage = None def selectComponent(self, page, detail): if self.prevPage: self.prevPage.selectNone() self.selection = detail self.prevPage = page self.selComp.Enable(True) self.selComp.SetLabel(' '+detail[0]) self.selComp.SetValue(True) def selectNone(self): if self.prevPage: self.prevPage.selectNone() self.selection = None self.selComp.Enable(False) self.selComp.SetLabel(' (Nothing selected)') self.selComp.SetValue(False) class BasePalettePage: pass class ListCtrlPalettePage(wx.ListCtrl, BasePalettePage): pass class CompositeListCtrlPalPage(ListCtrlPalettePage): pass class TemplateListCtrlPalPage(ListCtrlPalettePage): pass class PanelPalettePage(wx.Panel, BasePalettePage): buttonSep = 11 buttonBorder = 7 def __init__(self, parent, name, bitmapPath, eventOwner, widgets, components, palette): # default size provided for better sizing on GTK where notebook page # size isn't available at button creation time wx.Panel.__init__(self, parent, -1, size=(44, 44)) self.palette = palette self.components = components self.name = name self.bitmapPath = bitmapPath self.widgets = widgets self.buttons = {} parent.AddPage(self, name) self.posX = self.buttonSep/2 self.posY = (self.GetSize().y -(24+self.buttonBorder))/2 self.eventOwner = eventOwner self.menu =wx.Menu() self.menusCheckable = False def destroy(self): if hasattr(self, 'widgets'): del self.widgets self.DestroyChildren() for btn in self.buttons.values(): btn.faceDnClr = None btn.shadowPen = None btn.highlightPen = None btn.focusIndPen = None btn.bmpLabel = None if self.palette.paletteStyle == 'tabs': self.menu.Destroy() def addButton(self, widgetName, wxClass, constrClass, clickEvt, hintFunc, hintLeaveFunc, btnType): mID = wx.NewId() self.menu.Append(mID, widgetName, '', self.menusCheckable) self.palette.Bind(wx.EVT_MENU, clickEvt, id=mID) self.widgets[mID] = (widgetName, wxClass, constrClass) if self.palette.paletteStyle == 'menu': return mID bmp = self.getButtonBmp(widgetName, wxClass) width = bmp.GetWidth() + self.buttonBorder height = bmp.GetHeight() + self.buttonBorder newButton = btnType(self, mID, None, wx.Point(self.posX, self.posY), wx.Size(width, height)) newButton.SetBezelWidth(1) newButton.SetUseFocusIndicator(0) newButton.SetToolTipString(widgetName) try: newButton.SetBitmapLabel(bmp, False) except TypeError: newButton.SetBitmapLabel(bmp) self.Bind(wx.EVT_BUTTON, clickEvt, id=mID) self.buttons[widgetName] = newButton self.posX = self.posX + bmp.GetWidth() + 11 return mID def getButtonBmp(self, name, wxClass): return PaletteStore.bitmapForComponent(wxClass) class NewPalettePage(PanelPalettePage): def __init__(self, parent, name, bitmapPath, eventOwner, widgets, palette): PanelPalettePage.__init__(self, parent, name, bitmapPath, eventOwner, widgets, palette, palette) self.selection = None def destroy(self): PanelPalettePage.destroy(self) def addButton(self, widgetName, wxClass, constrClass, clickEvt, hintFunc, hintLeaveFunc, btnType): mID = PanelPalettePage.addButton(self, widgetName, wxClass, constrClass, clickEvt, hintFunc, hintLeaveFunc, btnType) return mID def addButton2(self, name, Controller, btnType): mID = PanelPalettePage.addButton(self, name, Controller, None, self.OnClickTrap, None, None, btnType) self.palette.editor.Bind(wx.EVT_MENU, self.OnClickTrap, id=mID) return mID def getButtonBmp(self, name, wxClass): return IS.load('%s%s.png' %(self.bitmapPath, name)) def OnClickTrap(self, event): modPageInfo = self.widgets[event.GetId()] wx.CallAfter(self.palette.OnCreateNew, name=modPageInfo[0], controller=modPageInfo[1]) class PalettePage(PanelPalettePage): def __init__(self, parent, name, bitmapPath, eventOwner, widgets, components, palette): PanelPalettePage.__init__(self, parent, name, bitmapPath, eventOwner, widgets, components, palette) self.clickEvt = None self.selection = None self.menusCheckable = True def addToggleBitmaps(self, classes, hintFunc, hintLeaveFunc): for wxClass in classes: ci = PaletteMapping.compInfo[wxClass] self.addButton(ci[0], wxClass, ci[1], self.OnClickTrap, hintFunc, hintLeaveFunc, wx.lib.buttons.GenBitmapToggleButton) def OnClickTrap(self, event): wId = event.GetId() if self.palette.paletteStyle == 'tabs': obj = event.GetButtonObj() if obj.up: self.selectNone() self.components.selectNone() else: self.components.selectComponent(self, self.widgets[wId]) self.selection = obj elif self.palette.paletteStyle == 'menu': sel = self.menu.FindItemById(wId) if not sel.IsChecked(): self.selectNone() self.components.selectNone() else: self.components.selectComponent(self, self.widgets[wId]) sel.Check(True) self.selection = sel event.Skip() def selectNone(self): if self.selection: if self.palette.paletteStyle == 'tabs': self.selection.SetToggle(False) self.selection.Refresh() self.selection = None elif self.palette.paletteStyle == 'menu': self.selection.Check(False) self.selection = None class ZopePalettePage(PalettePage): def __init__(self, parent, name, bitmapPath, eventOwner, widgets, components, palette): PalettePage.__init__(self, parent, name, bitmapPath, eventOwner, widgets, components, palette) def getButtonBmp(self, name, wxClass): return IS.load('%s%s.png' %(self.bitmapPath, name)) if __name__ == '__main__': app = wx.PySimpleApp() wx.InitAllImageHandlers() palette = BoaFrame(None, -1, app) palette.Show() app.MainLoop()