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 = %s (%s)" % (wx.VERSION_STRING, wx.USE_UNICODE and 'unicode' or 'ansi')
40 ##print "pid:", os.getpid()
41 ##raw_input("Press Enter...")
44 #---------------------------------------------------------------------------
49 ('Recent Additions/Updates', [
51 'AUI_DockingWindowMgr',
63 # managed windows == things with a (optional) caption you can close
64 ('Frames and Dialogs', [
65 'AUI_DockingWindowMgr',
89 # dialogs from libraries
92 'ScrolledMessageDialog',
96 ('Core Windows/Controls', [
133 ('"Book" Controls', [
142 ('Custom Controls', [
156 # controls coming from other libraries
157 ('More Windows/Controls', [
158 'ActiveX_FlashWindow',
159 'ActiveX_IEHtmlWindow',
161 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
164 'CheckListCtrlMixin',
179 'MaskedEditControls',
182 'MultiSplitterWindow',
199 # How to lay out the controls in a frame/dialog
209 'XmlResourceHandler',
210 'XmlResourceSubclass',
214 ('Process and Events', [
221 ##'infoframe', # needs better explanation and some fixing
225 ('Clipboard and DnD', [
248 ##'DialogUnits', # needs more explanations
266 ('Check out the samples dir too', [
273 #---------------------------------------------------------------------------
274 # Show how to derive a custom wxLog class
276 class MyLog(wx
.PyLog
):
277 def __init__(self
, textCtrl
, logTime
=0):
278 wx
.PyLog
.__init
__(self
)
280 self
.logTime
= logTime
282 def DoLogString(self
, message
, timeStamp
):
283 #print message, timeStamp
285 # message = time.strftime("%X", time.localtime(timeStamp)) + \
288 self
.tc
.AppendText(message
+ '\n')
291 class MyTP(wx
.PyTipProvider
):
293 return "This is my tip"
295 #---------------------------------------------------------------------------
296 # A class to be used to simply display a message in the demo pane
297 # rather than running the sample itself.
299 class MessagePanel(wx
.Panel
):
300 def __init__(self
, parent
, message
, caption
='', flags
=0):
301 wx
.Panel
.__init
__(self
, parent
)
306 if flags
& wx
.ICON_EXCLAMATION
:
307 artid
= wx
.ART_WARNING
308 elif flags
& wx
.ICON_ERROR
:
310 elif flags
& wx
.ICON_QUESTION
:
311 artid
= wx
.ART_QUESTION
312 elif flags
& wx
.ICON_INFORMATION
:
313 artid
= wx
.ART_INFORMATION
315 if artid
is not None:
316 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
317 icon
= wx
.StaticBitmap(self
, -1, bmp
)
319 icon
= (32,32) # make a spacer instead
322 caption
= wx
.StaticText(self
, -1, caption
)
323 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
325 message
= wx
.StaticText(self
, -1, message
)
327 # add to sizers for layout
328 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
334 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
341 box
= wx
.BoxSizer(wx
.VERTICAL
)
343 box
.Add(hbox
, 0, wx
.EXPAND
)
350 #---------------------------------------------------------------------------
351 # A class to be used to display source code in the demo. Try using the
352 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
353 # if there is an error, such as the stc module not being present.
357 ##raise ImportError # for testing the alternate implementation
359 from StyledTextCtrl_2
import PythonSTC
361 class DemoCodeEditor(PythonSTC
):
362 def __init__(self
, parent
):
363 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
366 # Some methods to make it compatible with how the wxTextCtrl is used
367 def SetValue(self
, value
):
369 value
= value
.decode('iso8859_1')
371 self
.EmptyUndoBuffer()
374 def IsModified(self
):
375 return self
.GetModify()
380 def SetInsertionPoint(self
, pos
):
381 self
.SetCurrentPos(pos
)
384 def ShowPosition(self
, pos
):
385 line
= self
.LineFromPosition(pos
)
386 #self.EnsureVisible(line)
389 def GetLastPosition(self
):
390 return self
.GetLength()
392 def GetPositionFromLine(self
, line
):
393 return self
.PositionFromLine(line
)
395 def GetRange(self
, start
, end
):
396 return self
.GetTextRange(start
, end
)
398 def GetSelection(self
):
399 return self
.GetAnchor(), self
.GetCurrentPos()
401 def SetSelection(self
, start
, end
):
402 self
.SetSelectionStart(start
)
403 self
.SetSelectionEnd(end
)
405 def SelectLine(self
, line
):
406 start
= self
.PositionFromLine(line
)
407 end
= self
.GetLineEndPosition(line
)
408 self
.SetSelection(start
, end
)
410 def SetUpEditor(self
):
412 This method carries out the work of setting up the demo editor.
413 It's seperate so as not to clutter up the init code.
417 self
.SetLexer(stc
.STC_LEX_PYTHON
)
418 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
421 self
.SetProperty("fold", "1" )
423 # Highlight tab/space mixing (shouldn't be any)
424 self
.SetProperty("tab.timmy.whinge.level", "1")
426 # Set left and right margins
429 # Set up the numbers in the margin for margin #1
430 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
431 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
432 self
.SetMarginWidth(1, 40)
434 # Indentation and tab stuff
435 self
.SetIndent(4) # Proscribed indent size for wx
436 self
.SetIndentationGuides(True) # Show indent guides
437 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
438 self
.SetTabIndents(True) # Tab key indents
439 self
.SetTabWidth(4) # Proscribed tab size for wx
440 self
.SetUseTabs(False) # Use spaces rather than tabs, or
441 # TabTimmy will complain!
443 self
.SetViewWhiteSpace(False) # Don't view white space
445 # EOL: Since we are loading/saving ourselves, and the
446 # strings will always have \n's in them, set the STC to
447 # edit them that way.
448 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
449 self
.SetViewEOL(False)
451 # No right-edge mode indicator
452 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
454 # Setup a margin to hold fold markers
455 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
456 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
457 self
.SetMarginSensitive(2, True)
458 self
.SetMarginWidth(2, 12)
460 # and now set up the fold markers
461 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
462 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
463 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
464 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
465 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
466 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
467 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
469 # Global default style
470 if wx
.Platform
== '__WXMSW__':
471 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
472 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
474 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
475 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
477 # Clear styles and revert to default.
480 # Following style specs only indicate differences from default.
481 # The rest remains unchanged.
483 # Line numbers in margin
484 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
486 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
488 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
490 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
493 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
495 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
496 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
498 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
499 # Strings and characters
500 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
501 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
503 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
505 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
506 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
508 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
510 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
512 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
513 # Identifiers. I leave this as not bold because everything seems
514 # to be an identifier if it doesn't match the above criterae
515 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
518 self
.SetCaretForeground("BLUE")
519 # Selection background
520 self
.SetSelBackground(1, '#66CCFF')
522 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
523 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
525 def RegisterModifiedEvent(self
, eventHandler
):
526 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
530 class DemoCodeEditor(wx
.TextCtrl
):
531 def __init__(self
, parent
):
532 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
533 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
535 def RegisterModifiedEvent(self
, eventHandler
):
536 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
538 def SetReadOnly(self
, flag
):
539 self
.SetEditable(not flag
)
540 # NOTE: STC already has this method
543 return self
.GetValue()
545 def GetPositionFromLine(self
, line
):
546 return self
.XYToPosition(0,line
)
548 def GotoLine(self
, line
):
549 pos
= self
.GetPositionFromLine(line
)
550 self
.SetInsertionPoint(pos
)
551 self
.ShowPosition(pos
)
553 def SelectLine(self
, line
):
554 start
= self
.GetPositionFromLine(line
)
555 end
= start
+ self
.GetLineLength(line
)
556 self
.SetSelection(start
, end
)
559 #---------------------------------------------------------------------------
560 # Constants for module versions
564 modDefault
= modOriginal
566 #---------------------------------------------------------------------------
568 class DemoCodePanel(wx
.Panel
):
569 """Panel for the 'Demo Code' tab"""
570 def __init__(self
, parent
, mainFrame
):
571 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
572 if 'wxMSW' in wx
.PlatformInfo
:
574 self
.mainFrame
= mainFrame
575 self
.editor
= DemoCodeEditor(self
)
576 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
578 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
579 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
580 self
.btnSave
.Enable(False)
581 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
582 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
584 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
585 modModified
: wx
.RadioButton(self
, -1, "Modified") }
587 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
588 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
589 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
590 for modID
, radioButton
in self
.radioButtons
.items():
591 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
592 radioButton
.modID
= modID
# makes it easier for the event handler
593 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
595 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
596 self
.controlBox
.Add(self
.btnRestore
, 0)
598 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
599 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
600 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
601 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
604 self
.SetSizer(self
.box
)
607 # Loads a demo from a DemoModules object
608 def LoadDemo(self
, demoModules
):
609 self
.demoModules
= demoModules
610 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
611 demoModules
.SetActive(modModified
)
613 demoModules
.SetActive(modOriginal
)
614 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
615 self
.ActiveModuleChanged()
618 def ActiveModuleChanged(self
):
619 self
.LoadDemoSource(self
.demoModules
.GetSource())
620 self
.UpdateControlState()
624 def LoadDemoSource(self
, source
):
626 self
.editor
.SetValue(source
)
628 self
.btnSave
.Enable(False)
631 def JumpToLine(self
, line
, highlight
=False):
632 self
.editor
.GotoLine(line
)
633 self
.editor
.SetFocus()
635 self
.editor
.SelectLine(line
)
638 def UpdateControlState(self
):
639 active
= self
.demoModules
.GetActiveID()
640 # Update the radio/restore buttons
641 for moduleID
in self
.radioButtons
:
642 btn
= self
.radioButtons
[moduleID
]
643 if moduleID
== active
:
648 if self
.demoModules
.Exists(moduleID
):
650 if moduleID
== modModified
:
651 self
.btnRestore
.Enable(True)
654 if moduleID
== modModified
:
655 self
.btnRestore
.Enable(False)
658 def OnRadioButton(self
, event
):
659 radioSelected
= event
.GetEventObject()
660 modSelected
= radioSelected
.modID
661 if modSelected
!= self
.demoModules
.GetActiveID():
662 busy
= wx
.BusyInfo("Reloading demo module...")
663 self
.demoModules
.SetActive(modSelected
)
664 self
.ActiveModuleChanged()
667 def ReloadDemo(self
):
668 if self
.demoModules
.name
!= __name__
:
669 self
.mainFrame
.RunModule()
672 def OnCodeModified(self
, event
):
673 self
.btnSave
.Enable(self
.editor
.IsModified())
676 def OnSave(self
, event
):
677 if self
.demoModules
.Exists(modModified
):
678 if self
.demoModules
.GetActiveID() == modOriginal
:
679 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
680 "Do you want to continue?"
681 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
682 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
683 result
= dlg
.ShowModal()
684 if result
== wx
.ID_NO
:
688 self
.demoModules
.SetActive(modModified
)
689 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
691 # Create the demo directory if one doesn't already exist
692 if not os
.path
.exists(GetModifiedDirectory()):
694 os
.makedirs(GetModifiedDirectory())
695 if not os
.path
.exists(GetModifiedDirectory()):
696 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
699 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
702 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
705 f
= open(modifiedFilename
, "wt")
706 source
= self
.editor
.GetText()
712 busy
= wx
.BusyInfo("Reloading demo module...")
713 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
714 self
.ActiveModuleChanged()
717 def OnRestore(self
, event
): # Handles the "Delete Modified" button
718 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
719 self
.demoModules
.Delete(modModified
)
720 os
.unlink(modifiedFilename
) # Delete the modified copy
721 busy
= wx
.BusyInfo("Reloading demo module...")
722 self
.ActiveModuleChanged()
725 #---------------------------------------------------------------------------
728 """Convert paths to the platform-specific separator"""
729 str = apply(os
.path
.join
, tuple(path
.split('/')))
730 # HACK: on Linux, a leading / gets lost...
731 if path
.startswith('/'):
736 def GetModifiedDirectory():
738 Returns the directory where modified versions of the demo files
741 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
744 def GetModifiedFilename(name
):
746 Returns the filename of the modified version of the specified demo
748 if not name
.endswith(".py"):
750 return GetModifiedDirectory() + name
753 def GetOriginalFilename(name
):
755 Returns the filename of the original version of the specified demo
757 if not name
.endswith(".py"):
762 def DoesModifiedExist(name
):
763 """Returns whether the specified demo has a modified copy"""
764 if os
.path
.exists(GetModifiedFilename(name
)):
770 #---------------------------------------------------------------------------
772 class ModuleDictWrapper
:
773 """Emulates a module with a dynamically compiled __dict__"""
774 def __init__(self
, dict):
777 def __getattr__(self
, name
):
778 if name
in self
.dict:
779 return self
.dict[name
]
785 Dynamically manages the original/modified versions of a demo
788 def __init__(self
, name
):
792 # (dict , source , filename , description , error information )
793 # ( 0 , 1 , 2 , 3 , 4 )
794 self
.modules
= [[None, "" , "" , "<original>" , None],
795 [None, "" , "" , "<modified>" , None]]
797 # load original module
798 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
799 self
.SetActive(modOriginal
)
801 # load modified module (if one exists)
802 if DoesModifiedExist(name
):
803 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
806 def LoadFromFile(self
, modID
, filename
):
807 self
.modules
[modID
][2] = filename
808 file = open(filename
, "rt")
809 self
.LoadFromSource(modID
, file.read())
813 def LoadFromSource(self
, modID
, source
):
814 self
.modules
[modID
][1] = source
818 def LoadDict(self
, modID
):
819 if self
.name
!= __name__
:
820 source
= self
.modules
[modID
][1]
821 #description = self.modules[modID][3]
822 description
= self
.modules
[modID
][2]
825 self
.modules
[modID
][0] = {}
826 code
= compile(source
, description
, "exec")
827 exec code
in self
.modules
[modID
][0]
829 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
830 self
.modules
[modID
][0] = None
832 self
.modules
[modID
][4] = None
835 def SetActive(self
, modID
):
836 if modID
!= modOriginal
and modID
!= modModified
:
839 self
.modActive
= modID
843 dict = self
.modules
[self
.modActive
][0]
847 return ModuleDictWrapper(dict)
850 def GetActiveID(self
):
851 return self
.modActive
854 def GetSource(self
, modID
= None):
856 modID
= self
.modActive
857 return self
.modules
[modID
][1]
860 def GetFilename(self
, modID
= None):
862 modID
= self
.modActive
863 return self
.modules
[self
.modActive
][2]
866 def GetErrorInfo(self
, modID
= None):
868 modID
= self
.modActive
869 return self
.modules
[self
.modActive
][4]
872 def Exists(self
, modID
):
873 return self
.modules
[modID
][1] != ""
876 def UpdateFile(self
, modID
= None):
877 """Updates the file from which a module was loaded
878 with (possibly updated) source"""
880 modID
= self
.modActive
882 source
= self
.modules
[modID
][1]
883 filename
= self
.modules
[modID
][2]
886 file = open(filename
, "wt")
892 def Delete(self
, modID
):
893 if self
.modActive
== modID
:
896 self
.modules
[modID
][0] = None
897 self
.modules
[modID
][1] = ""
898 self
.modules
[modID
][2] = ""
901 #---------------------------------------------------------------------------
904 """Wraps and stores information about the current exception"""
905 def __init__(self
, exc_info
):
908 excType
, excValue
= exc_info
[:2]
909 # traceback list entries: (filename, line number, function name, text)
910 self
.traceback
= traceback
.extract_tb(exc_info
[2])
912 # --Based on traceback.py::format_exception_only()--
913 if type(excType
) == types
.ClassType
:
914 self
.exception_type
= excType
.__name
__
916 self
.exception_type
= excType
918 # If it's a syntax error, extra information needs
919 # to be added to the traceback
920 if excType
is SyntaxError:
922 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
927 filename
= "<string>"
929 self
.traceback
.append( (filename
, lineno
, "", line
) )
932 self
.exception_details
= str(excValue
)
934 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
941 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
944 #---------------------------------------------------------------------------
946 class DemoErrorPanel(wx
.Panel
):
947 """Panel put into the demo tab when the demo fails to run due to errors"""
949 def __init__(self
, parent
, codePanel
, demoError
, log
):
950 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
951 self
.codePanel
= codePanel
955 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
958 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
959 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
961 # Exception Information
962 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
963 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
964 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
965 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
966 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
967 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
968 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
969 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
970 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
971 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
973 # Set up the traceback list
974 # This one automatically resizes last column to take up remaining space
975 from ListCtrl
import TestListCtrl
976 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
977 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
978 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
979 self
.list.InsertColumn(0, "Filename")
980 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
981 self
.list.InsertColumn(2, "Function")
982 self
.list.InsertColumn(3, "Code")
983 self
.InsertTraceback(self
.list, demoError
.traceback
)
984 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
985 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
986 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
987 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
988 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
989 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
990 + "Double-click on them to go to the offending line")
991 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
994 self
.SetSizer(self
.box
)
997 def InsertTraceback(self
, list, traceback
):
998 #Add the traceback data
999 for x
in range(len(traceback
)):
1001 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
1002 list.SetStringItem(x
, 1, str(data
[1])) # Line
1003 list.SetStringItem(x
, 2, str(data
[2])) # Function
1004 list.SetStringItem(x
, 3, str(data
[3])) # Code
1006 # Check whether this entry is from the demo module
1007 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1008 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1009 # Give it a blue colour
1010 item
= self
.list.GetItem(x
)
1011 item
.SetTextColour(wx
.BLUE
)
1012 self
.list.SetItem(item
)
1014 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1017 def OnItemSelected(self
, event
):
1018 # This occurs before OnDoubleClick and can be used to set the
1019 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1020 self
.currentItem
= event
.m_itemIndex
1024 def OnDoubleClick(self
, event
):
1025 # If double-clicking on a demo's entry, jump to the line number
1026 line
= self
.list.GetItemData(self
.currentItem
)
1028 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1029 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1033 #---------------------------------------------------------------------------
1035 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1036 TBMENU_RESTORE
= wx
.NewId()
1037 TBMENU_CLOSE
= wx
.NewId()
1038 TBMENU_CHANGE
= wx
.NewId()
1039 TBMENU_REMOVE
= wx
.NewId()
1041 def __init__(self
, frame
):
1042 wx
.TaskBarIcon
.__init
__(self
)
1046 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1047 self
.SetIcon(icon
, "wxPython Demo")
1051 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1052 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1053 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1054 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1055 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1058 def CreatePopupMenu(self
):
1060 This method is called by the base class when it needs to popup
1061 the menu for the default EVT_RIGHT_DOWN event. Just create
1062 the menu how you want it and return it from this function,
1063 the base class takes care of the rest.
1066 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1067 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1068 menu
.AppendSeparator()
1069 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1070 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1074 def MakeIcon(self
, img
):
1076 The various platforms have different requirements for the
1079 if "wxMSW" in wx
.PlatformInfo
:
1080 img
= img
.Scale(16, 16)
1081 elif "wxGTK" in wx
.PlatformInfo
:
1082 img
= img
.Scale(22, 22)
1083 # wxMac can be any size upto 128x128, so leave the source img alone....
1084 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1088 def OnTaskBarActivate(self
, evt
):
1089 if self
.frame
.IsIconized():
1090 self
.frame
.Iconize(False)
1091 if not self
.frame
.IsShown():
1092 self
.frame
.Show(True)
1096 def OnTaskBarClose(self
, evt
):
1100 def OnTaskBarChange(self
, evt
):
1101 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1102 name
= names
[self
.imgidx
]
1104 getFunc
= getattr(images
, "get%sImage" % name
)
1106 if self
.imgidx
>= len(names
):
1109 icon
= self
.MakeIcon(getFunc())
1110 self
.SetIcon(icon
, "This is a new icon: " + name
)
1113 def OnTaskBarRemove(self
, evt
):
1117 #---------------------------------------------------------------------------
1118 class wxPythonDemo(wx
.Frame
):
1119 overviewText
= "wxPython Overview"
1121 def __init__(self
, parent
, title
):
1122 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1123 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1125 self
.SetMinSize((640,480))
1128 self
.cwd
= os
.getcwd()
1129 self
.curOverview
= ""
1130 self
.demoPage
= None
1131 self
.codePage
= None
1133 self
.firstTime
= True
1136 icon
= images
.getWXPdemoIcon()
1139 self
.tbicon
= DemoTaskBarIcon(self
)
1141 wx
.CallAfter(self
.ShowTip
)
1143 self
.otherWin
= None
1144 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1145 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1146 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1147 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1149 self
.Centre(wx
.BOTH
)
1150 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1152 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1153 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1155 def EmptyHandler(evt
): pass
1156 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1157 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1159 # Prevent TreeCtrl from displaying all items after destruction when True
1163 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1166 self
.mainmenu
= wx
.MenuBar()
1168 item
= menu
.Append(-1, '&Redirect Output',
1169 'Redirect print statements to a window',
1171 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1173 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1174 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1175 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1176 self
.mainmenu
.Append(menu
, '&File')
1180 for item
in _treeList
:
1182 for childItem
in item
[1]:
1183 mi
= submenu
.Append(-1, childItem
)
1184 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1185 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1186 self
.mainmenu
.Append(menu
, '&Demo')
1191 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1192 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1193 menu
.AppendSeparator()
1195 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1196 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1197 menu
.AppendSeparator()
1198 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1199 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1201 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1202 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1203 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1204 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1205 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1206 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1207 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1208 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1209 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1210 self
.mainmenu
.Append(menu
, '&Help')
1211 self
.SetMenuBar(self
.mainmenu
)
1213 self
.finddata
= wx
.FindReplaceData()
1214 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1217 # This is another way to set Accelerators, in addition to
1218 # using the '\t<key>' syntax in the menu items.
1219 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1220 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1221 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1222 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1224 self
.SetAcceleratorTable(aTable
)
1230 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1231 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1234 root
= self
.tree
.AddRoot("wxPython Overview")
1236 for item
in _treeList
:
1237 child
= self
.tree
.AppendItem(root
, item
[0])
1238 if not firstChild
: firstChild
= child
1239 for childItem
in item
[1]:
1240 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1241 self
.treeMap
[childItem
] = theDemo
1243 self
.tree
.Expand(root
)
1244 self
.tree
.Expand(firstChild
)
1245 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1246 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1247 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1248 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1250 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1251 # we put it in a panel first because there seems to be a
1252 # refresh bug of some sort (wxGTK) when it is directly in
1255 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1256 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1258 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1259 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1260 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1261 self
.nb
.AddPage(panel
, self
.overviewText
)
1263 def OnOvrSize(evt
, ovr
=self
.ovr
):
1264 ovr
.SetSize(evt
.GetSize())
1265 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1266 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1268 if "gtk2" in wx
.PlatformInfo
:
1269 self
.ovr
.SetStandardFonts()
1270 self
.SetOverview(self
.overviewText
, mainOverview
)
1273 # Set up a log window
1274 self
.log
= wx
.TextCtrl(splitter2
, -1,
1275 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1277 # Set the wxWindows log target to be this textctrl
1278 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1280 # But instead of the above we want to show how to use our own wx.Log class
1281 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1283 # for serious debugging
1284 #wx.Log_SetActiveTarget(wx.LogStderr())
1285 #wx.Log_SetTraceMask(wx.TraceMessages)
1288 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1289 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1291 # add the windows to the splitter and split it.
1292 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1293 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1295 splitter
.SetMinimumPaneSize(120)
1296 splitter2
.SetMinimumPaneSize(60)
1298 # Make the splitter on the right expand the top window when resized
1299 def SplitterOnSize(evt
):
1300 splitter
= evt
.GetEventObject()
1301 sz
= splitter
.GetSize()
1302 splitter
.SetSashPosition(sz
.height
- 160, False)
1305 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1307 # select initial items
1308 self
.nb
.SetSelection(0)
1309 self
.tree
.SelectItem(root
)
1311 # Load 'Main' module
1312 self
.LoadDemo(self
.overviewText
)
1315 # select some other initial module?
1316 if len(sys
.argv
) > 1:
1318 if arg
.endswith('.py'):
1320 selectedDemo
= self
.treeMap
.get(arg
, None)
1322 self
.tree
.SelectItem(selectedDemo
)
1323 self
.tree
.EnsureVisible(selectedDemo
)
1326 #---------------------------------------------
1327 def WriteText(self
, text
):
1328 if text
[-1:] == '\n':
1332 def write(self
, txt
):
1335 #---------------------------------------------
1336 def OnItemExpanded(self
, event
):
1337 item
= event
.GetItem()
1338 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1341 #---------------------------------------------
1342 def OnItemCollapsed(self
, event
):
1343 item
= event
.GetItem()
1344 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1347 #---------------------------------------------
1348 def OnTreeLeftDown(self
, event
):
1349 # reset the overview text if the tree item is clicked on again
1350 pt
= event
.GetPosition();
1351 item
, flags
= self
.tree
.HitTest(pt
)
1352 if item
== self
.tree
.GetSelection():
1353 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1356 #---------------------------------------------
1357 def OnSelChanged(self
, event
):
1358 if self
.dying
or not self
.loaded
:
1361 item
= event
.GetItem()
1362 itemText
= self
.tree
.GetItemText(item
)
1363 self
.LoadDemo(itemText
)
1365 #---------------------------------------------
1366 def LoadDemo(self
, demoName
):
1368 wx
.BeginBusyCursor()
1371 self
.ShutdownDemoModule()
1373 if demoName
== self
.overviewText
:
1374 # User selected the "wxPython Overview" node
1376 # Changing the main window at runtime not yet supported...
1377 self
.demoModules
= DemoModules(__name__
)
1378 self
.SetOverview(self
.overviewText
, mainOverview
)
1379 self
.LoadDemoSource()
1380 self
.UpdateNotebook(0)
1382 if os
.path
.exists(GetOriginalFilename(demoName
)):
1383 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1384 self
.demoModules
= DemoModules(demoName
)
1385 self
.LoadDemoSource()
1388 self
.SetOverview("wxPython", mainOverview
)
1389 self
.codePage
= None
1390 self
.UpdateNotebook(0)
1394 #---------------------------------------------
1395 def LoadDemoSource(self
):
1396 self
.codePage
= None
1397 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1398 self
.codePage
.LoadDemo(self
.demoModules
)
1400 #---------------------------------------------
1401 def RunModule(self
):
1402 """Runs the active module"""
1404 module
= self
.demoModules
.GetActive()
1405 self
.ShutdownDemoModule()
1408 # o The RunTest() for all samples must now return a window that can
1409 # be palced in a tab in the main notebook.
1410 # o If an error occurs (or has occurred before) an error tab is created.
1412 if module
is not None:
1413 wx
.LogMessage("Running demo module...")
1414 if hasattr(module
, "overview"):
1415 overviewText
= module
.overview
1418 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1420 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1421 DemoError(sys
.exc_info()), self
)
1423 assert self
.demoPage
is not None, "runTest must return a window!"
1426 # There was a previous error in compiling or exec-ing
1427 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1428 self
.demoModules
.GetErrorInfo(), self
)
1430 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1433 # cahnge to the demo page the first time a module is run
1434 self
.UpdateNotebook(2)
1435 self
.firstTime
= False
1437 # otherwise just stay on the same tab in case the user has changed to another one
1438 self
.UpdateNotebook()
1440 #---------------------------------------------
1441 def ShutdownDemoModule(self
):
1443 # inform the window that it's time to quit if it cares
1444 if hasattr(self
.demoPage
, "ShutdownDemo"):
1445 self
.demoPage
.ShutdownDemo()
1446 wx
.YieldIfNeeded() # in case the page has pending events
1447 self
.demoPage
= None
1449 #---------------------------------------------
1450 def UpdateNotebook(self
, select
= -1):
1454 def UpdatePage(page
, pageText
):
1457 for i
in range(nb
.GetPageCount()):
1458 if nb
.GetPageText(i
) == pageText
:
1466 nb
.AddPage(page
, pageText
)
1467 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1469 if nb
.GetPage(pagePos
) != page
:
1470 # Reload an existing page
1472 nb
.DeletePage(pagePos
)
1473 nb
.InsertPage(pagePos
, page
, pageText
)
1475 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1477 # Excellent! No redraw/flicker
1478 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1481 nb
.DeletePage(pagePos
)
1482 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1484 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1487 select
= nb
.GetSelection()
1489 UpdatePage(self
.codePage
, "Demo Code")
1490 UpdatePage(self
.demoPage
, "Demo")
1492 if select
>= 0 and select
< nb
.GetPageCount():
1493 nb
.SetSelection(select
)
1495 #---------------------------------------------
1496 def SetOverview(self
, name
, text
):
1497 self
.curOverview
= text
1499 if lead
!= '<html>' and lead
!= '<HTML>':
1500 text
= '<br>'.join(text
.split('\n'))
1502 text
= text
.decode('iso8859_1')
1503 self
.ovr
.SetPage(text
)
1504 self
.nb
.SetPageText(0, name
)
1506 #---------------------------------------------
1508 def OnFileExit(self
, *event
):
1511 def OnToggleRedirect(self
, event
):
1515 print "Print statements and other standard output will now be directed to this window."
1518 print "Print statements and other standard output will now be sent to the usual location."
1520 def OnHelpAbout(self
, event
):
1521 from About
import MyAboutBox
1522 about
= MyAboutBox(self
)
1526 def OnHelpFind(self
, event
):
1527 if self
.finddlg
!= None:
1530 self
.nb
.SetSelection(1)
1531 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1532 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1533 self
.finddlg
.Show(True)
1536 def OnUpdateFindItems(self
, evt
):
1537 evt
.Enable(self
.finddlg
== None)
1540 def OnFind(self
, event
):
1541 editor
= self
.codePage
.editor
1542 self
.nb
.SetSelection(1)
1543 end
= editor
.GetLastPosition()
1544 textstring
= editor
.GetRange(0, end
).lower()
1545 findstring
= self
.finddata
.GetFindString().lower()
1546 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1548 start
= editor
.GetSelection()[0]
1549 loc
= textstring
.rfind(findstring
, 0, start
)
1551 start
= editor
.GetSelection()[1]
1552 loc
= textstring
.find(findstring
, start
)
1553 if loc
== -1 and start
!= 0:
1554 # string not found, start at beginning
1557 loc
= textstring
.rfind(findstring
, 0, start
)
1560 loc
= textstring
.find(findstring
, start
)
1562 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1563 'Find String Not Found in Demo File',
1564 wx
.OK | wx
.ICON_INFORMATION
)
1569 self
.finddlg
.SetFocus()
1572 self
.finddlg
.Destroy()
1574 editor
.ShowPosition(loc
)
1575 editor
.SetSelection(loc
, loc
+ len(findstring
))
1579 def OnFindNext(self
, event
):
1580 if self
.finddata
.GetFindString():
1583 self
.OnHelpFind(event
)
1585 def OnFindClose(self
, event
):
1586 event
.GetDialog().Destroy()
1590 def OnOpenShellWindow(self
, evt
):
1592 # if it already exists then just make sure it's visible
1598 # Make a PyShell window
1600 namespace
= { 'wx' : wx
,
1601 'app' : wx
.GetApp(),
1604 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1605 self
.shell
.SetSize((640,480))
1608 # Hook the close event of the main frame window so that we
1609 # close the shell at the same time if it still exists
1610 def CloseShell(evt
):
1614 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1617 #---------------------------------------------
1618 def OnCloseWindow(self
, event
):
1620 self
.demoPage
= None
1621 self
.codePage
= None
1622 self
.mainmenu
= None
1623 self
.tbicon
.Destroy()
1627 #---------------------------------------------
1628 def OnIdle(self
, event
):
1630 self
.otherWin
.Raise()
1631 self
.demoPage
= self
.otherWin
1632 self
.otherWin
= None
1635 #---------------------------------------------
1638 showTipText
= open(opj("data/showTips")).read()
1639 showTip
, index
= eval(showTipText
)
1641 showTip
, index
= (1, 0)
1643 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1645 showTip
= wx
.ShowTip(self
, tp
)
1646 index
= tp
.GetCurrentTip()
1647 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1650 #---------------------------------------------
1651 def OnDemoMenu(self
, event
):
1653 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1657 self
.tree
.SelectItem(selectedDemo
)
1658 self
.tree
.EnsureVisible(selectedDemo
)
1662 #---------------------------------------------
1663 def OnIconfiy(self
, evt
):
1664 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1667 #---------------------------------------------
1668 def OnMaximize(self
, evt
):
1669 wx
.LogMessage("OnMaximize")
1672 #---------------------------------------------
1673 def OnActivate(self
, evt
):
1674 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1677 #---------------------------------------------
1678 def OnAppActivate(self
, evt
):
1679 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1682 #---------------------------------------------------------------------------
1683 #---------------------------------------------------------------------------
1685 class MySplashScreen(wx
.SplashScreen
):
1687 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1688 wx
.SplashScreen
.__init
__(self
, bmp
,
1689 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1691 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1692 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1695 def OnClose(self
, evt
):
1696 # Make sure the default handler runs too so this window gets
1701 # if the timer is still running then go ahead and show the
1703 if self
.fc
.IsRunning():
1709 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1711 if self
.fc
.IsRunning():
1715 class MyApp(wx
.App
):
1718 Create and show the splash screen. It will then create and show
1719 the main frame when it is time to do so.
1722 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1725 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1727 # Normally when using a SplashScreen you would create it, show
1728 # it and then continue on with the applicaiton's
1729 # initialization, finally creating and showing the main
1730 # application window(s). In this case we have nothing else to
1731 # do so we'll delay showing the main frame until later (see
1732 # ShowMain above) so the users can see the SplashScreen effect.
1733 splash
= MySplashScreen()
1740 #---------------------------------------------------------------------------
1744 demoPath
= os
.path
.dirname(__file__
)
1751 #---------------------------------------------------------------------------
1754 mainOverview
= """<html><body>
1757 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1758 language. It allows Python programmers to create programs with a
1759 robust, highly functional graphical user interface, simply and easily.
1760 It is implemented as a Python extension module (native code) that
1761 wraps the popular wxWindows cross platform GUI library, which is
1764 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1765 means that it is free for anyone to use and the source code is
1766 available for anyone to look at and modify. Or anyone can contribute
1767 fixes or enhancements to the project.
1769 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1770 same program will run on multiple platforms without modification.
1771 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1772 or unix-like systems, and Macintosh OS X. Since the language is
1773 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1776 <p> <b>This demo</b> is not only a collection of test cases for
1777 wxPython, but is also designed to help you learn about and how to use
1778 wxPython. Each sample is listed in the tree control on the left.
1779 When a sample is selected in the tree then a module is loaded and run
1780 (usually in a tab of this notebook,) and the source code of the module
1781 is loaded in another tab for you to browse and learn from.
1786 #----------------------------------------------------------------------------
1787 #----------------------------------------------------------------------------
1789 if __name__
== '__main__':
1793 #----------------------------------------------------------------------------