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()
535 def LoadDemoSource(self
, source
):
537 self
.editor
.SetValue(source
)
539 self
.btnSave
.Enable(False)
542 def JumpToLine(self
, line
, highlight
=False):
543 self
.editor
.GotoLine(line
)
544 self
.editor
.SetFocus()
546 self
.editor
.SelectLine(line
)
549 def UpdateControlState(self
):
550 active
= self
.demoModules
.GetActiveID()
551 # Update the radio/restore buttons
552 for moduleID
in self
.radioButtons
:
553 btn
= self
.radioButtons
[moduleID
]
554 if moduleID
== active
:
559 if self
.demoModules
.Exists(moduleID
):
561 if moduleID
== modModified
:
562 self
.btnRestore
.Enable(True)
565 if moduleID
== modModified
:
566 self
.btnRestore
.Enable(False)
569 def OnRadioButton(self
, event
):
570 radioSelected
= event
.GetEventObject()
571 modSelected
= radioSelected
.modID
572 if modSelected
!= self
.demoModules
.GetActiveID():
573 busy
= wx
.BusyInfo("Reloading demo module...")
574 self
.demoModules
.SetActive(modSelected
)
575 self
.ActiveModuleChanged()
579 def ReloadDemo(self
):
580 if self
.demoModules
.name
!= __name__
:
581 self
.mainFrame
.RunModule(False)
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()
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()
639 #---------------------------------------------------------------------------
642 """Convert paths to the platform-specific separator"""
643 str = apply(os
.path
.join
, tuple(path
.split('/')))
644 # HACK: on Linux, a leading / gets lost...
645 if path
.startswith('/'):
650 def GetModifiedDirectory():
652 Returns the directory where modified versions of the demo files
655 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
658 def GetModifiedFilename(name
):
660 Returns the filename of the modified version of the specified demo
662 if not name
.endswith(".py"):
664 return GetModifiedDirectory() + name
667 def GetOriginalFilename(name
):
669 Returns the filename of the original version of the specified demo
671 if not name
.endswith(".py"):
676 def DoesModifiedExist(name
):
677 """Returns whether the specified demo has a modified copy"""
678 if os
.path
.exists(GetModifiedFilename(name
)):
684 #---------------------------------------------------------------------------
686 class ModuleDictWrapper
:
687 """Emulates a module with a dynamically compiled __dict__"""
688 def __init__(self
, dict):
691 def __getattr__(self
, name
):
692 if name
in self
.dict:
693 return self
.dict[name
]
699 Dynamically manages the original/modified versions of a demo
702 def __init__(self
, name
):
706 # (dict , source , filename , description , error information )
707 # ( 0 , 1 , 2 , 3 , 4 )
708 self
.modules
= [[None, "" , "" , "<original>" , None],
709 [None, "" , "" , "<modified>" , None]]
711 # load original module
712 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
713 self
.SetActive(modOriginal
)
715 # load modified module (if one exists)
716 if DoesModifiedExist(name
):
717 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
718 if (modDefault
== modModified
):
719 self
.SetActive(modModified
)
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 #---------------------------------------------------------------------------
817 class ReloadDemoPanel(wx
.Panel
):
819 Panel put into the demo tab when the demo just shows some
820 top-level window. Enables the demo to be reloaded after being
824 infoText
= "This demo runs outside the main window"
826 def __init__(self
, parent
, codePanel
, log
):
827 wx
.Panel
.__init
__(self
, parent
, -1)
828 self
.codePanel
= codePanel
831 self
.label
= wx
.StaticText(self
, -1, self
.infoText
)
832 self
.btnReload
= wx
.Button(self
, -1, "Reload Demo")
833 self
.btnReload
.Bind(wx
.EVT_BUTTON
, self
.OnReload
)
835 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
836 self
.box
.Add(self
.label
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 10)
837 self
.box
.Add(self
.btnReload
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 10)
840 self
.SetSizer(self
.box
)
842 def OnReload(self
, event
):
843 self
.codePanel
.ReloadDemo()
845 #---------------------------------------------------------------------------
848 """Wraps and stores information about the current exception"""
849 def __init__(self
, exc_info
):
852 excType
, excValue
= exc_info
[:2]
853 # traceback list entries: (filename, line number, function name, text)
854 self
.traceback
= traceback
.extract_tb(exc_info
[2])
856 # --Based on traceback.py::format_exception_only()--
857 if type(excType
) == types
.ClassType
:
858 self
.exception_type
= excType
.__name
__
860 self
.exception_type
= excType
862 # If it's a syntax error, extra information needs
863 # to be added to the traceback
864 if excType
is SyntaxError:
866 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
871 filename
= "<string>"
873 self
.traceback
.append( (filename
, lineno
, "", line
) )
876 self
.exception_details
= str(excValue
)
878 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
885 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
888 #---------------------------------------------------------------------------
890 class DemoErrorPanel(wx
.Panel
):
891 """Panel put into the demo tab when the demo fails to run due to errors"""
893 def __init__(self
, parent
, codePanel
, demoError
, log
):
894 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
895 self
.codePanel
= codePanel
899 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
902 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
903 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
905 # Exception Information
906 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
907 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
908 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
909 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
910 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
911 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
912 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
913 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
914 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
915 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
917 # Set up the traceback list
918 # This one automatically resizes last column to take up remaining space
919 from ListCtrl
import TestListCtrl
920 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
921 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
922 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
923 self
.list.InsertColumn(0, "Filename")
924 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
925 self
.list.InsertColumn(2, "Function")
926 self
.list.InsertColumn(3, "Code")
927 self
.InsertTraceback(self
.list, demoError
.traceback
)
928 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
929 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
930 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
931 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
932 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
933 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
934 + "Double-click on them to go to the offending line")
935 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
938 self
.SetSizer(self
.box
)
941 def InsertTraceback(self
, list, traceback
):
942 #Add the traceback data
943 for x
in range(len(traceback
)):
945 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
946 list.SetStringItem(x
, 1, str(data
[1])) # Line
947 list.SetStringItem(x
, 2, str(data
[2])) # Function
948 list.SetStringItem(x
, 3, str(data
[3])) # Code
950 # Check whether this entry is from the demo module
951 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
952 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
953 # Give it a blue colour
954 item
= self
.list.GetItem(x
)
955 item
.SetTextColour(wx
.BLUE
)
956 self
.list.SetItem(item
)
958 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
961 def OnItemSelected(self
, event
):
962 # This occurs before OnDoubleClick and can be used to set the
963 # currentItem. OnDoubleClick doesn't get a wxListEvent....
964 self
.currentItem
= event
.m_itemIndex
968 def OnDoubleClick(self
, event
):
969 # If double-clicking on a demo's entry, jump to the line number
970 line
= self
.list.GetItemData(self
.currentItem
)
972 self
.nb
.SetSelection(1) # Switch to the code viewer tab
973 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
977 #---------------------------------------------------------------------------
979 class wxPythonDemo(wx
.Frame
):
980 overviewText
= "wxPython Overview"
982 def __init__(self
, parent
, title
):
983 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
984 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
987 self
.cwd
= os
.getcwd()
988 self
.curOverview
= ""
991 self
.useModified
= False
994 icon
= images
.getMondrianIcon()
997 if wx
.Platform
!= '__WXMAC__':
998 # setup a taskbar icon, and catch some events from it
999 dim
= 16 # (may want to use 22 on wxGTK, but 16 looks okay too)
1000 icon
= wx
.IconFromBitmap(
1001 images
.getMondrianImage().Scale(dim
,dim
).ConvertToBitmap() )
1002 #icon = wx.Icon('bmp_source/mondrian.ico', wx.BITMAP_TYPE_ICO)
1003 #icon = images.getMondrianIcon()
1004 self
.tbicon
= wx
.TaskBarIcon()
1005 self
.tbicon
.SetIcon(icon
, "wxPython Demo")
1006 self
.tbicon
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1007 self
.tbicon
.Bind(wx
.EVT_TASKBAR_RIGHT_UP
, self
.OnTaskBarMenu
)
1008 self
.tbicon
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1009 self
.tbicon
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1011 wx
.CallAfter(self
.ShowTip
)
1013 self
.otherWin
= None
1014 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1015 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1016 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1017 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1019 self
.Centre(wx
.BOTH
)
1020 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1022 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1023 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1025 def EmptyHandler(evt
): pass
1026 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1027 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1029 # Prevent TreeCtrl from displaying all items after destruction when True
1033 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1036 self
.mainmenu
= wx
.MenuBar()
1038 item
= menu
.Append(-1, '&Redirect Output',
1039 'Redirect print statements to a window',
1041 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1043 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1044 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1045 wx
.App_SetMacExitMenuItemId(item
.GetId())
1046 self
.mainmenu
.Append(menu
, '&File')
1050 for item
in _treeList
:
1052 for childItem
in item
[1]:
1053 mi
= submenu
.Append(-1, childItem
)
1054 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1055 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1056 self
.mainmenu
.Append(menu
, '&Demo')
1058 # Make a Demo Code menu
1059 #TODO: Add new menu items
1060 # Like the option-enabled entries to select the
1062 #TODO: should we bother?
1065 #saveID = wx.NewId()
1066 #restoreID = wx.NewId()
1068 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1069 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1070 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1071 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1072 #self.mainmenu.Append(menu, 'Demo &Code')
1077 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1078 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1079 menu
.AppendSeparator()
1081 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1082 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1083 menu
.AppendSeparator()
1084 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1085 wx
.App_SetMacAboutMenuItemId(helpItem
.GetId())
1087 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1088 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1089 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1090 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1091 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1092 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1093 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1094 self
.mainmenu
.Append(menu
, '&Help')
1095 self
.SetMenuBar(self
.mainmenu
)
1097 self
.finddata
= wx
.FindReplaceData()
1100 # This is another way to set Accelerators, in addition to
1101 # using the '\t<key>' syntax in the menu items.
1102 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1103 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1104 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1105 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1107 self
.SetAcceleratorTable(aTable
)
1113 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1114 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1117 root
= self
.tree
.AddRoot("wxPython Overview")
1119 for item
in _treeList
:
1120 child
= self
.tree
.AppendItem(root
, item
[0])
1121 if not firstChild
: firstChild
= child
1122 for childItem
in item
[1]:
1123 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1124 self
.treeMap
[childItem
] = theDemo
1126 self
.tree
.Expand(root
)
1127 self
.tree
.Expand(firstChild
)
1128 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1129 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1130 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1131 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1133 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1134 # we put it in a panel first because there seems to be a
1135 # refresh bug of some sort (wxGTK) when it is directly in
1138 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1139 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1141 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1142 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1143 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1144 self
.nb
.AddPage(panel
, self
.overviewText
)
1146 def OnOvrSize(evt
, ovr
=self
.ovr
):
1147 ovr
.SetSize(evt
.GetSize())
1148 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1149 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1151 if "gtk2" in wx
.PlatformInfo
:
1152 self
.ovr
.NormalizeFontSizes()
1153 self
.SetOverview(self
.overviewText
, mainOverview
)
1156 # Set up a log window
1157 self
.log
= wx
.TextCtrl(splitter2
, -1,
1158 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1160 # Set the wxWindows log target to be this textctrl
1161 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1163 # But instead of the above we want to show how to use our own wx.Log class
1164 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1166 # for serious debugging
1167 #wx.Log_SetActiveTarget(wx.LogStderr())
1168 #wx.Log_SetTraceMask(wx.TraceMessages)
1171 # add the windows to the splitter and split it.
1172 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1173 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1175 splitter
.SetMinimumPaneSize(20)
1176 splitter2
.SetMinimumPaneSize(20)
1178 # Make the splitter on the right expand the top window when resized
1179 def SplitterOnSize(evt
):
1180 splitter
= evt
.GetEventObject()
1181 sz
= splitter
.GetSize()
1182 splitter
.SetSashPosition(sz
.height
- 160, False)
1185 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1187 # select initial items
1188 self
.nb
.SetSelection(0)
1189 self
.tree
.SelectItem(root
)
1191 # Load 'Main' module
1192 self
.LoadDemo(self
.overviewText
)
1195 # select some other initial module?
1196 if len(sys
.argv
) > 1:
1198 if arg
.endswith('.py'):
1200 selectedDemo
= self
.treeMap
.get(arg
, None)
1202 self
.tree
.SelectItem(selectedDemo
)
1203 self
.tree
.EnsureVisible(selectedDemo
)
1206 #---------------------------------------------
1207 def WriteText(self
, text
):
1208 if text
[-1:] == '\n':
1212 def write(self
, txt
):
1215 #---------------------------------------------
1216 def OnItemExpanded(self
, event
):
1217 item
= event
.GetItem()
1218 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1221 #---------------------------------------------
1222 def OnItemCollapsed(self
, event
):
1223 item
= event
.GetItem()
1224 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1227 #---------------------------------------------
1228 def OnTreeLeftDown(self
, event
):
1229 # reset the overview text if the tree item is clicked on again
1230 pt
= event
.GetPosition();
1231 item
, flags
= self
.tree
.HitTest(pt
)
1232 if item
== self
.tree
.GetSelection():
1233 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1236 #---------------------------------------------
1237 def OnSelChanged(self
, event
):
1238 if self
.dying
or not self
.loaded
:
1241 item
= event
.GetItem()
1242 itemText
= self
.tree
.GetItemText(item
)
1243 self
.LoadDemo(itemText
)
1245 #---------------------------------------------
1246 def LoadDemo(self
, demoName
):
1248 wx
.BeginBusyCursor()
1251 self
.ShutdownDemoModule()
1253 if demoName
== self
.overviewText
:
1254 # User selected the "wxPython Overview" node
1256 # Changing the main window at runtime not yet supported...
1257 self
.demoModules
= DemoModules(__name__
)
1258 self
.SetOverview(self
.overviewText
, mainOverview
)
1259 self
.LoadDemoSource()
1260 self
.UpdateNotebook(0)
1262 if os
.path
.exists(GetOriginalFilename(demoName
)):
1263 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1264 self
.demoModules
= DemoModules(demoName
)
1265 self
.RunModule(True)
1268 self
.SetOverview("wxPython", mainOverview
)
1269 self
.codePage
= None
1270 self
.UpdateNotebook(0)
1274 #---------------------------------------------
1275 def LoadDemoSource(self
):
1276 self
.codePage
= None
1277 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1278 self
.codePage
.LoadDemo(self
.demoModules
)
1280 #---------------------------------------------
1281 def RunModule(self
, loadSource
):
1282 """Runs the active module"""
1284 module
= self
.demoModules
.GetActive()
1285 self
.ShutdownDemoModule()
1288 # o If the demo returns a window it is placed in a tab.
1289 # o Otherwise, a placeholder tab is created, informing the user that the
1290 # demo runs outside the main window, and allowing it to be reloaded.
1291 # o If an error occurs (or has occured before) an error tab is created.
1293 if module
is not None:
1294 wx
.LogMessage("Running demo module...")
1295 if hasattr(module
, "overview"):
1296 overviewText
= module
.overview
1299 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1300 if self
.demoPage
is None:
1301 self
.demoPage
= ReloadDemoPanel(self
.nb
, self
.codePage
, self
)
1303 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1304 DemoError(sys
.exc_info()), self
)
1306 # There was a previous error in compiling or exec-ing
1307 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1308 self
.demoModules
.GetErrorInfo(), self
)
1311 self
.LoadDemoSource()
1312 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1313 self
.UpdateNotebook()
1315 #---------------------------------------------
1316 def ShutdownDemoModule(self
):
1318 # inform the window that it's time to quit if it cares
1319 if hasattr(self
.demoPage
, "ShutdownDemo"):
1320 self
.demoPage
.ShutdownDemo()
1321 wx
.YieldIfNeeded() # in case the page has pending events
1322 self
.demoPage
= None
1324 #---------------------------------------------
1325 def UpdateNotebook(self
, select
= -1):
1329 def UpdatePage(page
, pageText
):
1332 for i
in range(nb
.GetPageCount()):
1333 if nb
.GetPageText(i
) == pageText
:
1341 nb
.AddPage(page
, pageText
)
1342 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1344 if nb
.GetPage(pagePos
) != page
:
1345 # Reload an existing page
1347 nb
.DeletePage(pagePos
)
1348 nb
.InsertPage(pagePos
, page
, pageText
)
1350 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1352 # Excellent! No redraw/flicker
1353 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1356 nb
.DeletePage(pagePos
)
1357 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1359 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1362 select
= nb
.GetSelection()
1364 UpdatePage(self
.codePage
, "Demo Code")
1365 UpdatePage(self
.demoPage
, "Demo")
1367 if select
>= 0 and select
< nb
.GetPageCount():
1368 nb
.SetSelection(select
)
1370 #---------------------------------------------
1371 def SetOverview(self
, name
, text
):
1372 self
.curOverview
= text
1374 if lead
!= '<html>' and lead
!= '<HTML>':
1375 text
= '<br>'.join(text
.split('\n'))
1377 text
= text
.decode('iso8859_1')
1378 self
.ovr
.SetPage(text
)
1379 self
.nb
.SetPageText(0, name
)
1381 #---------------------------------------------
1383 def OnFileExit(self
, *event
):
1386 def OnToggleRedirect(self
, event
):
1390 print "Print statements and other standard output will now be directed to this window."
1393 print "Print statements and other standard output will now be sent to the usual location."
1395 def OnHelpAbout(self
, event
):
1396 from About
import MyAboutBox
1397 about
= MyAboutBox(self
)
1401 def OnHelpFind(self
, event
):
1402 self
.nb
.SetSelection(1)
1403 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1407 self
.finddlg
.Show(True)
1409 def OnFind(self
, event
):
1410 editor
= self
.codePage
.editor
1411 self
.nb
.SetSelection(1)
1412 end
= editor
.GetLastPosition()
1413 textstring
= editor
.GetRange(0, end
).lower()
1414 start
= editor
.GetSelection()[1]
1415 findstring
= self
.finddata
.GetFindString().lower()
1416 loc
= textstring
.find(findstring
, start
)
1417 if loc
== -1 and start
!= 0:
1418 # string not found, start at beginning
1420 loc
= textstring
.find(findstring
, start
)
1422 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1423 'Find String Not Found in Demo File',
1424 wx
.OK | wx
.ICON_INFORMATION
)
1429 self
.finddlg
.SetFocus()
1432 self
.finddlg
.Destroy()
1433 editor
.ShowPosition(loc
)
1434 editor
.SetSelection(loc
, loc
+ len(findstring
))
1438 def OnFindNext(self
, event
):
1439 if self
.finddata
.GetFindString():
1442 self
.OnHelpFind(event
)
1444 def OnFindClose(self
, event
):
1445 event
.GetDialog().Destroy()
1448 def OnOpenShellWindow(self
, evt
):
1450 # if it already exists then just make sure it's visible
1456 # Make a PyShell window
1458 namespace
= { 'wx' : wx
,
1459 'app' : wx
.GetApp(),
1462 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1463 self
.shell
.SetSize((640,480))
1466 # Hook the close event of the main frame window so that we
1467 # close the shell at the same time if it still exists
1468 def CloseShell(evt
):
1472 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1475 #---------------------------------------------
1476 def OnCloseWindow(self
, event
):
1478 self
.demoPage
= None
1479 self
.codePage
= None
1480 self
.mainmenu
= None
1484 #---------------------------------------------
1485 def OnIdle(self
, event
):
1487 self
.otherWin
.Raise()
1488 self
.demoPage
= self
.otherWin
1489 self
.otherWin
= None
1492 #---------------------------------------------
1495 showTipText
= open(opj("data/showTips")).read()
1496 showTip
, index
= eval(showTipText
)
1498 showTip
, index
= (1, 0)
1500 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1502 showTip
= wx
.ShowTip(self
, tp
)
1503 index
= tp
.GetCurrentTip()
1504 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1507 #---------------------------------------------
1508 def OnDemoMenu(self
, event
):
1510 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1514 self
.tree
.SelectItem(selectedDemo
)
1515 self
.tree
.EnsureVisible(selectedDemo
)
1518 #---------------------------------------------
1519 def OnTaskBarActivate(self
, evt
):
1520 if self
.IsIconized():
1522 if not self
.IsShown():
1526 #---------------------------------------------
1528 TBMENU_RESTORE
= 1000
1531 def OnTaskBarMenu(self
, evt
):
1533 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1534 menu
.Append(self
.TBMENU_CLOSE
, "Close")
1535 self
.tbicon
.PopupMenu(menu
)
1538 #---------------------------------------------
1539 def OnTaskBarClose(self
, evt
):
1542 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
1543 # prod the main idle handler a bit to get the window to actually close
1544 wx
.GetApp().ProcessIdle()
1547 #---------------------------------------------
1548 def OnIconfiy(self
, evt
):
1549 wx
.LogMessage("OnIconfiy: %d" % evt
.Iconized())
1552 #---------------------------------------------
1553 def OnMaximize(self
, evt
):
1554 wx
.LogMessage("OnMaximize")
1560 #---------------------------------------------------------------------------
1561 #---------------------------------------------------------------------------
1563 class MySplashScreen(wx
.SplashScreen
):
1565 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1566 wx
.SplashScreen
.__init
__(self
, bmp
,
1567 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1569 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1571 def OnClose(self
, evt
):
1573 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1575 evt
.Skip() # Make sure the default handler runs too...
1578 class MyApp(wx
.App
):
1581 Create and show the splash screen. It will then create and show
1582 the main frame when it is time to do so.
1586 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1588 # Normally when using a SplashScreen you would create it, show
1589 # it and then continue on with the applicaiton's
1590 # initialization, finally creating and showing the main
1591 # application window(s). In this case we have nothing else to
1592 # do so we'll delay showing the main frame until later (see
1593 # OnClose above) so the users can see the SplashScreen effect.
1594 splash
= MySplashScreen()
1601 #---------------------------------------------------------------------------
1605 demoPath
= os
.path
.dirname(__file__
)
1612 #---------------------------------------------------------------------------
1615 mainOverview
= """<html><body>
1618 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1619 language. It allows Python programmers to create programs with a
1620 robust, highly functional graphical user interface, simply and easily.
1621 It is implemented as a Python extension module (native code) that
1622 wraps the popular wxWindows cross platform GUI library, which is
1625 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1626 means that it is free for anyone to use and the source code is
1627 available for anyone to look at and modify. Or anyone can contribute
1628 fixes or enhancements to the project.
1630 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1631 same program will run on multiple platforms without modification.
1632 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1633 or unix-like systems, and Macintosh OS X. Since the language is
1634 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1637 <p> <b>This demo</b> is not only a collection of test cases for
1638 wxPython, but is also designed to help you learn about and how to use
1639 wxPython. Each sample is listed in the tree control on the left.
1640 When a sample is selected in the tree then a module is loaded and run
1641 (usually in a tab of this notebook,) and the source code of the module
1642 is loaded in another tab for you to browse and learn from.
1647 #----------------------------------------------------------------------------
1648 #----------------------------------------------------------------------------
1650 if __name__
== '__main__':
1654 #----------------------------------------------------------------------------