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 ('Base Frames and Dialogs', [
79 # dialogs from libraries
82 'MultipleChoiceDialog',
83 'ScrolledMessageDialog',
87 ('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',
170 # How to lay out the controls in a frame/dialog
180 'XmlResourceHandler',
181 'XmlResourceSubclass',
185 ('Process and Events', [
196 ('Clipboard and DnD', [
229 # need libs not coming with the demo
230 ('Samples using an external library', [
235 ('Check out the samples dir too', [
242 #---------------------------------------------------------------------------
243 # Show how to derive a custom wxLog class
245 class MyLog(wx
.PyLog
):
246 def __init__(self
, textCtrl
, logTime
=0):
247 wx
.PyLog
.__init
__(self
)
249 self
.logTime
= logTime
251 def DoLogString(self
, message
, timeStamp
):
253 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
256 self
.tc
.AppendText(message
+ '\n')
259 class MyTP(wx
.PyTipProvider
):
261 return "This is my tip"
264 #---------------------------------------------------------------------------
265 # A class to be used to display source code in the demo. Try using the
266 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
267 # if there is an error, such as the stc module not being present.
271 ##raise ImportError # for testing the alternate implementation
273 from StyledTextCtrl_2
import PythonSTC
275 class DemoCodeEditor(PythonSTC
):
276 def __init__(self
, parent
):
277 PythonSTC
.__init
__(self
, parent
, -1, wx
.BORDER_NONE
)
280 # Some methods to make it compatible with how the wxTextCtrl is used
281 def SetValue(self
, value
):
283 value
= value
.decode('iso8859_1')
285 self
.EmptyUndoBuffer()
288 def IsModified(self
):
289 return self
.GetModify()
294 def SetInsertionPoint(self
, pos
):
295 self
.SetCurrentPos(pos
)
298 def ShowPosition(self
, pos
):
299 line
= self
.LineFromPosition(pos
)
300 #self.EnsureVisible(line)
303 def GetLastPosition(self
):
304 return self
.GetLength()
306 def GetPositionFromLine(self
, line
):
307 return self
.PositionFromLine(line
)
309 def GetRange(self
, start
, end
):
310 return self
.GetTextRange(start
, end
)
312 def GetSelection(self
):
313 return self
.GetAnchor(), self
.GetCurrentPos()
315 def SetSelection(self
, start
, end
):
316 self
.SetSelectionStart(start
)
317 self
.SetSelectionEnd(end
)
319 def SelectLine(self
, line
):
320 start
= self
.PositionFromLine(line
)
321 end
= self
.GetLineEndPosition(line
)
322 self
.SetSelection(start
, end
)
324 def SetUpEditor(self
):
326 This method carries out the work of setting up the demo editor.
327 It's seperate so as not to clutter up the init code.
331 self
.SetLexer(stc
.STC_LEX_PYTHON
)
332 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
335 self
.SetProperty("fold", "1" )
337 # Highlight tab/space mixing (shouldn't be any)
338 self
.SetProperty("tab.timmy.whinge.level", "1")
340 # Set left and right margins
343 # Set up the numbers in the margin for margin #1
344 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
345 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
346 self
.SetMarginWidth(1, 40)
348 # Indentation and tab stuff
349 self
.SetIndent(4) # Proscribed indent size for wx
350 self
.SetIndentationGuides(True) # Show indent guides
351 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
352 self
.SetTabIndents(True) # Tab key indents
353 self
.SetTabWidth(4) # Proscribed tab size for wx
354 self
.SetUseTabs(False) # Use spaces rather than tabs, or
355 # TabTimmy will complain!
357 self
.SetViewWhiteSpace(False) # Don't view white space
359 # EOL: Since we are loading/saving ourselves, and the
360 # strings will always have \n's in them, set the STC to
361 # edit them that way.
362 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
363 self
.SetViewEOL(False)
365 # No right-edge mode indicator
366 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
368 # Setup a margin to hold fold markers
369 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
370 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
371 self
.SetMarginSensitive(2, True)
372 self
.SetMarginWidth(2, 12)
374 # and now set up the fold markers
375 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
376 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
377 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
378 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
379 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
380 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
381 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
383 # Global default style
384 if wx
.Platform
== '__WXMSW__':
385 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
386 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
388 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
389 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
391 # Clear styles and revert to default.
394 # Following style specs only indicate differences from default.
395 # The rest remains unchanged.
397 # Line numbers in margin
398 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
401 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
403 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
405 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
408 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
410 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
411 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
413 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
414 # Strings and characters
415 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
416 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
418 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
420 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
421 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
423 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
425 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
427 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
428 # Identifiers. I leave this as not bold because everything seems
429 # to be an identifier if it doesn't match the above criterae
430 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
433 self
.SetCaretForeground("BLUE")
434 # Selection background
435 self
.SetSelBackground(1, '#66CCFF')
437 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
438 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
440 def RegisterModifiedEvent(self
, eventHandler
):
441 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
445 class DemoCodeEditor(wx
.TextCtrl
):
446 def __init__(self
, parent
):
447 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
= wx
.TE_MULTILINE |
448 wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
450 def RegisterModifiedEvent(self
, eventHandler
):
451 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
453 def SetReadOnly(self
, flag
):
454 self
.SetEditable(not flag
)
455 # NOTE: STC already has this method
458 return self
.GetValue()
460 def GetPositionFromLine(line
):
461 return self
.XYToPosition(0,line
)
463 def GotoLine(self
, line
):
464 pos
= self
.editor
.GetPositionFromLine(line
)
465 self
.editor
.SetInsertionPoint(pos
)
466 self
.editor
.ShowPosition(pos
)
468 def SelectLine(self
, line
):
469 start
= self
.GetPositionFromLine(line
)
470 end
= start
+ self
.GetLineLength(line
)
471 self
.SetSelection(start
, end
)
474 #---------------------------------------------------------------------------
475 # Constants for module versions
479 modDefault
= modOriginal
481 #---------------------------------------------------------------------------
483 class DemoCodePanel(wx
.Panel
):
484 """Panel for the 'Demo Code' tab"""
485 def __init__(self
, parent
, mainFrame
):
486 wx
.Panel
.__init
__(self
, parent
)
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
))
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 #---------------------------------------------------------------------------
813 class ReloadDemoPanel(wx
.Panel
):
815 Panel put into the demo tab when the demo just shows some
816 top-level window. Enables the demo to be reloaded after being
820 infoText
= "This demo runs outside the main window"
822 def __init__(self
, parent
, codePanel
, log
):
823 wx
.Panel
.__init
__(self
, parent
, -1)
824 self
.codePanel
= codePanel
827 self
.label
= wx
.StaticText(self
, -1, self
.infoText
)
828 self
.btnReload
= wx
.Button(self
, -1, "Reload Demo")
829 self
.btnReload
.Bind(wx
.EVT_BUTTON
, self
.OnReload
)
831 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
832 self
.box
.Add(self
.label
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 10)
833 self
.box
.Add(self
.btnReload
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 10)
836 self
.SetSizer(self
.box
)
838 def OnReload(self
, event
):
839 self
.codePanel
.ReloadDemo()
841 #---------------------------------------------------------------------------
844 """Wraps and stores information about the current exception"""
845 def __init__(self
, exc_info
):
848 excType
, excValue
= exc_info
[:2]
849 # traceback list entries: (filename, line number, function name, text)
850 self
.traceback
= traceback
.extract_tb(exc_info
[2])
852 # --Based on traceback.py::format_exception_only()--
853 if type(excType
) == types
.ClassType
:
854 self
.exception_type
= excType
.__name
__
856 self
.exception_type
= excType
858 # If it's a syntax error, extra information needs
859 # to be added to the traceback
860 if excType
is SyntaxError:
862 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
867 filename
= "<string>"
869 self
.traceback
.append( (filename
, lineno
, "", line
) )
872 self
.exception_details
= str(excValue
)
874 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
881 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
884 #---------------------------------------------------------------------------
886 class DemoErrorPanel(wx
.Panel
):
887 """Panel put into the demo tab when the demo fails to run due to errors"""
889 def __init__(self
, parent
, codePanel
, demoError
, log
):
890 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
891 self
.codePanel
= codePanel
895 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
898 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
899 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
901 # Exception Information
902 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
903 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
904 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
905 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
906 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
907 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
908 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
909 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
910 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
911 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
913 # Set up the traceback list
914 # This one automatically resizes last column to take up remaining space
915 from ListCtrl
import TestListCtrl
916 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
917 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
918 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
919 self
.list.InsertColumn(0, "Filename")
920 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
921 self
.list.InsertColumn(2, "Function")
922 self
.list.InsertColumn(3, "Code")
923 self
.InsertTraceback(self
.list, demoError
.traceback
)
924 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
925 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
926 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
927 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
928 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
929 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
930 + "Double-click on them to go to the offending line")
931 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
934 self
.SetSizer(self
.box
)
937 def InsertTraceback(self
, list, traceback
):
938 #Add the traceback data
939 for x
in range(len(traceback
)):
941 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
942 list.SetStringItem(x
, 1, str(data
[1])) # Line
943 list.SetStringItem(x
, 2, str(data
[2])) # Function
944 list.SetStringItem(x
, 3, str(data
[3])) # Code
946 # Check whether this entry is from the demo module
947 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
948 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
949 # Give it a blue colour
950 item
= self
.list.GetItem(x
)
951 item
.SetTextColour(wx
.BLUE
)
952 self
.list.SetItem(item
)
954 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
957 def OnItemSelected(self
, event
):
958 # This occurs before OnDoubleClick and can be used to set the
959 # currentItem. OnDoubleClick doesn't get a wxListEvent....
960 self
.currentItem
= event
.m_itemIndex
964 def OnDoubleClick(self
, event
):
965 # If double-clicking on a demo's entry, jump to the line number
966 line
= self
.list.GetItemData(self
.currentItem
)
968 self
.nb
.SetSelection(1) # Switch to the code viewer tab
969 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
973 #---------------------------------------------------------------------------
975 class wxPythonDemo(wx
.Frame
):
976 overviewText
= "wxPython Overview"
978 def __init__(self
, parent
, title
):
979 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 750),
980 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
983 self
.cwd
= os
.getcwd()
984 self
.curOverview
= ""
987 self
.useModified
= False
990 icon
= images
.getMondrianIcon()
993 if wx
.Platform
!= '__WXMAC__':
994 # setup a taskbar icon, and catch some events from it
995 dim
= 16 # (may want to use 22 on wxGTK, but 16 looks okay too)
996 icon
= wx
.IconFromBitmap(
997 images
.getMondrianImage().Scale(dim
,dim
).ConvertToBitmap() )
998 #icon = wx.Icon('bmp_source/mondrian.ico', wx.BITMAP_TYPE_ICO)
999 #icon = images.getMondrianIcon()
1000 self
.tbicon
= wx
.TaskBarIcon()
1001 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
1002 self
.tbicon
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1003 self
.tbicon
.Bind(wx
.EVT_TASKBAR_RIGHT_UP
, self
.OnTaskBarMenu
)
1004 self
.tbicon
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1005 self
.tbicon
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1007 wx
.CallAfter(self
.ShowTip
)
1009 self
.otherWin
= None
1010 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1011 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1012 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1013 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1015 self
.Centre(wx
.BOTH
)
1016 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1018 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1019 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1021 def EmptyHandler(evt
): pass
1022 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1023 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1025 # Prevent TreeCtrl from displaying all items after destruction when True
1029 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1032 self
.mainmenu
= wx
.MenuBar()
1034 item
= menu
.Append(-1, '&Redirect Output',
1035 'Redirect print statements to a window',
1037 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1039 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1040 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1041 wx
.App_SetMacExitMenuItemId(item
.GetId())
1042 self
.mainmenu
.Append(menu
, '&File')
1046 for item
in _treeList
:
1048 for childItem
in item
[1]:
1049 mi
= submenu
.Append(-1, childItem
)
1050 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1051 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1052 self
.mainmenu
.Append(menu
, '&Demo')
1054 # Make a Demo Code menu
1055 #TODO: Add new menu items
1056 # Like the option-enabled entries to select the
1058 #TODO: should we bother?
1061 #saveID = wx.NewId()
1062 #restoreID = wx.NewId()
1064 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1065 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1066 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1067 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1068 #self.mainmenu.Append(menu, 'Demo &Code')
1073 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1074 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1075 menu
.AppendSeparator()
1077 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1078 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1079 menu
.AppendSeparator()
1080 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1081 wx
.App_SetMacAboutMenuItemId(helpItem
.GetId())
1083 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1084 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1085 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1086 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1087 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1088 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1089 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1090 self
.mainmenu
.Append(menu
, '&Help')
1091 self
.SetMenuBar(self
.mainmenu
)
1093 self
.finddata
= wx
.FindReplaceData()
1096 # This is another way to set Accelerators, in addition to
1097 # using the '\t<key>' syntax in the menu items.
1098 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1099 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1100 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1101 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1103 self
.SetAcceleratorTable(aTable
)
1109 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1110 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1113 root
= self
.tree
.AddRoot("wxPython Overview")
1115 for item
in _treeList
:
1116 child
= self
.tree
.AppendItem(root
, item
[0])
1117 if not firstChild
: firstChild
= child
1118 for childItem
in item
[1]:
1119 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1120 self
.treeMap
[childItem
] = theDemo
1122 self
.tree
.Expand(root
)
1123 self
.tree
.Expand(firstChild
)
1124 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1125 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1126 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1127 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1129 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1130 # we put it in a panel first because there seems to be a
1131 # refresh bug of some sort (wxGTK) when it is directly in
1134 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1135 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1137 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1138 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1139 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1140 self
.nb
.AddPage(panel
, self
.overviewText
)
1142 def OnOvrSize(evt
, ovr
=self
.ovr
):
1143 ovr
.SetSize(evt
.GetSize())
1144 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1145 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1147 if "gtk2" in wx
.PlatformInfo
:
1148 self
.ovr
.NormalizeFontSizes()
1149 self
.SetOverview(self
.overviewText
, mainOverview
)
1152 # Set up a log window
1153 self
.log
= wx
.TextCtrl(splitter2
, -1,
1154 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1156 # Set the wxWindows log target to be this textctrl
1157 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1159 # But instead of the above we want to show how to use our own wx.Log class
1160 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1162 # for serious debugging
1163 #wx.Log_SetActiveTarget(wx.LogStderr())
1164 #wx.Log_SetTraceMask(wx.TraceMessages)
1167 # add the windows to the splitter and split it.
1168 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1169 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1171 splitter
.SetMinimumPaneSize(20)
1172 splitter2
.SetMinimumPaneSize(20)
1174 # Make the splitter on the right expand the top window when resized
1175 def SplitterOnSize(evt
):
1176 splitter
= evt
.GetEventObject()
1177 sz
= splitter
.GetSize()
1178 splitter
.SetSashPosition(sz
.height
- 160, False)
1181 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1183 # select initial items
1184 self
.nb
.SetSelection(0)
1185 self
.tree
.SelectItem(root
)
1187 # Load 'Main' module
1188 self
.LoadDemo(self
.overviewText
)
1191 # select some other initial module?
1192 if len(sys
.argv
) > 1:
1194 if arg
.endswith('.py'):
1196 selectedDemo
= self
.treeMap
.get(arg
, None)
1198 self
.tree
.SelectItem(selectedDemo
)
1199 self
.tree
.EnsureVisible(selectedDemo
)
1202 #---------------------------------------------
1203 def WriteText(self
, text
):
1204 if text
[-1:] == '\n':
1208 def write(self
, txt
):
1211 #---------------------------------------------
1212 def OnItemExpanded(self
, event
):
1213 item
= event
.GetItem()
1214 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1217 #---------------------------------------------
1218 def OnItemCollapsed(self
, event
):
1219 item
= event
.GetItem()
1220 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1223 #---------------------------------------------
1224 def OnTreeLeftDown(self
, event
):
1225 # reset the overview text if the tree item is clicked on again
1226 pt
= event
.GetPosition();
1227 item
, flags
= self
.tree
.HitTest(pt
)
1228 if item
== self
.tree
.GetSelection():
1229 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1232 #---------------------------------------------
1233 def OnSelChanged(self
, event
):
1234 if self
.dying
or not self
.loaded
:
1237 item
= event
.GetItem()
1238 itemText
= self
.tree
.GetItemText(item
)
1239 self
.LoadDemo(itemText
)
1241 #---------------------------------------------
1242 def LoadDemo(self
, demoName
):
1244 wx
.BeginBusyCursor()
1247 self
.ShutdownDemoModule()
1249 if demoName
== self
.overviewText
:
1250 # User selected the "wxPython Overview" node
1252 # Changing the main window at runtime not yet supported...
1253 self
.demoModules
= DemoModules(__name__
)
1254 self
.SetOverview(self
.overviewText
, mainOverview
)
1255 self
.LoadDemoSource()
1256 self
.UpdateNotebook(0)
1258 if os
.path
.exists(GetOriginalFilename(demoName
)):
1259 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1260 self
.demoModules
= DemoModules(demoName
)
1261 self
.LoadDemoSource()
1264 self
.SetOverview("wxPython", mainOverview
)
1265 self
.codePage
= None
1266 self
.UpdateNotebook(0)
1270 #---------------------------------------------
1271 def LoadDemoSource(self
):
1272 self
.codePage
= None
1273 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1274 self
.codePage
.LoadDemo(self
.demoModules
)
1276 #---------------------------------------------
1277 def RunModule(self
):
1278 """Runs the active module"""
1280 module
= self
.demoModules
.GetActive()
1281 self
.ShutdownDemoModule()
1285 # o If the demo returns a window it is placed in a tab.
1286 # o Otherwise, a placeholder tab is created, informing the user that the
1287 # demo runs outside the main window, and allowing it to be reloaded.
1288 # o If an error occurs (or has occured before) an error tab is created.
1290 if module
is not None:
1291 wx
.LogMessage("Running demo module...")
1292 if hasattr(module
, "overview"):
1293 overviewText
= module
.overview
1295 # in case runTest is modal, make sure things look right
1296 # before it starts...
1297 prevSelect
= self
.UpdateNotebook()
1301 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1302 if self
.demoPage
is None:
1303 self
.demoPage
= ReloadDemoPanel(self
.nb
, self
.codePage
, self
)
1305 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
, DemoError(sys
.exc_info()), self
)
1307 # There was a previous error in compiling or exec-ing
1308 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
, self
.demoModules
.GetErrorInfo(), self
)
1310 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1311 self
.UpdateNotebook(prevSelect
)
1313 #---------------------------------------------
1314 def ShutdownDemoModule(self
):
1316 # inform the window that it's time to quit if it cares
1317 if hasattr(self
.demoPage
, "ShutdownDemo"):
1318 self
.demoPage
.ShutdownDemo()
1319 wx
.YieldIfNeeded() # in case the page has pending events
1320 self
.demoPage
= None
1322 #---------------------------------------------
1323 def UpdateNotebook(self
, select
= -1):
1327 def UpdatePage(page
, pageText
):
1330 for i
in range(nb
.GetPageCount()):
1331 if nb
.GetPageText(i
) == pageText
:
1340 # panel = wx.Panel(nb, -1)
1341 # page.Reparent(panel)
1343 # nb.AddPage(panel, pageText)
1344 nb
.AddPage(page
, pageText
)
1345 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1347 # if nb.GetPage(pagePos).page != page:
1348 if nb
.GetPage(pagePos
) != page
:
1349 # Reload an existing page
1352 # panel = nb.GetPage(pagePos)
1354 # page.Reparent(panel)
1356 nb
.DeletePage(pagePos
)
1357 nb
.InsertPage(pagePos
, page
, pageText
)
1359 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1361 # Excellent! No redraw/flicker
1362 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1365 nb
.DeletePage(pagePos
)
1366 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1368 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1371 select
= nb
.GetSelection()
1373 UpdatePage(self
.codePage
, "Demo Code")
1374 UpdatePage(self
.demoPage
, "Demo")
1376 if select
>= 0 and select
< nb
.GetPageCount():
1377 nb
.SetSelection(select
)
1381 #---------------------------------------------
1382 def SetOverview(self
, name
, text
):
1383 self
.curOverview
= text
1385 if lead
!= '<html>' and lead
!= '<HTML>':
1386 text
= '<br>'.join(text
.split('\n'))
1388 text
= text
.decode('iso8859_1')
1389 self
.ovr
.SetPage(text
)
1390 self
.nb
.SetPageText(0, name
)
1392 #---------------------------------------------
1394 def OnFileExit(self
, *event
):
1397 def OnToggleRedirect(self
, event
):
1401 print "Print statements and other standard output will now be directed to this window."
1404 print "Print statements and other standard output will now be sent to the usual location."
1406 def OnHelpAbout(self
, event
):
1407 from About
import MyAboutBox
1408 about
= MyAboutBox(self
)
1412 def OnHelpFind(self
, event
):
1413 self
.nb
.SetSelection(1)
1414 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1418 self
.finddlg
.Show(True)
1420 def OnFind(self
, event
):
1421 editor
= self
.codePage
.editor
1422 self
.nb
.SetSelection(1)
1423 end
= editor
.GetLastPosition()
1424 textstring
= editor
.GetRange(0, end
).lower()
1425 start
= editor
.GetSelection()[1]
1426 findstring
= self
.finddata
.GetFindString().lower()
1427 loc
= textstring
.find(findstring
, start
)
1428 if loc
== -1 and start
!= 0:
1429 # string not found, start at beginning
1431 loc
= textstring
.find(findstring
, start
)
1433 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1434 'Find String Not Found in Demo File',
1435 wx
.OK | wx
.ICON_INFORMATION
)
1440 self
.finddlg
.SetFocus()
1443 self
.finddlg
.Destroy()
1444 editor
.ShowPosition(loc
)
1445 editor
.SetSelection(loc
, loc
+ len(findstring
))
1449 def OnFindNext(self
, event
):
1450 if self
.finddata
.GetFindString():
1453 self
.OnHelpFind(event
)
1455 def OnFindClose(self
, event
):
1456 event
.GetDialog().Destroy()
1459 def OnOpenShellWindow(self
, evt
):
1461 # if it already exists then just make sure it's visible
1467 # Make a PyShell window
1469 namespace
= { 'wx' : wx
,
1470 'app' : wx
.GetApp(),
1473 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1474 self
.shell
.SetSize((640,480))
1477 # Hook the close event of the main frame window so that we
1478 # close the shell at the same time if it still exists
1479 def CloseShell(evt
):
1483 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1486 #---------------------------------------------
1487 def OnCloseWindow(self
, event
):
1489 self
.demoPage
= None
1490 self
.codePage
= None
1491 self
.mainmenu
= None
1495 #---------------------------------------------
1496 def OnIdle(self
, event
):
1498 self
.otherWin
.Raise()
1499 self
.demoPage
= self
.otherWin
1500 self
.otherWin
= None
1503 #---------------------------------------------
1506 showTipText
= open(opj("data/showTips")).read()
1507 showTip
, index
= eval(showTipText
)
1509 showTip
, index
= (1, 0)
1511 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1513 showTip
= wx
.ShowTip(self
, tp
)
1514 index
= tp
.GetCurrentTip()
1515 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1518 #---------------------------------------------
1519 def OnDemoMenu(self
, event
):
1521 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1525 self
.tree
.SelectItem(selectedDemo
)
1526 self
.tree
.EnsureVisible(selectedDemo
)
1529 #---------------------------------------------
1530 def OnTaskBarActivate(self
, evt
):
1531 if self
.IsIconized():
1533 if not self
.IsShown():
1537 #---------------------------------------------
1539 TBMENU_RESTORE
= 1000
1542 def OnTaskBarMenu(self
, evt
):
1544 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1545 menu
.Append(self
.TBMENU_CLOSE
, "Close")
1546 self
.tbicon
.PopupMenu(menu
)
1549 #---------------------------------------------
1550 def OnTaskBarClose(self
, evt
):
1553 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
1554 # prod the main idle handler a bit to get the window to actually close
1555 wx
.GetApp().ProcessIdle()
1558 #---------------------------------------------
1559 def OnIconfiy(self
, evt
):
1560 wx
.LogMessage("OnIconfiy: %d" % evt
.Iconized())
1563 #---------------------------------------------
1564 def OnMaximize(self
, evt
):
1565 wx
.LogMessage("OnMaximize")
1571 #---------------------------------------------------------------------------
1572 #---------------------------------------------------------------------------
1574 class MySplashScreen(wx
.SplashScreen
):
1576 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1577 wx
.SplashScreen
.__init
__(self
, bmp
,
1578 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1580 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1582 def OnClose(self
, evt
):
1584 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1586 evt
.Skip() # Make sure the default handler runs too...
1589 class MyApp(wx
.App
):
1592 Create and show the splash screen. It will then create and show
1593 the main frame when it is time to do so.
1597 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1599 # Normally when using a SplashScreen you would create it, show
1600 # it and then continue on with the applicaiton's
1601 # initialization, finally creating and showing the main
1602 # application window(s). In this case we have nothing else to
1603 # do so we'll delay showing the main frame until later (see
1604 # OnClose above) so the users can see the SplashScreen effect.
1605 splash
= MySplashScreen()
1612 #---------------------------------------------------------------------------
1616 demoPath
= os
.path
.dirname(__file__
)
1620 app
= MyApp(0) ##wx.Platform == "__WXMAC__")
1623 #---------------------------------------------------------------------------
1626 mainOverview
= """<html><body>
1629 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1630 language. It allows Python programmers to create programs with a
1631 robust, highly functional graphical user interface, simply and easily.
1632 It is implemented as a Python extension module (native code) that
1633 wraps the popular wxWindows cross platform GUI library, which is
1636 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1637 means that it is free for anyone to use and the source code is
1638 available for anyone to look at and modify. Or anyone can contribute
1639 fixes or enhancements to the project.
1641 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1642 same program will run on multiple platforms without modification.
1643 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1644 or unix-like systems, and Macintosh OS X. Since the language is
1645 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1648 <p> <b>This demo</b> is not only a collection of test cases for
1649 wxPython, but is also designed to help you learn about and how to use
1650 wxPython. Each sample is listed in the tree control on the left.
1651 When a sample is selected in the tree then a module is loaded and run
1652 (usually in a tab of this notebook,) and the source code of the module
1653 is loaded in another tab for you to browse and learn from.
1658 #----------------------------------------------------------------------------
1659 #----------------------------------------------------------------------------
1661 if __name__
== '__main__':
1665 #----------------------------------------------------------------------------