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', [
123 ('Custom Controls', [
136 # controls coming from other libraries
137 ('More Windows/Controls', [
138 'ActiveX_FlashWindow',
139 'ActiveX_IEHtmlWindow',
141 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
154 'MaskedEditControls',
171 # How to lay out the controls in a frame/dialog
181 'XmlResourceHandler',
182 'XmlResourceSubclass',
186 ('Process and Events', [
193 ##'infoframe', # needs better explaination and some fixing
197 ('Clipboard and DnD', [
218 ##'DialogUnits', # needs more explainations
230 # need libs not coming with the demo
231 ('Samples using an external library', [
236 ('Check out the samples dir too', [
243 #---------------------------------------------------------------------------
244 # Show how to derive a custom wxLog class
246 class MyLog(wx
.PyLog
):
247 def __init__(self
, textCtrl
, logTime
=0):
248 wx
.PyLog
.__init
__(self
)
250 self
.logTime
= logTime
252 def DoLogString(self
, message
, timeStamp
):
254 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
257 self
.tc
.AppendText(message
+ '\n')
260 class MyTP(wx
.PyTipProvider
):
262 return "This is my tip"
265 #---------------------------------------------------------------------------
266 # A class to be used to display source code in the demo. Try using the
267 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
268 # if there is an error, such as the stc module not being present.
272 ##raise ImportError # for testing the alternate implementation
274 from StyledTextCtrl_2
import PythonSTC
276 class DemoCodeEditor(PythonSTC
):
277 def __init__(self
, parent
):
278 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
281 # Some methods to make it compatible with how the wxTextCtrl is used
282 def SetValue(self
, value
):
284 value
= value
.decode('iso8859_1')
286 self
.EmptyUndoBuffer()
289 def IsModified(self
):
290 return self
.GetModify()
295 def SetInsertionPoint(self
, pos
):
296 self
.SetCurrentPos(pos
)
299 def ShowPosition(self
, pos
):
300 line
= self
.LineFromPosition(pos
)
301 #self.EnsureVisible(line)
304 def GetLastPosition(self
):
305 return self
.GetLength()
307 def GetPositionFromLine(self
, line
):
308 return self
.PositionFromLine(line
)
310 def GetRange(self
, start
, end
):
311 return self
.GetTextRange(start
, end
)
313 def GetSelection(self
):
314 return self
.GetAnchor(), self
.GetCurrentPos()
316 def SetSelection(self
, start
, end
):
317 self
.SetSelectionStart(start
)
318 self
.SetSelectionEnd(end
)
320 def SelectLine(self
, line
):
321 start
= self
.PositionFromLine(line
)
322 end
= self
.GetLineEndPosition(line
)
323 self
.SetSelection(start
, end
)
325 def SetUpEditor(self
):
327 This method carries out the work of setting up the demo editor.
328 It's seperate so as not to clutter up the init code.
332 self
.SetLexer(stc
.STC_LEX_PYTHON
)
333 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
336 self
.SetProperty("fold", "1" )
338 # Highlight tab/space mixing (shouldn't be any)
339 self
.SetProperty("tab.timmy.whinge.level", "1")
341 # Set left and right margins
344 # Set up the numbers in the margin for margin #1
345 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
346 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
347 self
.SetMarginWidth(1, 40)
349 # Indentation and tab stuff
350 self
.SetIndent(4) # Proscribed indent size for wx
351 self
.SetIndentationGuides(True) # Show indent guides
352 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
353 self
.SetTabIndents(True) # Tab key indents
354 self
.SetTabWidth(4) # Proscribed tab size for wx
355 self
.SetUseTabs(False) # Use spaces rather than tabs, or
356 # TabTimmy will complain!
358 self
.SetViewWhiteSpace(False) # Don't view white space
360 # EOL: Since we are loading/saving ourselves, and the
361 # strings will always have \n's in them, set the STC to
362 # edit them that way.
363 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
364 self
.SetViewEOL(False)
366 # No right-edge mode indicator
367 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
369 # Setup a margin to hold fold markers
370 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
371 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
372 self
.SetMarginSensitive(2, True)
373 self
.SetMarginWidth(2, 12)
375 # and now set up the fold markers
376 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
377 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
378 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
379 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
380 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
381 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
382 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
384 # Global default style
385 if wx
.Platform
== '__WXMSW__':
386 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
387 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
389 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
390 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
392 # Clear styles and revert to default.
395 # Following style specs only indicate differences from default.
396 # The rest remains unchanged.
398 # Line numbers in margin
399 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
402 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
404 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
406 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
409 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
411 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
412 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
414 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
415 # Strings and characters
416 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
417 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
419 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
421 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
422 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
424 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
426 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
428 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
429 # Identifiers. I leave this as not bold because everything seems
430 # to be an identifier if it doesn't match the above criterae
431 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
434 self
.SetCaretForeground("BLUE")
435 # Selection background
436 self
.SetSelBackground(1, '#66CCFF')
438 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
439 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
441 def RegisterModifiedEvent(self
, eventHandler
):
442 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
446 class DemoCodeEditor(wx
.TextCtrl
):
447 def __init__(self
, parent
):
448 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
449 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
451 def RegisterModifiedEvent(self
, eventHandler
):
452 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
454 def SetReadOnly(self
, flag
):
455 self
.SetEditable(not flag
)
456 # NOTE: STC already has this method
459 return self
.GetValue()
461 def GetPositionFromLine(line
):
462 return self
.XYToPosition(0,line
)
464 def GotoLine(self
, line
):
465 pos
= self
.editor
.GetPositionFromLine(line
)
466 self
.editor
.SetInsertionPoint(pos
)
467 self
.editor
.ShowPosition(pos
)
469 def SelectLine(self
, line
):
470 start
= self
.GetPositionFromLine(line
)
471 end
= start
+ self
.GetLineLength(line
)
472 self
.SetSelection(start
, end
)
475 #---------------------------------------------------------------------------
476 # Constants for module versions
480 modDefault
= modOriginal
482 #---------------------------------------------------------------------------
484 class DemoCodePanel(wx
.Panel
):
485 """Panel for the 'Demo Code' tab"""
486 def __init__(self
, parent
, mainFrame
):
487 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
488 if 'wxMSW' in wx
.PlatformInfo
:
490 self
.mainFrame
= mainFrame
491 self
.editor
= DemoCodeEditor(self
)
492 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
494 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
495 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
496 self
.btnSave
.Enable(False)
497 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
498 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
500 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
501 modModified
: wx
.RadioButton(self
, -1, "Modified") }
503 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
504 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
505 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
506 for modID
, radioButton
in self
.radioButtons
.items():
507 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
508 radioButton
.modID
= modID
# makes it easier for the event handler
509 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
511 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
512 self
.controlBox
.Add(self
.btnRestore
, 0)
514 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
515 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
516 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
517 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
520 self
.SetSizer(self
.box
)
523 # Loads a demo from a DemoModules object
524 def LoadDemo(self
, demoModules
):
525 self
.demoModules
= demoModules
526 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
527 demoModules
.SetActive(modModified
)
529 demoModules
.SetActive(modOriginal
)
530 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
531 self
.ActiveModuleChanged()
534 def ActiveModuleChanged(self
):
535 self
.LoadDemoSource(self
.demoModules
.GetSource())
536 self
.UpdateControlState()
540 def LoadDemoSource(self
, source
):
542 self
.editor
.SetValue(source
)
544 self
.btnSave
.Enable(False)
547 def JumpToLine(self
, line
, highlight
=False):
548 self
.editor
.GotoLine(line
)
549 self
.editor
.SetFocus()
551 self
.editor
.SelectLine(line
)
554 def UpdateControlState(self
):
555 active
= self
.demoModules
.GetActiveID()
556 # Update the radio/restore buttons
557 for moduleID
in self
.radioButtons
:
558 btn
= self
.radioButtons
[moduleID
]
559 if moduleID
== active
:
564 if self
.demoModules
.Exists(moduleID
):
566 if moduleID
== modModified
:
567 self
.btnRestore
.Enable(True)
570 if moduleID
== modModified
:
571 self
.btnRestore
.Enable(False)
574 def OnRadioButton(self
, event
):
575 radioSelected
= event
.GetEventObject()
576 modSelected
= radioSelected
.modID
577 if modSelected
!= self
.demoModules
.GetActiveID():
578 busy
= wx
.BusyInfo("Reloading demo module...")
579 self
.demoModules
.SetActive(modSelected
)
580 self
.ActiveModuleChanged()
583 def ReloadDemo(self
):
584 if self
.demoModules
.name
!= __name__
:
585 self
.mainFrame
.RunModule()
588 def OnCodeModified(self
, event
):
589 self
.btnSave
.Enable(self
.editor
.IsModified())
592 def OnSave(self
, event
):
593 if self
.demoModules
.Exists(modModified
):
594 if self
.demoModules
.GetActiveID() == modOriginal
:
595 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
596 "Do you want to continue?"
597 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
598 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
599 result
= dlg
.ShowModal()
600 if result
== wx
.ID_NO
:
604 self
.demoModules
.SetActive(modModified
)
605 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
607 # Create the demo directory if one doesn't already exist
608 if not os
.path
.exists(GetModifiedDirectory()):
610 os
.makedirs(GetModifiedDirectory())
611 if not os
.path
.exists(GetModifiedDirectory()):
612 wx
.LogMessage("BUG: Created demo directory but it still doesn't exit")
615 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
618 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
621 f
= open(modifiedFilename
, "wt")
622 source
= self
.editor
.GetText()
628 busy
= wx
.BusyInfo("Reloading demo module...")
629 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
630 self
.ActiveModuleChanged()
633 def OnRestore(self
, event
): # Handles the "Delete Modified" button
634 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
635 self
.demoModules
.Delete(modModified
)
636 os
.unlink(modifiedFilename
) # Delete the modified copy
637 busy
= wx
.BusyInfo("Reloading demo module...")
638 self
.ActiveModuleChanged()
641 #---------------------------------------------------------------------------
644 """Convert paths to the platform-specific separator"""
645 str = apply(os
.path
.join
, tuple(path
.split('/')))
646 # HACK: on Linux, a leading / gets lost...
647 if path
.startswith('/'):
652 def GetModifiedDirectory():
654 Returns the directory where modified versions of the demo files
657 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
660 def GetModifiedFilename(name
):
662 Returns the filename of the modified version of the specified demo
664 if not name
.endswith(".py"):
666 return GetModifiedDirectory() + name
669 def GetOriginalFilename(name
):
671 Returns the filename of the original version of the specified demo
673 if not name
.endswith(".py"):
678 def DoesModifiedExist(name
):
679 """Returns whether the specified demo has a modified copy"""
680 if os
.path
.exists(GetModifiedFilename(name
)):
686 #---------------------------------------------------------------------------
688 class ModuleDictWrapper
:
689 """Emulates a module with a dynamically compiled __dict__"""
690 def __init__(self
, dict):
693 def __getattr__(self
, name
):
694 if name
in self
.dict:
695 return self
.dict[name
]
701 Dynamically manages the original/modified versions of a demo
704 def __init__(self
, name
):
708 # (dict , source , filename , description , error information )
709 # ( 0 , 1 , 2 , 3 , 4 )
710 self
.modules
= [[None, "" , "" , "<original>" , None],
711 [None, "" , "" , "<modified>" , None]]
713 # load original module
714 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
715 self
.SetActive(modOriginal
)
717 # load modified module (if one exists)
718 if DoesModifiedExist(name
):
719 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
722 def LoadFromFile(self
, modID
, filename
):
723 self
.modules
[modID
][2] = filename
724 file = open(filename
, "rt")
725 self
.LoadFromSource(modID
, file.read())
729 def LoadFromSource(self
, modID
, source
):
730 self
.modules
[modID
][1] = source
734 def LoadDict(self
, modID
):
735 if self
.name
!= __name__
:
736 source
= self
.modules
[modID
][1]
737 description
= self
.modules
[modID
][3]
740 self
.modules
[modID
][0] = {}
741 code
= compile(source
, description
, "exec")
742 exec code
in self
.modules
[modID
][0]
744 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
745 self
.modules
[modID
][0] = None
747 self
.modules
[modID
][4] = None
750 def SetActive(self
, modID
):
751 if modID
!= modOriginal
and modID
!= modModified
:
754 self
.modActive
= modID
758 dict = self
.modules
[self
.modActive
][0]
762 return ModuleDictWrapper(dict)
765 def GetActiveID(self
):
766 return self
.modActive
769 def GetSource(self
, modID
= None):
771 modID
= self
.modActive
772 return self
.modules
[modID
][1]
775 def GetFilename(self
, modID
= None):
777 modID
= self
.modActive
778 return self
.modules
[self
.modActive
][2]
781 def GetErrorInfo(self
, modID
= None):
783 modID
= self
.modActive
784 return self
.modules
[self
.modActive
][4]
787 def Exists(self
, modID
):
788 return self
.modules
[modID
][1] != ""
791 def UpdateFile(self
, modID
= None):
792 """Updates the file from which a module was loaded
793 with (possibly updated) source"""
795 modID
= self
.modActive
797 source
= self
.modules
[modID
][1]
798 filename
= self
.modules
[modID
][2]
801 file = open(filename
, "wt")
807 def Delete(self
, modID
):
808 if self
.modActive
== modID
:
811 self
.modules
[modID
][0] = None
812 self
.modules
[modID
][1] = ""
813 self
.modules
[modID
][2] = ""
816 #---------------------------------------------------------------------------
819 """Wraps and stores information about the current exception"""
820 def __init__(self
, exc_info
):
823 excType
, excValue
= exc_info
[:2]
824 # traceback list entries: (filename, line number, function name, text)
825 self
.traceback
= traceback
.extract_tb(exc_info
[2])
827 # --Based on traceback.py::format_exception_only()--
828 if type(excType
) == types
.ClassType
:
829 self
.exception_type
= excType
.__name
__
831 self
.exception_type
= excType
833 # If it's a syntax error, extra information needs
834 # to be added to the traceback
835 if excType
is SyntaxError:
837 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
842 filename
= "<string>"
844 self
.traceback
.append( (filename
, lineno
, "", line
) )
847 self
.exception_details
= str(excValue
)
849 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
856 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
859 #---------------------------------------------------------------------------
861 class DemoErrorPanel(wx
.Panel
):
862 """Panel put into the demo tab when the demo fails to run due to errors"""
864 def __init__(self
, parent
, codePanel
, demoError
, log
):
865 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
866 self
.codePanel
= codePanel
870 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
873 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
874 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
876 # Exception Information
877 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
878 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
879 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
880 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
881 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
882 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
883 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
884 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
885 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
886 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
888 # Set up the traceback list
889 # This one automatically resizes last column to take up remaining space
890 from ListCtrl
import TestListCtrl
891 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
892 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
893 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
894 self
.list.InsertColumn(0, "Filename")
895 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
896 self
.list.InsertColumn(2, "Function")
897 self
.list.InsertColumn(3, "Code")
898 self
.InsertTraceback(self
.list, demoError
.traceback
)
899 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
900 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
901 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
902 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
903 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
904 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
905 + "Double-click on them to go to the offending line")
906 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
909 self
.SetSizer(self
.box
)
912 def InsertTraceback(self
, list, traceback
):
913 #Add the traceback data
914 for x
in range(len(traceback
)):
916 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
917 list.SetStringItem(x
, 1, str(data
[1])) # Line
918 list.SetStringItem(x
, 2, str(data
[2])) # Function
919 list.SetStringItem(x
, 3, str(data
[3])) # Code
921 # Check whether this entry is from the demo module
922 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
923 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
924 # Give it a blue colour
925 item
= self
.list.GetItem(x
)
926 item
.SetTextColour(wx
.BLUE
)
927 self
.list.SetItem(item
)
929 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
932 def OnItemSelected(self
, event
):
933 # This occurs before OnDoubleClick and can be used to set the
934 # currentItem. OnDoubleClick doesn't get a wxListEvent....
935 self
.currentItem
= event
.m_itemIndex
939 def OnDoubleClick(self
, event
):
940 # If double-clicking on a demo's entry, jump to the line number
941 line
= self
.list.GetItemData(self
.currentItem
)
943 self
.nb
.SetSelection(1) # Switch to the code viewer tab
944 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
948 #---------------------------------------------------------------------------
950 class wxPythonDemo(wx
.Frame
):
951 overviewText
= "wxPython Overview"
953 def __init__(self
, parent
, title
):
954 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
955 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
958 self
.cwd
= os
.getcwd()
959 self
.curOverview
= ""
963 self
.firstTime
= True
965 icon
= images
.getMondrianIcon()
968 if wx
.Platform
!= '__WXMAC__':
969 # setup a taskbar icon, and catch some events from it
970 dim
= 16 # (may want to use 22 on wxGTK, but 16 looks okay too)
971 icon
= wx
.IconFromBitmap(
972 images
.getMondrianImage().Scale(dim
,dim
).ConvertToBitmap() )
973 #icon = wx.Icon('bmp_source/mondrian.ico', wx.BITMAP_TYPE_ICO)
974 #icon = images.getMondrianIcon()
975 self
.tbicon
= wx
.TaskBarIcon()
976 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
977 self
.tbicon
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
978 self
.tbicon
.Bind(wx
.EVT_TASKBAR_RIGHT_UP
, self
.OnTaskBarMenu
)
979 self
.tbicon
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
980 self
.tbicon
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
982 wx
.CallAfter(self
.ShowTip
)
985 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
986 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
987 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
988 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
991 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
993 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
994 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
996 def EmptyHandler(evt
): pass
997 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
998 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1000 # Prevent TreeCtrl from displaying all items after destruction when True
1004 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1007 self
.mainmenu
= wx
.MenuBar()
1009 item
= menu
.Append(-1, '&Redirect Output',
1010 'Redirect print statements to a window',
1012 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1014 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1015 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1016 wx
.App_SetMacExitMenuItemId(item
.GetId())
1017 self
.mainmenu
.Append(menu
, '&File')
1021 for item
in _treeList
:
1023 for childItem
in item
[1]:
1024 mi
= submenu
.Append(-1, childItem
)
1025 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1026 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1027 self
.mainmenu
.Append(menu
, '&Demo')
1029 # Make a Demo Code menu
1030 #TODO: Add new menu items
1031 # Like the option-enabled entries to select the
1033 #TODO: should we bother?
1036 #saveID = wx.NewId()
1037 #restoreID = wx.NewId()
1039 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1040 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1041 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1042 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1043 #self.mainmenu.Append(menu, 'Demo &Code')
1048 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1049 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1050 menu
.AppendSeparator()
1052 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1053 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1054 menu
.AppendSeparator()
1055 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1056 wx
.App_SetMacAboutMenuItemId(helpItem
.GetId())
1058 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1059 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1060 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1061 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1062 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1063 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1064 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1065 self
.mainmenu
.Append(menu
, '&Help')
1066 self
.SetMenuBar(self
.mainmenu
)
1068 self
.finddata
= wx
.FindReplaceData()
1071 # This is another way to set Accelerators, in addition to
1072 # using the '\t<key>' syntax in the menu items.
1073 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1074 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1075 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1076 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1078 self
.SetAcceleratorTable(aTable
)
1084 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1085 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1088 root
= self
.tree
.AddRoot("wxPython Overview")
1090 for item
in _treeList
:
1091 child
= self
.tree
.AppendItem(root
, item
[0])
1092 if not firstChild
: firstChild
= child
1093 for childItem
in item
[1]:
1094 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1095 self
.treeMap
[childItem
] = theDemo
1097 self
.tree
.Expand(root
)
1098 self
.tree
.Expand(firstChild
)
1099 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1100 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1101 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1102 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1104 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1105 # we put it in a panel first because there seems to be a
1106 # refresh bug of some sort (wxGTK) when it is directly in
1109 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1110 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1112 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1113 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1114 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1115 self
.nb
.AddPage(panel
, self
.overviewText
)
1117 def OnOvrSize(evt
, ovr
=self
.ovr
):
1118 ovr
.SetSize(evt
.GetSize())
1119 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1120 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1122 if "gtk2" in wx
.PlatformInfo
:
1123 self
.ovr
.NormalizeFontSizes()
1124 self
.SetOverview(self
.overviewText
, mainOverview
)
1127 # Set up a log window
1128 self
.log
= wx
.TextCtrl(splitter2
, -1,
1129 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1131 # Set the wxWindows log target to be this textctrl
1132 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1134 # But instead of the above we want to show how to use our own wx.Log class
1135 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1137 # for serious debugging
1138 #wx.Log_SetActiveTarget(wx.LogStderr())
1139 #wx.Log_SetTraceMask(wx.TraceMessages)
1142 # add the windows to the splitter and split it.
1143 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1144 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1146 splitter
.SetMinimumPaneSize(20)
1147 splitter2
.SetMinimumPaneSize(20)
1149 # Make the splitter on the right expand the top window when resized
1150 def SplitterOnSize(evt
):
1151 splitter
= evt
.GetEventObject()
1152 sz
= splitter
.GetSize()
1153 splitter
.SetSashPosition(sz
.height
- 160, False)
1156 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1158 # select initial items
1159 self
.nb
.SetSelection(0)
1160 self
.tree
.SelectItem(root
)
1162 # Load 'Main' module
1163 self
.LoadDemo(self
.overviewText
)
1166 # select some other initial module?
1167 if len(sys
.argv
) > 1:
1169 if arg
.endswith('.py'):
1171 selectedDemo
= self
.treeMap
.get(arg
, None)
1173 self
.tree
.SelectItem(selectedDemo
)
1174 self
.tree
.EnsureVisible(selectedDemo
)
1177 #---------------------------------------------
1178 def WriteText(self
, text
):
1179 if text
[-1:] == '\n':
1183 def write(self
, txt
):
1186 #---------------------------------------------
1187 def OnItemExpanded(self
, event
):
1188 item
= event
.GetItem()
1189 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1192 #---------------------------------------------
1193 def OnItemCollapsed(self
, event
):
1194 item
= event
.GetItem()
1195 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1198 #---------------------------------------------
1199 def OnTreeLeftDown(self
, event
):
1200 # reset the overview text if the tree item is clicked on again
1201 pt
= event
.GetPosition();
1202 item
, flags
= self
.tree
.HitTest(pt
)
1203 if item
== self
.tree
.GetSelection():
1204 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1207 #---------------------------------------------
1208 def OnSelChanged(self
, event
):
1209 if self
.dying
or not self
.loaded
:
1212 item
= event
.GetItem()
1213 itemText
= self
.tree
.GetItemText(item
)
1214 self
.LoadDemo(itemText
)
1216 #---------------------------------------------
1217 def LoadDemo(self
, demoName
):
1219 wx
.BeginBusyCursor()
1222 self
.ShutdownDemoModule()
1224 if demoName
== self
.overviewText
:
1225 # User selected the "wxPython Overview" node
1227 # Changing the main window at runtime not yet supported...
1228 self
.demoModules
= DemoModules(__name__
)
1229 self
.SetOverview(self
.overviewText
, mainOverview
)
1230 self
.LoadDemoSource()
1231 self
.UpdateNotebook(0)
1233 if os
.path
.exists(GetOriginalFilename(demoName
)):
1234 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1235 self
.demoModules
= DemoModules(demoName
)
1236 self
.LoadDemoSource()
1239 self
.SetOverview("wxPython", mainOverview
)
1240 self
.codePage
= None
1241 self
.UpdateNotebook(0)
1245 #---------------------------------------------
1246 def LoadDemoSource(self
):
1247 self
.codePage
= None
1248 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1249 self
.codePage
.LoadDemo(self
.demoModules
)
1251 #---------------------------------------------
1252 def RunModule(self
):
1253 """Runs the active module"""
1255 module
= self
.demoModules
.GetActive()
1256 self
.ShutdownDemoModule()
1259 # o If the demo returns a window it is placed in a tab.
1260 # o Otherwise, a placeholder tab is created, informing the user that the
1261 # demo runs outside the main window, and allowing it to be reloaded.
1262 # o If an error occurs (or has occured before) an error tab is created.
1264 if module
is not None:
1265 wx
.LogMessage("Running demo module...")
1266 if hasattr(module
, "overview"):
1267 overviewText
= module
.overview
1270 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1272 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1273 DemoError(sys
.exc_info()), self
)
1275 assert self
.demoPage
is not None, "runTest must return a window!"
1278 # There was a previous error in compiling or exec-ing
1279 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1280 self
.demoModules
.GetErrorInfo(), self
)
1282 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1285 # cahnge to the demo page the first time a module is run
1286 self
.UpdateNotebook(2)
1287 self
.firstTime
= False
1289 # otherwise just stay on the same tab in case the user has changed to another one
1290 self
.UpdateNotebook()
1292 #---------------------------------------------
1293 def ShutdownDemoModule(self
):
1295 # inform the window that it's time to quit if it cares
1296 if hasattr(self
.demoPage
, "ShutdownDemo"):
1297 self
.demoPage
.ShutdownDemo()
1298 wx
.YieldIfNeeded() # in case the page has pending events
1299 self
.demoPage
= None
1301 #---------------------------------------------
1302 def UpdateNotebook(self
, select
= -1):
1306 def UpdatePage(page
, pageText
):
1309 for i
in range(nb
.GetPageCount()):
1310 if nb
.GetPageText(i
) == pageText
:
1318 nb
.AddPage(page
, pageText
)
1319 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1321 if nb
.GetPage(pagePos
) != page
:
1322 # Reload an existing page
1324 nb
.DeletePage(pagePos
)
1325 nb
.InsertPage(pagePos
, page
, pageText
)
1327 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1329 # Excellent! No redraw/flicker
1330 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1333 nb
.DeletePage(pagePos
)
1334 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1336 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1339 select
= nb
.GetSelection()
1341 UpdatePage(self
.codePage
, "Demo Code")
1342 UpdatePage(self
.demoPage
, "Demo")
1344 if select
>= 0 and select
< nb
.GetPageCount():
1345 nb
.SetSelection(select
)
1347 #---------------------------------------------
1348 def SetOverview(self
, name
, text
):
1349 self
.curOverview
= text
1351 if lead
!= '<html>' and lead
!= '<HTML>':
1352 text
= '<br>'.join(text
.split('\n'))
1354 text
= text
.decode('iso8859_1')
1355 self
.ovr
.SetPage(text
)
1356 self
.nb
.SetPageText(0, name
)
1358 #---------------------------------------------
1360 def OnFileExit(self
, *event
):
1363 def OnToggleRedirect(self
, event
):
1367 print "Print statements and other standard output will now be directed to this window."
1370 print "Print statements and other standard output will now be sent to the usual location."
1372 def OnHelpAbout(self
, event
):
1373 from About
import MyAboutBox
1374 about
= MyAboutBox(self
)
1378 def OnHelpFind(self
, event
):
1379 self
.nb
.SetSelection(1)
1380 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1384 self
.finddlg
.Show(True)
1386 def OnFind(self
, event
):
1387 editor
= self
.codePage
.editor
1388 self
.nb
.SetSelection(1)
1389 end
= editor
.GetLastPosition()
1390 textstring
= editor
.GetRange(0, end
).lower()
1391 start
= editor
.GetSelection()[1]
1392 findstring
= self
.finddata
.GetFindString().lower()
1393 loc
= textstring
.find(findstring
, start
)
1394 if loc
== -1 and start
!= 0:
1395 # string not found, start at beginning
1397 loc
= textstring
.find(findstring
, start
)
1399 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1400 'Find String Not Found in Demo File',
1401 wx
.OK | wx
.ICON_INFORMATION
)
1406 self
.finddlg
.SetFocus()
1409 self
.finddlg
.Destroy()
1410 editor
.ShowPosition(loc
)
1411 editor
.SetSelection(loc
, loc
+ len(findstring
))
1415 def OnFindNext(self
, event
):
1416 if self
.finddata
.GetFindString():
1419 self
.OnHelpFind(event
)
1421 def OnFindClose(self
, event
):
1422 event
.GetDialog().Destroy()
1425 def OnOpenShellWindow(self
, evt
):
1427 # if it already exists then just make sure it's visible
1433 # Make a PyShell window
1435 namespace
= { 'wx' : wx
,
1436 'app' : wx
.GetApp(),
1439 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1440 self
.shell
.SetSize((640,480))
1443 # Hook the close event of the main frame window so that we
1444 # close the shell at the same time if it still exists
1445 def CloseShell(evt
):
1449 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1452 #---------------------------------------------
1453 def OnCloseWindow(self
, event
):
1455 self
.demoPage
= None
1456 self
.codePage
= None
1457 self
.mainmenu
= None
1461 #---------------------------------------------
1462 def OnIdle(self
, event
):
1464 self
.otherWin
.Raise()
1465 self
.demoPage
= self
.otherWin
1466 self
.otherWin
= None
1469 #---------------------------------------------
1472 showTipText
= open(opj("data/showTips")).read()
1473 showTip
, index
= eval(showTipText
)
1475 showTip
, index
= (1, 0)
1477 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1479 showTip
= wx
.ShowTip(self
, tp
)
1480 index
= tp
.GetCurrentTip()
1481 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1484 #---------------------------------------------
1485 def OnDemoMenu(self
, event
):
1487 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1491 self
.tree
.SelectItem(selectedDemo
)
1492 self
.tree
.EnsureVisible(selectedDemo
)
1495 #---------------------------------------------
1496 def OnTaskBarActivate(self
, evt
):
1497 if self
.IsIconized():
1499 if not self
.IsShown():
1503 #---------------------------------------------
1505 TBMENU_RESTORE
= 1000
1508 def OnTaskBarMenu(self
, evt
):
1510 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1511 menu
.Append(self
.TBMENU_CLOSE
, "Close")
1512 self
.tbicon
.PopupMenu(menu
)
1515 #---------------------------------------------
1516 def OnTaskBarClose(self
, evt
):
1519 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
1520 # prod the main idle handler a bit to get the window to actually close
1521 wx
.GetApp().ProcessIdle()
1524 #---------------------------------------------
1525 def OnIconfiy(self
, evt
):
1526 wx
.LogMessage("OnIconfiy: %d" % evt
.Iconized())
1529 #---------------------------------------------
1530 def OnMaximize(self
, evt
):
1531 wx
.LogMessage("OnMaximize")
1537 #---------------------------------------------------------------------------
1538 #---------------------------------------------------------------------------
1540 class MySplashScreen(wx
.SplashScreen
):
1542 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1543 wx
.SplashScreen
.__init
__(self
, bmp
,
1544 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1546 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1548 def OnClose(self
, evt
):
1550 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1552 evt
.Skip() # Make sure the default handler runs too...
1555 class MyApp(wx
.App
):
1558 Create and show the splash screen. It will then create and show
1559 the main frame when it is time to do so.
1563 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1565 # Normally when using a SplashScreen you would create it, show
1566 # it and then continue on with the applicaiton's
1567 # initialization, finally creating and showing the main
1568 # application window(s). In this case we have nothing else to
1569 # do so we'll delay showing the main frame until later (see
1570 # OnClose above) so the users can see the SplashScreen effect.
1571 splash
= MySplashScreen()
1578 #---------------------------------------------------------------------------
1582 demoPath
= os
.path
.dirname(__file__
)
1589 #---------------------------------------------------------------------------
1592 mainOverview
= """<html><body>
1595 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1596 language. It allows Python programmers to create programs with a
1597 robust, highly functional graphical user interface, simply and easily.
1598 It is implemented as a Python extension module (native code) that
1599 wraps the popular wxWindows cross platform GUI library, which is
1602 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1603 means that it is free for anyone to use and the source code is
1604 available for anyone to look at and modify. Or anyone can contribute
1605 fixes or enhancements to the project.
1607 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1608 same program will run on multiple platforms without modification.
1609 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1610 or unix-like systems, and Macintosh OS X. Since the language is
1611 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1614 <p> <b>This demo</b> is not only a collection of test cases for
1615 wxPython, but is also designed to help you learn about and how to use
1616 wxPython. Each sample is listed in the tree control on the left.
1617 When a sample is selected in the tree then a module is loaded and run
1618 (usually in a tab of this notebook,) and the source code of the module
1619 is loaded in another tab for you to browse and learn from.
1624 #----------------------------------------------------------------------------
1625 #----------------------------------------------------------------------------
1627 if __name__
== '__main__':
1631 #----------------------------------------------------------------------------