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',
66 # managed windows == things with a (optional) caption you can close
67 ('Frames and Dialogs', [
68 'AUI_DockingWindowMgr',
92 # dialogs from libraries
95 'ScrolledMessageDialog',
99 ('Core Windows/Controls', [
136 ('"Book" Controls', [
145 ('Custom Controls', [
159 # controls coming from other libraries
160 ('More Windows/Controls', [
161 'ActiveX_FlashWindow',
162 'ActiveX_IEHtmlWindow',
164 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
167 'CheckListCtrlMixin',
182 'MaskedEditControls',
185 'MultiSplitterWindow',
202 # How to lay out the controls in a frame/dialog
212 'XmlResourceHandler',
213 'XmlResourceSubclass',
217 ('Process and Events', [
224 ##'infoframe', # needs better explanation and some fixing
228 ('Clipboard and DnD', [
254 ##'DialogUnits', # needs more explanations
273 ('Check out the samples dir too', [
280 #---------------------------------------------------------------------------
281 # Show how to derive a custom wxLog class
283 class MyLog(wx
.PyLog
):
284 def __init__(self
, textCtrl
, logTime
=0):
285 wx
.PyLog
.__init
__(self
)
287 self
.logTime
= logTime
289 def DoLogString(self
, message
, timeStamp
):
290 #print message, timeStamp
292 # message = time.strftime("%X", time.localtime(timeStamp)) + \
295 self
.tc
.AppendText(message
+ '\n')
298 class MyTP(wx
.PyTipProvider
):
300 return "This is my tip"
302 #---------------------------------------------------------------------------
303 # A class to be used to simply display a message in the demo pane
304 # rather than running the sample itself.
306 class MessagePanel(wx
.Panel
):
307 def __init__(self
, parent
, message
, caption
='', flags
=0):
308 wx
.Panel
.__init
__(self
, parent
)
313 if flags
& wx
.ICON_EXCLAMATION
:
314 artid
= wx
.ART_WARNING
315 elif flags
& wx
.ICON_ERROR
:
317 elif flags
& wx
.ICON_QUESTION
:
318 artid
= wx
.ART_QUESTION
319 elif flags
& wx
.ICON_INFORMATION
:
320 artid
= wx
.ART_INFORMATION
322 if artid
is not None:
323 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
324 icon
= wx
.StaticBitmap(self
, -1, bmp
)
326 icon
= (32,32) # make a spacer instead
329 caption
= wx
.StaticText(self
, -1, caption
)
330 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
332 message
= wx
.StaticText(self
, -1, message
)
334 # add to sizers for layout
335 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
341 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
348 box
= wx
.BoxSizer(wx
.VERTICAL
)
350 box
.Add(hbox
, 0, wx
.EXPAND
)
357 #---------------------------------------------------------------------------
358 # A class to be used to display source code in the demo. Try using the
359 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
360 # if there is an error, such as the stc module not being present.
364 ##raise ImportError # for testing the alternate implementation
366 from StyledTextCtrl_2
import PythonSTC
368 class DemoCodeEditor(PythonSTC
):
369 def __init__(self
, parent
):
370 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
373 # Some methods to make it compatible with how the wxTextCtrl is used
374 def SetValue(self
, value
):
376 value
= value
.decode('iso8859_1')
378 self
.EmptyUndoBuffer()
381 def IsModified(self
):
382 return self
.GetModify()
387 def SetInsertionPoint(self
, pos
):
388 self
.SetCurrentPos(pos
)
391 def ShowPosition(self
, pos
):
392 line
= self
.LineFromPosition(pos
)
393 #self.EnsureVisible(line)
396 def GetLastPosition(self
):
397 return self
.GetLength()
399 def GetPositionFromLine(self
, line
):
400 return self
.PositionFromLine(line
)
402 def GetRange(self
, start
, end
):
403 return self
.GetTextRange(start
, end
)
405 def GetSelection(self
):
406 return self
.GetAnchor(), self
.GetCurrentPos()
408 def SetSelection(self
, start
, end
):
409 self
.SetSelectionStart(start
)
410 self
.SetSelectionEnd(end
)
412 def SelectLine(self
, line
):
413 start
= self
.PositionFromLine(line
)
414 end
= self
.GetLineEndPosition(line
)
415 self
.SetSelection(start
, end
)
417 def SetUpEditor(self
):
419 This method carries out the work of setting up the demo editor.
420 It's seperate so as not to clutter up the init code.
424 self
.SetLexer(stc
.STC_LEX_PYTHON
)
425 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
428 self
.SetProperty("fold", "1" )
430 # Highlight tab/space mixing (shouldn't be any)
431 self
.SetProperty("tab.timmy.whinge.level", "1")
433 # Set left and right margins
436 # Set up the numbers in the margin for margin #1
437 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
438 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
439 self
.SetMarginWidth(1, 40)
441 # Indentation and tab stuff
442 self
.SetIndent(4) # Proscribed indent size for wx
443 self
.SetIndentationGuides(True) # Show indent guides
444 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
445 self
.SetTabIndents(True) # Tab key indents
446 self
.SetTabWidth(4) # Proscribed tab size for wx
447 self
.SetUseTabs(False) # Use spaces rather than tabs, or
448 # TabTimmy will complain!
450 self
.SetViewWhiteSpace(False) # Don't view white space
452 # EOL: Since we are loading/saving ourselves, and the
453 # strings will always have \n's in them, set the STC to
454 # edit them that way.
455 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
456 self
.SetViewEOL(False)
458 # No right-edge mode indicator
459 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
461 # Setup a margin to hold fold markers
462 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
463 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
464 self
.SetMarginSensitive(2, True)
465 self
.SetMarginWidth(2, 12)
467 # and now set up the fold markers
468 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
469 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
470 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
471 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
472 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
473 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
474 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
476 # Global default style
477 if wx
.Platform
== '__WXMSW__':
478 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
479 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
481 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
482 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
484 # Clear styles and revert to default.
487 # Following style specs only indicate differences from default.
488 # The rest remains unchanged.
490 # Line numbers in margin
491 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
493 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
495 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
497 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
500 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
502 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
503 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
505 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
506 # Strings and characters
507 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
508 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
510 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
512 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
513 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
515 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
517 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
519 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
520 # Identifiers. I leave this as not bold because everything seems
521 # to be an identifier if it doesn't match the above criterae
522 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
525 self
.SetCaretForeground("BLUE")
526 # Selection background
527 self
.SetSelBackground(1, '#66CCFF')
529 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
530 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
532 def RegisterModifiedEvent(self
, eventHandler
):
533 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
537 class DemoCodeEditor(wx
.TextCtrl
):
538 def __init__(self
, parent
):
539 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
540 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
542 def RegisterModifiedEvent(self
, eventHandler
):
543 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
545 def SetReadOnly(self
, flag
):
546 self
.SetEditable(not flag
)
547 # NOTE: STC already has this method
550 return self
.GetValue()
552 def GetPositionFromLine(self
, line
):
553 return self
.XYToPosition(0,line
)
555 def GotoLine(self
, line
):
556 pos
= self
.GetPositionFromLine(line
)
557 self
.SetInsertionPoint(pos
)
558 self
.ShowPosition(pos
)
560 def SelectLine(self
, line
):
561 start
= self
.GetPositionFromLine(line
)
562 end
= start
+ self
.GetLineLength(line
)
563 self
.SetSelection(start
, end
)
566 #---------------------------------------------------------------------------
567 # Constants for module versions
571 modDefault
= modOriginal
573 #---------------------------------------------------------------------------
575 class DemoCodePanel(wx
.Panel
):
576 """Panel for the 'Demo Code' tab"""
577 def __init__(self
, parent
, mainFrame
):
578 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
579 if 'wxMSW' in wx
.PlatformInfo
:
581 self
.mainFrame
= mainFrame
582 self
.editor
= DemoCodeEditor(self
)
583 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
585 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
586 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
587 self
.btnSave
.Enable(False)
588 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
589 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
591 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
592 modModified
: wx
.RadioButton(self
, -1, "Modified") }
594 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
595 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
596 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
597 for modID
, radioButton
in self
.radioButtons
.items():
598 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
599 radioButton
.modID
= modID
# makes it easier for the event handler
600 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
602 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
603 self
.controlBox
.Add(self
.btnRestore
, 0)
605 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
606 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
607 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
608 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
611 self
.SetSizer(self
.box
)
614 # Loads a demo from a DemoModules object
615 def LoadDemo(self
, demoModules
):
616 self
.demoModules
= demoModules
617 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
618 demoModules
.SetActive(modModified
)
620 demoModules
.SetActive(modOriginal
)
621 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
622 self
.ActiveModuleChanged()
625 def ActiveModuleChanged(self
):
626 self
.LoadDemoSource(self
.demoModules
.GetSource())
627 self
.UpdateControlState()
631 def LoadDemoSource(self
, source
):
633 self
.editor
.SetValue(source
)
635 self
.btnSave
.Enable(False)
638 def JumpToLine(self
, line
, highlight
=False):
639 self
.editor
.GotoLine(line
)
640 self
.editor
.SetFocus()
642 self
.editor
.SelectLine(line
)
645 def UpdateControlState(self
):
646 active
= self
.demoModules
.GetActiveID()
647 # Update the radio/restore buttons
648 for moduleID
in self
.radioButtons
:
649 btn
= self
.radioButtons
[moduleID
]
650 if moduleID
== active
:
655 if self
.demoModules
.Exists(moduleID
):
657 if moduleID
== modModified
:
658 self
.btnRestore
.Enable(True)
661 if moduleID
== modModified
:
662 self
.btnRestore
.Enable(False)
665 def OnRadioButton(self
, event
):
666 radioSelected
= event
.GetEventObject()
667 modSelected
= radioSelected
.modID
668 if modSelected
!= self
.demoModules
.GetActiveID():
669 busy
= wx
.BusyInfo("Reloading demo module...")
670 self
.demoModules
.SetActive(modSelected
)
671 self
.ActiveModuleChanged()
674 def ReloadDemo(self
):
675 if self
.demoModules
.name
!= __name__
:
676 self
.mainFrame
.RunModule()
679 def OnCodeModified(self
, event
):
680 self
.btnSave
.Enable(self
.editor
.IsModified())
683 def OnSave(self
, event
):
684 if self
.demoModules
.Exists(modModified
):
685 if self
.demoModules
.GetActiveID() == modOriginal
:
686 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
687 "Do you want to continue?"
688 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
689 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
690 result
= dlg
.ShowModal()
691 if result
== wx
.ID_NO
:
695 self
.demoModules
.SetActive(modModified
)
696 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
698 # Create the demo directory if one doesn't already exist
699 if not os
.path
.exists(GetModifiedDirectory()):
701 os
.makedirs(GetModifiedDirectory())
702 if not os
.path
.exists(GetModifiedDirectory()):
703 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
706 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
709 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
712 f
= open(modifiedFilename
, "wt")
713 source
= self
.editor
.GetText()
719 busy
= wx
.BusyInfo("Reloading demo module...")
720 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
721 self
.ActiveModuleChanged()
724 def OnRestore(self
, event
): # Handles the "Delete Modified" button
725 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
726 self
.demoModules
.Delete(modModified
)
727 os
.unlink(modifiedFilename
) # Delete the modified copy
728 busy
= wx
.BusyInfo("Reloading demo module...")
729 self
.ActiveModuleChanged()
732 #---------------------------------------------------------------------------
735 """Convert paths to the platform-specific separator"""
736 str = apply(os
.path
.join
, tuple(path
.split('/')))
737 # HACK: on Linux, a leading / gets lost...
738 if path
.startswith('/'):
743 def GetModifiedDirectory():
745 Returns the directory where modified versions of the demo files
748 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
751 def GetModifiedFilename(name
):
753 Returns the filename of the modified version of the specified demo
755 if not name
.endswith(".py"):
757 return GetModifiedDirectory() + name
760 def GetOriginalFilename(name
):
762 Returns the filename of the original version of the specified demo
764 if not name
.endswith(".py"):
769 def DoesModifiedExist(name
):
770 """Returns whether the specified demo has a modified copy"""
771 if os
.path
.exists(GetModifiedFilename(name
)):
777 #---------------------------------------------------------------------------
779 class ModuleDictWrapper
:
780 """Emulates a module with a dynamically compiled __dict__"""
781 def __init__(self
, dict):
784 def __getattr__(self
, name
):
785 if name
in self
.dict:
786 return self
.dict[name
]
792 Dynamically manages the original/modified versions of a demo
795 def __init__(self
, name
):
799 # (dict , source , filename , description , error information )
800 # ( 0 , 1 , 2 , 3 , 4 )
801 self
.modules
= [[None, "" , "" , "<original>" , None],
802 [None, "" , "" , "<modified>" , None]]
804 # load original module
805 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
806 self
.SetActive(modOriginal
)
808 # load modified module (if one exists)
809 if DoesModifiedExist(name
):
810 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
813 def LoadFromFile(self
, modID
, filename
):
814 self
.modules
[modID
][2] = filename
815 file = open(filename
, "rt")
816 self
.LoadFromSource(modID
, file.read())
820 def LoadFromSource(self
, modID
, source
):
821 self
.modules
[modID
][1] = source
825 def LoadDict(self
, modID
):
826 if self
.name
!= __name__
:
827 source
= self
.modules
[modID
][1]
828 #description = self.modules[modID][3]
829 description
= self
.modules
[modID
][2]
832 self
.modules
[modID
][0] = {}
833 code
= compile(source
, description
, "exec")
834 exec code
in self
.modules
[modID
][0]
836 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
837 self
.modules
[modID
][0] = None
839 self
.modules
[modID
][4] = None
842 def SetActive(self
, modID
):
843 if modID
!= modOriginal
and modID
!= modModified
:
846 self
.modActive
= modID
850 dict = self
.modules
[self
.modActive
][0]
854 return ModuleDictWrapper(dict)
857 def GetActiveID(self
):
858 return self
.modActive
861 def GetSource(self
, modID
= None):
863 modID
= self
.modActive
864 return self
.modules
[modID
][1]
867 def GetFilename(self
, modID
= None):
869 modID
= self
.modActive
870 return self
.modules
[self
.modActive
][2]
873 def GetErrorInfo(self
, modID
= None):
875 modID
= self
.modActive
876 return self
.modules
[self
.modActive
][4]
879 def Exists(self
, modID
):
880 return self
.modules
[modID
][1] != ""
883 def UpdateFile(self
, modID
= None):
884 """Updates the file from which a module was loaded
885 with (possibly updated) source"""
887 modID
= self
.modActive
889 source
= self
.modules
[modID
][1]
890 filename
= self
.modules
[modID
][2]
893 file = open(filename
, "wt")
899 def Delete(self
, modID
):
900 if self
.modActive
== modID
:
903 self
.modules
[modID
][0] = None
904 self
.modules
[modID
][1] = ""
905 self
.modules
[modID
][2] = ""
908 #---------------------------------------------------------------------------
911 """Wraps and stores information about the current exception"""
912 def __init__(self
, exc_info
):
915 excType
, excValue
= exc_info
[:2]
916 # traceback list entries: (filename, line number, function name, text)
917 self
.traceback
= traceback
.extract_tb(exc_info
[2])
919 # --Based on traceback.py::format_exception_only()--
920 if type(excType
) == types
.ClassType
:
921 self
.exception_type
= excType
.__name
__
923 self
.exception_type
= excType
925 # If it's a syntax error, extra information needs
926 # to be added to the traceback
927 if excType
is SyntaxError:
929 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
934 filename
= "<string>"
936 self
.traceback
.append( (filename
, lineno
, "", line
) )
939 self
.exception_details
= str(excValue
)
941 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
948 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
951 #---------------------------------------------------------------------------
953 class DemoErrorPanel(wx
.Panel
):
954 """Panel put into the demo tab when the demo fails to run due to errors"""
956 def __init__(self
, parent
, codePanel
, demoError
, log
):
957 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
958 self
.codePanel
= codePanel
962 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
965 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
966 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
968 # Exception Information
969 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
970 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
971 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
972 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
973 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
974 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
975 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
976 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
977 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
978 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
980 # Set up the traceback list
981 # This one automatically resizes last column to take up remaining space
982 from ListCtrl
import TestListCtrl
983 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
984 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
985 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
986 self
.list.InsertColumn(0, "Filename")
987 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
988 self
.list.InsertColumn(2, "Function")
989 self
.list.InsertColumn(3, "Code")
990 self
.InsertTraceback(self
.list, demoError
.traceback
)
991 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
992 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
993 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
994 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
995 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
996 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
997 + "Double-click on them to go to the offending line")
998 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
1001 self
.SetSizer(self
.box
)
1004 def InsertTraceback(self
, list, traceback
):
1005 #Add the traceback data
1006 for x
in range(len(traceback
)):
1008 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
1009 list.SetStringItem(x
, 1, str(data
[1])) # Line
1010 list.SetStringItem(x
, 2, str(data
[2])) # Function
1011 list.SetStringItem(x
, 3, str(data
[3])) # Code
1013 # Check whether this entry is from the demo module
1014 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1015 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1016 # Give it a blue colour
1017 item
= self
.list.GetItem(x
)
1018 item
.SetTextColour(wx
.BLUE
)
1019 self
.list.SetItem(item
)
1021 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1024 def OnItemSelected(self
, event
):
1025 # This occurs before OnDoubleClick and can be used to set the
1026 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1027 self
.currentItem
= event
.m_itemIndex
1031 def OnDoubleClick(self
, event
):
1032 # If double-clicking on a demo's entry, jump to the line number
1033 line
= self
.list.GetItemData(self
.currentItem
)
1035 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1036 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1040 #---------------------------------------------------------------------------
1042 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1043 TBMENU_RESTORE
= wx
.NewId()
1044 TBMENU_CLOSE
= wx
.NewId()
1045 TBMENU_CHANGE
= wx
.NewId()
1046 TBMENU_REMOVE
= wx
.NewId()
1048 def __init__(self
, frame
):
1049 wx
.TaskBarIcon
.__init
__(self
)
1053 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1054 self
.SetIcon(icon
, "wxPython Demo")
1058 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1059 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1060 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1061 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1062 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1065 def CreatePopupMenu(self
):
1067 This method is called by the base class when it needs to popup
1068 the menu for the default EVT_RIGHT_DOWN event. Just create
1069 the menu how you want it and return it from this function,
1070 the base class takes care of the rest.
1073 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1074 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1075 menu
.AppendSeparator()
1076 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1077 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1081 def MakeIcon(self
, img
):
1083 The various platforms have different requirements for the
1086 if "wxMSW" in wx
.PlatformInfo
:
1087 img
= img
.Scale(16, 16)
1088 elif "wxGTK" in wx
.PlatformInfo
:
1089 img
= img
.Scale(22, 22)
1090 # wxMac can be any size upto 128x128, so leave the source img alone....
1091 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1095 def OnTaskBarActivate(self
, evt
):
1096 if self
.frame
.IsIconized():
1097 self
.frame
.Iconize(False)
1098 if not self
.frame
.IsShown():
1099 self
.frame
.Show(True)
1103 def OnTaskBarClose(self
, evt
):
1107 def OnTaskBarChange(self
, evt
):
1108 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1109 name
= names
[self
.imgidx
]
1111 getFunc
= getattr(images
, "get%sImage" % name
)
1113 if self
.imgidx
>= len(names
):
1116 icon
= self
.MakeIcon(getFunc())
1117 self
.SetIcon(icon
, "This is a new icon: " + name
)
1120 def OnTaskBarRemove(self
, evt
):
1124 #---------------------------------------------------------------------------
1125 class wxPythonDemo(wx
.Frame
):
1126 overviewText
= "wxPython Overview"
1128 def __init__(self
, parent
, title
):
1129 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1130 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1132 self
.SetMinSize((640,480))
1135 self
.cwd
= os
.getcwd()
1136 self
.curOverview
= ""
1137 self
.demoPage
= None
1138 self
.codePage
= None
1140 self
.firstTime
= True
1143 icon
= images
.getWXPdemoIcon()
1146 self
.tbicon
= DemoTaskBarIcon(self
)
1148 wx
.CallAfter(self
.ShowTip
)
1150 self
.otherWin
= None
1151 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1152 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1153 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1154 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1156 self
.Centre(wx
.BOTH
)
1157 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1159 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1160 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1162 def EmptyHandler(evt
): pass
1163 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1164 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1166 # Prevent TreeCtrl from displaying all items after destruction when True
1170 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1173 self
.mainmenu
= wx
.MenuBar()
1175 item
= menu
.Append(-1, '&Redirect Output',
1176 'Redirect print statements to a window',
1178 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1180 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1181 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1182 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1183 self
.mainmenu
.Append(menu
, '&File')
1187 for item
in _treeList
:
1189 for childItem
in item
[1]:
1190 mi
= submenu
.Append(-1, childItem
)
1191 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1192 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1193 self
.mainmenu
.Append(menu
, '&Demo')
1198 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1199 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1200 menu
.AppendSeparator()
1202 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1203 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1204 menu
.AppendSeparator()
1205 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1206 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1208 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1209 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1210 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1211 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1212 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1213 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1214 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1215 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1216 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1217 self
.mainmenu
.Append(menu
, '&Help')
1218 self
.SetMenuBar(self
.mainmenu
)
1220 self
.finddata
= wx
.FindReplaceData()
1221 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1224 # This is another way to set Accelerators, in addition to
1225 # using the '\t<key>' syntax in the menu items.
1226 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1227 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1228 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1229 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1231 self
.SetAcceleratorTable(aTable
)
1237 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1238 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1241 root
= self
.tree
.AddRoot("wxPython Overview")
1243 for item
in _treeList
:
1244 child
= self
.tree
.AppendItem(root
, item
[0])
1245 if not firstChild
: firstChild
= child
1246 for childItem
in item
[1]:
1247 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1248 self
.treeMap
[childItem
] = theDemo
1250 self
.tree
.Expand(root
)
1251 self
.tree
.Expand(firstChild
)
1252 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1253 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1254 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1255 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1257 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1258 # we put it in a panel first because there seems to be a
1259 # refresh bug of some sort (wxGTK) when it is directly in
1262 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1263 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1265 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1266 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1267 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1268 self
.nb
.AddPage(panel
, self
.overviewText
)
1270 def OnOvrSize(evt
, ovr
=self
.ovr
):
1271 ovr
.SetSize(evt
.GetSize())
1272 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1273 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1275 if "gtk2" in wx
.PlatformInfo
:
1276 self
.ovr
.SetStandardFonts()
1277 self
.SetOverview(self
.overviewText
, mainOverview
)
1280 # Set up a log window
1281 self
.log
= wx
.TextCtrl(splitter2
, -1,
1282 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1284 # Set the wxWindows log target to be this textctrl
1285 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1287 # But instead of the above we want to show how to use our own wx.Log class
1288 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1290 # for serious debugging
1291 #wx.Log_SetActiveTarget(wx.LogStderr())
1292 #wx.Log_SetTraceMask(wx.TraceMessages)
1295 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1296 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1298 # add the windows to the splitter and split it.
1299 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1300 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1302 splitter
.SetMinimumPaneSize(120)
1303 splitter2
.SetMinimumPaneSize(60)
1305 # Make the splitter on the right expand the top window when resized
1306 def SplitterOnSize(evt
):
1307 splitter
= evt
.GetEventObject()
1308 sz
= splitter
.GetSize()
1309 splitter
.SetSashPosition(sz
.height
- 160, False)
1312 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1314 # select initial items
1315 self
.nb
.SetSelection(0)
1316 self
.tree
.SelectItem(root
)
1318 # Load 'Main' module
1319 self
.LoadDemo(self
.overviewText
)
1322 # select some other initial module?
1323 if len(sys
.argv
) > 1:
1325 if arg
.endswith('.py'):
1327 selectedDemo
= self
.treeMap
.get(arg
, None)
1329 self
.tree
.SelectItem(selectedDemo
)
1330 self
.tree
.EnsureVisible(selectedDemo
)
1333 #---------------------------------------------
1334 def WriteText(self
, text
):
1335 if text
[-1:] == '\n':
1339 def write(self
, txt
):
1342 #---------------------------------------------
1343 def OnItemExpanded(self
, event
):
1344 item
= event
.GetItem()
1345 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1348 #---------------------------------------------
1349 def OnItemCollapsed(self
, event
):
1350 item
= event
.GetItem()
1351 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1354 #---------------------------------------------
1355 def OnTreeLeftDown(self
, event
):
1356 # reset the overview text if the tree item is clicked on again
1357 pt
= event
.GetPosition();
1358 item
, flags
= self
.tree
.HitTest(pt
)
1359 if item
== self
.tree
.GetSelection():
1360 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1363 #---------------------------------------------
1364 def OnSelChanged(self
, event
):
1365 if self
.dying
or not self
.loaded
:
1368 item
= event
.GetItem()
1369 itemText
= self
.tree
.GetItemText(item
)
1370 self
.LoadDemo(itemText
)
1372 #---------------------------------------------
1373 def LoadDemo(self
, demoName
):
1375 wx
.BeginBusyCursor()
1378 self
.ShutdownDemoModule()
1380 if demoName
== self
.overviewText
:
1381 # User selected the "wxPython Overview" node
1383 # Changing the main window at runtime not yet supported...
1384 self
.demoModules
= DemoModules(__name__
)
1385 self
.SetOverview(self
.overviewText
, mainOverview
)
1386 self
.LoadDemoSource()
1387 self
.UpdateNotebook(0)
1389 if os
.path
.exists(GetOriginalFilename(demoName
)):
1390 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1391 self
.demoModules
= DemoModules(demoName
)
1392 self
.LoadDemoSource()
1395 self
.SetOverview("wxPython", mainOverview
)
1396 self
.codePage
= None
1397 self
.UpdateNotebook(0)
1401 #---------------------------------------------
1402 def LoadDemoSource(self
):
1403 self
.codePage
= None
1404 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1405 self
.codePage
.LoadDemo(self
.demoModules
)
1407 #---------------------------------------------
1408 def RunModule(self
):
1409 """Runs the active module"""
1411 module
= self
.demoModules
.GetActive()
1412 self
.ShutdownDemoModule()
1415 # o The RunTest() for all samples must now return a window that can
1416 # be palced in a tab in the main notebook.
1417 # o If an error occurs (or has occurred before) an error tab is created.
1419 if module
is not None:
1420 wx
.LogMessage("Running demo module...")
1421 if hasattr(module
, "overview"):
1422 overviewText
= module
.overview
1425 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1427 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1428 DemoError(sys
.exc_info()), self
)
1430 assert self
.demoPage
is not None, "runTest must return a window!"
1433 # There was a previous error in compiling or exec-ing
1434 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1435 self
.demoModules
.GetErrorInfo(), self
)
1437 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1440 # cahnge to the demo page the first time a module is run
1441 self
.UpdateNotebook(2)
1442 self
.firstTime
= False
1444 # otherwise just stay on the same tab in case the user has changed to another one
1445 self
.UpdateNotebook()
1447 #---------------------------------------------
1448 def ShutdownDemoModule(self
):
1450 # inform the window that it's time to quit if it cares
1451 if hasattr(self
.demoPage
, "ShutdownDemo"):
1452 self
.demoPage
.ShutdownDemo()
1453 wx
.YieldIfNeeded() # in case the page has pending events
1454 self
.demoPage
= None
1456 #---------------------------------------------
1457 def UpdateNotebook(self
, select
= -1):
1461 def UpdatePage(page
, pageText
):
1464 for i
in range(nb
.GetPageCount()):
1465 if nb
.GetPageText(i
) == pageText
:
1473 nb
.AddPage(page
, pageText
)
1474 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1476 if nb
.GetPage(pagePos
) != page
:
1477 # Reload an existing page
1479 nb
.DeletePage(pagePos
)
1480 nb
.InsertPage(pagePos
, page
, pageText
)
1482 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1484 # Excellent! No redraw/flicker
1485 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1488 nb
.DeletePage(pagePos
)
1489 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1491 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1494 select
= nb
.GetSelection()
1496 UpdatePage(self
.codePage
, "Demo Code")
1497 UpdatePage(self
.demoPage
, "Demo")
1499 if select
>= 0 and select
< nb
.GetPageCount():
1500 nb
.SetSelection(select
)
1502 #---------------------------------------------
1503 def SetOverview(self
, name
, text
):
1504 self
.curOverview
= text
1506 if lead
!= '<html>' and lead
!= '<HTML>':
1507 text
= '<br>'.join(text
.split('\n'))
1509 text
= text
.decode('iso8859_1')
1510 self
.ovr
.SetPage(text
)
1511 self
.nb
.SetPageText(0, name
)
1513 #---------------------------------------------
1515 def OnFileExit(self
, *event
):
1518 def OnToggleRedirect(self
, event
):
1522 print "Print statements and other standard output will now be directed to this window."
1525 print "Print statements and other standard output will now be sent to the usual location."
1527 def OnHelpAbout(self
, event
):
1528 from About
import MyAboutBox
1529 about
= MyAboutBox(self
)
1533 def OnHelpFind(self
, event
):
1534 if self
.finddlg
!= None:
1537 self
.nb
.SetSelection(1)
1538 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1539 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1540 self
.finddlg
.Show(True)
1543 def OnUpdateFindItems(self
, evt
):
1544 evt
.Enable(self
.finddlg
== None)
1547 def OnFind(self
, event
):
1548 editor
= self
.codePage
.editor
1549 self
.nb
.SetSelection(1)
1550 end
= editor
.GetLastPosition()
1551 textstring
= editor
.GetRange(0, end
).lower()
1552 findstring
= self
.finddata
.GetFindString().lower()
1553 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1555 start
= editor
.GetSelection()[0]
1556 loc
= textstring
.rfind(findstring
, 0, start
)
1558 start
= editor
.GetSelection()[1]
1559 loc
= textstring
.find(findstring
, start
)
1560 if loc
== -1 and start
!= 0:
1561 # string not found, start at beginning
1564 loc
= textstring
.rfind(findstring
, 0, start
)
1567 loc
= textstring
.find(findstring
, start
)
1569 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1570 'Find String Not Found in Demo File',
1571 wx
.OK | wx
.ICON_INFORMATION
)
1576 self
.finddlg
.SetFocus()
1579 self
.finddlg
.Destroy()
1581 editor
.ShowPosition(loc
)
1582 editor
.SetSelection(loc
, loc
+ len(findstring
))
1586 def OnFindNext(self
, event
):
1587 if self
.finddata
.GetFindString():
1590 self
.OnHelpFind(event
)
1592 def OnFindClose(self
, event
):
1593 event
.GetDialog().Destroy()
1597 def OnOpenShellWindow(self
, evt
):
1599 # if it already exists then just make sure it's visible
1605 # Make a PyShell window
1607 namespace
= { 'wx' : wx
,
1608 'app' : wx
.GetApp(),
1611 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1612 self
.shell
.SetSize((640,480))
1615 # Hook the close event of the main frame window so that we
1616 # close the shell at the same time if it still exists
1617 def CloseShell(evt
):
1621 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1624 #---------------------------------------------
1625 def OnCloseWindow(self
, event
):
1627 self
.demoPage
= None
1628 self
.codePage
= None
1629 self
.mainmenu
= None
1630 self
.tbicon
.Destroy()
1634 #---------------------------------------------
1635 def OnIdle(self
, event
):
1637 self
.otherWin
.Raise()
1638 self
.demoPage
= self
.otherWin
1639 self
.otherWin
= None
1642 #---------------------------------------------
1645 showTipText
= open(opj("data/showTips")).read()
1646 showTip
, index
= eval(showTipText
)
1648 showTip
, index
= (1, 0)
1650 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1652 showTip
= wx
.ShowTip(self
, tp
)
1653 index
= tp
.GetCurrentTip()
1654 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1657 #---------------------------------------------
1658 def OnDemoMenu(self
, event
):
1660 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1664 self
.tree
.SelectItem(selectedDemo
)
1665 self
.tree
.EnsureVisible(selectedDemo
)
1669 #---------------------------------------------
1670 def OnIconfiy(self
, evt
):
1671 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1674 #---------------------------------------------
1675 def OnMaximize(self
, evt
):
1676 wx
.LogMessage("OnMaximize")
1679 #---------------------------------------------
1680 def OnActivate(self
, evt
):
1681 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1684 #---------------------------------------------
1685 def OnAppActivate(self
, evt
):
1686 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1689 #---------------------------------------------------------------------------
1690 #---------------------------------------------------------------------------
1692 class MySplashScreen(wx
.SplashScreen
):
1694 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1695 wx
.SplashScreen
.__init
__(self
, bmp
,
1696 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1698 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1699 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1702 def OnClose(self
, evt
):
1703 # Make sure the default handler runs too so this window gets
1708 # if the timer is still running then go ahead and show the
1710 if self
.fc
.IsRunning():
1716 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1718 if self
.fc
.IsRunning():
1722 class MyApp(wx
.App
):
1725 Create and show the splash screen. It will then create and show
1726 the main frame when it is time to do so.
1729 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1732 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1734 # Normally when using a SplashScreen you would create it, show
1735 # it and then continue on with the applicaiton's
1736 # initialization, finally creating and showing the main
1737 # application window(s). In this case we have nothing else to
1738 # do so we'll delay showing the main frame until later (see
1739 # ShowMain above) so the users can see the SplashScreen effect.
1740 splash
= MySplashScreen()
1747 #---------------------------------------------------------------------------
1751 demoPath
= os
.path
.dirname(__file__
)
1758 #---------------------------------------------------------------------------
1761 mainOverview
= """<html><body>
1764 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1765 language. It allows Python programmers to create programs with a
1766 robust, highly functional graphical user interface, simply and easily.
1767 It is implemented as a Python extension module (native code) that
1768 wraps the popular wxWindows cross platform GUI library, which is
1771 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1772 means that it is free for anyone to use and the source code is
1773 available for anyone to look at and modify. Or anyone can contribute
1774 fixes or enhancements to the project.
1776 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1777 same program will run on multiple platforms without modification.
1778 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1779 or unix-like systems, and Macintosh OS X. Since the language is
1780 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1783 <p> <b>This demo</b> is not only a collection of test cases for
1784 wxPython, but is also designed to help you learn about and how to use
1785 wxPython. Each sample is listed in the tree control on the left.
1786 When a sample is selected in the tree then a module is loaded and run
1787 (usually in a tab of this notebook,) and the source code of the module
1788 is loaded in another tab for you to browse and learn from.
1793 #----------------------------------------------------------------------------
1794 #----------------------------------------------------------------------------
1796 if __name__
== '__main__':
1800 #----------------------------------------------------------------------------