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', [
79 # dialogs from libraries
82 'MultipleChoiceDialog',
83 'ScrolledMessageDialog',
87 ('Core Windows/Controls', [
127 ('Custom Controls', [
140 # controls coming from other libraries
141 ('More Windows/Controls', [
142 'ActiveX_FlashWindow',
143 'ActiveX_IEHtmlWindow',
145 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
162 'MaskedEditControls',
179 # How to lay out the controls in a frame/dialog
189 'XmlResourceHandler',
190 'XmlResourceSubclass',
194 ('Process and Events', [
201 ##'infoframe', # needs better explanation and some fixing
205 ('Clipboard and DnD', [
227 ##'DialogUnits', # needs more explanations
241 # need libs not coming with the demo
242 ('Samples using an external library', [
247 ('Check out the samples dir too', [
254 #---------------------------------------------------------------------------
255 # Show how to derive a custom wxLog class
257 class MyLog(wx
.PyLog
):
258 def __init__(self
, textCtrl
, logTime
=0):
259 wx
.PyLog
.__init
__(self
)
261 self
.logTime
= logTime
263 def DoLogString(self
, message
, timeStamp
):
264 #print message, timeStamp
266 # message = time.strftime("%X", time.localtime(timeStamp)) + \
269 self
.tc
.AppendText(message
+ '\n')
272 class MyTP(wx
.PyTipProvider
):
274 return "This is my tip"
276 #---------------------------------------------------------------------------
277 # A class to be used to simply display a message in the demo pane
278 # rather than running the sample itself.
280 class MessagePanel(wx
.Panel
):
281 def __init__(self
, parent
, message
, caption
='', flags
=0):
282 wx
.Panel
.__init
__(self
, parent
)
287 if flags
& wx
.ICON_EXCLAMATION
:
288 artid
= wx
.ART_WARNING
289 elif flags
& wx
.ICON_ERROR
:
291 elif flags
& wx
.ICON_QUESTION
:
292 artid
= wx
.ART_QUESTION
293 elif flags
& wx
.ICON_INFORMATION
:
294 artid
= wx
.ART_INFORMATION
296 if artid
is not None:
297 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
298 icon
= wx
.StaticBitmap(self
, -1, bmp
)
300 icon
= (32,32) # make a spacer instead
303 caption
= wx
.StaticText(self
, -1, caption
)
304 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
306 message
= wx
.StaticText(self
, -1, message
)
308 # add to sizers for layout
309 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
315 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
322 box
= wx
.BoxSizer(wx
.VERTICAL
)
324 box
.Add(hbox
, 0, wx
.EXPAND
)
331 #---------------------------------------------------------------------------
332 # A class to be used to display source code in the demo. Try using the
333 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
334 # if there is an error, such as the stc module not being present.
338 ##raise ImportError # for testing the alternate implementation
340 from StyledTextCtrl_2
import PythonSTC
342 class DemoCodeEditor(PythonSTC
):
343 def __init__(self
, parent
):
344 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
347 # Some methods to make it compatible with how the wxTextCtrl is used
348 def SetValue(self
, value
):
350 value
= value
.decode('iso8859_1')
352 self
.EmptyUndoBuffer()
355 def IsModified(self
):
356 return self
.GetModify()
361 def SetInsertionPoint(self
, pos
):
362 self
.SetCurrentPos(pos
)
365 def ShowPosition(self
, pos
):
366 line
= self
.LineFromPosition(pos
)
367 #self.EnsureVisible(line)
370 def GetLastPosition(self
):
371 return self
.GetLength()
373 def GetPositionFromLine(self
, line
):
374 return self
.PositionFromLine(line
)
376 def GetRange(self
, start
, end
):
377 return self
.GetTextRange(start
, end
)
379 def GetSelection(self
):
380 return self
.GetAnchor(), self
.GetCurrentPos()
382 def SetSelection(self
, start
, end
):
383 self
.SetSelectionStart(start
)
384 self
.SetSelectionEnd(end
)
386 def SelectLine(self
, line
):
387 start
= self
.PositionFromLine(line
)
388 end
= self
.GetLineEndPosition(line
)
389 self
.SetSelection(start
, end
)
391 def SetUpEditor(self
):
393 This method carries out the work of setting up the demo editor.
394 It's seperate so as not to clutter up the init code.
398 self
.SetLexer(stc
.STC_LEX_PYTHON
)
399 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
402 self
.SetProperty("fold", "1" )
404 # Highlight tab/space mixing (shouldn't be any)
405 self
.SetProperty("tab.timmy.whinge.level", "1")
407 # Set left and right margins
410 # Set up the numbers in the margin for margin #1
411 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
412 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
413 self
.SetMarginWidth(1, 40)
415 # Indentation and tab stuff
416 self
.SetIndent(4) # Proscribed indent size for wx
417 self
.SetIndentationGuides(True) # Show indent guides
418 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
419 self
.SetTabIndents(True) # Tab key indents
420 self
.SetTabWidth(4) # Proscribed tab size for wx
421 self
.SetUseTabs(False) # Use spaces rather than tabs, or
422 # TabTimmy will complain!
424 self
.SetViewWhiteSpace(False) # Don't view white space
426 # EOL: Since we are loading/saving ourselves, and the
427 # strings will always have \n's in them, set the STC to
428 # edit them that way.
429 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
430 self
.SetViewEOL(False)
432 # No right-edge mode indicator
433 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
435 # Setup a margin to hold fold markers
436 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
437 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
438 self
.SetMarginSensitive(2, True)
439 self
.SetMarginWidth(2, 12)
441 # and now set up the fold markers
442 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
443 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
444 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
445 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
446 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
447 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
448 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
450 # Global default style
451 if wx
.Platform
== '__WXMSW__':
452 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
453 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
455 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
456 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
458 # Clear styles and revert to default.
461 # Following style specs only indicate differences from default.
462 # The rest remains unchanged.
464 # Line numbers in margin
465 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
467 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
469 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
471 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
474 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
476 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
477 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
479 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
480 # Strings and characters
481 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
482 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
484 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
486 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
487 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
489 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
491 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
493 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
494 # Identifiers. I leave this as not bold because everything seems
495 # to be an identifier if it doesn't match the above criterae
496 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
499 self
.SetCaretForeground("BLUE")
500 # Selection background
501 self
.SetSelBackground(1, '#66CCFF')
503 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
504 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
506 def RegisterModifiedEvent(self
, eventHandler
):
507 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
511 class DemoCodeEditor(wx
.TextCtrl
):
512 def __init__(self
, parent
):
513 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
514 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
516 def RegisterModifiedEvent(self
, eventHandler
):
517 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
519 def SetReadOnly(self
, flag
):
520 self
.SetEditable(not flag
)
521 # NOTE: STC already has this method
524 return self
.GetValue()
526 def GetPositionFromLine(self
, line
):
527 return self
.XYToPosition(0,line
)
529 def GotoLine(self
, line
):
530 pos
= self
.GetPositionFromLine(line
)
531 self
.SetInsertionPoint(pos
)
532 self
.ShowPosition(pos
)
534 def SelectLine(self
, line
):
535 start
= self
.GetPositionFromLine(line
)
536 end
= start
+ self
.GetLineLength(line
)
537 self
.SetSelection(start
, end
)
540 #---------------------------------------------------------------------------
541 # Constants for module versions
545 modDefault
= modOriginal
547 #---------------------------------------------------------------------------
549 class DemoCodePanel(wx
.Panel
):
550 """Panel for the 'Demo Code' tab"""
551 def __init__(self
, parent
, mainFrame
):
552 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
553 if 'wxMSW' in wx
.PlatformInfo
:
555 self
.mainFrame
= mainFrame
556 self
.editor
= DemoCodeEditor(self
)
557 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
559 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
560 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
561 self
.btnSave
.Enable(False)
562 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
563 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
565 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
566 modModified
: wx
.RadioButton(self
, -1, "Modified") }
568 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
569 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
570 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
571 for modID
, radioButton
in self
.radioButtons
.items():
572 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
573 radioButton
.modID
= modID
# makes it easier for the event handler
574 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
576 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
577 self
.controlBox
.Add(self
.btnRestore
, 0)
579 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
580 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
581 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
582 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
585 self
.SetSizer(self
.box
)
588 # Loads a demo from a DemoModules object
589 def LoadDemo(self
, demoModules
):
590 self
.demoModules
= demoModules
591 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
592 demoModules
.SetActive(modModified
)
594 demoModules
.SetActive(modOriginal
)
595 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
596 self
.ActiveModuleChanged()
599 def ActiveModuleChanged(self
):
600 self
.LoadDemoSource(self
.demoModules
.GetSource())
601 self
.UpdateControlState()
605 def LoadDemoSource(self
, source
):
607 self
.editor
.SetValue(source
)
609 self
.btnSave
.Enable(False)
612 def JumpToLine(self
, line
, highlight
=False):
613 self
.editor
.GotoLine(line
)
614 self
.editor
.SetFocus()
616 self
.editor
.SelectLine(line
)
619 def UpdateControlState(self
):
620 active
= self
.demoModules
.GetActiveID()
621 # Update the radio/restore buttons
622 for moduleID
in self
.radioButtons
:
623 btn
= self
.radioButtons
[moduleID
]
624 if moduleID
== active
:
629 if self
.demoModules
.Exists(moduleID
):
631 if moduleID
== modModified
:
632 self
.btnRestore
.Enable(True)
635 if moduleID
== modModified
:
636 self
.btnRestore
.Enable(False)
639 def OnRadioButton(self
, event
):
640 radioSelected
= event
.GetEventObject()
641 modSelected
= radioSelected
.modID
642 if modSelected
!= self
.demoModules
.GetActiveID():
643 busy
= wx
.BusyInfo("Reloading demo module...")
644 self
.demoModules
.SetActive(modSelected
)
645 self
.ActiveModuleChanged()
648 def ReloadDemo(self
):
649 if self
.demoModules
.name
!= __name__
:
650 self
.mainFrame
.RunModule()
653 def OnCodeModified(self
, event
):
654 self
.btnSave
.Enable(self
.editor
.IsModified())
657 def OnSave(self
, event
):
658 if self
.demoModules
.Exists(modModified
):
659 if self
.demoModules
.GetActiveID() == modOriginal
:
660 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
661 "Do you want to continue?"
662 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
663 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
664 result
= dlg
.ShowModal()
665 if result
== wx
.ID_NO
:
669 self
.demoModules
.SetActive(modModified
)
670 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
672 # Create the demo directory if one doesn't already exist
673 if not os
.path
.exists(GetModifiedDirectory()):
675 os
.makedirs(GetModifiedDirectory())
676 if not os
.path
.exists(GetModifiedDirectory()):
677 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
680 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
683 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
686 f
= open(modifiedFilename
, "wt")
687 source
= self
.editor
.GetText()
693 busy
= wx
.BusyInfo("Reloading demo module...")
694 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
695 self
.ActiveModuleChanged()
698 def OnRestore(self
, event
): # Handles the "Delete Modified" button
699 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
700 self
.demoModules
.Delete(modModified
)
701 os
.unlink(modifiedFilename
) # Delete the modified copy
702 busy
= wx
.BusyInfo("Reloading demo module...")
703 self
.ActiveModuleChanged()
706 #---------------------------------------------------------------------------
709 """Convert paths to the platform-specific separator"""
710 str = apply(os
.path
.join
, tuple(path
.split('/')))
711 # HACK: on Linux, a leading / gets lost...
712 if path
.startswith('/'):
717 def GetModifiedDirectory():
719 Returns the directory where modified versions of the demo files
722 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
725 def GetModifiedFilename(name
):
727 Returns the filename of the modified version of the specified demo
729 if not name
.endswith(".py"):
731 return GetModifiedDirectory() + name
734 def GetOriginalFilename(name
):
736 Returns the filename of the original version of the specified demo
738 if not name
.endswith(".py"):
743 def DoesModifiedExist(name
):
744 """Returns whether the specified demo has a modified copy"""
745 if os
.path
.exists(GetModifiedFilename(name
)):
751 #---------------------------------------------------------------------------
753 class ModuleDictWrapper
:
754 """Emulates a module with a dynamically compiled __dict__"""
755 def __init__(self
, dict):
758 def __getattr__(self
, name
):
759 if name
in self
.dict:
760 return self
.dict[name
]
766 Dynamically manages the original/modified versions of a demo
769 def __init__(self
, name
):
773 # (dict , source , filename , description , error information )
774 # ( 0 , 1 , 2 , 3 , 4 )
775 self
.modules
= [[None, "" , "" , "<original>" , None],
776 [None, "" , "" , "<modified>" , None]]
778 # load original module
779 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
780 self
.SetActive(modOriginal
)
782 # load modified module (if one exists)
783 if DoesModifiedExist(name
):
784 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
787 def LoadFromFile(self
, modID
, filename
):
788 self
.modules
[modID
][2] = filename
789 file = open(filename
, "rt")
790 self
.LoadFromSource(modID
, file.read())
794 def LoadFromSource(self
, modID
, source
):
795 self
.modules
[modID
][1] = source
799 def LoadDict(self
, modID
):
800 if self
.name
!= __name__
:
801 source
= self
.modules
[modID
][1]
802 description
= self
.modules
[modID
][3]
805 self
.modules
[modID
][0] = {}
806 code
= compile(source
, description
, "exec")
807 exec code
in self
.modules
[modID
][0]
809 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
810 self
.modules
[modID
][0] = None
812 self
.modules
[modID
][4] = None
815 def SetActive(self
, modID
):
816 if modID
!= modOriginal
and modID
!= modModified
:
819 self
.modActive
= modID
823 dict = self
.modules
[self
.modActive
][0]
827 return ModuleDictWrapper(dict)
830 def GetActiveID(self
):
831 return self
.modActive
834 def GetSource(self
, modID
= None):
836 modID
= self
.modActive
837 return self
.modules
[modID
][1]
840 def GetFilename(self
, modID
= None):
842 modID
= self
.modActive
843 return self
.modules
[self
.modActive
][2]
846 def GetErrorInfo(self
, modID
= None):
848 modID
= self
.modActive
849 return self
.modules
[self
.modActive
][4]
852 def Exists(self
, modID
):
853 return self
.modules
[modID
][1] != ""
856 def UpdateFile(self
, modID
= None):
857 """Updates the file from which a module was loaded
858 with (possibly updated) source"""
860 modID
= self
.modActive
862 source
= self
.modules
[modID
][1]
863 filename
= self
.modules
[modID
][2]
866 file = open(filename
, "wt")
872 def Delete(self
, modID
):
873 if self
.modActive
== modID
:
876 self
.modules
[modID
][0] = None
877 self
.modules
[modID
][1] = ""
878 self
.modules
[modID
][2] = ""
881 #---------------------------------------------------------------------------
884 """Wraps and stores information about the current exception"""
885 def __init__(self
, exc_info
):
888 excType
, excValue
= exc_info
[:2]
889 # traceback list entries: (filename, line number, function name, text)
890 self
.traceback
= traceback
.extract_tb(exc_info
[2])
892 # --Based on traceback.py::format_exception_only()--
893 if type(excType
) == types
.ClassType
:
894 self
.exception_type
= excType
.__name
__
896 self
.exception_type
= excType
898 # If it's a syntax error, extra information needs
899 # to be added to the traceback
900 if excType
is SyntaxError:
902 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
907 filename
= "<string>"
909 self
.traceback
.append( (filename
, lineno
, "", line
) )
912 self
.exception_details
= str(excValue
)
914 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
921 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
924 #---------------------------------------------------------------------------
926 class DemoErrorPanel(wx
.Panel
):
927 """Panel put into the demo tab when the demo fails to run due to errors"""
929 def __init__(self
, parent
, codePanel
, demoError
, log
):
930 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
931 self
.codePanel
= codePanel
935 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
938 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
939 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
941 # Exception Information
942 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
943 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
944 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
945 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
946 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
947 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
948 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
949 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
950 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
951 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
953 # Set up the traceback list
954 # This one automatically resizes last column to take up remaining space
955 from ListCtrl
import TestListCtrl
956 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
957 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
958 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
959 self
.list.InsertColumn(0, "Filename")
960 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
961 self
.list.InsertColumn(2, "Function")
962 self
.list.InsertColumn(3, "Code")
963 self
.InsertTraceback(self
.list, demoError
.traceback
)
964 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
965 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
966 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
967 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
968 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
969 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
970 + "Double-click on them to go to the offending line")
971 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
974 self
.SetSizer(self
.box
)
977 def InsertTraceback(self
, list, traceback
):
978 #Add the traceback data
979 for x
in range(len(traceback
)):
981 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
982 list.SetStringItem(x
, 1, str(data
[1])) # Line
983 list.SetStringItem(x
, 2, str(data
[2])) # Function
984 list.SetStringItem(x
, 3, str(data
[3])) # Code
986 # Check whether this entry is from the demo module
987 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
988 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
989 # Give it a blue colour
990 item
= self
.list.GetItem(x
)
991 item
.SetTextColour(wx
.BLUE
)
992 self
.list.SetItem(item
)
994 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
997 def OnItemSelected(self
, event
):
998 # This occurs before OnDoubleClick and can be used to set the
999 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1000 self
.currentItem
= event
.m_itemIndex
1004 def OnDoubleClick(self
, event
):
1005 # If double-clicking on a demo's entry, jump to the line number
1006 line
= self
.list.GetItemData(self
.currentItem
)
1008 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1009 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1013 #---------------------------------------------------------------------------
1015 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1016 TBMENU_RESTORE
= wx
.NewId()
1017 TBMENU_CLOSE
= wx
.NewId()
1018 TBMENU_CHANGE
= wx
.NewId()
1019 TBMENU_REMOVE
= wx
.NewId()
1021 def __init__(self
, frame
):
1022 wx
.TaskBarIcon
.__init
__(self
)
1026 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1027 self
.SetIcon(icon
, "wxPython Demo")
1031 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1032 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1033 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1034 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1035 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1038 def CreatePopupMenu(self
):
1040 This method is called by the base class when it needs to popup
1041 the menu for the default EVT_RIGHT_DOWN event. Just create
1042 the menu how you want it and return it from this function,
1043 the base class takes care of the rest.
1046 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1047 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1048 menu
.AppendSeparator()
1049 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1050 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1054 def MakeIcon(self
, img
):
1056 The various platforms have different requirements for the
1059 if "wxMSW" in wx
.PlatformInfo
:
1060 img
= img
.Scale(16, 16)
1061 elif "wxGTK" in wx
.PlatformInfo
:
1062 img
= img
.Scale(22, 22)
1063 # wxMac can be any size upto 128x128, so leave the source img alone....
1064 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1068 def OnTaskBarActivate(self
, evt
):
1069 if self
.frame
.IsIconized():
1070 self
.frame
.Iconize(False)
1071 if not self
.frame
.IsShown():
1072 self
.frame
.Show(True)
1076 def OnTaskBarClose(self
, evt
):
1080 def OnTaskBarChange(self
, evt
):
1081 names
= [ "WXPdemo", "WXP", "Mondrian", "Test2m",
1082 "Blom08m", "Blom10m", "Blom15m" ]
1083 name
= names
[self
.imgidx
]
1085 getFunc
= getattr(images
, "get%sImage" % name
)
1087 if self
.imgidx
>= len(names
):
1090 icon
= self
.MakeIcon(getFunc())
1091 self
.SetIcon(icon
, "This is a new icon: " + name
)
1094 def OnTaskBarRemove(self
, evt
):
1098 #---------------------------------------------------------------------------
1099 class wxPythonDemo(wx
.Frame
):
1100 overviewText
= "wxPython Overview"
1102 def __init__(self
, parent
, title
):
1103 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1104 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1106 self
.SetMinSize((640,480))
1109 self
.cwd
= os
.getcwd()
1110 self
.curOverview
= ""
1111 self
.demoPage
= None
1112 self
.codePage
= None
1114 self
.firstTime
= True
1117 icon
= images
.getWXPdemoIcon()
1120 self
.tbicon
= DemoTaskBarIcon(self
)
1122 wx
.CallAfter(self
.ShowTip
)
1124 self
.otherWin
= None
1125 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1126 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1127 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1128 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1130 self
.Centre(wx
.BOTH
)
1131 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1133 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1134 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1136 def EmptyHandler(evt
): pass
1137 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1138 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1140 # Prevent TreeCtrl from displaying all items after destruction when True
1144 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1147 self
.mainmenu
= wx
.MenuBar()
1149 item
= menu
.Append(-1, '&Redirect Output',
1150 'Redirect print statements to a window',
1152 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1154 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1155 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1156 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1157 self
.mainmenu
.Append(menu
, '&File')
1161 for item
in _treeList
:
1163 for childItem
in item
[1]:
1164 mi
= submenu
.Append(-1, childItem
)
1165 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1166 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1167 self
.mainmenu
.Append(menu
, '&Demo')
1169 # Make a Demo Code menu
1170 #TODO: Add new menu items
1171 # Like the option-enabled entries to select the
1173 #TODO: should we bother?
1176 #saveID = wx.NewId()
1177 #restoreID = wx.NewId()
1179 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1180 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1181 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1182 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1183 #self.mainmenu.Append(menu, 'Demo &Code')
1188 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1189 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1190 menu
.AppendSeparator()
1192 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1193 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1194 menu
.AppendSeparator()
1195 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1196 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1198 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1199 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1200 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1201 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1202 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1203 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1204 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1205 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1206 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1207 self
.mainmenu
.Append(menu
, '&Help')
1208 self
.SetMenuBar(self
.mainmenu
)
1210 self
.finddata
= wx
.FindReplaceData()
1213 # This is another way to set Accelerators, in addition to
1214 # using the '\t<key>' syntax in the menu items.
1215 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1216 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1217 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1218 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1220 self
.SetAcceleratorTable(aTable
)
1226 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1227 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1230 root
= self
.tree
.AddRoot("wxPython Overview")
1232 for item
in _treeList
:
1233 child
= self
.tree
.AppendItem(root
, item
[0])
1234 if not firstChild
: firstChild
= child
1235 for childItem
in item
[1]:
1236 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1237 self
.treeMap
[childItem
] = theDemo
1239 self
.tree
.Expand(root
)
1240 self
.tree
.Expand(firstChild
)
1241 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1242 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1243 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1244 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1246 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1247 # we put it in a panel first because there seems to be a
1248 # refresh bug of some sort (wxGTK) when it is directly in
1251 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1252 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1254 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1255 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1256 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1257 self
.nb
.AddPage(panel
, self
.overviewText
)
1259 def OnOvrSize(evt
, ovr
=self
.ovr
):
1260 ovr
.SetSize(evt
.GetSize())
1261 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1262 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1264 if "gtk2" in wx
.PlatformInfo
:
1265 self
.ovr
.SetStandardFonts()
1266 self
.SetOverview(self
.overviewText
, mainOverview
)
1269 # Set up a log window
1270 self
.log
= wx
.TextCtrl(splitter2
, -1,
1271 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1273 # Set the wxWindows log target to be this textctrl
1274 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1276 # But instead of the above we want to show how to use our own wx.Log class
1277 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1279 # for serious debugging
1280 #wx.Log_SetActiveTarget(wx.LogStderr())
1281 #wx.Log_SetTraceMask(wx.TraceMessages)
1284 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1285 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1287 # add the windows to the splitter and split it.
1288 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1289 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1291 splitter
.SetMinimumPaneSize(120)
1292 splitter2
.SetMinimumPaneSize(60)
1294 # Make the splitter on the right expand the top window when resized
1295 def SplitterOnSize(evt
):
1296 splitter
= evt
.GetEventObject()
1297 sz
= splitter
.GetSize()
1298 splitter
.SetSashPosition(sz
.height
- 160, False)
1301 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1303 # select initial items
1304 self
.nb
.SetSelection(0)
1305 self
.tree
.SelectItem(root
)
1307 # Load 'Main' module
1308 self
.LoadDemo(self
.overviewText
)
1311 # select some other initial module?
1312 if len(sys
.argv
) > 1:
1314 if arg
.endswith('.py'):
1316 selectedDemo
= self
.treeMap
.get(arg
, None)
1318 self
.tree
.SelectItem(selectedDemo
)
1319 self
.tree
.EnsureVisible(selectedDemo
)
1322 #---------------------------------------------
1323 def WriteText(self
, text
):
1324 if text
[-1:] == '\n':
1328 def write(self
, txt
):
1331 #---------------------------------------------
1332 def OnItemExpanded(self
, event
):
1333 item
= event
.GetItem()
1334 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1337 #---------------------------------------------
1338 def OnItemCollapsed(self
, event
):
1339 item
= event
.GetItem()
1340 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1343 #---------------------------------------------
1344 def OnTreeLeftDown(self
, event
):
1345 # reset the overview text if the tree item is clicked on again
1346 pt
= event
.GetPosition();
1347 item
, flags
= self
.tree
.HitTest(pt
)
1348 if item
== self
.tree
.GetSelection():
1349 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1352 #---------------------------------------------
1353 def OnSelChanged(self
, event
):
1354 if self
.dying
or not self
.loaded
:
1357 item
= event
.GetItem()
1358 itemText
= self
.tree
.GetItemText(item
)
1359 self
.LoadDemo(itemText
)
1361 #---------------------------------------------
1362 def LoadDemo(self
, demoName
):
1364 wx
.BeginBusyCursor()
1367 self
.ShutdownDemoModule()
1369 if demoName
== self
.overviewText
:
1370 # User selected the "wxPython Overview" node
1372 # Changing the main window at runtime not yet supported...
1373 self
.demoModules
= DemoModules(__name__
)
1374 self
.SetOverview(self
.overviewText
, mainOverview
)
1375 self
.LoadDemoSource()
1376 self
.UpdateNotebook(0)
1378 if os
.path
.exists(GetOriginalFilename(demoName
)):
1379 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1380 self
.demoModules
= DemoModules(demoName
)
1381 self
.LoadDemoSource()
1384 self
.SetOverview("wxPython", mainOverview
)
1385 self
.codePage
= None
1386 self
.UpdateNotebook(0)
1390 #---------------------------------------------
1391 def LoadDemoSource(self
):
1392 self
.codePage
= None
1393 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1394 self
.codePage
.LoadDemo(self
.demoModules
)
1396 #---------------------------------------------
1397 def RunModule(self
):
1398 """Runs the active module"""
1400 module
= self
.demoModules
.GetActive()
1401 self
.ShutdownDemoModule()
1404 # o The RunTest() for all samples must now return a window that can
1405 # be palced in a tab in the main notebook.
1406 # o If an error occurs (or has occured before) an error tab is created.
1408 if module
is not None:
1409 wx
.LogMessage("Running demo module...")
1410 if hasattr(module
, "overview"):
1411 overviewText
= module
.overview
1414 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1416 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1417 DemoError(sys
.exc_info()), self
)
1419 assert self
.demoPage
is not None, "runTest must return a window!"
1422 # There was a previous error in compiling or exec-ing
1423 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1424 self
.demoModules
.GetErrorInfo(), self
)
1426 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1429 # cahnge to the demo page the first time a module is run
1430 self
.UpdateNotebook(2)
1431 self
.firstTime
= False
1433 # otherwise just stay on the same tab in case the user has changed to another one
1434 self
.UpdateNotebook()
1436 #---------------------------------------------
1437 def ShutdownDemoModule(self
):
1439 # inform the window that it's time to quit if it cares
1440 if hasattr(self
.demoPage
, "ShutdownDemo"):
1441 self
.demoPage
.ShutdownDemo()
1442 wx
.YieldIfNeeded() # in case the page has pending events
1443 self
.demoPage
= None
1445 #---------------------------------------------
1446 def UpdateNotebook(self
, select
= -1):
1450 def UpdatePage(page
, pageText
):
1453 for i
in range(nb
.GetPageCount()):
1454 if nb
.GetPageText(i
) == pageText
:
1462 nb
.AddPage(page
, pageText
)
1463 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1465 if nb
.GetPage(pagePos
) != page
:
1466 # Reload an existing page
1468 nb
.DeletePage(pagePos
)
1469 nb
.InsertPage(pagePos
, page
, pageText
)
1471 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1473 # Excellent! No redraw/flicker
1474 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1477 nb
.DeletePage(pagePos
)
1478 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1480 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1483 select
= nb
.GetSelection()
1485 UpdatePage(self
.codePage
, "Demo Code")
1486 UpdatePage(self
.demoPage
, "Demo")
1488 if select
>= 0 and select
< nb
.GetPageCount():
1489 nb
.SetSelection(select
)
1491 #---------------------------------------------
1492 def SetOverview(self
, name
, text
):
1493 self
.curOverview
= text
1495 if lead
!= '<html>' and lead
!= '<HTML>':
1496 text
= '<br>'.join(text
.split('\n'))
1498 text
= text
.decode('iso8859_1')
1499 self
.ovr
.SetPage(text
)
1500 self
.nb
.SetPageText(0, name
)
1502 #---------------------------------------------
1504 def OnFileExit(self
, *event
):
1507 def OnToggleRedirect(self
, event
):
1511 print "Print statements and other standard output will now be directed to this window."
1514 print "Print statements and other standard output will now be sent to the usual location."
1516 def OnHelpAbout(self
, event
):
1517 from About
import MyAboutBox
1518 about
= MyAboutBox(self
)
1522 def OnHelpFind(self
, event
):
1523 if self
.finddlg
!= None:
1526 self
.nb
.SetSelection(1)
1527 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1531 self
.finddlg
.Show(True)
1534 def OnUpdateFindItems(self
, evt
):
1535 evt
.Enable(self
.finddlg
== None)
1538 def OnFind(self
, event
):
1539 editor
= self
.codePage
.editor
1540 self
.nb
.SetSelection(1)
1541 end
= editor
.GetLastPosition()
1542 textstring
= editor
.GetRange(0, end
).lower()
1543 start
= editor
.GetSelection()[1]
1544 findstring
= self
.finddata
.GetFindString().lower()
1545 loc
= textstring
.find(findstring
, start
)
1546 if loc
== -1 and start
!= 0:
1547 # string not found, start at beginning
1549 loc
= textstring
.find(findstring
, start
)
1551 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1552 'Find String Not Found in Demo File',
1553 wx
.OK | wx
.ICON_INFORMATION
)
1558 self
.finddlg
.SetFocus()
1561 self
.finddlg
.Destroy()
1563 editor
.ShowPosition(loc
)
1564 editor
.SetSelection(loc
, loc
+ len(findstring
))
1568 def OnFindNext(self
, event
):
1569 if self
.finddata
.GetFindString():
1572 self
.OnHelpFind(event
)
1574 def OnFindClose(self
, event
):
1575 event
.GetDialog().Destroy()
1579 def OnOpenShellWindow(self
, evt
):
1581 # if it already exists then just make sure it's visible
1587 # Make a PyShell window
1589 namespace
= { 'wx' : wx
,
1590 'app' : wx
.GetApp(),
1593 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1594 self
.shell
.SetSize((640,480))
1597 # Hook the close event of the main frame window so that we
1598 # close the shell at the same time if it still exists
1599 def CloseShell(evt
):
1603 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1606 #---------------------------------------------
1607 def OnCloseWindow(self
, event
):
1609 self
.demoPage
= None
1610 self
.codePage
= None
1611 self
.mainmenu
= None
1612 self
.tbicon
.Destroy()
1616 #---------------------------------------------
1617 def OnIdle(self
, event
):
1619 self
.otherWin
.Raise()
1620 self
.demoPage
= self
.otherWin
1621 self
.otherWin
= None
1624 #---------------------------------------------
1627 showTipText
= open(opj("data/showTips")).read()
1628 showTip
, index
= eval(showTipText
)
1630 showTip
, index
= (1, 0)
1632 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1634 showTip
= wx
.ShowTip(self
, tp
)
1635 index
= tp
.GetCurrentTip()
1636 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1639 #---------------------------------------------
1640 def OnDemoMenu(self
, event
):
1642 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1646 self
.tree
.SelectItem(selectedDemo
)
1647 self
.tree
.EnsureVisible(selectedDemo
)
1651 #---------------------------------------------
1652 def OnIconfiy(self
, evt
):
1653 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1656 #---------------------------------------------
1657 def OnMaximize(self
, evt
):
1658 wx
.LogMessage("OnMaximize")
1661 #---------------------------------------------
1662 def OnActivate(self
, evt
):
1663 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1666 #---------------------------------------------
1667 def OnAppActivate(self
, evt
):
1668 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1671 #---------------------------------------------------------------------------
1672 #---------------------------------------------------------------------------
1674 class MySplashScreen(wx
.SplashScreen
):
1676 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1677 wx
.SplashScreen
.__init
__(self
, bmp
,
1678 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1680 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1682 def OnClose(self
, evt
):
1684 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1686 evt
.Skip() # Make sure the default handler runs too...
1689 class MyApp(wx
.App
):
1692 Create and show the splash screen. It will then create and show
1693 the main frame when it is time to do so.
1696 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1699 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1701 # Normally when using a SplashScreen you would create it, show
1702 # it and then continue on with the applicaiton's
1703 # initialization, finally creating and showing the main
1704 # application window(s). In this case we have nothing else to
1705 # do so we'll delay showing the main frame until later (see
1706 # OnClose above) so the users can see the SplashScreen effect.
1707 splash
= MySplashScreen()
1714 #---------------------------------------------------------------------------
1718 demoPath
= os
.path
.dirname(__file__
)
1725 #---------------------------------------------------------------------------
1728 mainOverview
= """<html><body>
1731 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1732 language. It allows Python programmers to create programs with a
1733 robust, highly functional graphical user interface, simply and easily.
1734 It is implemented as a Python extension module (native code) that
1735 wraps the popular wxWindows cross platform GUI library, which is
1738 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1739 means that it is free for anyone to use and the source code is
1740 available for anyone to look at and modify. Or anyone can contribute
1741 fixes or enhancements to the project.
1743 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1744 same program will run on multiple platforms without modification.
1745 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1746 or unix-like systems, and Macintosh OS X. Since the language is
1747 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1750 <p> <b>This demo</b> is not only a collection of test cases for
1751 wxPython, but is also designed to help you learn about and how to use
1752 wxPython. Each sample is listed in the tree control on the left.
1753 When a sample is selected in the tree then a module is loaded and run
1754 (usually in a tab of this notebook,) and the source code of the module
1755 is loaded in another tab for you to browse and learn from.
1760 #----------------------------------------------------------------------------
1761 #----------------------------------------------------------------------------
1763 if __name__
== '__main__':
1767 #----------------------------------------------------------------------------