2 #----------------------------------------------------------------------------
4 # Purpose: Testing lots of stuff, controls, window types, etc.
8 # Created: A long time ago, in a galaxy far, far away...
10 # Copyright: (c) 1999 by Total Control Software
11 # Licence: wxWindows license
12 #----------------------------------------------------------------------------
15 # * Problems with flickering related to ERASE_BACKGROUND
16 # and the splitters. Might be a problem with this 2.5 beta...?
17 # UPDATE: can't see on 2.5.2 GTK - maybe just a faster machine :)
19 # * Annoying switching between tabs and resulting flicker
20 # how to replace a page in the notebook without deleting/adding?
21 # Where is SetPage!? tried freeze...tried reparent of dummy panel....
24 # * UI design more prefessional
25 # * save file positions (new field in demoModules) (@ LoadDemoSource)
26 # * Update main overview
28 # * Why don't we move _treeList into a separate module
30 import sys
, os
, time
, traceback
, types
32 import wx
# This module uses the new wx namespace
39 ##print "wx.VERSION_STRING = ", wx.VERSION_STRING
41 ##raw_input("Press Enter...")
44 #---------------------------------------------------------------------------
49 ('Recent Additions/Updates', [
56 # managed windows == things with a (optional) caption you can close
57 ('Frames and Dialogs', [
80 # dialogs from libraries
83 'MultipleChoiceDialog',
84 'ScrolledMessageDialog',
88 ('Core Windows/Controls', [
127 ('Custom Controls', [
140 # controls coming from other libraries
141 ('More Windows/Controls', [
142 'ActiveX_FlashWindow',
143 'ActiveX_IEHtmlWindow',
145 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
158 'MaskedEditControls',
175 # How to lay out the controls in a frame/dialog
185 'XmlResourceHandler',
186 'XmlResourceSubclass',
190 ('Process and Events', [
197 ##'infoframe', # needs better explaination and some fixing
201 ('Clipboard and DnD', [
222 ##'DialogUnits', # needs more explainations
234 # need libs not coming with the demo
235 ('Samples using an external library', [
240 ('Check out the samples dir too', [
247 #---------------------------------------------------------------------------
248 # Show how to derive a custom wxLog class
250 class MyLog(wx
.PyLog
):
251 def __init__(self
, textCtrl
, logTime
=0):
252 wx
.PyLog
.__init
__(self
)
254 self
.logTime
= logTime
256 def DoLogString(self
, message
, timeStamp
):
258 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
261 self
.tc
.AppendText(message
+ '\n')
264 class MyTP(wx
.PyTipProvider
):
266 return "This is my tip"
269 #---------------------------------------------------------------------------
270 # A class to be used to display source code in the demo. Try using the
271 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
272 # if there is an error, such as the stc module not being present.
276 ##raise ImportError # for testing the alternate implementation
278 from StyledTextCtrl_2
import PythonSTC
280 class DemoCodeEditor(PythonSTC
):
281 def __init__(self
, parent
):
282 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
285 # Some methods to make it compatible with how the wxTextCtrl is used
286 def SetValue(self
, value
):
288 value
= value
.decode('iso8859_1')
290 self
.EmptyUndoBuffer()
293 def IsModified(self
):
294 return self
.GetModify()
299 def SetInsertionPoint(self
, pos
):
300 self
.SetCurrentPos(pos
)
303 def ShowPosition(self
, pos
):
304 line
= self
.LineFromPosition(pos
)
305 #self.EnsureVisible(line)
308 def GetLastPosition(self
):
309 return self
.GetLength()
311 def GetPositionFromLine(self
, line
):
312 return self
.PositionFromLine(line
)
314 def GetRange(self
, start
, end
):
315 return self
.GetTextRange(start
, end
)
317 def GetSelection(self
):
318 return self
.GetAnchor(), self
.GetCurrentPos()
320 def SetSelection(self
, start
, end
):
321 self
.SetSelectionStart(start
)
322 self
.SetSelectionEnd(end
)
324 def SelectLine(self
, line
):
325 start
= self
.PositionFromLine(line
)
326 end
= self
.GetLineEndPosition(line
)
327 self
.SetSelection(start
, end
)
329 def SetUpEditor(self
):
331 This method carries out the work of setting up the demo editor.
332 It's seperate so as not to clutter up the init code.
336 self
.SetLexer(stc
.STC_LEX_PYTHON
)
337 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
340 self
.SetProperty("fold", "1" )
342 # Highlight tab/space mixing (shouldn't be any)
343 self
.SetProperty("tab.timmy.whinge.level", "1")
345 # Set left and right margins
348 # Set up the numbers in the margin for margin #1
349 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
350 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
351 self
.SetMarginWidth(1, 40)
353 # Indentation and tab stuff
354 self
.SetIndent(4) # Proscribed indent size for wx
355 self
.SetIndentationGuides(True) # Show indent guides
356 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
357 self
.SetTabIndents(True) # Tab key indents
358 self
.SetTabWidth(4) # Proscribed tab size for wx
359 self
.SetUseTabs(False) # Use spaces rather than tabs, or
360 # TabTimmy will complain!
362 self
.SetViewWhiteSpace(False) # Don't view white space
364 # EOL: Since we are loading/saving ourselves, and the
365 # strings will always have \n's in them, set the STC to
366 # edit them that way.
367 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
368 self
.SetViewEOL(False)
370 # No right-edge mode indicator
371 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
373 # Setup a margin to hold fold markers
374 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
375 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
376 self
.SetMarginSensitive(2, True)
377 self
.SetMarginWidth(2, 12)
379 # and now set up the fold markers
380 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
381 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
382 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
383 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
384 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
385 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
386 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
388 # Global default style
389 if wx
.Platform
== '__WXMSW__':
390 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
391 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
393 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
394 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
396 # Clear styles and revert to default.
399 # Following style specs only indicate differences from default.
400 # The rest remains unchanged.
402 # Line numbers in margin
403 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
405 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
407 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
409 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
412 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
414 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
415 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
417 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
418 # Strings and characters
419 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
420 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
422 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
424 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
425 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
427 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
429 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
431 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
432 # Identifiers. I leave this as not bold because everything seems
433 # to be an identifier if it doesn't match the above criterae
434 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
437 self
.SetCaretForeground("BLUE")
438 # Selection background
439 self
.SetSelBackground(1, '#66CCFF')
441 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
442 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
444 def RegisterModifiedEvent(self
, eventHandler
):
445 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
449 class DemoCodeEditor(wx
.TextCtrl
):
450 def __init__(self
, parent
):
451 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
452 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
454 def RegisterModifiedEvent(self
, eventHandler
):
455 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
457 def SetReadOnly(self
, flag
):
458 self
.SetEditable(not flag
)
459 # NOTE: STC already has this method
462 return self
.GetValue()
464 def GetPositionFromLine(line
):
465 return self
.XYToPosition(0,line
)
467 def GotoLine(self
, line
):
468 pos
= self
.editor
.GetPositionFromLine(line
)
469 self
.editor
.SetInsertionPoint(pos
)
470 self
.editor
.ShowPosition(pos
)
472 def SelectLine(self
, line
):
473 start
= self
.GetPositionFromLine(line
)
474 end
= start
+ self
.GetLineLength(line
)
475 self
.SetSelection(start
, end
)
478 #---------------------------------------------------------------------------
479 # Constants for module versions
483 modDefault
= modOriginal
485 #---------------------------------------------------------------------------
487 class DemoCodePanel(wx
.Panel
):
488 """Panel for the 'Demo Code' tab"""
489 def __init__(self
, parent
, mainFrame
):
490 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
491 if 'wxMSW' in wx
.PlatformInfo
:
493 self
.mainFrame
= mainFrame
494 self
.editor
= DemoCodeEditor(self
)
495 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
497 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
498 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
499 self
.btnSave
.Enable(False)
500 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
501 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
503 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
504 modModified
: wx
.RadioButton(self
, -1, "Modified") }
506 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
507 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
508 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
509 for modID
, radioButton
in self
.radioButtons
.items():
510 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
511 radioButton
.modID
= modID
# makes it easier for the event handler
512 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
514 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
515 self
.controlBox
.Add(self
.btnRestore
, 0)
517 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
518 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
519 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
520 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
523 self
.SetSizer(self
.box
)
526 # Loads a demo from a DemoModules object
527 def LoadDemo(self
, demoModules
):
528 self
.demoModules
= demoModules
529 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
530 demoModules
.SetActive(modModified
)
532 demoModules
.SetActive(modOriginal
)
533 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
534 self
.ActiveModuleChanged()
537 def ActiveModuleChanged(self
):
538 self
.LoadDemoSource(self
.demoModules
.GetSource())
539 self
.UpdateControlState()
543 def LoadDemoSource(self
, source
):
545 self
.editor
.SetValue(source
)
547 self
.btnSave
.Enable(False)
550 def JumpToLine(self
, line
, highlight
=False):
551 self
.editor
.GotoLine(line
)
552 self
.editor
.SetFocus()
554 self
.editor
.SelectLine(line
)
557 def UpdateControlState(self
):
558 active
= self
.demoModules
.GetActiveID()
559 # Update the radio/restore buttons
560 for moduleID
in self
.radioButtons
:
561 btn
= self
.radioButtons
[moduleID
]
562 if moduleID
== active
:
567 if self
.demoModules
.Exists(moduleID
):
569 if moduleID
== modModified
:
570 self
.btnRestore
.Enable(True)
573 if moduleID
== modModified
:
574 self
.btnRestore
.Enable(False)
577 def OnRadioButton(self
, event
):
578 radioSelected
= event
.GetEventObject()
579 modSelected
= radioSelected
.modID
580 if modSelected
!= self
.demoModules
.GetActiveID():
581 busy
= wx
.BusyInfo("Reloading demo module...")
582 self
.demoModules
.SetActive(modSelected
)
583 self
.ActiveModuleChanged()
586 def ReloadDemo(self
):
587 if self
.demoModules
.name
!= __name__
:
588 self
.mainFrame
.RunModule()
591 def OnCodeModified(self
, event
):
592 self
.btnSave
.Enable(self
.editor
.IsModified())
595 def OnSave(self
, event
):
596 if self
.demoModules
.Exists(modModified
):
597 if self
.demoModules
.GetActiveID() == modOriginal
:
598 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
599 "Do you want to continue?"
600 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
601 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
602 result
= dlg
.ShowModal()
603 if result
== wx
.ID_NO
:
607 self
.demoModules
.SetActive(modModified
)
608 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
610 # Create the demo directory if one doesn't already exist
611 if not os
.path
.exists(GetModifiedDirectory()):
613 os
.makedirs(GetModifiedDirectory())
614 if not os
.path
.exists(GetModifiedDirectory()):
615 wx
.LogMessage("BUG: Created demo directory but it still doesn't exit")
618 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
621 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
624 f
= open(modifiedFilename
, "wt")
625 source
= self
.editor
.GetText()
631 busy
= wx
.BusyInfo("Reloading demo module...")
632 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
633 self
.ActiveModuleChanged()
636 def OnRestore(self
, event
): # Handles the "Delete Modified" button
637 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
638 self
.demoModules
.Delete(modModified
)
639 os
.unlink(modifiedFilename
) # Delete the modified copy
640 busy
= wx
.BusyInfo("Reloading demo module...")
641 self
.ActiveModuleChanged()
644 #---------------------------------------------------------------------------
647 """Convert paths to the platform-specific separator"""
648 str = apply(os
.path
.join
, tuple(path
.split('/')))
649 # HACK: on Linux, a leading / gets lost...
650 if path
.startswith('/'):
655 def GetModifiedDirectory():
657 Returns the directory where modified versions of the demo files
660 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
663 def GetModifiedFilename(name
):
665 Returns the filename of the modified version of the specified demo
667 if not name
.endswith(".py"):
669 return GetModifiedDirectory() + name
672 def GetOriginalFilename(name
):
674 Returns the filename of the original version of the specified demo
676 if not name
.endswith(".py"):
681 def DoesModifiedExist(name
):
682 """Returns whether the specified demo has a modified copy"""
683 if os
.path
.exists(GetModifiedFilename(name
)):
689 #---------------------------------------------------------------------------
691 class ModuleDictWrapper
:
692 """Emulates a module with a dynamically compiled __dict__"""
693 def __init__(self
, dict):
696 def __getattr__(self
, name
):
697 if name
in self
.dict:
698 return self
.dict[name
]
704 Dynamically manages the original/modified versions of a demo
707 def __init__(self
, name
):
711 # (dict , source , filename , description , error information )
712 # ( 0 , 1 , 2 , 3 , 4 )
713 self
.modules
= [[None, "" , "" , "<original>" , None],
714 [None, "" , "" , "<modified>" , None]]
716 # load original module
717 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
718 self
.SetActive(modOriginal
)
720 # load modified module (if one exists)
721 if DoesModifiedExist(name
):
722 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
725 def LoadFromFile(self
, modID
, filename
):
726 self
.modules
[modID
][2] = filename
727 file = open(filename
, "rt")
728 self
.LoadFromSource(modID
, file.read())
732 def LoadFromSource(self
, modID
, source
):
733 self
.modules
[modID
][1] = source
737 def LoadDict(self
, modID
):
738 if self
.name
!= __name__
:
739 source
= self
.modules
[modID
][1]
740 description
= self
.modules
[modID
][3]
743 self
.modules
[modID
][0] = {}
744 code
= compile(source
, description
, "exec")
745 exec code
in self
.modules
[modID
][0]
747 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
748 self
.modules
[modID
][0] = None
750 self
.modules
[modID
][4] = None
753 def SetActive(self
, modID
):
754 if modID
!= modOriginal
and modID
!= modModified
:
757 self
.modActive
= modID
761 dict = self
.modules
[self
.modActive
][0]
765 return ModuleDictWrapper(dict)
768 def GetActiveID(self
):
769 return self
.modActive
772 def GetSource(self
, modID
= None):
774 modID
= self
.modActive
775 return self
.modules
[modID
][1]
778 def GetFilename(self
, modID
= None):
780 modID
= self
.modActive
781 return self
.modules
[self
.modActive
][2]
784 def GetErrorInfo(self
, modID
= None):
786 modID
= self
.modActive
787 return self
.modules
[self
.modActive
][4]
790 def Exists(self
, modID
):
791 return self
.modules
[modID
][1] != ""
794 def UpdateFile(self
, modID
= None):
795 """Updates the file from which a module was loaded
796 with (possibly updated) source"""
798 modID
= self
.modActive
800 source
= self
.modules
[modID
][1]
801 filename
= self
.modules
[modID
][2]
804 file = open(filename
, "wt")
810 def Delete(self
, modID
):
811 if self
.modActive
== modID
:
814 self
.modules
[modID
][0] = None
815 self
.modules
[modID
][1] = ""
816 self
.modules
[modID
][2] = ""
819 #---------------------------------------------------------------------------
822 """Wraps and stores information about the current exception"""
823 def __init__(self
, exc_info
):
826 excType
, excValue
= exc_info
[:2]
827 # traceback list entries: (filename, line number, function name, text)
828 self
.traceback
= traceback
.extract_tb(exc_info
[2])
830 # --Based on traceback.py::format_exception_only()--
831 if type(excType
) == types
.ClassType
:
832 self
.exception_type
= excType
.__name
__
834 self
.exception_type
= excType
836 # If it's a syntax error, extra information needs
837 # to be added to the traceback
838 if excType
is SyntaxError:
840 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
845 filename
= "<string>"
847 self
.traceback
.append( (filename
, lineno
, "", line
) )
850 self
.exception_details
= str(excValue
)
852 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
859 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
862 #---------------------------------------------------------------------------
864 class DemoErrorPanel(wx
.Panel
):
865 """Panel put into the demo tab when the demo fails to run due to errors"""
867 def __init__(self
, parent
, codePanel
, demoError
, log
):
868 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
869 self
.codePanel
= codePanel
873 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
876 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
877 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
879 # Exception Information
880 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
881 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
882 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
883 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
884 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
885 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
886 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
887 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
888 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
889 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
891 # Set up the traceback list
892 # This one automatically resizes last column to take up remaining space
893 from ListCtrl
import TestListCtrl
894 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
895 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
896 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
897 self
.list.InsertColumn(0, "Filename")
898 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
899 self
.list.InsertColumn(2, "Function")
900 self
.list.InsertColumn(3, "Code")
901 self
.InsertTraceback(self
.list, demoError
.traceback
)
902 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
903 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
904 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
905 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
906 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
907 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
908 + "Double-click on them to go to the offending line")
909 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
912 self
.SetSizer(self
.box
)
915 def InsertTraceback(self
, list, traceback
):
916 #Add the traceback data
917 for x
in range(len(traceback
)):
919 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
920 list.SetStringItem(x
, 1, str(data
[1])) # Line
921 list.SetStringItem(x
, 2, str(data
[2])) # Function
922 list.SetStringItem(x
, 3, str(data
[3])) # Code
924 # Check whether this entry is from the demo module
925 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
926 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
927 # Give it a blue colour
928 item
= self
.list.GetItem(x
)
929 item
.SetTextColour(wx
.BLUE
)
930 self
.list.SetItem(item
)
932 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
935 def OnItemSelected(self
, event
):
936 # This occurs before OnDoubleClick and can be used to set the
937 # currentItem. OnDoubleClick doesn't get a wxListEvent....
938 self
.currentItem
= event
.m_itemIndex
942 def OnDoubleClick(self
, event
):
943 # If double-clicking on a demo's entry, jump to the line number
944 line
= self
.list.GetItemData(self
.currentItem
)
946 self
.nb
.SetSelection(1) # Switch to the code viewer tab
947 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
951 #---------------------------------------------------------------------------
953 class DemoTaskBarIcon(wx
.TaskBarIcon
):
954 TBMENU_RESTORE
= wx
.NewId()
955 TBMENU_CLOSE
= wx
.NewId()
956 TBMENU_CHANGE
= wx
.NewId()
957 TBMENU_REMOVE
= wx
.NewId()
959 def __init__(self
, frame
):
960 wx
.TaskBarIcon
.__init
__(self
)
964 icon
= self
.MakeIcon(images
.getWXPdemoImage())
965 self
.SetIcon(icon
, "wxPython Demo")
969 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
970 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
971 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
972 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
973 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
976 def CreatePopupMenu(self
):
978 This method is called by the base class when it needs to popup
979 the menu for the default EVT_RIGHT_DOWN event. Just create
980 the menu how you want it and return it from this function,
981 the base class takes care of the rest.
984 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
985 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
986 menu
.AppendSeparator()
987 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
988 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
992 def MakeIcon(self
, img
):
994 The various platforms have different requirements for the
997 if "wxMSW" in wx
.PlatformInfo
:
998 img
= img
.Scale(16, 16)
999 elif "wxGTK" in wx
.PlatformInfo
:
1000 img
= img
.Scale(22, 22)
1001 # wxMac can be any size upto 128x128, so leave the source img alone....
1002 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1006 def OnTaskBarActivate(self
, evt
):
1007 if self
.frame
.IsIconized():
1008 self
.frame
.Iconize(False)
1009 if not self
.frame
.IsShown():
1010 self
.frame
.Show(True)
1014 def OnTaskBarClose(self
, evt
):
1018 def OnTaskBarChange(self
, evt
):
1019 names
= [ "WXPdemo", "WXP", "Mondrian", "Test2m",
1020 "Blom08m", "Blom10m", "Blom15m" ]
1021 name
= names
[self
.imgidx
]
1023 getFunc
= getattr(images
, "get%sImage" % name
)
1025 if self
.imgidx
>= len(names
):
1028 icon
= self
.MakeIcon(getFunc())
1029 self
.SetIcon(icon
, "This is a new icon: " + name
)
1032 def OnTaskBarRemove(self
, evt
):
1036 #---------------------------------------------------------------------------
1037 class wxPythonDemo(wx
.Frame
):
1038 overviewText
= "wxPython Overview"
1040 def __init__(self
, parent
, title
):
1041 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1042 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1045 self
.cwd
= os
.getcwd()
1046 self
.curOverview
= ""
1047 self
.demoPage
= None
1048 self
.codePage
= None
1050 self
.firstTime
= True
1052 icon
= images
.getWXPdemoIcon()
1055 self
.tbicon
= DemoTaskBarIcon(self
)
1057 wx
.CallAfter(self
.ShowTip
)
1059 self
.otherWin
= None
1060 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1061 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1062 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1063 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1065 self
.Centre(wx
.BOTH
)
1066 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1068 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1069 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1071 def EmptyHandler(evt
): pass
1072 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1073 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1075 # Prevent TreeCtrl from displaying all items after destruction when True
1079 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1082 self
.mainmenu
= wx
.MenuBar()
1084 item
= menu
.Append(-1, '&Redirect Output',
1085 'Redirect print statements to a window',
1087 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1089 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1090 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1091 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1092 self
.mainmenu
.Append(menu
, '&File')
1096 for item
in _treeList
:
1098 for childItem
in item
[1]:
1099 mi
= submenu
.Append(-1, childItem
)
1100 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1101 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1102 self
.mainmenu
.Append(menu
, '&Demo')
1104 # Make a Demo Code menu
1105 #TODO: Add new menu items
1106 # Like the option-enabled entries to select the
1108 #TODO: should we bother?
1111 #saveID = wx.NewId()
1112 #restoreID = wx.NewId()
1114 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1115 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1116 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1117 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1118 #self.mainmenu.Append(menu, 'Demo &Code')
1123 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1124 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1125 menu
.AppendSeparator()
1127 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1128 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1129 menu
.AppendSeparator()
1130 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1131 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1133 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1134 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1135 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1136 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1137 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1138 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1139 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1140 self
.mainmenu
.Append(menu
, '&Help')
1141 self
.SetMenuBar(self
.mainmenu
)
1143 self
.finddata
= wx
.FindReplaceData()
1146 # This is another way to set Accelerators, in addition to
1147 # using the '\t<key>' syntax in the menu items.
1148 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1149 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1150 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1151 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1153 self
.SetAcceleratorTable(aTable
)
1159 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1160 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1163 root
= self
.tree
.AddRoot("wxPython Overview")
1165 for item
in _treeList
:
1166 child
= self
.tree
.AppendItem(root
, item
[0])
1167 if not firstChild
: firstChild
= child
1168 for childItem
in item
[1]:
1169 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1170 self
.treeMap
[childItem
] = theDemo
1172 self
.tree
.Expand(root
)
1173 self
.tree
.Expand(firstChild
)
1174 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1175 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1176 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1177 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1179 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1180 # we put it in a panel first because there seems to be a
1181 # refresh bug of some sort (wxGTK) when it is directly in
1184 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1185 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1187 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1188 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1189 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1190 self
.nb
.AddPage(panel
, self
.overviewText
)
1192 def OnOvrSize(evt
, ovr
=self
.ovr
):
1193 ovr
.SetSize(evt
.GetSize())
1194 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1195 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1197 if "gtk2" in wx
.PlatformInfo
:
1198 self
.ovr
.SetStandardFonts()
1199 self
.SetOverview(self
.overviewText
, mainOverview
)
1202 # Set up a log window
1203 self
.log
= wx
.TextCtrl(splitter2
, -1,
1204 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1206 # Set the wxWindows log target to be this textctrl
1207 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1209 # But instead of the above we want to show how to use our own wx.Log class
1210 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1212 # for serious debugging
1213 #wx.Log_SetActiveTarget(wx.LogStderr())
1214 #wx.Log_SetTraceMask(wx.TraceMessages)
1217 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1218 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1220 # add the windows to the splitter and split it.
1221 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1222 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1224 splitter
.SetMinimumPaneSize(20)
1225 splitter2
.SetMinimumPaneSize(20)
1227 # Make the splitter on the right expand the top window when resized
1228 def SplitterOnSize(evt
):
1229 splitter
= evt
.GetEventObject()
1230 sz
= splitter
.GetSize()
1231 splitter
.SetSashPosition(sz
.height
- 160, False)
1234 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1236 # select initial items
1237 self
.nb
.SetSelection(0)
1238 self
.tree
.SelectItem(root
)
1240 # Load 'Main' module
1241 self
.LoadDemo(self
.overviewText
)
1244 # select some other initial module?
1245 if len(sys
.argv
) > 1:
1247 if arg
.endswith('.py'):
1249 selectedDemo
= self
.treeMap
.get(arg
, None)
1251 self
.tree
.SelectItem(selectedDemo
)
1252 self
.tree
.EnsureVisible(selectedDemo
)
1255 #---------------------------------------------
1256 def WriteText(self
, text
):
1257 if text
[-1:] == '\n':
1261 def write(self
, txt
):
1264 #---------------------------------------------
1265 def OnItemExpanded(self
, event
):
1266 item
= event
.GetItem()
1267 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1270 #---------------------------------------------
1271 def OnItemCollapsed(self
, event
):
1272 item
= event
.GetItem()
1273 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1276 #---------------------------------------------
1277 def OnTreeLeftDown(self
, event
):
1278 # reset the overview text if the tree item is clicked on again
1279 pt
= event
.GetPosition();
1280 item
, flags
= self
.tree
.HitTest(pt
)
1281 if item
== self
.tree
.GetSelection():
1282 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1285 #---------------------------------------------
1286 def OnSelChanged(self
, event
):
1287 if self
.dying
or not self
.loaded
:
1290 item
= event
.GetItem()
1291 itemText
= self
.tree
.GetItemText(item
)
1292 self
.LoadDemo(itemText
)
1294 #---------------------------------------------
1295 def LoadDemo(self
, demoName
):
1297 wx
.BeginBusyCursor()
1300 self
.ShutdownDemoModule()
1302 if demoName
== self
.overviewText
:
1303 # User selected the "wxPython Overview" node
1305 # Changing the main window at runtime not yet supported...
1306 self
.demoModules
= DemoModules(__name__
)
1307 self
.SetOverview(self
.overviewText
, mainOverview
)
1308 self
.LoadDemoSource()
1309 self
.UpdateNotebook(0)
1311 if os
.path
.exists(GetOriginalFilename(demoName
)):
1312 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1313 self
.demoModules
= DemoModules(demoName
)
1314 self
.LoadDemoSource()
1317 self
.SetOverview("wxPython", mainOverview
)
1318 self
.codePage
= None
1319 self
.UpdateNotebook(0)
1323 #---------------------------------------------
1324 def LoadDemoSource(self
):
1325 self
.codePage
= None
1326 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1327 self
.codePage
.LoadDemo(self
.demoModules
)
1329 #---------------------------------------------
1330 def RunModule(self
):
1331 """Runs the active module"""
1333 module
= self
.demoModules
.GetActive()
1334 self
.ShutdownDemoModule()
1337 # o The RunTest() for all samples must now return a window that can
1338 # be palced in a tab in the main notebook.
1339 # o If an error occurs (or has occured before) an error tab is created.
1341 if module
is not None:
1342 wx
.LogMessage("Running demo module...")
1343 if hasattr(module
, "overview"):
1344 overviewText
= module
.overview
1347 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1349 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1350 DemoError(sys
.exc_info()), self
)
1352 assert self
.demoPage
is not None, "runTest must return a window!"
1355 # There was a previous error in compiling or exec-ing
1356 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1357 self
.demoModules
.GetErrorInfo(), self
)
1359 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1362 # cahnge to the demo page the first time a module is run
1363 self
.UpdateNotebook(2)
1364 self
.firstTime
= False
1366 # otherwise just stay on the same tab in case the user has changed to another one
1367 self
.UpdateNotebook()
1369 #---------------------------------------------
1370 def ShutdownDemoModule(self
):
1372 # inform the window that it's time to quit if it cares
1373 if hasattr(self
.demoPage
, "ShutdownDemo"):
1374 self
.demoPage
.ShutdownDemo()
1375 wx
.YieldIfNeeded() # in case the page has pending events
1376 self
.demoPage
= None
1378 #---------------------------------------------
1379 def UpdateNotebook(self
, select
= -1):
1383 def UpdatePage(page
, pageText
):
1386 for i
in range(nb
.GetPageCount()):
1387 if nb
.GetPageText(i
) == pageText
:
1395 nb
.AddPage(page
, pageText
)
1396 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1398 if nb
.GetPage(pagePos
) != page
:
1399 # Reload an existing page
1401 nb
.DeletePage(pagePos
)
1402 nb
.InsertPage(pagePos
, page
, pageText
)
1404 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1406 # Excellent! No redraw/flicker
1407 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1410 nb
.DeletePage(pagePos
)
1411 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1413 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1416 select
= nb
.GetSelection()
1418 UpdatePage(self
.codePage
, "Demo Code")
1419 UpdatePage(self
.demoPage
, "Demo")
1421 if select
>= 0 and select
< nb
.GetPageCount():
1422 nb
.SetSelection(select
)
1424 #---------------------------------------------
1425 def SetOverview(self
, name
, text
):
1426 self
.curOverview
= text
1428 if lead
!= '<html>' and lead
!= '<HTML>':
1429 text
= '<br>'.join(text
.split('\n'))
1431 text
= text
.decode('iso8859_1')
1432 self
.ovr
.SetPage(text
)
1433 self
.nb
.SetPageText(0, name
)
1435 #---------------------------------------------
1437 def OnFileExit(self
, *event
):
1440 def OnToggleRedirect(self
, event
):
1444 print "Print statements and other standard output will now be directed to this window."
1447 print "Print statements and other standard output will now be sent to the usual location."
1449 def OnHelpAbout(self
, event
):
1450 from About
import MyAboutBox
1451 about
= MyAboutBox(self
)
1455 def OnHelpFind(self
, event
):
1456 self
.nb
.SetSelection(1)
1457 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1461 self
.finddlg
.Show(True)
1463 def OnFind(self
, event
):
1464 editor
= self
.codePage
.editor
1465 self
.nb
.SetSelection(1)
1466 end
= editor
.GetLastPosition()
1467 textstring
= editor
.GetRange(0, end
).lower()
1468 start
= editor
.GetSelection()[1]
1469 findstring
= self
.finddata
.GetFindString().lower()
1470 loc
= textstring
.find(findstring
, start
)
1471 if loc
== -1 and start
!= 0:
1472 # string not found, start at beginning
1474 loc
= textstring
.find(findstring
, start
)
1476 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1477 'Find String Not Found in Demo File',
1478 wx
.OK | wx
.ICON_INFORMATION
)
1483 self
.finddlg
.SetFocus()
1486 self
.finddlg
.Destroy()
1487 editor
.ShowPosition(loc
)
1488 editor
.SetSelection(loc
, loc
+ len(findstring
))
1492 def OnFindNext(self
, event
):
1493 if self
.finddata
.GetFindString():
1496 self
.OnHelpFind(event
)
1498 def OnFindClose(self
, event
):
1499 event
.GetDialog().Destroy()
1502 def OnOpenShellWindow(self
, evt
):
1504 # if it already exists then just make sure it's visible
1510 # Make a PyShell window
1512 namespace
= { 'wx' : wx
,
1513 'app' : wx
.GetApp(),
1516 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1517 self
.shell
.SetSize((640,480))
1520 # Hook the close event of the main frame window so that we
1521 # close the shell at the same time if it still exists
1522 def CloseShell(evt
):
1526 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1529 #---------------------------------------------
1530 def OnCloseWindow(self
, event
):
1532 self
.demoPage
= None
1533 self
.codePage
= None
1534 self
.mainmenu
= None
1535 self
.tbicon
.Destroy()
1539 #---------------------------------------------
1540 def OnIdle(self
, event
):
1542 self
.otherWin
.Raise()
1543 self
.demoPage
= self
.otherWin
1544 self
.otherWin
= None
1547 #---------------------------------------------
1550 showTipText
= open(opj("data/showTips")).read()
1551 showTip
, index
= eval(showTipText
)
1553 showTip
, index
= (1, 0)
1555 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1557 showTip
= wx
.ShowTip(self
, tp
)
1558 index
= tp
.GetCurrentTip()
1559 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1562 #---------------------------------------------
1563 def OnDemoMenu(self
, event
):
1565 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1569 self
.tree
.SelectItem(selectedDemo
)
1570 self
.tree
.EnsureVisible(selectedDemo
)
1574 #---------------------------------------------
1575 def OnIconfiy(self
, evt
):
1576 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1579 #---------------------------------------------
1580 def OnMaximize(self
, evt
):
1581 wx
.LogMessage("OnMaximize")
1584 #---------------------------------------------
1585 def OnActivate(self
, evt
):
1586 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1589 #---------------------------------------------
1590 def OnAppActivate(self
, evt
):
1591 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1594 #---------------------------------------------------------------------------
1595 #---------------------------------------------------------------------------
1597 class MySplashScreen(wx
.SplashScreen
):
1599 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1600 wx
.SplashScreen
.__init
__(self
, bmp
,
1601 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1603 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1605 def OnClose(self
, evt
):
1607 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1609 evt
.Skip() # Make sure the default handler runs too...
1612 class MyApp(wx
.App
):
1615 Create and show the splash screen. It will then create and show
1616 the main frame when it is time to do so.
1620 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1622 # Normally when using a SplashScreen you would create it, show
1623 # it and then continue on with the applicaiton's
1624 # initialization, finally creating and showing the main
1625 # application window(s). In this case we have nothing else to
1626 # do so we'll delay showing the main frame until later (see
1627 # OnClose above) so the users can see the SplashScreen effect.
1628 splash
= MySplashScreen()
1635 #---------------------------------------------------------------------------
1639 demoPath
= os
.path
.dirname(__file__
)
1646 #---------------------------------------------------------------------------
1649 mainOverview
= """<html><body>
1652 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1653 language. It allows Python programmers to create programs with a
1654 robust, highly functional graphical user interface, simply and easily.
1655 It is implemented as a Python extension module (native code) that
1656 wraps the popular wxWindows cross platform GUI library, which is
1659 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1660 means that it is free for anyone to use and the source code is
1661 available for anyone to look at and modify. Or anyone can contribute
1662 fixes or enhancements to the project.
1664 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1665 same program will run on multiple platforms without modification.
1666 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1667 or unix-like systems, and Macintosh OS X. Since the language is
1668 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1671 <p> <b>This demo</b> is not only a collection of test cases for
1672 wxPython, but is also designed to help you learn about and how to use
1673 wxPython. Each sample is listed in the tree control on the left.
1674 When a sample is selected in the tree then a module is loaded and run
1675 (usually in a tab of this notebook,) and the source code of the module
1676 is loaded in another tab for you to browse and learn from.
1681 #----------------------------------------------------------------------------
1682 #----------------------------------------------------------------------------
1684 if __name__
== '__main__':
1688 #----------------------------------------------------------------------------