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', [
54 # managed windows == things with a (optional) caption you can close
55 ('Frames and Dialogs', [
78 # dialogs from libraries
81 'MultipleChoiceDialog',
82 'ScrolledMessageDialog',
86 ('Core Windows/Controls', [
122 ('Custom Controls', [
135 # controls coming from other libraries
136 ('More Windows/Controls', [
137 'ActiveX_FlashWindow',
138 'ActiveX_IEHtmlWindow',
140 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
153 'MaskedEditControls',
169 # How to lay out the controls in a frame/dialog
179 'XmlResourceHandler',
180 'XmlResourceSubclass',
184 ('Process and Events', [
191 ##'infoframe', # needs better explaination and some fixing
195 ('Clipboard and DnD', [
216 ##'DialogUnits', # needs more explainations
228 # need libs not coming with the demo
229 ('Samples using an external library', [
234 ('Check out the samples dir too', [
241 #---------------------------------------------------------------------------
242 # Show how to derive a custom wxLog class
244 class MyLog(wx
.PyLog
):
245 def __init__(self
, textCtrl
, logTime
=0):
246 wx
.PyLog
.__init
__(self
)
248 self
.logTime
= logTime
250 def DoLogString(self
, message
, timeStamp
):
252 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
255 self
.tc
.AppendText(message
+ '\n')
258 class MyTP(wx
.PyTipProvider
):
260 return "This is my tip"
263 #---------------------------------------------------------------------------
264 # A class to be used to display source code in the demo. Try using the
265 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
266 # if there is an error, such as the stc module not being present.
270 ##raise ImportError # for testing the alternate implementation
272 from StyledTextCtrl_2
import PythonSTC
274 class DemoCodeEditor(PythonSTC
):
275 def __init__(self
, parent
):
276 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
279 # Some methods to make it compatible with how the wxTextCtrl is used
280 def SetValue(self
, value
):
282 value
= value
.decode('iso8859_1')
284 self
.EmptyUndoBuffer()
287 def IsModified(self
):
288 return self
.GetModify()
293 def SetInsertionPoint(self
, pos
):
294 self
.SetCurrentPos(pos
)
297 def ShowPosition(self
, pos
):
298 line
= self
.LineFromPosition(pos
)
299 #self.EnsureVisible(line)
302 def GetLastPosition(self
):
303 return self
.GetLength()
305 def GetPositionFromLine(self
, line
):
306 return self
.PositionFromLine(line
)
308 def GetRange(self
, start
, end
):
309 return self
.GetTextRange(start
, end
)
311 def GetSelection(self
):
312 return self
.GetAnchor(), self
.GetCurrentPos()
314 def SetSelection(self
, start
, end
):
315 self
.SetSelectionStart(start
)
316 self
.SetSelectionEnd(end
)
318 def SelectLine(self
, line
):
319 start
= self
.PositionFromLine(line
)
320 end
= self
.GetLineEndPosition(line
)
321 self
.SetSelection(start
, end
)
323 def SetUpEditor(self
):
325 This method carries out the work of setting up the demo editor.
326 It's seperate so as not to clutter up the init code.
330 self
.SetLexer(stc
.STC_LEX_PYTHON
)
331 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
334 self
.SetProperty("fold", "1" )
336 # Highlight tab/space mixing (shouldn't be any)
337 self
.SetProperty("tab.timmy.whinge.level", "1")
339 # Set left and right margins
342 # Set up the numbers in the margin for margin #1
343 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
344 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
345 self
.SetMarginWidth(1, 40)
347 # Indentation and tab stuff
348 self
.SetIndent(4) # Proscribed indent size for wx
349 self
.SetIndentationGuides(True) # Show indent guides
350 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
351 self
.SetTabIndents(True) # Tab key indents
352 self
.SetTabWidth(4) # Proscribed tab size for wx
353 self
.SetUseTabs(False) # Use spaces rather than tabs, or
354 # TabTimmy will complain!
356 self
.SetViewWhiteSpace(False) # Don't view white space
358 # EOL: Since we are loading/saving ourselves, and the
359 # strings will always have \n's in them, set the STC to
360 # edit them that way.
361 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
362 self
.SetViewEOL(False)
364 # No right-edge mode indicator
365 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
367 # Setup a margin to hold fold markers
368 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
369 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
370 self
.SetMarginSensitive(2, True)
371 self
.SetMarginWidth(2, 12)
373 # and now set up the fold markers
374 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
375 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
376 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
377 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
378 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
379 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
380 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
382 # Global default style
383 if wx
.Platform
== '__WXMSW__':
384 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
385 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
387 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
388 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
390 # Clear styles and revert to default.
393 # Following style specs only indicate differences from default.
394 # The rest remains unchanged.
396 # Line numbers in margin
397 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
400 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
402 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
404 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
407 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
409 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
410 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
412 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
413 # Strings and characters
414 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
415 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
417 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
419 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
420 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
422 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
424 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
426 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
427 # Identifiers. I leave this as not bold because everything seems
428 # to be an identifier if it doesn't match the above criterae
429 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
432 self
.SetCaretForeground("BLUE")
433 # Selection background
434 self
.SetSelBackground(1, '#66CCFF')
436 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
437 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
439 def RegisterModifiedEvent(self
, eventHandler
):
440 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
444 class DemoCodeEditor(wx
.TextCtrl
):
445 def __init__(self
, parent
):
446 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
447 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
449 def RegisterModifiedEvent(self
, eventHandler
):
450 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
452 def SetReadOnly(self
, flag
):
453 self
.SetEditable(not flag
)
454 # NOTE: STC already has this method
457 return self
.GetValue()
459 def GetPositionFromLine(line
):
460 return self
.XYToPosition(0,line
)
462 def GotoLine(self
, line
):
463 pos
= self
.editor
.GetPositionFromLine(line
)
464 self
.editor
.SetInsertionPoint(pos
)
465 self
.editor
.ShowPosition(pos
)
467 def SelectLine(self
, line
):
468 start
= self
.GetPositionFromLine(line
)
469 end
= start
+ self
.GetLineLength(line
)
470 self
.SetSelection(start
, end
)
473 #---------------------------------------------------------------------------
474 # Constants for module versions
478 modDefault
= modOriginal
480 #---------------------------------------------------------------------------
482 class DemoCodePanel(wx
.Panel
):
483 """Panel for the 'Demo Code' tab"""
484 def __init__(self
, parent
, mainFrame
):
485 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
487 self
.mainFrame
= mainFrame
488 self
.editor
= DemoCodeEditor(self
)
489 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
491 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
492 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
493 self
.btnSave
.Enable(False)
494 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
495 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
497 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
498 modModified
: wx
.RadioButton(self
, -1, "Modified") }
500 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
501 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
502 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
503 for modID
, radioButton
in self
.radioButtons
.items():
504 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
505 radioButton
.modID
= modID
# makes it easier for the event handler
506 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
508 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
509 self
.controlBox
.Add(self
.btnRestore
, 0)
511 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
512 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
513 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
514 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
517 self
.SetSizer(self
.box
)
520 # Loads a demo from a DemoModules object
521 def LoadDemo(self
, demoModules
):
522 self
.demoModules
= demoModules
523 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
524 demoModules
.SetActive(modModified
)
526 demoModules
.SetActive(modOriginal
)
527 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
528 self
.ActiveModuleChanged()
531 def ActiveModuleChanged(self
):
532 self
.LoadDemoSource(self
.demoModules
.GetSource())
533 self
.UpdateControlState()
537 def LoadDemoSource(self
, source
):
539 self
.editor
.SetValue(source
)
541 self
.btnSave
.Enable(False)
544 def JumpToLine(self
, line
, highlight
=False):
545 self
.editor
.GotoLine(line
)
546 self
.editor
.SetFocus()
548 self
.editor
.SelectLine(line
)
551 def UpdateControlState(self
):
552 active
= self
.demoModules
.GetActiveID()
553 # Update the radio/restore buttons
554 for moduleID
in self
.radioButtons
:
555 btn
= self
.radioButtons
[moduleID
]
556 if moduleID
== active
:
561 if self
.demoModules
.Exists(moduleID
):
563 if moduleID
== modModified
:
564 self
.btnRestore
.Enable(True)
567 if moduleID
== modModified
:
568 self
.btnRestore
.Enable(False)
571 def OnRadioButton(self
, event
):
572 radioSelected
= event
.GetEventObject()
573 modSelected
= radioSelected
.modID
574 if modSelected
!= self
.demoModules
.GetActiveID():
575 busy
= wx
.BusyInfo("Reloading demo module...")
576 self
.demoModules
.SetActive(modSelected
)
577 self
.ActiveModuleChanged()
580 def ReloadDemo(self
):
581 if self
.demoModules
.name
!= __name__
:
582 self
.mainFrame
.RunModule()
585 def OnCodeModified(self
, event
):
586 self
.btnSave
.Enable(self
.editor
.IsModified())
589 def OnSave(self
, event
):
590 if self
.demoModules
.Exists(modModified
):
591 if self
.demoModules
.GetActiveID() == modOriginal
:
592 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
593 "Do you want to continue?"
594 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
595 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
596 result
= dlg
.ShowModal()
597 if result
== wx
.ID_NO
:
601 self
.demoModules
.SetActive(modModified
)
602 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
604 # Create the demo directory if one doesn't already exist
605 if not os
.path
.exists(GetModifiedDirectory()):
607 os
.makedirs(GetModifiedDirectory())
608 if not os
.path
.exists(GetModifiedDirectory()):
609 wx
.LogMessage("BUG: Created demo directory but it still doesn't exit")
612 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
615 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
618 f
= open(modifiedFilename
, "wt")
619 source
= self
.editor
.GetText()
625 busy
= wx
.BusyInfo("Reloading demo module...")
626 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
627 self
.ActiveModuleChanged()
630 def OnRestore(self
, event
): # Handles the "Delete Modified" button
631 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
632 self
.demoModules
.Delete(modModified
)
633 os
.unlink(modifiedFilename
) # Delete the modified copy
634 busy
= wx
.BusyInfo("Reloading demo module...")
635 self
.ActiveModuleChanged()
638 #---------------------------------------------------------------------------
641 """Convert paths to the platform-specific separator"""
642 str = apply(os
.path
.join
, tuple(path
.split('/')))
643 # HACK: on Linux, a leading / gets lost...
644 if path
.startswith('/'):
649 def GetModifiedDirectory():
651 Returns the directory where modified versions of the demo files
654 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
657 def GetModifiedFilename(name
):
659 Returns the filename of the modified version of the specified demo
661 if not name
.endswith(".py"):
663 return GetModifiedDirectory() + name
666 def GetOriginalFilename(name
):
668 Returns the filename of the original version of the specified demo
670 if not name
.endswith(".py"):
675 def DoesModifiedExist(name
):
676 """Returns whether the specified demo has a modified copy"""
677 if os
.path
.exists(GetModifiedFilename(name
)):
683 #---------------------------------------------------------------------------
685 class ModuleDictWrapper
:
686 """Emulates a module with a dynamically compiled __dict__"""
687 def __init__(self
, dict):
690 def __getattr__(self
, name
):
691 if name
in self
.dict:
692 return self
.dict[name
]
698 Dynamically manages the original/modified versions of a demo
701 def __init__(self
, name
):
705 # (dict , source , filename , description , error information )
706 # ( 0 , 1 , 2 , 3 , 4 )
707 self
.modules
= [[None, "" , "" , "<original>" , None],
708 [None, "" , "" , "<modified>" , None]]
710 # load original module
711 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
712 self
.SetActive(modOriginal
)
714 # load modified module (if one exists)
715 if DoesModifiedExist(name
):
716 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
719 def LoadFromFile(self
, modID
, filename
):
720 self
.modules
[modID
][2] = filename
721 file = open(filename
, "rt")
722 self
.LoadFromSource(modID
, file.read())
726 def LoadFromSource(self
, modID
, source
):
727 self
.modules
[modID
][1] = source
731 def LoadDict(self
, modID
):
732 if self
.name
!= __name__
:
733 source
= self
.modules
[modID
][1]
734 description
= self
.modules
[modID
][3]
737 self
.modules
[modID
][0] = {}
738 code
= compile(source
, description
, "exec")
739 exec code
in self
.modules
[modID
][0]
741 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
742 self
.modules
[modID
][0] = None
744 self
.modules
[modID
][4] = None
747 def SetActive(self
, modID
):
748 if modID
!= modOriginal
and modID
!= modModified
:
751 self
.modActive
= modID
755 dict = self
.modules
[self
.modActive
][0]
759 return ModuleDictWrapper(dict)
762 def GetActiveID(self
):
763 return self
.modActive
766 def GetSource(self
, modID
= None):
768 modID
= self
.modActive
769 return self
.modules
[modID
][1]
772 def GetFilename(self
, modID
= None):
774 modID
= self
.modActive
775 return self
.modules
[self
.modActive
][2]
778 def GetErrorInfo(self
, modID
= None):
780 modID
= self
.modActive
781 return self
.modules
[self
.modActive
][4]
784 def Exists(self
, modID
):
785 return self
.modules
[modID
][1] != ""
788 def UpdateFile(self
, modID
= None):
789 """Updates the file from which a module was loaded
790 with (possibly updated) source"""
792 modID
= self
.modActive
794 source
= self
.modules
[modID
][1]
795 filename
= self
.modules
[modID
][2]
798 file = open(filename
, "wt")
804 def Delete(self
, modID
):
805 if self
.modActive
== modID
:
808 self
.modules
[modID
][0] = None
809 self
.modules
[modID
][1] = ""
810 self
.modules
[modID
][2] = ""
813 #---------------------------------------------------------------------------
816 """Wraps and stores information about the current exception"""
817 def __init__(self
, exc_info
):
820 excType
, excValue
= exc_info
[:2]
821 # traceback list entries: (filename, line number, function name, text)
822 self
.traceback
= traceback
.extract_tb(exc_info
[2])
824 # --Based on traceback.py::format_exception_only()--
825 if type(excType
) == types
.ClassType
:
826 self
.exception_type
= excType
.__name
__
828 self
.exception_type
= excType
830 # If it's a syntax error, extra information needs
831 # to be added to the traceback
832 if excType
is SyntaxError:
834 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
839 filename
= "<string>"
841 self
.traceback
.append( (filename
, lineno
, "", line
) )
844 self
.exception_details
= str(excValue
)
846 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
853 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
856 #---------------------------------------------------------------------------
858 class DemoErrorPanel(wx
.Panel
):
859 """Panel put into the demo tab when the demo fails to run due to errors"""
861 def __init__(self
, parent
, codePanel
, demoError
, log
):
862 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
863 self
.codePanel
= codePanel
867 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
870 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
871 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
873 # Exception Information
874 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
875 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
876 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
877 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
878 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
879 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
880 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
881 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
882 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
883 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
885 # Set up the traceback list
886 # This one automatically resizes last column to take up remaining space
887 from ListCtrl
import TestListCtrl
888 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
889 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
890 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
891 self
.list.InsertColumn(0, "Filename")
892 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
893 self
.list.InsertColumn(2, "Function")
894 self
.list.InsertColumn(3, "Code")
895 self
.InsertTraceback(self
.list, demoError
.traceback
)
896 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
897 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
898 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
899 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
900 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
901 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
902 + "Double-click on them to go to the offending line")
903 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
906 self
.SetSizer(self
.box
)
909 def InsertTraceback(self
, list, traceback
):
910 #Add the traceback data
911 for x
in range(len(traceback
)):
913 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
914 list.SetStringItem(x
, 1, str(data
[1])) # Line
915 list.SetStringItem(x
, 2, str(data
[2])) # Function
916 list.SetStringItem(x
, 3, str(data
[3])) # Code
918 # Check whether this entry is from the demo module
919 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
920 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
921 # Give it a blue colour
922 item
= self
.list.GetItem(x
)
923 item
.SetTextColour(wx
.BLUE
)
924 self
.list.SetItem(item
)
926 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
929 def OnItemSelected(self
, event
):
930 # This occurs before OnDoubleClick and can be used to set the
931 # currentItem. OnDoubleClick doesn't get a wxListEvent....
932 self
.currentItem
= event
.m_itemIndex
936 def OnDoubleClick(self
, event
):
937 # If double-clicking on a demo's entry, jump to the line number
938 line
= self
.list.GetItemData(self
.currentItem
)
940 self
.nb
.SetSelection(1) # Switch to the code viewer tab
941 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
945 #---------------------------------------------------------------------------
947 class wxPythonDemo(wx
.Frame
):
948 overviewText
= "wxPython Overview"
950 def __init__(self
, parent
, title
):
951 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
952 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
955 self
.cwd
= os
.getcwd()
956 self
.curOverview
= ""
960 self
.firstTime
= True
962 icon
= images
.getMondrianIcon()
965 if wx
.Platform
!= '__WXMAC__':
966 # setup a taskbar icon, and catch some events from it
967 dim
= 16 # (may want to use 22 on wxGTK, but 16 looks okay too)
968 icon
= wx
.IconFromBitmap(
969 images
.getMondrianImage().Scale(dim
,dim
).ConvertToBitmap() )
970 #icon = wx.Icon('bmp_source/mondrian.ico', wx.BITMAP_TYPE_ICO)
971 #icon = images.getMondrianIcon()
972 self
.tbicon
= wx
.TaskBarIcon()
973 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
974 self
.tbicon
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
975 self
.tbicon
.Bind(wx
.EVT_TASKBAR_RIGHT_UP
, self
.OnTaskBarMenu
)
976 self
.tbicon
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
977 self
.tbicon
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
979 wx
.CallAfter(self
.ShowTip
)
982 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
983 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
984 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
985 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
988 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
990 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
991 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
993 def EmptyHandler(evt
): pass
994 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
995 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
997 # Prevent TreeCtrl from displaying all items after destruction when True
1001 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1004 self
.mainmenu
= wx
.MenuBar()
1006 item
= menu
.Append(-1, '&Redirect Output',
1007 'Redirect print statements to a window',
1009 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1011 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1012 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1013 wx
.App_SetMacExitMenuItemId(item
.GetId())
1014 self
.mainmenu
.Append(menu
, '&File')
1018 for item
in _treeList
:
1020 for childItem
in item
[1]:
1021 mi
= submenu
.Append(-1, childItem
)
1022 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1023 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1024 self
.mainmenu
.Append(menu
, '&Demo')
1026 # Make a Demo Code menu
1027 #TODO: Add new menu items
1028 # Like the option-enabled entries to select the
1030 #TODO: should we bother?
1033 #saveID = wx.NewId()
1034 #restoreID = wx.NewId()
1036 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1037 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1038 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1039 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1040 #self.mainmenu.Append(menu, 'Demo &Code')
1045 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1046 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1047 menu
.AppendSeparator()
1049 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1050 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1051 menu
.AppendSeparator()
1052 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1053 wx
.App_SetMacAboutMenuItemId(helpItem
.GetId())
1055 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1056 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1057 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1058 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1059 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1060 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1061 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1062 self
.mainmenu
.Append(menu
, '&Help')
1063 self
.SetMenuBar(self
.mainmenu
)
1065 self
.finddata
= wx
.FindReplaceData()
1068 # This is another way to set Accelerators, in addition to
1069 # using the '\t<key>' syntax in the menu items.
1070 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1071 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1072 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1073 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1075 self
.SetAcceleratorTable(aTable
)
1081 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1082 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1085 root
= self
.tree
.AddRoot("wxPython Overview")
1087 for item
in _treeList
:
1088 child
= self
.tree
.AppendItem(root
, item
[0])
1089 if not firstChild
: firstChild
= child
1090 for childItem
in item
[1]:
1091 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1092 self
.treeMap
[childItem
] = theDemo
1094 self
.tree
.Expand(root
)
1095 self
.tree
.Expand(firstChild
)
1096 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1097 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1098 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1099 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1101 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1102 # we put it in a panel first because there seems to be a
1103 # refresh bug of some sort (wxGTK) when it is directly in
1106 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1107 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1109 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1110 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1111 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1112 self
.nb
.AddPage(panel
, self
.overviewText
)
1114 def OnOvrSize(evt
, ovr
=self
.ovr
):
1115 ovr
.SetSize(evt
.GetSize())
1116 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1117 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1119 if "gtk2" in wx
.PlatformInfo
:
1120 self
.ovr
.NormalizeFontSizes()
1121 self
.SetOverview(self
.overviewText
, mainOverview
)
1124 # Set up a log window
1125 self
.log
= wx
.TextCtrl(splitter2
, -1,
1126 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1128 # Set the wxWindows log target to be this textctrl
1129 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1131 # But instead of the above we want to show how to use our own wx.Log class
1132 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1134 # for serious debugging
1135 #wx.Log_SetActiveTarget(wx.LogStderr())
1136 #wx.Log_SetTraceMask(wx.TraceMessages)
1139 # add the windows to the splitter and split it.
1140 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1141 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1143 splitter
.SetMinimumPaneSize(20)
1144 splitter2
.SetMinimumPaneSize(20)
1146 # Make the splitter on the right expand the top window when resized
1147 def SplitterOnSize(evt
):
1148 splitter
= evt
.GetEventObject()
1149 sz
= splitter
.GetSize()
1150 splitter
.SetSashPosition(sz
.height
- 160, False)
1153 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1155 # select initial items
1156 self
.nb
.SetSelection(0)
1157 self
.tree
.SelectItem(root
)
1159 # Load 'Main' module
1160 self
.LoadDemo(self
.overviewText
)
1163 # select some other initial module?
1164 if len(sys
.argv
) > 1:
1166 if arg
.endswith('.py'):
1168 selectedDemo
= self
.treeMap
.get(arg
, None)
1170 self
.tree
.SelectItem(selectedDemo
)
1171 self
.tree
.EnsureVisible(selectedDemo
)
1174 #---------------------------------------------
1175 def WriteText(self
, text
):
1176 if text
[-1:] == '\n':
1180 def write(self
, txt
):
1183 #---------------------------------------------
1184 def OnItemExpanded(self
, event
):
1185 item
= event
.GetItem()
1186 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1189 #---------------------------------------------
1190 def OnItemCollapsed(self
, event
):
1191 item
= event
.GetItem()
1192 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1195 #---------------------------------------------
1196 def OnTreeLeftDown(self
, event
):
1197 # reset the overview text if the tree item is clicked on again
1198 pt
= event
.GetPosition();
1199 item
, flags
= self
.tree
.HitTest(pt
)
1200 if item
== self
.tree
.GetSelection():
1201 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1204 #---------------------------------------------
1205 def OnSelChanged(self
, event
):
1206 if self
.dying
or not self
.loaded
:
1209 item
= event
.GetItem()
1210 itemText
= self
.tree
.GetItemText(item
)
1211 self
.LoadDemo(itemText
)
1213 #---------------------------------------------
1214 def LoadDemo(self
, demoName
):
1216 wx
.BeginBusyCursor()
1219 self
.ShutdownDemoModule()
1221 if demoName
== self
.overviewText
:
1222 # User selected the "wxPython Overview" node
1224 # Changing the main window at runtime not yet supported...
1225 self
.demoModules
= DemoModules(__name__
)
1226 self
.SetOverview(self
.overviewText
, mainOverview
)
1227 self
.LoadDemoSource()
1228 self
.UpdateNotebook(0)
1230 if os
.path
.exists(GetOriginalFilename(demoName
)):
1231 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1232 self
.demoModules
= DemoModules(demoName
)
1233 self
.LoadDemoSource()
1236 self
.SetOverview("wxPython", mainOverview
)
1237 self
.codePage
= None
1238 self
.UpdateNotebook(0)
1242 #---------------------------------------------
1243 def LoadDemoSource(self
):
1244 self
.codePage
= None
1245 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1246 self
.codePage
.LoadDemo(self
.demoModules
)
1248 #---------------------------------------------
1249 def RunModule(self
):
1250 """Runs the active module"""
1252 module
= self
.demoModules
.GetActive()
1253 self
.ShutdownDemoModule()
1256 # o If the demo returns a window it is placed in a tab.
1257 # o Otherwise, a placeholder tab is created, informing the user that the
1258 # demo runs outside the main window, and allowing it to be reloaded.
1259 # o If an error occurs (or has occured before) an error tab is created.
1261 if module
is not None:
1262 wx
.LogMessage("Running demo module...")
1263 if hasattr(module
, "overview"):
1264 overviewText
= module
.overview
1267 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1269 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1270 DemoError(sys
.exc_info()), self
)
1272 assert self
.demoPage
is not None, "runTest must return a window!"
1275 # There was a previous error in compiling or exec-ing
1276 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1277 self
.demoModules
.GetErrorInfo(), self
)
1279 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1282 # cahnge to the demo page the first time a module is run
1283 self
.UpdateNotebook(2)
1284 self
.firstTime
= False
1286 # otherwise just stay on the same tab in case the user has changed to another one
1287 self
.UpdateNotebook()
1289 #---------------------------------------------
1290 def ShutdownDemoModule(self
):
1292 # inform the window that it's time to quit if it cares
1293 if hasattr(self
.demoPage
, "ShutdownDemo"):
1294 self
.demoPage
.ShutdownDemo()
1295 wx
.YieldIfNeeded() # in case the page has pending events
1296 self
.demoPage
= None
1298 #---------------------------------------------
1299 def UpdateNotebook(self
, select
= -1):
1303 def UpdatePage(page
, pageText
):
1306 for i
in range(nb
.GetPageCount()):
1307 if nb
.GetPageText(i
) == pageText
:
1315 nb
.AddPage(page
, pageText
)
1316 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1318 if nb
.GetPage(pagePos
) != page
:
1319 # Reload an existing page
1321 nb
.DeletePage(pagePos
)
1322 nb
.InsertPage(pagePos
, page
, pageText
)
1324 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1326 # Excellent! No redraw/flicker
1327 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1330 nb
.DeletePage(pagePos
)
1331 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1333 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1336 select
= nb
.GetSelection()
1338 UpdatePage(self
.codePage
, "Demo Code")
1339 UpdatePage(self
.demoPage
, "Demo")
1341 if select
>= 0 and select
< nb
.GetPageCount():
1342 nb
.SetSelection(select
)
1344 #---------------------------------------------
1345 def SetOverview(self
, name
, text
):
1346 self
.curOverview
= text
1348 if lead
!= '<html>' and lead
!= '<HTML>':
1349 text
= '<br>'.join(text
.split('\n'))
1351 text
= text
.decode('iso8859_1')
1352 self
.ovr
.SetPage(text
)
1353 self
.nb
.SetPageText(0, name
)
1355 #---------------------------------------------
1357 def OnFileExit(self
, *event
):
1360 def OnToggleRedirect(self
, event
):
1364 print "Print statements and other standard output will now be directed to this window."
1367 print "Print statements and other standard output will now be sent to the usual location."
1369 def OnHelpAbout(self
, event
):
1370 from About
import MyAboutBox
1371 about
= MyAboutBox(self
)
1375 def OnHelpFind(self
, event
):
1376 self
.nb
.SetSelection(1)
1377 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1381 self
.finddlg
.Show(True)
1383 def OnFind(self
, event
):
1384 editor
= self
.codePage
.editor
1385 self
.nb
.SetSelection(1)
1386 end
= editor
.GetLastPosition()
1387 textstring
= editor
.GetRange(0, end
).lower()
1388 start
= editor
.GetSelection()[1]
1389 findstring
= self
.finddata
.GetFindString().lower()
1390 loc
= textstring
.find(findstring
, start
)
1391 if loc
== -1 and start
!= 0:
1392 # string not found, start at beginning
1394 loc
= textstring
.find(findstring
, start
)
1396 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1397 'Find String Not Found in Demo File',
1398 wx
.OK | wx
.ICON_INFORMATION
)
1403 self
.finddlg
.SetFocus()
1406 self
.finddlg
.Destroy()
1407 editor
.ShowPosition(loc
)
1408 editor
.SetSelection(loc
, loc
+ len(findstring
))
1412 def OnFindNext(self
, event
):
1413 if self
.finddata
.GetFindString():
1416 self
.OnHelpFind(event
)
1418 def OnFindClose(self
, event
):
1419 event
.GetDialog().Destroy()
1422 def OnOpenShellWindow(self
, evt
):
1424 # if it already exists then just make sure it's visible
1430 # Make a PyShell window
1432 namespace
= { 'wx' : wx
,
1433 'app' : wx
.GetApp(),
1436 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1437 self
.shell
.SetSize((640,480))
1440 # Hook the close event of the main frame window so that we
1441 # close the shell at the same time if it still exists
1442 def CloseShell(evt
):
1446 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1449 #---------------------------------------------
1450 def OnCloseWindow(self
, event
):
1452 self
.demoPage
= None
1453 self
.codePage
= None
1454 self
.mainmenu
= None
1458 #---------------------------------------------
1459 def OnIdle(self
, event
):
1461 self
.otherWin
.Raise()
1462 self
.demoPage
= self
.otherWin
1463 self
.otherWin
= None
1466 #---------------------------------------------
1469 showTipText
= open(opj("data/showTips")).read()
1470 showTip
, index
= eval(showTipText
)
1472 showTip
, index
= (1, 0)
1474 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1476 showTip
= wx
.ShowTip(self
, tp
)
1477 index
= tp
.GetCurrentTip()
1478 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1481 #---------------------------------------------
1482 def OnDemoMenu(self
, event
):
1484 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1488 self
.tree
.SelectItem(selectedDemo
)
1489 self
.tree
.EnsureVisible(selectedDemo
)
1492 #---------------------------------------------
1493 def OnTaskBarActivate(self
, evt
):
1494 if self
.IsIconized():
1496 if not self
.IsShown():
1500 #---------------------------------------------
1502 TBMENU_RESTORE
= 1000
1505 def OnTaskBarMenu(self
, evt
):
1507 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1508 menu
.Append(self
.TBMENU_CLOSE
, "Close")
1509 self
.tbicon
.PopupMenu(menu
)
1512 #---------------------------------------------
1513 def OnTaskBarClose(self
, evt
):
1516 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
1517 # prod the main idle handler a bit to get the window to actually close
1518 wx
.GetApp().ProcessIdle()
1521 #---------------------------------------------
1522 def OnIconfiy(self
, evt
):
1523 wx
.LogMessage("OnIconfiy: %d" % evt
.Iconized())
1526 #---------------------------------------------
1527 def OnMaximize(self
, evt
):
1528 wx
.LogMessage("OnMaximize")
1534 #---------------------------------------------------------------------------
1535 #---------------------------------------------------------------------------
1537 class MySplashScreen(wx
.SplashScreen
):
1539 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1540 wx
.SplashScreen
.__init
__(self
, bmp
,
1541 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1543 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1545 def OnClose(self
, evt
):
1547 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1549 evt
.Skip() # Make sure the default handler runs too...
1552 class MyApp(wx
.App
):
1555 Create and show the splash screen. It will then create and show
1556 the main frame when it is time to do so.
1560 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1562 # Normally when using a SplashScreen you would create it, show
1563 # it and then continue on with the applicaiton's
1564 # initialization, finally creating and showing the main
1565 # application window(s). In this case we have nothing else to
1566 # do so we'll delay showing the main frame until later (see
1567 # OnClose above) so the users can see the SplashScreen effect.
1568 splash
= MySplashScreen()
1575 #---------------------------------------------------------------------------
1579 demoPath
= os
.path
.dirname(__file__
)
1586 #---------------------------------------------------------------------------
1589 mainOverview
= """<html><body>
1592 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1593 language. It allows Python programmers to create programs with a
1594 robust, highly functional graphical user interface, simply and easily.
1595 It is implemented as a Python extension module (native code) that
1596 wraps the popular wxWindows cross platform GUI library, which is
1599 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1600 means that it is free for anyone to use and the source code is
1601 available for anyone to look at and modify. Or anyone can contribute
1602 fixes or enhancements to the project.
1604 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1605 same program will run on multiple platforms without modification.
1606 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1607 or unix-like systems, and Macintosh OS X. Since the language is
1608 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1611 <p> <b>This demo</b> is not only a collection of test cases for
1612 wxPython, but is also designed to help you learn about and how to use
1613 wxPython. Each sample is listed in the tree control on the left.
1614 When a sample is selected in the tree then a module is loaded and run
1615 (usually in a tab of this notebook,) and the source code of the module
1616 is loaded in another tab for you to browse and learn from.
1621 #----------------------------------------------------------------------------
1622 #----------------------------------------------------------------------------
1624 if __name__
== '__main__':
1628 #----------------------------------------------------------------------------