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, 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
= wx
.TE_MULTILINE |
447 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
)
486 self
.mainFrame
= mainFrame
487 self
.editor
= DemoCodeEditor(self
)
488 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
490 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
491 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
492 self
.btnSave
.Enable(False)
493 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
494 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
496 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
497 modModified
: wx
.RadioButton(self
, -1, "Modified") }
499 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
500 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
501 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
502 for modID
, radioButton
in self
.radioButtons
.items():
503 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
504 radioButton
.modID
= modID
# makes it easier for the event handler
505 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
507 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
508 self
.controlBox
.Add(self
.btnRestore
, 0)
510 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
511 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
512 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
513 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
516 self
.SetSizer(self
.box
)
519 # Loads a demo from a DemoModules object
520 def LoadDemo(self
, demoModules
):
521 self
.demoModules
= demoModules
522 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
523 demoModules
.SetActive(modModified
)
525 demoModules
.SetActive(modOriginal
)
526 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
527 self
.ActiveModuleChanged()
530 def ActiveModuleChanged(self
):
531 self
.LoadDemoSource(self
.demoModules
.GetSource())
532 self
.UpdateControlState()
536 def LoadDemoSource(self
, source
):
538 self
.editor
.SetValue(source
)
540 self
.btnSave
.Enable(False)
543 def JumpToLine(self
, line
, highlight
=False):
544 self
.editor
.GotoLine(line
)
545 self
.editor
.SetFocus()
547 self
.editor
.SelectLine(line
)
550 def UpdateControlState(self
):
551 active
= self
.demoModules
.GetActiveID()
552 # Update the radio/restore buttons
553 for moduleID
in self
.radioButtons
:
554 btn
= self
.radioButtons
[moduleID
]
555 if moduleID
== active
:
560 if self
.demoModules
.Exists(moduleID
):
562 if moduleID
== modModified
:
563 self
.btnRestore
.Enable(True)
566 if moduleID
== modModified
:
567 self
.btnRestore
.Enable(False)
570 def OnRadioButton(self
, event
):
571 radioSelected
= event
.GetEventObject()
572 modSelected
= radioSelected
.modID
573 if modSelected
!= self
.demoModules
.GetActiveID():
574 busy
= wx
.BusyInfo("Reloading demo module...")
575 self
.demoModules
.SetActive(modSelected
)
576 self
.ActiveModuleChanged()
579 def ReloadDemo(self
):
580 if self
.demoModules
.name
!= __name__
:
581 self
.mainFrame
.RunModule()
584 def OnCodeModified(self
, event
):
585 self
.btnSave
.Enable(self
.editor
.IsModified())
588 def OnSave(self
, event
):
589 if self
.demoModules
.Exists(modModified
):
590 if self
.demoModules
.GetActiveID() == modOriginal
:
591 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
592 "Do you want to continue?"
593 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
594 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
595 result
= dlg
.ShowModal()
596 if result
== wx
.ID_NO
:
600 self
.demoModules
.SetActive(modModified
)
601 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
603 # Create the demo directory if one doesn't already exist
604 if not os
.path
.exists(GetModifiedDirectory()):
606 os
.makedirs(GetModifiedDirectory())
607 if not os
.path
.exists(GetModifiedDirectory()):
608 wx
.LogMessage("BUG: Created demo directory but it still doesn't exit")
611 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
614 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
617 f
= open(modifiedFilename
, "wt")
618 source
= self
.editor
.GetText()
624 busy
= wx
.BusyInfo("Reloading demo module...")
625 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
626 self
.ActiveModuleChanged()
629 def OnRestore(self
, event
): # Handles the "Delete Modified" button
630 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
631 self
.demoModules
.Delete(modModified
)
632 os
.unlink(modifiedFilename
) # Delete the modified copy
633 busy
= wx
.BusyInfo("Reloading demo module...")
634 self
.ActiveModuleChanged()
637 #---------------------------------------------------------------------------
640 """Convert paths to the platform-specific separator"""
641 str = apply(os
.path
.join
, tuple(path
.split('/')))
642 # HACK: on Linux, a leading / gets lost...
643 if path
.startswith('/'):
648 def GetModifiedDirectory():
650 Returns the directory where modified versions of the demo files
653 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
656 def GetModifiedFilename(name
):
658 Returns the filename of the modified version of the specified demo
660 if not name
.endswith(".py"):
662 return GetModifiedDirectory() + name
665 def GetOriginalFilename(name
):
667 Returns the filename of the original version of the specified demo
669 if not name
.endswith(".py"):
674 def DoesModifiedExist(name
):
675 """Returns whether the specified demo has a modified copy"""
676 if os
.path
.exists(GetModifiedFilename(name
)):
682 #---------------------------------------------------------------------------
684 class ModuleDictWrapper
:
685 """Emulates a module with a dynamically compiled __dict__"""
686 def __init__(self
, dict):
689 def __getattr__(self
, name
):
690 if name
in self
.dict:
691 return self
.dict[name
]
697 Dynamically manages the original/modified versions of a demo
700 def __init__(self
, name
):
704 # (dict , source , filename , description , error information )
705 # ( 0 , 1 , 2 , 3 , 4 )
706 self
.modules
= [[None, "" , "" , "<original>" , None],
707 [None, "" , "" , "<modified>" , None]]
709 # load original module
710 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
711 self
.SetActive(modOriginal
)
713 # load modified module (if one exists)
714 if DoesModifiedExist(name
):
715 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
718 def LoadFromFile(self
, modID
, filename
):
719 self
.modules
[modID
][2] = filename
720 file = open(filename
, "rt")
721 self
.LoadFromSource(modID
, file.read())
725 def LoadFromSource(self
, modID
, source
):
726 self
.modules
[modID
][1] = source
730 def LoadDict(self
, modID
):
731 if self
.name
!= __name__
:
732 source
= self
.modules
[modID
][1]
733 description
= self
.modules
[modID
][3]
736 self
.modules
[modID
][0] = {}
737 code
= compile(source
, description
, "exec")
738 exec code
in self
.modules
[modID
][0]
740 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
741 self
.modules
[modID
][0] = None
743 self
.modules
[modID
][4] = None
746 def SetActive(self
, modID
):
747 if modID
!= modOriginal
and modID
!= modModified
:
750 self
.modActive
= modID
754 dict = self
.modules
[self
.modActive
][0]
758 return ModuleDictWrapper(dict)
761 def GetActiveID(self
):
762 return self
.modActive
765 def GetSource(self
, modID
= None):
767 modID
= self
.modActive
768 return self
.modules
[modID
][1]
771 def GetFilename(self
, modID
= None):
773 modID
= self
.modActive
774 return self
.modules
[self
.modActive
][2]
777 def GetErrorInfo(self
, modID
= None):
779 modID
= self
.modActive
780 return self
.modules
[self
.modActive
][4]
783 def Exists(self
, modID
):
784 return self
.modules
[modID
][1] != ""
787 def UpdateFile(self
, modID
= None):
788 """Updates the file from which a module was loaded
789 with (possibly updated) source"""
791 modID
= self
.modActive
793 source
= self
.modules
[modID
][1]
794 filename
= self
.modules
[modID
][2]
797 file = open(filename
, "wt")
803 def Delete(self
, modID
):
804 if self
.modActive
== modID
:
807 self
.modules
[modID
][0] = None
808 self
.modules
[modID
][1] = ""
809 self
.modules
[modID
][2] = ""
812 #---------------------------------------------------------------------------
815 """Wraps and stores information about the current exception"""
816 def __init__(self
, exc_info
):
819 excType
, excValue
= exc_info
[:2]
820 # traceback list entries: (filename, line number, function name, text)
821 self
.traceback
= traceback
.extract_tb(exc_info
[2])
823 # --Based on traceback.py::format_exception_only()--
824 if type(excType
) == types
.ClassType
:
825 self
.exception_type
= excType
.__name
__
827 self
.exception_type
= excType
829 # If it's a syntax error, extra information needs
830 # to be added to the traceback
831 if excType
is SyntaxError:
833 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
838 filename
= "<string>"
840 self
.traceback
.append( (filename
, lineno
, "", line
) )
843 self
.exception_details
= str(excValue
)
845 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
852 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
855 #---------------------------------------------------------------------------
857 class DemoErrorPanel(wx
.Panel
):
858 """Panel put into the demo tab when the demo fails to run due to errors"""
860 def __init__(self
, parent
, codePanel
, demoError
, log
):
861 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
862 self
.codePanel
= codePanel
866 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
869 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
870 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
872 # Exception Information
873 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
874 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
875 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
876 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
877 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
878 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
879 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
880 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
881 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
882 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
884 # Set up the traceback list
885 # This one automatically resizes last column to take up remaining space
886 from ListCtrl
import TestListCtrl
887 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
888 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
889 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
890 self
.list.InsertColumn(0, "Filename")
891 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
892 self
.list.InsertColumn(2, "Function")
893 self
.list.InsertColumn(3, "Code")
894 self
.InsertTraceback(self
.list, demoError
.traceback
)
895 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
896 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
897 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
898 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
899 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
900 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
901 + "Double-click on them to go to the offending line")
902 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
905 self
.SetSizer(self
.box
)
908 def InsertTraceback(self
, list, traceback
):
909 #Add the traceback data
910 for x
in range(len(traceback
)):
912 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
913 list.SetStringItem(x
, 1, str(data
[1])) # Line
914 list.SetStringItem(x
, 2, str(data
[2])) # Function
915 list.SetStringItem(x
, 3, str(data
[3])) # Code
917 # Check whether this entry is from the demo module
918 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
919 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
920 # Give it a blue colour
921 item
= self
.list.GetItem(x
)
922 item
.SetTextColour(wx
.BLUE
)
923 self
.list.SetItem(item
)
925 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
928 def OnItemSelected(self
, event
):
929 # This occurs before OnDoubleClick and can be used to set the
930 # currentItem. OnDoubleClick doesn't get a wxListEvent....
931 self
.currentItem
= event
.m_itemIndex
935 def OnDoubleClick(self
, event
):
936 # If double-clicking on a demo's entry, jump to the line number
937 line
= self
.list.GetItemData(self
.currentItem
)
939 self
.nb
.SetSelection(1) # Switch to the code viewer tab
940 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
944 #---------------------------------------------------------------------------
946 class wxPythonDemo(wx
.Frame
):
947 overviewText
= "wxPython Overview"
949 def __init__(self
, parent
, title
):
950 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
951 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
954 self
.cwd
= os
.getcwd()
955 self
.curOverview
= ""
959 self
.firstTime
= True
961 icon
= images
.getMondrianIcon()
964 if wx
.Platform
!= '__WXMAC__':
965 # setup a taskbar icon, and catch some events from it
966 dim
= 16 # (may want to use 22 on wxGTK, but 16 looks okay too)
967 icon
= wx
.IconFromBitmap(
968 images
.getMondrianImage().Scale(dim
,dim
).ConvertToBitmap() )
969 #icon = wx.Icon('bmp_source/mondrian.ico', wx.BITMAP_TYPE_ICO)
970 #icon = images.getMondrianIcon()
971 self
.tbicon
= wx
.TaskBarIcon()
972 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
973 self
.tbicon
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
974 self
.tbicon
.Bind(wx
.EVT_TASKBAR_RIGHT_UP
, self
.OnTaskBarMenu
)
975 self
.tbicon
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
976 self
.tbicon
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
978 wx
.CallAfter(self
.ShowTip
)
981 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
982 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
983 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
984 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
987 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
989 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
990 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
992 def EmptyHandler(evt
): pass
993 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
994 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
996 # Prevent TreeCtrl from displaying all items after destruction when True
1000 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1003 self
.mainmenu
= wx
.MenuBar()
1005 item
= menu
.Append(-1, '&Redirect Output',
1006 'Redirect print statements to a window',
1008 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1010 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1011 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1012 wx
.App_SetMacExitMenuItemId(item
.GetId())
1013 self
.mainmenu
.Append(menu
, '&File')
1017 for item
in _treeList
:
1019 for childItem
in item
[1]:
1020 mi
= submenu
.Append(-1, childItem
)
1021 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1022 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1023 self
.mainmenu
.Append(menu
, '&Demo')
1025 # Make a Demo Code menu
1026 #TODO: Add new menu items
1027 # Like the option-enabled entries to select the
1029 #TODO: should we bother?
1032 #saveID = wx.NewId()
1033 #restoreID = wx.NewId()
1035 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1036 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1037 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1038 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1039 #self.mainmenu.Append(menu, 'Demo &Code')
1044 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1045 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1046 menu
.AppendSeparator()
1048 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1049 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1050 menu
.AppendSeparator()
1051 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1052 wx
.App_SetMacAboutMenuItemId(helpItem
.GetId())
1054 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1055 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1056 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1057 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1058 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1059 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1060 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1061 self
.mainmenu
.Append(menu
, '&Help')
1062 self
.SetMenuBar(self
.mainmenu
)
1064 self
.finddata
= wx
.FindReplaceData()
1067 # This is another way to set Accelerators, in addition to
1068 # using the '\t<key>' syntax in the menu items.
1069 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1070 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1071 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1072 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1074 self
.SetAcceleratorTable(aTable
)
1080 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1081 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1084 root
= self
.tree
.AddRoot("wxPython Overview")
1086 for item
in _treeList
:
1087 child
= self
.tree
.AppendItem(root
, item
[0])
1088 if not firstChild
: firstChild
= child
1089 for childItem
in item
[1]:
1090 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1091 self
.treeMap
[childItem
] = theDemo
1093 self
.tree
.Expand(root
)
1094 self
.tree
.Expand(firstChild
)
1095 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1096 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1097 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1098 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1100 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1101 # we put it in a panel first because there seems to be a
1102 # refresh bug of some sort (wxGTK) when it is directly in
1105 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1106 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1108 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1109 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1110 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1111 self
.nb
.AddPage(panel
, self
.overviewText
)
1113 def OnOvrSize(evt
, ovr
=self
.ovr
):
1114 ovr
.SetSize(evt
.GetSize())
1115 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1116 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1118 if "gtk2" in wx
.PlatformInfo
:
1119 self
.ovr
.NormalizeFontSizes()
1120 self
.SetOverview(self
.overviewText
, mainOverview
)
1123 # Set up a log window
1124 self
.log
= wx
.TextCtrl(splitter2
, -1,
1125 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1127 # Set the wxWindows log target to be this textctrl
1128 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1130 # But instead of the above we want to show how to use our own wx.Log class
1131 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1133 # for serious debugging
1134 #wx.Log_SetActiveTarget(wx.LogStderr())
1135 #wx.Log_SetTraceMask(wx.TraceMessages)
1138 # add the windows to the splitter and split it.
1139 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1140 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1142 splitter
.SetMinimumPaneSize(20)
1143 splitter2
.SetMinimumPaneSize(20)
1145 # Make the splitter on the right expand the top window when resized
1146 def SplitterOnSize(evt
):
1147 splitter
= evt
.GetEventObject()
1148 sz
= splitter
.GetSize()
1149 splitter
.SetSashPosition(sz
.height
- 160, False)
1152 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1154 # select initial items
1155 self
.nb
.SetSelection(0)
1156 self
.tree
.SelectItem(root
)
1158 # Load 'Main' module
1159 self
.LoadDemo(self
.overviewText
)
1162 # select some other initial module?
1163 if len(sys
.argv
) > 1:
1165 if arg
.endswith('.py'):
1167 selectedDemo
= self
.treeMap
.get(arg
, None)
1169 self
.tree
.SelectItem(selectedDemo
)
1170 self
.tree
.EnsureVisible(selectedDemo
)
1173 #---------------------------------------------
1174 def WriteText(self
, text
):
1175 if text
[-1:] == '\n':
1179 def write(self
, txt
):
1182 #---------------------------------------------
1183 def OnItemExpanded(self
, event
):
1184 item
= event
.GetItem()
1185 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1188 #---------------------------------------------
1189 def OnItemCollapsed(self
, event
):
1190 item
= event
.GetItem()
1191 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1194 #---------------------------------------------
1195 def OnTreeLeftDown(self
, event
):
1196 # reset the overview text if the tree item is clicked on again
1197 pt
= event
.GetPosition();
1198 item
, flags
= self
.tree
.HitTest(pt
)
1199 if item
== self
.tree
.GetSelection():
1200 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1203 #---------------------------------------------
1204 def OnSelChanged(self
, event
):
1205 if self
.dying
or not self
.loaded
:
1208 item
= event
.GetItem()
1209 itemText
= self
.tree
.GetItemText(item
)
1210 self
.LoadDemo(itemText
)
1212 #---------------------------------------------
1213 def LoadDemo(self
, demoName
):
1215 wx
.BeginBusyCursor()
1218 self
.ShutdownDemoModule()
1220 if demoName
== self
.overviewText
:
1221 # User selected the "wxPython Overview" node
1223 # Changing the main window at runtime not yet supported...
1224 self
.demoModules
= DemoModules(__name__
)
1225 self
.SetOverview(self
.overviewText
, mainOverview
)
1226 self
.LoadDemoSource()
1227 self
.UpdateNotebook(0)
1229 if os
.path
.exists(GetOriginalFilename(demoName
)):
1230 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1231 self
.demoModules
= DemoModules(demoName
)
1232 self
.LoadDemoSource()
1235 self
.SetOverview("wxPython", mainOverview
)
1236 self
.codePage
= None
1237 self
.UpdateNotebook(0)
1241 #---------------------------------------------
1242 def LoadDemoSource(self
):
1243 self
.codePage
= None
1244 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1245 self
.codePage
.LoadDemo(self
.demoModules
)
1247 #---------------------------------------------
1248 def RunModule(self
):
1249 """Runs the active module"""
1251 module
= self
.demoModules
.GetActive()
1252 self
.ShutdownDemoModule()
1255 # o If the demo returns a window it is placed in a tab.
1256 # o Otherwise, a placeholder tab is created, informing the user that the
1257 # demo runs outside the main window, and allowing it to be reloaded.
1258 # o If an error occurs (or has occured before) an error tab is created.
1260 if module
is not None:
1261 wx
.LogMessage("Running demo module...")
1262 if hasattr(module
, "overview"):
1263 overviewText
= module
.overview
1266 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1268 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1269 DemoError(sys
.exc_info()), self
)
1271 assert self
.demoPage
is not None, "runTest must return a window!"
1274 # There was a previous error in compiling or exec-ing
1275 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1276 self
.demoModules
.GetErrorInfo(), self
)
1278 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1281 # cahnge to the demo page the first time a module is run
1282 self
.UpdateNotebook(2)
1283 self
.firstTime
= False
1285 # otherwise just stay on the same tab in case the user has changed to another one
1286 self
.UpdateNotebook()
1288 #---------------------------------------------
1289 def ShutdownDemoModule(self
):
1291 # inform the window that it's time to quit if it cares
1292 if hasattr(self
.demoPage
, "ShutdownDemo"):
1293 self
.demoPage
.ShutdownDemo()
1294 wx
.YieldIfNeeded() # in case the page has pending events
1295 self
.demoPage
= None
1297 #---------------------------------------------
1298 def UpdateNotebook(self
, select
= -1):
1302 def UpdatePage(page
, pageText
):
1305 for i
in range(nb
.GetPageCount()):
1306 if nb
.GetPageText(i
) == pageText
:
1314 nb
.AddPage(page
, pageText
)
1315 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1317 if nb
.GetPage(pagePos
) != page
:
1318 # Reload an existing page
1320 nb
.DeletePage(pagePos
)
1321 nb
.InsertPage(pagePos
, page
, pageText
)
1323 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1325 # Excellent! No redraw/flicker
1326 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1329 nb
.DeletePage(pagePos
)
1330 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1332 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1335 select
= nb
.GetSelection()
1337 UpdatePage(self
.codePage
, "Demo Code")
1338 UpdatePage(self
.demoPage
, "Demo")
1340 if select
>= 0 and select
< nb
.GetPageCount():
1341 nb
.SetSelection(select
)
1343 #---------------------------------------------
1344 def SetOverview(self
, name
, text
):
1345 self
.curOverview
= text
1347 if lead
!= '<html>' and lead
!= '<HTML>':
1348 text
= '<br>'.join(text
.split('\n'))
1350 text
= text
.decode('iso8859_1')
1351 self
.ovr
.SetPage(text
)
1352 self
.nb
.SetPageText(0, name
)
1354 #---------------------------------------------
1356 def OnFileExit(self
, *event
):
1359 def OnToggleRedirect(self
, event
):
1363 print "Print statements and other standard output will now be directed to this window."
1366 print "Print statements and other standard output will now be sent to the usual location."
1368 def OnHelpAbout(self
, event
):
1369 from About
import MyAboutBox
1370 about
= MyAboutBox(self
)
1374 def OnHelpFind(self
, event
):
1375 self
.nb
.SetSelection(1)
1376 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1380 self
.finddlg
.Show(True)
1382 def OnFind(self
, event
):
1383 editor
= self
.codePage
.editor
1384 self
.nb
.SetSelection(1)
1385 end
= editor
.GetLastPosition()
1386 textstring
= editor
.GetRange(0, end
).lower()
1387 start
= editor
.GetSelection()[1]
1388 findstring
= self
.finddata
.GetFindString().lower()
1389 loc
= textstring
.find(findstring
, start
)
1390 if loc
== -1 and start
!= 0:
1391 # string not found, start at beginning
1393 loc
= textstring
.find(findstring
, start
)
1395 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1396 'Find String Not Found in Demo File',
1397 wx
.OK | wx
.ICON_INFORMATION
)
1402 self
.finddlg
.SetFocus()
1405 self
.finddlg
.Destroy()
1406 editor
.ShowPosition(loc
)
1407 editor
.SetSelection(loc
, loc
+ len(findstring
))
1411 def OnFindNext(self
, event
):
1412 if self
.finddata
.GetFindString():
1415 self
.OnHelpFind(event
)
1417 def OnFindClose(self
, event
):
1418 event
.GetDialog().Destroy()
1421 def OnOpenShellWindow(self
, evt
):
1423 # if it already exists then just make sure it's visible
1429 # Make a PyShell window
1431 namespace
= { 'wx' : wx
,
1432 'app' : wx
.GetApp(),
1435 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1436 self
.shell
.SetSize((640,480))
1439 # Hook the close event of the main frame window so that we
1440 # close the shell at the same time if it still exists
1441 def CloseShell(evt
):
1445 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1448 #---------------------------------------------
1449 def OnCloseWindow(self
, event
):
1451 self
.demoPage
= None
1452 self
.codePage
= None
1453 self
.mainmenu
= None
1457 #---------------------------------------------
1458 def OnIdle(self
, event
):
1460 self
.otherWin
.Raise()
1461 self
.demoPage
= self
.otherWin
1462 self
.otherWin
= None
1465 #---------------------------------------------
1468 showTipText
= open(opj("data/showTips")).read()
1469 showTip
, index
= eval(showTipText
)
1471 showTip
, index
= (1, 0)
1473 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1475 showTip
= wx
.ShowTip(self
, tp
)
1476 index
= tp
.GetCurrentTip()
1477 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1480 #---------------------------------------------
1481 def OnDemoMenu(self
, event
):
1483 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1487 self
.tree
.SelectItem(selectedDemo
)
1488 self
.tree
.EnsureVisible(selectedDemo
)
1491 #---------------------------------------------
1492 def OnTaskBarActivate(self
, evt
):
1493 if self
.IsIconized():
1495 if not self
.IsShown():
1499 #---------------------------------------------
1501 TBMENU_RESTORE
= 1000
1504 def OnTaskBarMenu(self
, evt
):
1506 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1507 menu
.Append(self
.TBMENU_CLOSE
, "Close")
1508 self
.tbicon
.PopupMenu(menu
)
1511 #---------------------------------------------
1512 def OnTaskBarClose(self
, evt
):
1515 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
1516 # prod the main idle handler a bit to get the window to actually close
1517 wx
.GetApp().ProcessIdle()
1520 #---------------------------------------------
1521 def OnIconfiy(self
, evt
):
1522 wx
.LogMessage("OnIconfiy: %d" % evt
.Iconized())
1525 #---------------------------------------------
1526 def OnMaximize(self
, evt
):
1527 wx
.LogMessage("OnMaximize")
1533 #---------------------------------------------------------------------------
1534 #---------------------------------------------------------------------------
1536 class MySplashScreen(wx
.SplashScreen
):
1538 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1539 wx
.SplashScreen
.__init
__(self
, bmp
,
1540 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1542 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1544 def OnClose(self
, evt
):
1546 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1548 evt
.Skip() # Make sure the default handler runs too...
1551 class MyApp(wx
.App
):
1554 Create and show the splash screen. It will then create and show
1555 the main frame when it is time to do so.
1559 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1561 # Normally when using a SplashScreen you would create it, show
1562 # it and then continue on with the applicaiton's
1563 # initialization, finally creating and showing the main
1564 # application window(s). In this case we have nothing else to
1565 # do so we'll delay showing the main frame until later (see
1566 # OnClose above) so the users can see the SplashScreen effect.
1567 splash
= MySplashScreen()
1574 #---------------------------------------------------------------------------
1578 demoPath
= os
.path
.dirname(__file__
)
1585 #---------------------------------------------------------------------------
1588 mainOverview
= """<html><body>
1591 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1592 language. It allows Python programmers to create programs with a
1593 robust, highly functional graphical user interface, simply and easily.
1594 It is implemented as a Python extension module (native code) that
1595 wraps the popular wxWindows cross platform GUI library, which is
1598 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1599 means that it is free for anyone to use and the source code is
1600 available for anyone to look at and modify. Or anyone can contribute
1601 fixes or enhancements to the project.
1603 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1604 same program will run on multiple platforms without modification.
1605 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1606 or unix-like systems, and Macintosh OS X. Since the language is
1607 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1610 <p> <b>This demo</b> is not only a collection of test cases for
1611 wxPython, but is also designed to help you learn about and how to use
1612 wxPython. Each sample is listed in the tree control on the left.
1613 When a sample is selected in the tree then a module is loaded and run
1614 (usually in a tab of this notebook,) and the source code of the module
1615 is loaded in another tab for you to browse and learn from.
1620 #----------------------------------------------------------------------------
1621 #----------------------------------------------------------------------------
1623 if __name__
== '__main__':
1627 #----------------------------------------------------------------------------