X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/cccce1a6e7cbaab4ba1dc3e039753bdd9bef40e0..91fd8ba770eb3b9d9aa5e5143b916af04be3ee65:/wxPython/demo/Main.py?ds=sidebyside diff --git a/wxPython/demo/Main.py b/wxPython/demo/Main.py index 8fe436f994..495acedf76 100644 --- a/wxPython/demo/Main.py +++ b/wxPython/demo/Main.py @@ -19,9 +19,11 @@ # * Annoying switching between tabs and resulting flicker # how to replace a page in the notebook without deleting/adding? # Where is SetPage!? tried freeze...tried reparent of dummy panel.... +# AG: It looks like this issue is fixed by Freeze()ing and Thaw()ing the +# main frame and not the notebook # TODO List: -# * UI design more prefessional +# * UI design more professional (is the new version more professional?) # * save file positions (new field in demoModules) (@ LoadDemoSource) # * Update main overview @@ -30,28 +32,39 @@ import sys, os, time, traceback, types import wx # This module uses the new wx namespace +import wx.aui import wx.html import images # For debugging ##wx.Trap(); -##print "wx.VERSION_STRING = ", wx.VERSION_STRING -##print os.getpid(); +##print "wx.VERSION_STRING = %s (%s)" % (wx.VERSION_STRING, wx.USE_UNICODE and 'unicode' or 'ansi') +##print "pid:", os.getpid() ##raw_input("Press Enter...") #--------------------------------------------------------------------------- +USE_CUSTOMTREECTRL = False +ALLOW_AUI_FLOATING = False +DEFAULT_PERSPECTIVE = "Default Perspective" + +#--------------------------------------------------------------------------- + +_demoPngs = ["overview", "recent", "frame", "dialog", "moredialog", "core", + "book", "customcontrol", "morecontrols", "layout", "process", "clipboard", + "images", "miscellaneous"] _treeList = [ # new stuff ('Recent Additions/Updates', [ - 'Ticker', ]), # managed windows == things with a (optional) caption you can close ('Frames and Dialogs', [ + 'AUI_DockingWindowMgr', + 'AUI_MDI', 'Dialog', 'Frame', 'MDIWindows', @@ -61,12 +74,14 @@ _treeList = [ # the common dialogs ('Common Dialogs', [ + 'AboutBox', 'ColourDialog', 'DirDialog', 'FileDialog', 'FindReplaceDialog', 'FontDialog', 'MessageDialog', + 'MultiChoiceDialog', 'PageSetupDialog', 'PrintDialog', 'ProgressDialog', @@ -77,7 +92,6 @@ _treeList = [ # dialogs from libraries ('More Dialogs', [ 'ImageBrowser', - 'MultipleChoiceDialog', 'ScrolledMessageDialog', ]), @@ -95,33 +109,48 @@ _treeList = [ 'ListBox', 'ListCtrl', 'ListCtrl_virtual', - 'Listbook', + 'ListCtrl_edit', 'Menu', - 'Notebook', 'PopupMenu', 'PopupWindow', 'RadioBox', 'RadioButton', 'SashWindow', 'ScrolledWindow', + 'SearchCtrl', 'Slider', 'SpinButton', 'SpinCtrl', 'SplitterWindow', 'StaticBitmap', + 'StaticBox', 'StaticText', 'StatusBar', + 'StockButtons', 'TextCtrl', 'ToggleButton', 'ToolBar', 'TreeCtrl', 'Validator', ]), + + ('"Book" Controls', [ + 'AUI_Notebook', + 'Choicebook', + 'Listbook', + 'Notebook', + 'Toolbook', + 'Treebook', + ]), ('Custom Controls', [ - 'AnalogClockWindow', + 'AnalogClock', + 'ButtonPanel', 'ColourSelect', + 'ComboTreeBox', + 'CustomTreeCtrl', 'Editor', + 'FlatNotebook', 'GenericButtons', 'GenericDirCtrl', 'LEDNumberCtrl', @@ -136,25 +165,36 @@ _treeList = [ 'ActiveX_FlashWindow', 'ActiveX_IEHtmlWindow', 'ActiveX_PDFWindow', - #'RightTextCtrl', deprecated as we have wxTE_RIGHT now. + 'BitmapComboBox', 'Calendar', 'CalendarCtrl', + 'CheckListCtrlMixin', + 'CollapsiblePane', + 'ComboCtrl', 'ContextHelp', + 'DatePickerCtrl', 'DynamicSashWindow', 'EditableListBox', + 'ExpandoTextCtrl', 'FancyText', 'FileBrowseButton', 'FloatBar', 'FloatCanvas', + 'FoldPanelBar', 'HtmlWindow', + 'HyperLinkCtrl', 'IntCtrl', 'MVCTree', 'MaskedEditControls', 'MaskedNumCtrl', - 'MimeTypesManager', + 'MediaCtrl', + 'MultiSplitterWindow', + 'OwnerDrawnComboBox', + 'Pickers', 'PyCrust', 'PyPlot', 'PyShell', + 'RichTextCtrl', 'ScrolledPanel', 'SplitTree', 'StyledTextCtrl_1', @@ -163,6 +203,7 @@ _treeList = [ 'Throbber', 'Ticker', 'TimeCtrl', + 'TreeMixin', 'VListBox', ]), @@ -174,6 +215,7 @@ _treeList = [ 'Layoutf', 'RowColSizer', 'ScrolledPanel', + 'SizedControls', 'Sizers', 'XmlResource', 'XmlResourceHandler', @@ -182,13 +224,14 @@ _treeList = [ # ditto ('Process and Events', [ + 'DelayedResult', 'EventManager', 'KeyEvents', 'Process', 'PythonEvents', 'Threads', 'Timer', - ##'infoframe', # needs better explaination and some fixing + ##'infoframe', # needs better explanation and some fixing ]), # Clipboard and DnD @@ -200,36 +243,45 @@ _treeList = [ # Images ('Using Images', [ + 'AlphaDrawing', + 'AnimateCtrl', 'ArtProvider', + 'BitmapFromBuffer', 'Cursor', 'DragImage', 'Image', 'ImageAlpha', 'ImageFromStream', + 'Img2PyArtProvider', 'Mask', + 'RawBitmapAccess', 'Throbber', ]), # Other stuff ('Miscellaneous', [ + 'AlphaDrawing', 'ColourDB', - ##'DialogUnits', # needs more explainations + ##'DialogUnits', # needs more explanations + 'DragScroller', 'DrawXXXList', 'FileHistory', 'FontEnumerator', + 'GraphicsContext', + 'GLCanvas', + 'I18N', 'Joystick', + 'MimeTypesManager', + 'MouseGestures', 'OGL', 'PrintFramework', + 'PseudoDC', 'ShapedWindow', 'Sound', + 'StandardPaths', 'Unicode', ]), - # need libs not coming with the demo - ('Samples using an external library', [ - 'GLCanvas', - ]), - ('Check out the samples dir too', [ ]), @@ -248,9 +300,10 @@ class MyLog(wx.PyLog): self.logTime = logTime def DoLogString(self, message, timeStamp): - if self.logTime: - message = time.strftime("%X", time.localtime(timeStamp)) + \ - ": " + message + #print message, timeStamp + #if self.logTime: + # message = time.strftime("%X", time.localtime(timeStamp)) + \ + # ": " + message if self.tc: self.tc.AppendText(message + '\n') @@ -259,6 +312,60 @@ class MyTP(wx.PyTipProvider): def GetTip(self): return "This is my tip" +#--------------------------------------------------------------------------- +# A class to be used to simply display a message in the demo pane +# rather than running the sample itself. + +class MessagePanel(wx.Panel): + def __init__(self, parent, message, caption='', flags=0): + wx.Panel.__init__(self, parent) + + # Make widgets + if flags: + artid = None + if flags & wx.ICON_EXCLAMATION: + artid = wx.ART_WARNING + elif flags & wx.ICON_ERROR: + artid = wx.ART_ERROR + elif flags & wx.ICON_QUESTION: + artid = wx.ART_QUESTION + elif flags & wx.ICON_INFORMATION: + artid = wx.ART_INFORMATION + + if artid is not None: + bmp = wx.ArtProvider.GetBitmap(artid, wx.ART_MESSAGE_BOX, (32,32)) + icon = wx.StaticBitmap(self, -1, bmp) + else: + icon = (32,32) # make a spacer instead + + if caption: + caption = wx.StaticText(self, -1, caption) + caption.SetFont(wx.Font(28, wx.SWISS, wx.NORMAL, wx.BOLD)) + + message = wx.StaticText(self, -1, message) + + # add to sizers for layout + tbox = wx.BoxSizer(wx.VERTICAL) + if caption: + tbox.Add(caption) + tbox.Add((10,10)) + tbox.Add(message) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((10,10), 1) + hbox.Add(icon) + hbox.Add((10,10)) + hbox.Add(tbox) + hbox.Add((10,10), 1) + + box = wx.BoxSizer(wx.VERTICAL) + box.Add((10,10), 1) + box.Add(hbox, 0, wx.EXPAND) + box.Add((10,10), 2) + + self.SetSizer(box) + self.Fit() + #--------------------------------------------------------------------------- # A class to be used to display source code in the demo. Try using the @@ -383,9 +490,14 @@ try: if wx.Platform == '__WXMSW__': self.StyleSetSpec(stc.STC_STYLE_DEFAULT, 'fore:#000000,back:#FFFFFF,face:Courier New,size:9') + elif wx.Platform == '__WXMAC__': + # TODO: if this looks fine on Linux too, remove the Mac-specific case + # and use this whenever OS != MSW. + self.StyleSetSpec(stc.STC_STYLE_DEFAULT, + 'fore:#000000,back:#FFFFFF,face:Courier') else: self.StyleSetSpec(stc.STC_STYLE_DEFAULT, - 'fore:#000000,back:#FFFFFF,face:Courier,size:12') + 'fore:#000000,back:#FFFFFF,face:Courier,size:9') # Clear styles and revert to default. self.StyleClearAll() @@ -394,8 +506,7 @@ try: # The rest remains unchanged. # Line numbers in margin - self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2') - + self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2') # Highlighted brace self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00') # Unmatched brace @@ -456,13 +567,13 @@ except ImportError: def GetText(self): return self.GetValue() - def GetPositionFromLine(line): + def GetPositionFromLine(self, line): return self.XYToPosition(0,line) def GotoLine(self, line): - pos = self.editor.GetPositionFromLine(line) - self.editor.SetInsertionPoint(pos) - self.editor.ShowPosition(pos) + pos = self.GetPositionFromLine(line) + self.SetInsertionPoint(pos) + self.ShowPosition(pos) def SelectLine(self, line): start = self.GetPositionFromLine(line) @@ -532,7 +643,9 @@ class DemoCodePanel(wx.Panel): def ActiveModuleChanged(self): self.LoadDemoSource(self.demoModules.GetSource()) self.UpdateControlState() + self.mainFrame.Freeze() self.ReloadDemo() + self.mainFrame.Thaw() def LoadDemoSource(self, source): @@ -607,8 +720,8 @@ class DemoCodePanel(wx.Panel): try: os.makedirs(GetModifiedDirectory()) if not os.path.exists(GetModifiedDirectory()): - wx.LogMessage("BUG: Created demo directory but it still doesn't exit") - raise AssetionError + wx.LogMessage("BUG: Created demo directory but it still doesn't exist") + raise AssertionError except: wx.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory()) return @@ -627,24 +740,37 @@ class DemoCodePanel(wx.Panel): self.demoModules.LoadFromFile(modModified, modifiedFilename) self.ActiveModuleChanged() + self.mainFrame.SetTreeModified(True) + def OnRestore(self, event): # Handles the "Delete Modified" button modifiedFilename = GetModifiedFilename(self.demoModules.name) self.demoModules.Delete(modModified) os.unlink(modifiedFilename) # Delete the modified copy busy = wx.BusyInfo("Reloading demo module...") + self.ActiveModuleChanged() + self.mainFrame.SetTreeModified(False) + #--------------------------------------------------------------------------- def opj(path): """Convert paths to the platform-specific separator""" - str = apply(os.path.join, tuple(path.split('/'))) + st = apply(os.path.join, tuple(path.split('/'))) # HACK: on Linux, a leading / gets lost... if path.startswith('/'): - str = '/' + str - return str + st = '/' + st + return st + + +def GetDataDir(): + """ + Return the standard location on this platform for application data + """ + sp = wx.StandardPaths.Get() + return sp.GetUserDataDir() def GetModifiedDirectory(): @@ -652,7 +778,7 @@ def GetModifiedDirectory(): Returns the directory where modified versions of the demo files are stored """ - return opj(wx.GetHomeDir() + "/.wxPyDemo/modified/") + return os.path.join(GetDataDir(), "modified") def GetModifiedFilename(name): @@ -661,7 +787,7 @@ def GetModifiedFilename(name): """ if not name.endswith(".py"): name = name + ".py" - return GetModifiedDirectory() + name + return os.path.join(GetModifiedDirectory(), name) def GetOriginalFilename(name): @@ -681,6 +807,25 @@ def DoesModifiedExist(name): return False +def GetConfig(): + if not os.path.exists(GetDataDir()): + os.makedirs(GetDataDir()) + + config = wx.FileConfig( + localFilename=os.path.join(GetDataDir(), "options")) + return config + + +def SearchDemo(name, keyword): + """ Returns whether a demo contains the search keyword or not. """ + fid = open(GetOriginalFilename(name), "rt") + fullText = fid.read() + fid.close() + if fullText.find(keyword) >= 0: + return True + + return False + #--------------------------------------------------------------------------- class ModuleDictWrapper: @@ -732,7 +877,8 @@ class DemoModules: def LoadDict(self, modID): if self.name != __name__: source = self.modules[modID][1] - description = self.modules[modID][3] + #description = self.modules[modID][3] + description = self.modules[modID][2] try: self.modules[modID][0] = {} @@ -868,7 +1014,7 @@ class DemoErrorPanel(wx.Panel): self.box = wx.BoxSizer(wx.VERTICAL) # Main Label - self.box.Add(wx.StaticText(self, -1, "An error has occured while trying to run the demo") + self.box.Add(wx.StaticText(self, -1, "An error has occurred while trying to run the demo") , 0, wx.ALIGN_CENTER | wx.TOP, 10) # Exception Information @@ -877,7 +1023,7 @@ class DemoErrorPanel(wx.Panel): boxInfoGrid = wx.FlexGridSizer(0, 2, 0, 0) textFlags = wx.ALIGN_RIGHT | wx.LEFT | wx.RIGHT | wx.TOP boxInfoGrid.Add(wx.StaticText(self, -1, "Type: "), 0, textFlags, 5 ) - boxInfoGrid.Add(wx.StaticText(self, -1, demoError.exception_type) , 0, textFlags, 5 ) + boxInfoGrid.Add(wx.StaticText(self, -1, str(demoError.exception_type)) , 0, textFlags, 5 ) boxInfoGrid.Add(wx.StaticText(self, -1, "Details: ") , 0, textFlags, 5 ) boxInfoGrid.Add(wx.StaticText(self, -1, demoError.exception_details) , 0, textFlags, 5 ) boxInfoSizer.Add(boxInfoGrid, 0, wx.ALIGN_CENTRE | wx.ALL, 5 ) @@ -945,13 +1091,101 @@ class DemoErrorPanel(wx.Panel): #--------------------------------------------------------------------------- +class DemoTaskBarIcon(wx.TaskBarIcon): + TBMENU_RESTORE = wx.NewId() + TBMENU_CLOSE = wx.NewId() + TBMENU_CHANGE = wx.NewId() + TBMENU_REMOVE = wx.NewId() + + def __init__(self, frame): + wx.TaskBarIcon.__init__(self) + self.frame = frame + + # Set the image + icon = self.MakeIcon(images.getWXPdemoImage()) + self.SetIcon(icon, "wxPython Demo") + self.imgidx = 1 + + # bind some events + self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate) + self.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE) + self.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE) + self.Bind(wx.EVT_MENU, self.OnTaskBarChange, id=self.TBMENU_CHANGE) + self.Bind(wx.EVT_MENU, self.OnTaskBarRemove, id=self.TBMENU_REMOVE) + + + def CreatePopupMenu(self): + """ + This method is called by the base class when it needs to popup + the menu for the default EVT_RIGHT_DOWN event. Just create + the menu how you want it and return it from this function, + the base class takes care of the rest. + """ + menu = wx.Menu() + menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo") + menu.Append(self.TBMENU_CLOSE, "Close wxPython Demo") + menu.AppendSeparator() + menu.Append(self.TBMENU_CHANGE, "Change the TB Icon") + menu.Append(self.TBMENU_REMOVE, "Remove the TB Icon") + return menu + + + def MakeIcon(self, img): + """ + The various platforms have different requirements for the + icon size... + """ + if "wxMSW" in wx.PlatformInfo: + img = img.Scale(16, 16) + elif "wxGTK" in wx.PlatformInfo: + img = img.Scale(22, 22) + # wxMac can be any size upto 128x128, so leave the source img alone.... + icon = wx.IconFromBitmap(img.ConvertToBitmap() ) + return icon + + + def OnTaskBarActivate(self, evt): + if self.frame.IsIconized(): + self.frame.Iconize(False) + if not self.frame.IsShown(): + self.frame.Show(True) + self.frame.Raise() + + + def OnTaskBarClose(self, evt): + self.frame.Close() + + + def OnTaskBarChange(self, evt): + names = [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ] + name = names[self.imgidx] + + getFunc = getattr(images, "get%sImage" % name) + self.imgidx += 1 + if self.imgidx >= len(names): + self.imgidx = 0 + + icon = self.MakeIcon(getFunc()) + self.SetIcon(icon, "This is a new icon: " + name) + + + def OnTaskBarRemove(self, evt): + self.RemoveIcon() + + +#--------------------------------------------------------------------------- class wxPythonDemo(wx.Frame): overviewText = "wxPython Overview" def __init__(self, parent, title): - wx.Frame.__init__(self, parent, -1, title, size = (950, 720), + wx.Frame.__init__(self, parent, -1, title, size = (970, 720), style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE) + self.SetMinSize((640,480)) + + self.mgr = wx.aui.AuiManager() + self.mgr.SetManagedWindow(self) + self.loaded = False self.cwd = os.getcwd() self.curOverview = "" @@ -959,26 +1193,16 @@ class wxPythonDemo(wx.Frame): self.codePage = None self.shell = None self.firstTime = True + self.finddlg = None - icon = images.getMondrianIcon() + icon = images.getWXPdemoIcon() self.SetIcon(icon) - if wx.Platform != '__WXMAC__': - # setup a taskbar icon, and catch some events from it - dim = 16 # (may want to use 22 on wxGTK, but 16 looks okay too) - icon = wx.IconFromBitmap( - images.getMondrianImage().Scale(dim,dim).ConvertToBitmap() ) - #icon = wx.Icon('bmp_source/mondrian.ico', wx.BITMAP_TYPE_ICO) - #icon = images.getMondrianIcon() - self.tbicon = wx.TaskBarIcon() - self.tbicon.SetIcon(icon, "wxPython Demo") - self.tbicon.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate) - self.tbicon.Bind(wx.EVT_TASKBAR_RIGHT_UP, self.OnTaskBarMenu) - self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE) - self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE) - - wx.CallAfter(self.ShowTip) - + try: + self.tbicon = DemoTaskBarIcon(self) + except: + self.tbicon = None + self.otherWin = None self.Bind(wx.EVT_IDLE, self.OnIdle) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) @@ -988,129 +1212,67 @@ class wxPythonDemo(wx.Frame): self.Centre(wx.BOTH) self.CreateStatusBar(1, wx.ST_SIZEGRIP) - splitter = wx.SplitterWindow(self, -1, style=wx.CLIP_CHILDREN | wx.SP_LIVE_UPDATE | wx.SP_3D) - splitter2 = wx.SplitterWindow(splitter, -1, style=wx.CLIP_CHILDREN | wx.SP_LIVE_UPDATE | wx.SP_3D) - - def EmptyHandler(evt): pass - #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler) - #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler) - - # Prevent TreeCtrl from displaying all items after destruction when True self.dying = False + self.skipLoad = False + + def EmptyHandler(evt): pass + self.ReadConfigurationFile() + # Create a Notebook - self.nb = wx.Notebook(splitter2, -1, style=wx.CLIP_CHILDREN) - - # Make a File menu - self.mainmenu = wx.MenuBar() - menu = wx.Menu() - item = menu.Append(-1, '&Redirect Output', - 'Redirect print statements to a window', - wx.ITEM_CHECK) - self.Bind(wx.EVT_MENU, self.OnToggleRedirect, item) - - item = menu.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!') - self.Bind(wx.EVT_MENU, self.OnFileExit, item) - wx.App_SetMacExitMenuItemId(item.GetId()) - self.mainmenu.Append(menu, '&File') - - # Make a Demo menu - menu = wx.Menu() - for item in _treeList: - submenu = wx.Menu() - for childItem in item[1]: - mi = submenu.Append(-1, childItem) - self.Bind(wx.EVT_MENU, self.OnDemoMenu, mi) - menu.AppendMenu(wx.NewId(), item[0], submenu) - self.mainmenu.Append(menu, '&Demo') - - # Make a Demo Code menu - #TODO: Add new menu items - # Like the option-enabled entries to select the - # active module - #TODO: should we bother? - - #menu = wx.Menu() - #saveID = wx.NewId() - #restoreID = wx.NewId() - # - #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo') - #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy') - #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID) - #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID) - #self.mainmenu.Append(menu, 'Demo &Code') - # - - # Make a Help menu - menu = wx.Menu() - findItem = menu.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code') - findnextItem = menu.Append(-1, 'Find &Next\tF3', 'Find Next') - menu.AppendSeparator() - - shellItem = menu.Append(-1, 'Open Py&Shell Window\tF5', - 'An interactive interpreter window with the demo app and frame objects in the namesapce') - menu.AppendSeparator() - helpItem = menu.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!') - wx.App_SetMacAboutMenuItemId(helpItem.GetId()) - - self.Bind(wx.EVT_MENU, self.OnOpenShellWindow, shellItem) - self.Bind(wx.EVT_MENU, self.OnHelpAbout, helpItem) - self.Bind(wx.EVT_MENU, self.OnHelpFind, findItem) - self.Bind(wx.EVT_MENU, self.OnFindNext, findnextItem) - self.Bind(wx.EVT_COMMAND_FIND, self.OnFind) - self.Bind(wx.EVT_COMMAND_FIND_NEXT, self.OnFind) - self.Bind(wx.EVT_COMMAND_FIND_CLOSE, self.OnFindClose) - self.mainmenu.Append(menu, '&Help') - self.SetMenuBar(self.mainmenu) - + self.nb = wx.Notebook(self, -1, style=wx.CLIP_CHILDREN) + imgList = wx.ImageList(16, 16) + for png in ["overview", "code", "demo"]: + bmp = images.catalog[png].getBitmap() + imgList.Add(bmp) + self.nb.AssignImageList(imgList) + + self.BuildMenuBar() + self.finddata = wx.FindReplaceData() - - if 0: - # This is another way to set Accelerators, in addition to - # using the '\t' syntax in the menu items. - aTable = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), exitID), - (wx.ACCEL_CTRL, ord('H'), helpID), - (wx.ACCEL_CTRL, ord('F'), findID), - (wx.ACCEL_NORMAL, WXK_F3, findnextID) - ]) - self.SetAcceleratorTable(aTable) - + self.finddata.SetFlags(wx.FR_DOWN) # Create a TreeCtrl - tID = wx.NewId() + leftPanel = wx.Panel(self, style=wx.TAB_TRAVERSAL|wx.CLIP_CHILDREN) self.treeMap = {} - self.tree = wx.TreeCtrl(splitter, tID, style = - wx.TR_DEFAULT_STYLE #| wx.TR_HAS_VARIABLE_ROW_HEIGHT - ) - - root = self.tree.AddRoot("wxPython Overview") - firstChild = None - for item in _treeList: - child = self.tree.AppendItem(root, item[0]) - if not firstChild: firstChild = child - for childItem in item[1]: - theDemo = self.tree.AppendItem(child, childItem) - self.treeMap[childItem] = theDemo - - self.tree.Expand(root) - self.tree.Expand(firstChild) - self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, id=tID) - self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=tID) - self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=tID) + self.searchItems = {} + + self.tree = wxPythonDemoTree(leftPanel) + + self.filter = wx.SearchCtrl(leftPanel, style=wx.TE_PROCESS_ENTER) + self.filter.ShowCancelButton(True) + self.filter.Bind(wx.EVT_TEXT, self.RecreateTree) + self.filter.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, + lambda e: self.filter.SetValue('')) + self.filter.Bind(wx.EVT_TEXT_ENTER, self.OnSearch) + + searchMenu = wx.Menu() + item = searchMenu.AppendRadioItem(-1, "Sample Name") + self.Bind(wx.EVT_MENU, self.OnSearchMenu, item) + item = searchMenu.AppendRadioItem(-1, "Sample Content") + self.Bind(wx.EVT_MENU, self.OnSearchMenu, item) + self.filter.SetMenu(searchMenu) + + self.RecreateTree() + self.tree.SetExpansionState(self.expansionState) + self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded) + self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed) + self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged) self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown) - + # Set up a wx.html.HtmlWindow on the Overview Notebook page # we put it in a panel first because there seems to be a # refresh bug of some sort (wxGTK) when it is directly in # the notebook... + if 0: # the old way self.ovr = wx.html.HtmlWindow(self.nb, -1, size=(400, 400)) - self.nb.AddPage(self.ovr, self.overviewText) + self.nb.AddPage(self.ovr, self.overviewText, imageId=0) else: # hopefully I can remove this hacky code soon, see SF bug #216861 panel = wx.Panel(self.nb, -1, style=wx.CLIP_CHILDREN) self.ovr = wx.html.HtmlWindow(panel, -1, size=(400, 400)) - self.nb.AddPage(panel, self.overviewText) + self.nb.AddPage(panel, self.overviewText, imageId=0) def OnOvrSize(evt, ovr=self.ovr): ovr.SetSize(evt.GetSize()) @@ -1118,13 +1280,15 @@ class wxPythonDemo(wx.Frame): panel.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler) if "gtk2" in wx.PlatformInfo: - self.ovr.NormalizeFontSizes() + self.ovr.SetStandardFonts() self.SetOverview(self.overviewText, mainOverview) # Set up a log window - self.log = wx.TextCtrl(splitter2, -1, + self.log = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL) + if wx.Platform == "__WXMAC__": + self.log.MacCheckSpelling(False) # Set the wxWindows log target to be this textctrl #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log)) @@ -1136,26 +1300,19 @@ class wxPythonDemo(wx.Frame): #wx.Log_SetActiveTarget(wx.LogStderr()) #wx.Log_SetTraceMask(wx.TraceMessages) + self.Bind(wx.EVT_ACTIVATE, self.OnActivate) + wx.GetApp().Bind(wx.EVT_ACTIVATE_APP, self.OnAppActivate) # add the windows to the splitter and split it. - splitter2.SplitHorizontally(self.nb, self.log, -160) - splitter.SplitVertically(self.tree, splitter2, 200) - - splitter.SetMinimumPaneSize(20) - splitter2.SetMinimumPaneSize(20) - - # Make the splitter on the right expand the top window when resized - def SplitterOnSize(evt): - splitter = evt.GetEventObject() - sz = splitter.GetSize() - splitter.SetSashPosition(sz.height - 160, False) - evt.Skip() - - splitter2.Bind(wx.EVT_SIZE, SplitterOnSize) + leftBox = wx.BoxSizer(wx.VERTICAL) + leftBox.Add(self.tree, 1, wx.EXPAND) + leftBox.Add(wx.StaticText(leftPanel, label = "Filter Demos:"), 0, wx.TOP|wx.LEFT, 5) + leftBox.Add(self.filter, 0, wx.EXPAND|wx.ALL, 5) + leftPanel.SetSizer(leftBox) # select initial items self.nb.SetSelection(0) - self.tree.SelectItem(root) + self.tree.SelectItem(self.root) # Load 'Main' module self.LoadDemo(self.overviewText) @@ -1171,8 +1328,289 @@ class wxPythonDemo(wx.Frame): self.tree.SelectItem(selectedDemo) self.tree.EnsureVisible(selectedDemo) + # Use the aui manager to set up everything + self.mgr.AddPane(self.nb, wx.aui.AuiPaneInfo().CenterPane().Name("Notebook")) + self.mgr.AddPane(leftPanel, + wx.aui.AuiPaneInfo(). + Left().Layer(2).BestSize((240, -1)). + MinSize((160, -1)). + Floatable(ALLOW_AUI_FLOATING).FloatingSize((240, 700)). + Caption("wxPython Demos"). + CloseButton(False). + Name("DemoTree")) + self.mgr.AddPane(self.log, + wx.aui.AuiPaneInfo(). + Bottom().BestSize((-1, 150)). + MinSize((-1, 60)). + Floatable(ALLOW_AUI_FLOATING).FloatingSize((500, 160)). + Caption("Demo Log Messages"). + CloseButton(False). + Name("LogWindow")) + + self.auiConfigurations[DEFAULT_PERSPECTIVE] = self.mgr.SavePerspective() + self.mgr.Update() + + self.mgr.SetFlags(self.mgr.GetFlags() ^ wx.aui.AUI_MGR_TRANSPARENT_DRAG) + + - #--------------------------------------------- + def ReadConfigurationFile(self): + + self.auiConfigurations = {} + self.expansionState = [0, 1] + + config = GetConfig() + val = config.Read('ExpansionState') + if val: + self.expansionState = eval(val) + + val = config.Read('AUIPerspectives') + if val: + self.auiConfigurations = eval(val) + + + def BuildMenuBar(self): + + # Make a File menu + self.mainmenu = wx.MenuBar() + menu = wx.Menu() + item = menu.Append(-1, '&Redirect Output', + 'Redirect print statements to a window', + wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU, self.OnToggleRedirect, item) + + exitItem = wx.MenuItem(menu, -1, 'E&xit\tCtrl-Q', 'Get the heck outta here!') + exitItem.SetBitmap(images.catalog['exit'].getBitmap()) + menu.AppendItem(exitItem) + self.Bind(wx.EVT_MENU, self.OnFileExit, exitItem) + wx.App.SetMacExitMenuItemId(exitItem.GetId()) + self.mainmenu.Append(menu, '&File') + + # Make a Demo menu + menu = wx.Menu() + for indx, item in enumerate(_treeList[:-1]): + menuItem = wx.MenuItem(menu, -1, item[0]) + submenu = wx.Menu() + for childItem in item[1]: + mi = submenu.Append(-1, childItem) + self.Bind(wx.EVT_MENU, self.OnDemoMenu, mi) + menuItem.SetBitmap(images.catalog[_demoPngs[indx+1]].getBitmap()) + menuItem.SetSubMenu(submenu) + menu.AppendItem(menuItem) + self.mainmenu.Append(menu, '&Demo') + + # Make an Option menu + # If we've turned off floatable panels then this menu is not needed + if ALLOW_AUI_FLOATING: + menu = wx.Menu() + auiPerspectives = self.auiConfigurations.keys() + auiPerspectives.sort() + perspectivesMenu = wx.Menu() + item = wx.MenuItem(perspectivesMenu, -1, DEFAULT_PERSPECTIVE, "Load startup default perspective", wx.ITEM_RADIO) + self.Bind(wx.EVT_MENU, self.OnAUIPerspectives, item) + perspectivesMenu.AppendItem(item) + for indx, key in enumerate(auiPerspectives): + if key == DEFAULT_PERSPECTIVE: + continue + item = wx.MenuItem(perspectivesMenu, -1, key, "Load user perspective %d"%indx, wx.ITEM_RADIO) + perspectivesMenu.AppendItem(item) + self.Bind(wx.EVT_MENU, self.OnAUIPerspectives, item) + + menu.AppendMenu(wx.ID_ANY, "&AUI Perspectives", perspectivesMenu) + self.perspectives_menu = perspectivesMenu + + item = wx.MenuItem(menu, -1, 'Save Perspective', 'Save AUI perspective') + item.SetBitmap(images.catalog['saveperspective'].getBitmap()) + menu.AppendItem(item) + self.Bind(wx.EVT_MENU, self.OnSavePerspective, item) + + item = wx.MenuItem(menu, -1, 'Delete Perspective', 'Delete AUI perspective') + item.SetBitmap(images.catalog['deleteperspective'].getBitmap()) + menu.AppendItem(item) + self.Bind(wx.EVT_MENU, self.OnDeletePerspective, item) + + menu.AppendSeparator() + + item = wx.MenuItem(menu, -1, 'Restore Tree Expansion', 'Restore the initial tree expansion state') + item.SetBitmap(images.catalog['expansion'].getBitmap()) + menu.AppendItem(item) + self.Bind(wx.EVT_MENU, self.OnTreeExpansion, item) + + self.mainmenu.Append(menu, '&Options') + + # Make a Help menu + menu = wx.Menu() + findItem = wx.MenuItem(menu, -1, '&Find\tCtrl-F', 'Find in the Demo Code') + findItem.SetBitmap(images.catalog['find'].getBitmap()) + findNextItem = wx.MenuItem(menu, -1, 'Find &Next\tF3', 'Find Next') + findNextItem.SetBitmap(images.catalog['findnext'].getBitmap()) + menu.AppendItem(findItem) + menu.AppendItem(findNextItem) + menu.AppendSeparator() + + shellItem = wx.MenuItem(menu, -1, 'Open Py&Shell Window\tF5', + 'An interactive interpreter window with the demo app and frame objects in the namesapce') + shellItem.SetBitmap(images.catalog['pyshell'].getBitmap()) + menu.AppendItem(shellItem) + inspToolItem = wx.MenuItem(menu, -1, 'Open &Widget Inspector\tF6', + 'A tool that lets you browse the live widgets and sizers in an application') + inspToolItem.SetBitmap(images.catalog['inspect'].getBitmap()) + menu.AppendItem(inspToolItem) + menu.AppendSeparator() + helpItem = menu.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!') + wx.App.SetMacAboutMenuItemId(helpItem.GetId()) + + self.Bind(wx.EVT_MENU, self.OnOpenShellWindow, shellItem) + self.Bind(wx.EVT_MENU, self.OnOpenWidgetInspector, inspToolItem) + self.Bind(wx.EVT_MENU, self.OnHelpAbout, helpItem) + self.Bind(wx.EVT_MENU, self.OnHelpFind, findItem) + self.Bind(wx.EVT_MENU, self.OnFindNext, findNextItem) + self.Bind(wx.EVT_FIND, self.OnFind) + self.Bind(wx.EVT_FIND_NEXT, self.OnFind) + self.Bind(wx.EVT_FIND_CLOSE, self.OnFindClose) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateFindItems, findItem) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateFindItems, findNextItem) + self.mainmenu.Append(menu, '&Help') + self.SetMenuBar(self.mainmenu) + + if False: + # This is another way to set Accelerators, in addition to + # using the '\t' syntax in the menu items. + aTable = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), exitItem.GetId()), + (wx.ACCEL_CTRL, ord('H'), helpItem.GetId()), + (wx.ACCEL_CTRL, ord('F'), findItem.GetId()), + (wx.ACCEL_NORMAL, wx.WXK_F3, findnextItem.GetId()), + (wx.ACCEL_NORMAL, wx.WXK_F9, shellItem.GetId()), + ]) + self.SetAcceleratorTable(aTable) + + + #--------------------------------------------- + def RecreateTree(self, evt=None): + # Catch the search type (name or content) + searchMenu = self.filter.GetMenu().GetMenuItems() + fullSearch = searchMenu[1].IsChecked() + + if evt: + if fullSearch: + # Do not`scan all the demo files for every char + # the user input, use wx.EVT_TEXT_ENTER instead + return + + expansionState = self.tree.GetExpansionState() + + current = None + item = self.tree.GetSelection() + if item: + prnt = self.tree.GetItemParent(item) + if prnt: + current = (self.tree.GetItemText(item), + self.tree.GetItemText(prnt)) + + self.tree.Freeze() + self.tree.DeleteAllItems() + self.root = self.tree.AddRoot("wxPython Overview") + self.tree.SetItemImage(self.root, 0) + self.tree.SetItemPyData(self.root, 0) + + treeFont = self.tree.GetFont() + catFont = self.tree.GetFont() + + # The old native treectrl on MSW has a bug where it doesn't + # draw all of the text for an item if the font is larger than + # the default. It seems to be clipping the item's label as if + # it was the size of the same label in the default font. + if 'wxMSW' not in wx.PlatformInfo or wx.GetApp().GetComCtl32Version() >= 600: + treeFont.SetPointSize(treeFont.GetPointSize()+2) + treeFont.SetWeight(wx.BOLD) + catFont.SetWeight(wx.BOLD) + + self.tree.SetItemFont(self.root, treeFont) + + firstChild = None + selectItem = None + filter = self.filter.GetValue() + count = 0 + + for category, items in _treeList: + count += 1 + if filter: + if fullSearch: + items = self.searchItems[category] + else: + items = [item for item in items if filter.lower() in item.lower()] + if items: + child = self.tree.AppendItem(self.root, category, image=count) + self.tree.SetItemFont(child, catFont) + self.tree.SetItemPyData(child, count) + if not firstChild: firstChild = child + for childItem in items: + image = count + if DoesModifiedExist(childItem): + image = len(_demoPngs) + theDemo = self.tree.AppendItem(child, childItem, image=image) + self.tree.SetItemPyData(theDemo, count) + self.treeMap[childItem] = theDemo + if current and (childItem, category) == current: + selectItem = theDemo + + + self.tree.Expand(self.root) + if firstChild: + self.tree.Expand(firstChild) + if filter: + self.tree.ExpandAll() + elif expansionState: + self.tree.SetExpansionState(expansionState) + if selectItem: + self.skipLoad = True + self.tree.SelectItem(selectItem) + self.skipLoad = False + + self.tree.Thaw() + self.searchItems = {} + + + def OnSearchMenu(self, event): + + # Catch the search type (name or content) + searchMenu = self.filter.GetMenu().GetMenuItems() + fullSearch = searchMenu[1].IsChecked() + + if fullSearch: + self.OnSearch() + else: + self.RecreateTree() + + + def OnSearch(self, event=None): + + value = self.filter.GetValue() + if not value: + self.RecreateTree() + return + + wx.BeginBusyCursor() + + for category, items in _treeList: + self.searchItems[category] = [] + for childItem in items: + if SearchDemo(childItem, value): + self.searchItems[category].append(childItem) + + wx.EndBusyCursor() + self.RecreateTree() + + + def SetTreeModified(self, modified): + item = self.tree.GetSelection() + if modified: + image = len(_demoPngs) + else: + image = self.tree.GetItemPyData(item) + self.tree.SetItemImage(item, image) + + def WriteText(self, text): if text[-1:] == '\n': text = text[:-1] @@ -1204,7 +1642,7 @@ class wxPythonDemo(wx.Frame): #--------------------------------------------- def OnSelChanged(self, event): - if self.dying or not self.loaded: + if self.dying or not self.loaded or self.skipLoad: return item = event.GetItem() @@ -1215,6 +1653,7 @@ class wxPythonDemo(wx.Frame): def LoadDemo(self, demoName): try: wx.BeginBusyCursor() + self.Freeze() os.chdir(self.cwd) self.ShutdownDemoModule() @@ -1232,13 +1671,13 @@ class wxPythonDemo(wx.Frame): wx.LogMessage("Loading demo %s.py..." % demoName) self.demoModules = DemoModules(demoName) self.LoadDemoSource() - self.tree.Refresh() else: self.SetOverview("wxPython", mainOverview) self.codePage = None self.UpdateNotebook(0) finally: wx.EndBusyCursor() + self.Thaw() #--------------------------------------------- def LoadDemoSource(self): @@ -1254,10 +1693,9 @@ class wxPythonDemo(wx.Frame): self.ShutdownDemoModule() overviewText = "" - # o If the demo returns a window it is placed in a tab. - # o Otherwise, a placeholder tab is created, informing the user that the - # demo runs outside the main window, and allowing it to be reloaded. - # o If an error occurs (or has occured before) an error tab is created. + # o The RunTest() for all samples must now return a window that can + # be palced in a tab in the main notebook. + # o If an error occurs (or has occurred before) an error tab is created. if module is not None: wx.LogMessage("Running demo module...") @@ -1270,6 +1708,10 @@ class wxPythonDemo(wx.Frame): self.demoPage = DemoErrorPanel(self.nb, self.codePage, DemoError(sys.exc_info()), self) + bg = self.nb.GetThemeBackgroundColour() + if bg: + self.demoPage.SetBackgroundColour(bg) + assert self.demoPage is not None, "runTest must return a window!" else: @@ -1280,7 +1722,7 @@ class wxPythonDemo(wx.Frame): self.SetOverview(self.demoModules.name + " Overview", overviewText) if self.firstTime: - # cahnge to the demo page the first time a module is run + # change to the demo page the first time a module is run self.UpdateNotebook(2) self.firstTime = False else: @@ -1300,6 +1742,7 @@ class wxPythonDemo(wx.Frame): def UpdateNotebook(self, select = -1): nb = self.nb debug = False + self.Freeze() def UpdatePage(page, pageText): pageExists = False @@ -1313,15 +1756,13 @@ class wxPythonDemo(wx.Frame): if page: if not pageExists: # Add a new page - nb.AddPage(page, pageText) + nb.AddPage(page, pageText, imageId=nb.GetPageCount()) if debug: wx.LogMessage("DBG: ADDED %s" % pageText) else: if nb.GetPage(pagePos) != page: # Reload an existing page - nb.Freeze() nb.DeletePage(pagePos) - nb.InsertPage(pagePos, page, pageText) - nb.Thaw() + nb.InsertPage(pagePos, page, pageText, imageId=pagePos) if debug: wx.LogMessage("DBG: RELOADED %s" % pageText) else: # Excellent! No redraw/flicker @@ -1341,7 +1782,9 @@ class wxPythonDemo(wx.Frame): if select >= 0 and select < nb.GetPageCount(): nb.SetSelection(select) - + + self.Thaw() + #--------------------------------------------- def SetOverview(self, name, text): self.curOverview = text @@ -1366,6 +1809,70 @@ class wxPythonDemo(wx.Frame): else: app.RestoreStdio() print "Print statements and other standard output will now be sent to the usual location." + + + def OnAUIPerspectives(self, event): + perspective = self.perspectives_menu.GetLabel(event.GetId()) + self.mgr.LoadPerspective(self.auiConfigurations[perspective]) + self.mgr.Update() + + + def OnSavePerspective(self, event): + dlg = wx.TextEntryDialog(self, "Enter a name for the new perspective:", "AUI Configuration") + + dlg.SetValue(("Perspective %d")%(len(self.auiConfigurations)+1)) + if dlg.ShowModal() != wx.ID_OK: + return + + perspectiveName = dlg.GetValue() + menuItems = self.perspectives_menu.GetMenuItems() + for item in menuItems: + if item.GetLabel() == perspectiveName: + wx.MessageBox("The selected perspective name:\n\n%s\n\nAlready exists."%perspectiveName, + "Error", style=wx.ICON_ERROR) + return + + item = wx.MenuItem(self.perspectives_menu, -1, dlg.GetValue(), + "Load user perspective %d"%(len(self.auiConfigurations)+1), + wx.ITEM_RADIO) + self.Bind(wx.EVT_MENU, self.OnAUIPerspectives, item) + self.perspectives_menu.AppendItem(item) + item.Check(True) + self.auiConfigurations.update({dlg.GetValue(): self.mgr.SavePerspective()}) + + + def OnDeletePerspective(self, event): + menuItems = self.perspectives_menu.GetMenuItems()[1:] + lst = [] + loadDefault = False + + for item in menuItems: + lst.append(item.GetLabel()) + + dlg = wx.MultiChoiceDialog(self, + "Please select the perspectives\nyou would like to delete:", + "Delete AUI Perspectives", lst) + + if dlg.ShowModal() == wx.ID_OK: + selections = dlg.GetSelections() + strings = [lst[x] for x in selections] + for sel in strings: + self.auiConfigurations.pop(sel) + item = menuItems[lst.index(sel)] + if item.IsChecked(): + loadDefault = True + self.perspectives_menu.GetMenuItems()[0].Check(True) + self.perspectives_menu.DeleteItem(item) + lst.remove(sel) + + if loadDefault: + self.mgr.LoadPerspective(self.auiConfigurations[DEFAULT_PERSPECTIVE]) + self.mgr.Update() + + + def OnTreeExpansion(self, event): + self.tree.SetExpansionState(self.expansionState) + def OnHelpAbout(self, event): from About import MyAboutBox @@ -1374,25 +1881,40 @@ class wxPythonDemo(wx.Frame): about.Destroy() def OnHelpFind(self, event): + if self.finddlg != None: + return + self.nb.SetSelection(1) self.finddlg = wx.FindReplaceDialog(self, self.finddata, "Find", - wx.FR_NOUPDOWN | - wx.FR_NOMATCHCASE | - wx.FR_NOWHOLEWORD) + wx.FR_NOMATCHCASE | wx.FR_NOWHOLEWORD) self.finddlg.Show(True) + + def OnUpdateFindItems(self, evt): + evt.Enable(self.finddlg == None) + + def OnFind(self, event): editor = self.codePage.editor self.nb.SetSelection(1) end = editor.GetLastPosition() textstring = editor.GetRange(0, end).lower() - start = editor.GetSelection()[1] findstring = self.finddata.GetFindString().lower() - loc = textstring.find(findstring, start) + backward = not (self.finddata.GetFlags() & wx.FR_DOWN) + if backward: + start = editor.GetSelection()[0] + loc = textstring.rfind(findstring, 0, start) + else: + start = editor.GetSelection()[1] + loc = textstring.find(findstring, start) if loc == -1 and start != 0: # string not found, start at beginning - start = 0 - loc = textstring.find(findstring, start) + if backward: + start = end + loc = textstring.rfind(findstring, 0, start) + else: + start = 0 + loc = textstring.find(findstring, start) if loc == -1: dlg = wx.MessageDialog(self, 'Find String Not Found', 'Find String Not Found in Demo File', @@ -1405,6 +1927,7 @@ class wxPythonDemo(wx.Frame): return else: self.finddlg.Destroy() + self.finddlg = None editor.ShowPosition(loc) editor.SetSelection(loc, loc + len(findstring)) @@ -1418,6 +1941,7 @@ class wxPythonDemo(wx.Frame): def OnFindClose(self, event): event.GetDialog().Destroy() + self.finddlg = None def OnOpenShellWindow(self, evt): @@ -1446,6 +1970,20 @@ class wxPythonDemo(wx.Frame): evt.Skip() self.Bind(wx.EVT_CLOSE, CloseShell) + + def OnOpenWidgetInspector(self, evt): + # Activate the widget inspection tool + from wx.lib.inspection import InspectionTool + if not InspectionTool().initialized: + InspectionTool().Init() + + # Find a widget to be selected in the tree. Use either the + # one under the cursor, if any, or this frame. + wnd = wx.FindWindowAtPointer() + if not wnd: + wnd = self + InspectionTool().Show(wnd, True) + #--------------------------------------------- def OnCloseWindow(self, event): @@ -1453,6 +1991,14 @@ class wxPythonDemo(wx.Frame): self.demoPage = None self.codePage = None self.mainmenu = None + if self.tbicon is not None: + self.tbicon.Destroy() + + config = GetConfig() + config.Write('ExpansionState', str(self.tree.GetExpansionState())) + config.Write('AUIPerspectives', str(self.auiConfigurations)) + config.Flush() + self.Destroy() @@ -1466,18 +2012,20 @@ class wxPythonDemo(wx.Frame): #--------------------------------------------- def ShowTip(self): - try: - showTipText = open(opj("data/showTips")).read() + config = GetConfig() + showTipText = config.Read("tips") + if showTipText: showTip, index = eval(showTipText) - except IOError: + else: showTip, index = (1, 0) + if showTip: tp = wx.CreateFileTipProvider(opj("data/tips.txt"), index) ##tp = MyTP(0) showTip = wx.ShowTip(self, tp) index = tp.GetCurrentTip() - open(opj("data/showTips"), "w").write(str( (showTip, index) )) - + config.Write("tips", str( (showTip, index) )) + config.Flush() #--------------------------------------------- def OnDemoMenu(self, event): @@ -1490,38 +2038,10 @@ class wxPythonDemo(wx.Frame): self.tree.EnsureVisible(selectedDemo) - #--------------------------------------------- - def OnTaskBarActivate(self, evt): - if self.IsIconized(): - self.Iconize(False) - if not self.IsShown(): - self.Show(True) - self.Raise() - - #--------------------------------------------- - - TBMENU_RESTORE = 1000 - TBMENU_CLOSE = 1001 - - def OnTaskBarMenu(self, evt): - menu = wx.Menu() - menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo") - menu.Append(self.TBMENU_CLOSE, "Close") - self.tbicon.PopupMenu(menu) - menu.Destroy() - - #--------------------------------------------- - def OnTaskBarClose(self, evt): - self.Close() - - # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to - # prod the main idle handler a bit to get the window to actually close - wx.GetApp().ProcessIdle() - #--------------------------------------------- def OnIconfiy(self, evt): - wx.LogMessage("OnIconfiy: %d" % evt.Iconized()) + wx.LogMessage("OnIconfiy: %s" % evt.Iconized()) evt.Skip() #--------------------------------------------- @@ -1529,27 +2049,95 @@ class wxPythonDemo(wx.Frame): wx.LogMessage("OnMaximize") evt.Skip() + #--------------------------------------------- + def OnActivate(self, evt): + wx.LogMessage("OnActivate: %s" % evt.GetActive()) + evt.Skip() - + #--------------------------------------------- + def OnAppActivate(self, evt): + wx.LogMessage("OnAppActivate: %s" % evt.GetActive()) + evt.Skip() #--------------------------------------------------------------------------- #--------------------------------------------------------------------------- class MySplashScreen(wx.SplashScreen): def __init__(self): - bmp = wx.Image(opj("bitmaps/splash.gif")).ConvertToBitmap() + bmp = wx.Image(opj("bitmaps/splash.png")).ConvertToBitmap() wx.SplashScreen.__init__(self, bmp, wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT, - 3000, None, -1) + 5000, None, -1) self.Bind(wx.EVT_CLOSE, self.OnClose) + self.fc = wx.FutureCall(2000, self.ShowMain) + def OnClose(self, evt): + # Make sure the default handler runs too so this window gets + # destroyed + evt.Skip() self.Hide() + + # if the timer is still running then go ahead and show the + # main frame now + if self.fc.IsRunning(): + self.fc.Stop() + self.ShowMain() + + + def ShowMain(self): frame = wxPythonDemo(None, "wxPython: (A Demonstration)") frame.Show() - evt.Skip() # Make sure the default handler runs too... + if self.fc.IsRunning(): + self.Raise() + wx.CallAfter(frame.ShowTip) + + +#--------------------------------------------------------------------------- + +from wx.lib.mixins.treemixin import ExpansionState +if USE_CUSTOMTREECTRL: + import wx.lib.customtreectrl as CT + TreeBaseClass = CT.CustomTreeCtrl +else: + TreeBaseClass = wx.TreeCtrl + + +class wxPythonDemoTree(ExpansionState, TreeBaseClass): + def __init__(self, parent): + TreeBaseClass.__init__(self, parent, style=wx.TR_DEFAULT_STYLE| + wx.TR_HAS_VARIABLE_ROW_HEIGHT) + self.BuildTreeImageList() + if USE_CUSTOMTREECTRL: + self.SetSpacing(10) + self.SetWindowStyle(self.GetWindowStyle() & ~wx.TR_LINES_AT_ROOT) + + def AppendItem(self, parent, text, image=-1, wnd=None): + if USE_CUSTOMTREECTRL: + item = TreeBaseClass.AppendItem(self, parent, text, image=image, wnd=wnd) + else: + item = TreeBaseClass.AppendItem(self, parent, text, image=image) + return item + + def BuildTreeImageList(self): + imgList = wx.ImageList(16, 16) + for png in _demoPngs: + imgList.Add(images.catalog[png].getBitmap()) + + # add the image for modified demos. + imgList.Add(images.catalog["custom"].getBitmap()) + + self.AssignImageList(imgList) + + + def GetItemIdentity(self, item): + return self.GetPyData(item) + + +#--------------------------------------------------------------------------- + class MyApp(wx.App): def OnInit(self): """ @@ -1557,6 +2145,9 @@ class MyApp(wx.App): the main frame when it is time to do so. """ + wx.SystemOptions.SetOptionInt("mac.window-plain-transition", 1) + self.SetAppName("wxPyDemo") + # For debugging #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG) @@ -1565,7 +2156,7 @@ class MyApp(wx.App): # initialization, finally creating and showing the main # application window(s). In this case we have nothing else to # do so we'll delay showing the main frame until later (see - # OnClose above) so the users can see the SplashScreen effect. + # ShowMain above) so the users can see the SplashScreen effect. splash = MySplashScreen() splash.Show()