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',
62 # managed windows == things with a (optional) caption you can close
63 ('Frames and Dialogs', [
64 'AUI_DockingWindowMgr',
88 # dialogs from libraries
91 'ScrolledMessageDialog',
95 ('Core Windows/Controls', [
132 ('"Book" Controls', [
141 ('Custom Controls', [
155 # controls coming from other libraries
156 ('More Windows/Controls', [
157 'ActiveX_FlashWindow',
158 'ActiveX_IEHtmlWindow',
160 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
163 'CheckListCtrlMixin',
178 'MaskedEditControls',
181 'MultiSplitterWindow',
198 # How to lay out the controls in a frame/dialog
208 'XmlResourceHandler',
209 'XmlResourceSubclass',
213 ('Process and Events', [
220 ##'infoframe', # needs better explanation and some fixing
224 ('Clipboard and DnD', [
246 ##'DialogUnits', # needs more explanations
264 ('Check out the samples dir too', [
271 #---------------------------------------------------------------------------
272 # Show how to derive a custom wxLog class
274 class MyLog(wx
.PyLog
):
275 def __init__(self
, textCtrl
, logTime
=0):
276 wx
.PyLog
.__init
__(self
)
278 self
.logTime
= logTime
280 def DoLogString(self
, message
, timeStamp
):
281 #print message, timeStamp
283 # message = time.strftime("%X", time.localtime(timeStamp)) + \
286 self
.tc
.AppendText(message
+ '\n')
289 class MyTP(wx
.PyTipProvider
):
291 return "This is my tip"
293 #---------------------------------------------------------------------------
294 # A class to be used to simply display a message in the demo pane
295 # rather than running the sample itself.
297 class MessagePanel(wx
.Panel
):
298 def __init__(self
, parent
, message
, caption
='', flags
=0):
299 wx
.Panel
.__init
__(self
, parent
)
304 if flags
& wx
.ICON_EXCLAMATION
:
305 artid
= wx
.ART_WARNING
306 elif flags
& wx
.ICON_ERROR
:
308 elif flags
& wx
.ICON_QUESTION
:
309 artid
= wx
.ART_QUESTION
310 elif flags
& wx
.ICON_INFORMATION
:
311 artid
= wx
.ART_INFORMATION
313 if artid
is not None:
314 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
315 icon
= wx
.StaticBitmap(self
, -1, bmp
)
317 icon
= (32,32) # make a spacer instead
320 caption
= wx
.StaticText(self
, -1, caption
)
321 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
323 message
= wx
.StaticText(self
, -1, message
)
325 # add to sizers for layout
326 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
332 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
339 box
= wx
.BoxSizer(wx
.VERTICAL
)
341 box
.Add(hbox
, 0, wx
.EXPAND
)
348 #---------------------------------------------------------------------------
349 # A class to be used to display source code in the demo. Try using the
350 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
351 # if there is an error, such as the stc module not being present.
355 ##raise ImportError # for testing the alternate implementation
357 from StyledTextCtrl_2
import PythonSTC
359 class DemoCodeEditor(PythonSTC
):
360 def __init__(self
, parent
):
361 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
364 # Some methods to make it compatible with how the wxTextCtrl is used
365 def SetValue(self
, value
):
367 value
= value
.decode('iso8859_1')
369 self
.EmptyUndoBuffer()
372 def IsModified(self
):
373 return self
.GetModify()
378 def SetInsertionPoint(self
, pos
):
379 self
.SetCurrentPos(pos
)
382 def ShowPosition(self
, pos
):
383 line
= self
.LineFromPosition(pos
)
384 #self.EnsureVisible(line)
387 def GetLastPosition(self
):
388 return self
.GetLength()
390 def GetPositionFromLine(self
, line
):
391 return self
.PositionFromLine(line
)
393 def GetRange(self
, start
, end
):
394 return self
.GetTextRange(start
, end
)
396 def GetSelection(self
):
397 return self
.GetAnchor(), self
.GetCurrentPos()
399 def SetSelection(self
, start
, end
):
400 self
.SetSelectionStart(start
)
401 self
.SetSelectionEnd(end
)
403 def SelectLine(self
, line
):
404 start
= self
.PositionFromLine(line
)
405 end
= self
.GetLineEndPosition(line
)
406 self
.SetSelection(start
, end
)
408 def SetUpEditor(self
):
410 This method carries out the work of setting up the demo editor.
411 It's seperate so as not to clutter up the init code.
415 self
.SetLexer(stc
.STC_LEX_PYTHON
)
416 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
419 self
.SetProperty("fold", "1" )
421 # Highlight tab/space mixing (shouldn't be any)
422 self
.SetProperty("tab.timmy.whinge.level", "1")
424 # Set left and right margins
427 # Set up the numbers in the margin for margin #1
428 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
429 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
430 self
.SetMarginWidth(1, 40)
432 # Indentation and tab stuff
433 self
.SetIndent(4) # Proscribed indent size for wx
434 self
.SetIndentationGuides(True) # Show indent guides
435 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
436 self
.SetTabIndents(True) # Tab key indents
437 self
.SetTabWidth(4) # Proscribed tab size for wx
438 self
.SetUseTabs(False) # Use spaces rather than tabs, or
439 # TabTimmy will complain!
441 self
.SetViewWhiteSpace(False) # Don't view white space
443 # EOL: Since we are loading/saving ourselves, and the
444 # strings will always have \n's in them, set the STC to
445 # edit them that way.
446 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
447 self
.SetViewEOL(False)
449 # No right-edge mode indicator
450 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
452 # Setup a margin to hold fold markers
453 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
454 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
455 self
.SetMarginSensitive(2, True)
456 self
.SetMarginWidth(2, 12)
458 # and now set up the fold markers
459 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
460 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
461 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
462 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
463 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
464 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
465 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
467 # Global default style
468 if wx
.Platform
== '__WXMSW__':
469 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
470 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
472 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
473 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
475 # Clear styles and revert to default.
478 # Following style specs only indicate differences from default.
479 # The rest remains unchanged.
481 # Line numbers in margin
482 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
484 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
486 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
488 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
491 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
493 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
494 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
496 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
497 # Strings and characters
498 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
499 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
501 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
503 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
504 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
506 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
508 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
510 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
511 # Identifiers. I leave this as not bold because everything seems
512 # to be an identifier if it doesn't match the above criterae
513 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
516 self
.SetCaretForeground("BLUE")
517 # Selection background
518 self
.SetSelBackground(1, '#66CCFF')
520 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
521 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
523 def RegisterModifiedEvent(self
, eventHandler
):
524 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
528 class DemoCodeEditor(wx
.TextCtrl
):
529 def __init__(self
, parent
):
530 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
531 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
533 def RegisterModifiedEvent(self
, eventHandler
):
534 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
536 def SetReadOnly(self
, flag
):
537 self
.SetEditable(not flag
)
538 # NOTE: STC already has this method
541 return self
.GetValue()
543 def GetPositionFromLine(self
, line
):
544 return self
.XYToPosition(0,line
)
546 def GotoLine(self
, line
):
547 pos
= self
.GetPositionFromLine(line
)
548 self
.SetInsertionPoint(pos
)
549 self
.ShowPosition(pos
)
551 def SelectLine(self
, line
):
552 start
= self
.GetPositionFromLine(line
)
553 end
= start
+ self
.GetLineLength(line
)
554 self
.SetSelection(start
, end
)
557 #---------------------------------------------------------------------------
558 # Constants for module versions
562 modDefault
= modOriginal
564 #---------------------------------------------------------------------------
566 class DemoCodePanel(wx
.Panel
):
567 """Panel for the 'Demo Code' tab"""
568 def __init__(self
, parent
, mainFrame
):
569 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
570 if 'wxMSW' in wx
.PlatformInfo
:
572 self
.mainFrame
= mainFrame
573 self
.editor
= DemoCodeEditor(self
)
574 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
576 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
577 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
578 self
.btnSave
.Enable(False)
579 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
580 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
582 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
583 modModified
: wx
.RadioButton(self
, -1, "Modified") }
585 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
586 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
587 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
588 for modID
, radioButton
in self
.radioButtons
.items():
589 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
590 radioButton
.modID
= modID
# makes it easier for the event handler
591 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
593 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
594 self
.controlBox
.Add(self
.btnRestore
, 0)
596 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
597 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
598 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
599 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
602 self
.SetSizer(self
.box
)
605 # Loads a demo from a DemoModules object
606 def LoadDemo(self
, demoModules
):
607 self
.demoModules
= demoModules
608 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
609 demoModules
.SetActive(modModified
)
611 demoModules
.SetActive(modOriginal
)
612 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
613 self
.ActiveModuleChanged()
616 def ActiveModuleChanged(self
):
617 self
.LoadDemoSource(self
.demoModules
.GetSource())
618 self
.UpdateControlState()
622 def LoadDemoSource(self
, source
):
624 self
.editor
.SetValue(source
)
626 self
.btnSave
.Enable(False)
629 def JumpToLine(self
, line
, highlight
=False):
630 self
.editor
.GotoLine(line
)
631 self
.editor
.SetFocus()
633 self
.editor
.SelectLine(line
)
636 def UpdateControlState(self
):
637 active
= self
.demoModules
.GetActiveID()
638 # Update the radio/restore buttons
639 for moduleID
in self
.radioButtons
:
640 btn
= self
.radioButtons
[moduleID
]
641 if moduleID
== active
:
646 if self
.demoModules
.Exists(moduleID
):
648 if moduleID
== modModified
:
649 self
.btnRestore
.Enable(True)
652 if moduleID
== modModified
:
653 self
.btnRestore
.Enable(False)
656 def OnRadioButton(self
, event
):
657 radioSelected
= event
.GetEventObject()
658 modSelected
= radioSelected
.modID
659 if modSelected
!= self
.demoModules
.GetActiveID():
660 busy
= wx
.BusyInfo("Reloading demo module...")
661 self
.demoModules
.SetActive(modSelected
)
662 self
.ActiveModuleChanged()
665 def ReloadDemo(self
):
666 if self
.demoModules
.name
!= __name__
:
667 self
.mainFrame
.RunModule()
670 def OnCodeModified(self
, event
):
671 self
.btnSave
.Enable(self
.editor
.IsModified())
674 def OnSave(self
, event
):
675 if self
.demoModules
.Exists(modModified
):
676 if self
.demoModules
.GetActiveID() == modOriginal
:
677 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
678 "Do you want to continue?"
679 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
680 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
681 result
= dlg
.ShowModal()
682 if result
== wx
.ID_NO
:
686 self
.demoModules
.SetActive(modModified
)
687 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
689 # Create the demo directory if one doesn't already exist
690 if not os
.path
.exists(GetModifiedDirectory()):
692 os
.makedirs(GetModifiedDirectory())
693 if not os
.path
.exists(GetModifiedDirectory()):
694 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
697 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
700 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
703 f
= open(modifiedFilename
, "wt")
704 source
= self
.editor
.GetText()
710 busy
= wx
.BusyInfo("Reloading demo module...")
711 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
712 self
.ActiveModuleChanged()
715 def OnRestore(self
, event
): # Handles the "Delete Modified" button
716 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
717 self
.demoModules
.Delete(modModified
)
718 os
.unlink(modifiedFilename
) # Delete the modified copy
719 busy
= wx
.BusyInfo("Reloading demo module...")
720 self
.ActiveModuleChanged()
723 #---------------------------------------------------------------------------
726 """Convert paths to the platform-specific separator"""
727 str = apply(os
.path
.join
, tuple(path
.split('/')))
728 # HACK: on Linux, a leading / gets lost...
729 if path
.startswith('/'):
734 def GetModifiedDirectory():
736 Returns the directory where modified versions of the demo files
739 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
742 def GetModifiedFilename(name
):
744 Returns the filename of the modified version of the specified demo
746 if not name
.endswith(".py"):
748 return GetModifiedDirectory() + name
751 def GetOriginalFilename(name
):
753 Returns the filename of the original version of the specified demo
755 if not name
.endswith(".py"):
760 def DoesModifiedExist(name
):
761 """Returns whether the specified demo has a modified copy"""
762 if os
.path
.exists(GetModifiedFilename(name
)):
768 #---------------------------------------------------------------------------
770 class ModuleDictWrapper
:
771 """Emulates a module with a dynamically compiled __dict__"""
772 def __init__(self
, dict):
775 def __getattr__(self
, name
):
776 if name
in self
.dict:
777 return self
.dict[name
]
783 Dynamically manages the original/modified versions of a demo
786 def __init__(self
, name
):
790 # (dict , source , filename , description , error information )
791 # ( 0 , 1 , 2 , 3 , 4 )
792 self
.modules
= [[None, "" , "" , "<original>" , None],
793 [None, "" , "" , "<modified>" , None]]
795 # load original module
796 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
797 self
.SetActive(modOriginal
)
799 # load modified module (if one exists)
800 if DoesModifiedExist(name
):
801 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
804 def LoadFromFile(self
, modID
, filename
):
805 self
.modules
[modID
][2] = filename
806 file = open(filename
, "rt")
807 self
.LoadFromSource(modID
, file.read())
811 def LoadFromSource(self
, modID
, source
):
812 self
.modules
[modID
][1] = source
816 def LoadDict(self
, modID
):
817 if self
.name
!= __name__
:
818 source
= self
.modules
[modID
][1]
819 #description = self.modules[modID][3]
820 description
= self
.modules
[modID
][2]
823 self
.modules
[modID
][0] = {}
824 code
= compile(source
, description
, "exec")
825 exec code
in self
.modules
[modID
][0]
827 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
828 self
.modules
[modID
][0] = None
830 self
.modules
[modID
][4] = None
833 def SetActive(self
, modID
):
834 if modID
!= modOriginal
and modID
!= modModified
:
837 self
.modActive
= modID
841 dict = self
.modules
[self
.modActive
][0]
845 return ModuleDictWrapper(dict)
848 def GetActiveID(self
):
849 return self
.modActive
852 def GetSource(self
, modID
= None):
854 modID
= self
.modActive
855 return self
.modules
[modID
][1]
858 def GetFilename(self
, modID
= None):
860 modID
= self
.modActive
861 return self
.modules
[self
.modActive
][2]
864 def GetErrorInfo(self
, modID
= None):
866 modID
= self
.modActive
867 return self
.modules
[self
.modActive
][4]
870 def Exists(self
, modID
):
871 return self
.modules
[modID
][1] != ""
874 def UpdateFile(self
, modID
= None):
875 """Updates the file from which a module was loaded
876 with (possibly updated) source"""
878 modID
= self
.modActive
880 source
= self
.modules
[modID
][1]
881 filename
= self
.modules
[modID
][2]
884 file = open(filename
, "wt")
890 def Delete(self
, modID
):
891 if self
.modActive
== modID
:
894 self
.modules
[modID
][0] = None
895 self
.modules
[modID
][1] = ""
896 self
.modules
[modID
][2] = ""
899 #---------------------------------------------------------------------------
902 """Wraps and stores information about the current exception"""
903 def __init__(self
, exc_info
):
906 excType
, excValue
= exc_info
[:2]
907 # traceback list entries: (filename, line number, function name, text)
908 self
.traceback
= traceback
.extract_tb(exc_info
[2])
910 # --Based on traceback.py::format_exception_only()--
911 if type(excType
) == types
.ClassType
:
912 self
.exception_type
= excType
.__name
__
914 self
.exception_type
= excType
916 # If it's a syntax error, extra information needs
917 # to be added to the traceback
918 if excType
is SyntaxError:
920 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
925 filename
= "<string>"
927 self
.traceback
.append( (filename
, lineno
, "", line
) )
930 self
.exception_details
= str(excValue
)
932 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
939 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
942 #---------------------------------------------------------------------------
944 class DemoErrorPanel(wx
.Panel
):
945 """Panel put into the demo tab when the demo fails to run due to errors"""
947 def __init__(self
, parent
, codePanel
, demoError
, log
):
948 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
949 self
.codePanel
= codePanel
953 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
956 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
957 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
959 # Exception Information
960 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
961 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
962 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
963 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
964 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
965 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
966 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
967 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
968 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
969 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
971 # Set up the traceback list
972 # This one automatically resizes last column to take up remaining space
973 from ListCtrl
import TestListCtrl
974 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
975 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
976 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
977 self
.list.InsertColumn(0, "Filename")
978 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
979 self
.list.InsertColumn(2, "Function")
980 self
.list.InsertColumn(3, "Code")
981 self
.InsertTraceback(self
.list, demoError
.traceback
)
982 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
983 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
984 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
985 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
986 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
987 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
988 + "Double-click on them to go to the offending line")
989 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
992 self
.SetSizer(self
.box
)
995 def InsertTraceback(self
, list, traceback
):
996 #Add the traceback data
997 for x
in range(len(traceback
)):
999 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
1000 list.SetStringItem(x
, 1, str(data
[1])) # Line
1001 list.SetStringItem(x
, 2, str(data
[2])) # Function
1002 list.SetStringItem(x
, 3, str(data
[3])) # Code
1004 # Check whether this entry is from the demo module
1005 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1006 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1007 # Give it a blue colour
1008 item
= self
.list.GetItem(x
)
1009 item
.SetTextColour(wx
.BLUE
)
1010 self
.list.SetItem(item
)
1012 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1015 def OnItemSelected(self
, event
):
1016 # This occurs before OnDoubleClick and can be used to set the
1017 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1018 self
.currentItem
= event
.m_itemIndex
1022 def OnDoubleClick(self
, event
):
1023 # If double-clicking on a demo's entry, jump to the line number
1024 line
= self
.list.GetItemData(self
.currentItem
)
1026 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1027 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1031 #---------------------------------------------------------------------------
1033 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1034 TBMENU_RESTORE
= wx
.NewId()
1035 TBMENU_CLOSE
= wx
.NewId()
1036 TBMENU_CHANGE
= wx
.NewId()
1037 TBMENU_REMOVE
= wx
.NewId()
1039 def __init__(self
, frame
):
1040 wx
.TaskBarIcon
.__init
__(self
)
1044 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1045 self
.SetIcon(icon
, "wxPython Demo")
1049 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1050 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1051 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1052 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1053 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1056 def CreatePopupMenu(self
):
1058 This method is called by the base class when it needs to popup
1059 the menu for the default EVT_RIGHT_DOWN event. Just create
1060 the menu how you want it and return it from this function,
1061 the base class takes care of the rest.
1064 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1065 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1066 menu
.AppendSeparator()
1067 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1068 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1072 def MakeIcon(self
, img
):
1074 The various platforms have different requirements for the
1077 if "wxMSW" in wx
.PlatformInfo
:
1078 img
= img
.Scale(16, 16)
1079 elif "wxGTK" in wx
.PlatformInfo
:
1080 img
= img
.Scale(22, 22)
1081 # wxMac can be any size upto 128x128, so leave the source img alone....
1082 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1086 def OnTaskBarActivate(self
, evt
):
1087 if self
.frame
.IsIconized():
1088 self
.frame
.Iconize(False)
1089 if not self
.frame
.IsShown():
1090 self
.frame
.Show(True)
1094 def OnTaskBarClose(self
, evt
):
1098 def OnTaskBarChange(self
, evt
):
1099 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1100 name
= names
[self
.imgidx
]
1102 getFunc
= getattr(images
, "get%sImage" % name
)
1104 if self
.imgidx
>= len(names
):
1107 icon
= self
.MakeIcon(getFunc())
1108 self
.SetIcon(icon
, "This is a new icon: " + name
)
1111 def OnTaskBarRemove(self
, evt
):
1115 #---------------------------------------------------------------------------
1116 class wxPythonDemo(wx
.Frame
):
1117 overviewText
= "wxPython Overview"
1119 def __init__(self
, parent
, title
):
1120 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1121 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1123 self
.SetMinSize((640,480))
1126 self
.cwd
= os
.getcwd()
1127 self
.curOverview
= ""
1128 self
.demoPage
= None
1129 self
.codePage
= None
1131 self
.firstTime
= True
1134 icon
= images
.getWXPdemoIcon()
1137 self
.tbicon
= DemoTaskBarIcon(self
)
1139 wx
.CallAfter(self
.ShowTip
)
1141 self
.otherWin
= None
1142 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1143 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1144 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1145 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1147 self
.Centre(wx
.BOTH
)
1148 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1150 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1151 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1153 def EmptyHandler(evt
): pass
1154 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1155 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1157 # Prevent TreeCtrl from displaying all items after destruction when True
1161 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1164 self
.mainmenu
= wx
.MenuBar()
1166 item
= menu
.Append(-1, '&Redirect Output',
1167 'Redirect print statements to a window',
1169 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1171 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1172 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1173 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1174 self
.mainmenu
.Append(menu
, '&File')
1178 for item
in _treeList
:
1180 for childItem
in item
[1]:
1181 mi
= submenu
.Append(-1, childItem
)
1182 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1183 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1184 self
.mainmenu
.Append(menu
, '&Demo')
1189 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1190 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1191 menu
.AppendSeparator()
1193 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1194 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1195 menu
.AppendSeparator()
1196 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1197 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1199 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1200 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1201 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1202 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1203 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1204 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1205 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1206 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1207 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1208 self
.mainmenu
.Append(menu
, '&Help')
1209 self
.SetMenuBar(self
.mainmenu
)
1211 self
.finddata
= wx
.FindReplaceData()
1212 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1215 # This is another way to set Accelerators, in addition to
1216 # using the '\t<key>' syntax in the menu items.
1217 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1218 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1219 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1220 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1222 self
.SetAcceleratorTable(aTable
)
1228 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1229 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1232 root
= self
.tree
.AddRoot("wxPython Overview")
1234 for item
in _treeList
:
1235 child
= self
.tree
.AppendItem(root
, item
[0])
1236 if not firstChild
: firstChild
= child
1237 for childItem
in item
[1]:
1238 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1239 self
.treeMap
[childItem
] = theDemo
1241 self
.tree
.Expand(root
)
1242 self
.tree
.Expand(firstChild
)
1243 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1244 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1245 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1246 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1248 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1249 # we put it in a panel first because there seems to be a
1250 # refresh bug of some sort (wxGTK) when it is directly in
1253 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1254 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1256 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1257 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1258 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1259 self
.nb
.AddPage(panel
, self
.overviewText
)
1261 def OnOvrSize(evt
, ovr
=self
.ovr
):
1262 ovr
.SetSize(evt
.GetSize())
1263 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1264 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1266 if "gtk2" in wx
.PlatformInfo
:
1267 self
.ovr
.SetStandardFonts()
1268 self
.SetOverview(self
.overviewText
, mainOverview
)
1271 # Set up a log window
1272 self
.log
= wx
.TextCtrl(splitter2
, -1,
1273 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1275 # Set the wxWindows log target to be this textctrl
1276 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1278 # But instead of the above we want to show how to use our own wx.Log class
1279 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1281 # for serious debugging
1282 #wx.Log_SetActiveTarget(wx.LogStderr())
1283 #wx.Log_SetTraceMask(wx.TraceMessages)
1286 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1287 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1289 # add the windows to the splitter and split it.
1290 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1291 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1293 splitter
.SetMinimumPaneSize(120)
1294 splitter2
.SetMinimumPaneSize(60)
1296 # Make the splitter on the right expand the top window when resized
1297 def SplitterOnSize(evt
):
1298 splitter
= evt
.GetEventObject()
1299 sz
= splitter
.GetSize()
1300 splitter
.SetSashPosition(sz
.height
- 160, False)
1303 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1305 # select initial items
1306 self
.nb
.SetSelection(0)
1307 self
.tree
.SelectItem(root
)
1309 # Load 'Main' module
1310 self
.LoadDemo(self
.overviewText
)
1313 # select some other initial module?
1314 if len(sys
.argv
) > 1:
1316 if arg
.endswith('.py'):
1318 selectedDemo
= self
.treeMap
.get(arg
, None)
1320 self
.tree
.SelectItem(selectedDemo
)
1321 self
.tree
.EnsureVisible(selectedDemo
)
1324 #---------------------------------------------
1325 def WriteText(self
, text
):
1326 if text
[-1:] == '\n':
1330 def write(self
, txt
):
1333 #---------------------------------------------
1334 def OnItemExpanded(self
, event
):
1335 item
= event
.GetItem()
1336 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1339 #---------------------------------------------
1340 def OnItemCollapsed(self
, event
):
1341 item
= event
.GetItem()
1342 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1345 #---------------------------------------------
1346 def OnTreeLeftDown(self
, event
):
1347 # reset the overview text if the tree item is clicked on again
1348 pt
= event
.GetPosition();
1349 item
, flags
= self
.tree
.HitTest(pt
)
1350 if item
== self
.tree
.GetSelection():
1351 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1354 #---------------------------------------------
1355 def OnSelChanged(self
, event
):
1356 if self
.dying
or not self
.loaded
:
1359 item
= event
.GetItem()
1360 itemText
= self
.tree
.GetItemText(item
)
1361 self
.LoadDemo(itemText
)
1363 #---------------------------------------------
1364 def LoadDemo(self
, demoName
):
1366 wx
.BeginBusyCursor()
1369 self
.ShutdownDemoModule()
1371 if demoName
== self
.overviewText
:
1372 # User selected the "wxPython Overview" node
1374 # Changing the main window at runtime not yet supported...
1375 self
.demoModules
= DemoModules(__name__
)
1376 self
.SetOverview(self
.overviewText
, mainOverview
)
1377 self
.LoadDemoSource()
1378 self
.UpdateNotebook(0)
1380 if os
.path
.exists(GetOriginalFilename(demoName
)):
1381 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1382 self
.demoModules
= DemoModules(demoName
)
1383 self
.LoadDemoSource()
1386 self
.SetOverview("wxPython", mainOverview
)
1387 self
.codePage
= None
1388 self
.UpdateNotebook(0)
1392 #---------------------------------------------
1393 def LoadDemoSource(self
):
1394 self
.codePage
= None
1395 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1396 self
.codePage
.LoadDemo(self
.demoModules
)
1398 #---------------------------------------------
1399 def RunModule(self
):
1400 """Runs the active module"""
1402 module
= self
.demoModules
.GetActive()
1403 self
.ShutdownDemoModule()
1406 # o The RunTest() for all samples must now return a window that can
1407 # be palced in a tab in the main notebook.
1408 # o If an error occurs (or has occurred before) an error tab is created.
1410 if module
is not None:
1411 wx
.LogMessage("Running demo module...")
1412 if hasattr(module
, "overview"):
1413 overviewText
= module
.overview
1416 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1418 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1419 DemoError(sys
.exc_info()), self
)
1421 assert self
.demoPage
is not None, "runTest must return a window!"
1424 # There was a previous error in compiling or exec-ing
1425 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1426 self
.demoModules
.GetErrorInfo(), self
)
1428 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1431 # cahnge to the demo page the first time a module is run
1432 self
.UpdateNotebook(2)
1433 self
.firstTime
= False
1435 # otherwise just stay on the same tab in case the user has changed to another one
1436 self
.UpdateNotebook()
1438 #---------------------------------------------
1439 def ShutdownDemoModule(self
):
1441 # inform the window that it's time to quit if it cares
1442 if hasattr(self
.demoPage
, "ShutdownDemo"):
1443 self
.demoPage
.ShutdownDemo()
1444 wx
.YieldIfNeeded() # in case the page has pending events
1445 self
.demoPage
= None
1447 #---------------------------------------------
1448 def UpdateNotebook(self
, select
= -1):
1452 def UpdatePage(page
, pageText
):
1455 for i
in range(nb
.GetPageCount()):
1456 if nb
.GetPageText(i
) == pageText
:
1464 nb
.AddPage(page
, pageText
)
1465 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1467 if nb
.GetPage(pagePos
) != page
:
1468 # Reload an existing page
1470 nb
.DeletePage(pagePos
)
1471 nb
.InsertPage(pagePos
, page
, pageText
)
1473 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1475 # Excellent! No redraw/flicker
1476 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1479 nb
.DeletePage(pagePos
)
1480 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1482 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1485 select
= nb
.GetSelection()
1487 UpdatePage(self
.codePage
, "Demo Code")
1488 UpdatePage(self
.demoPage
, "Demo")
1490 if select
>= 0 and select
< nb
.GetPageCount():
1491 nb
.SetSelection(select
)
1493 #---------------------------------------------
1494 def SetOverview(self
, name
, text
):
1495 self
.curOverview
= text
1497 if lead
!= '<html>' and lead
!= '<HTML>':
1498 text
= '<br>'.join(text
.split('\n'))
1500 text
= text
.decode('iso8859_1')
1501 self
.ovr
.SetPage(text
)
1502 self
.nb
.SetPageText(0, name
)
1504 #---------------------------------------------
1506 def OnFileExit(self
, *event
):
1509 def OnToggleRedirect(self
, event
):
1513 print "Print statements and other standard output will now be directed to this window."
1516 print "Print statements and other standard output will now be sent to the usual location."
1518 def OnHelpAbout(self
, event
):
1519 from About
import MyAboutBox
1520 about
= MyAboutBox(self
)
1524 def OnHelpFind(self
, event
):
1525 if self
.finddlg
!= None:
1528 self
.nb
.SetSelection(1)
1529 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1530 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
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 findstring
= self
.finddata
.GetFindString().lower()
1544 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1546 start
= editor
.GetSelection()[0]
1547 loc
= textstring
.rfind(findstring
, 0, start
)
1549 start
= editor
.GetSelection()[1]
1550 loc
= textstring
.find(findstring
, start
)
1551 if loc
== -1 and start
!= 0:
1552 # string not found, start at beginning
1555 loc
= textstring
.rfind(findstring
, 0, start
)
1558 loc
= textstring
.find(findstring
, start
)
1560 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1561 'Find String Not Found in Demo File',
1562 wx
.OK | wx
.ICON_INFORMATION
)
1567 self
.finddlg
.SetFocus()
1570 self
.finddlg
.Destroy()
1572 editor
.ShowPosition(loc
)
1573 editor
.SetSelection(loc
, loc
+ len(findstring
))
1577 def OnFindNext(self
, event
):
1578 if self
.finddata
.GetFindString():
1581 self
.OnHelpFind(event
)
1583 def OnFindClose(self
, event
):
1584 event
.GetDialog().Destroy()
1588 def OnOpenShellWindow(self
, evt
):
1590 # if it already exists then just make sure it's visible
1596 # Make a PyShell window
1598 namespace
= { 'wx' : wx
,
1599 'app' : wx
.GetApp(),
1602 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1603 self
.shell
.SetSize((640,480))
1606 # Hook the close event of the main frame window so that we
1607 # close the shell at the same time if it still exists
1608 def CloseShell(evt
):
1612 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1615 #---------------------------------------------
1616 def OnCloseWindow(self
, event
):
1618 self
.demoPage
= None
1619 self
.codePage
= None
1620 self
.mainmenu
= None
1621 self
.tbicon
.Destroy()
1625 #---------------------------------------------
1626 def OnIdle(self
, event
):
1628 self
.otherWin
.Raise()
1629 self
.demoPage
= self
.otherWin
1630 self
.otherWin
= None
1633 #---------------------------------------------
1636 showTipText
= open(opj("data/showTips")).read()
1637 showTip
, index
= eval(showTipText
)
1639 showTip
, index
= (1, 0)
1641 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1643 showTip
= wx
.ShowTip(self
, tp
)
1644 index
= tp
.GetCurrentTip()
1645 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1648 #---------------------------------------------
1649 def OnDemoMenu(self
, event
):
1651 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1655 self
.tree
.SelectItem(selectedDemo
)
1656 self
.tree
.EnsureVisible(selectedDemo
)
1660 #---------------------------------------------
1661 def OnIconfiy(self
, evt
):
1662 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1665 #---------------------------------------------
1666 def OnMaximize(self
, evt
):
1667 wx
.LogMessage("OnMaximize")
1670 #---------------------------------------------
1671 def OnActivate(self
, evt
):
1672 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1675 #---------------------------------------------
1676 def OnAppActivate(self
, evt
):
1677 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1680 #---------------------------------------------------------------------------
1681 #---------------------------------------------------------------------------
1683 class MySplashScreen(wx
.SplashScreen
):
1685 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1686 wx
.SplashScreen
.__init
__(self
, bmp
,
1687 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1689 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1690 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1693 def OnClose(self
, evt
):
1694 # Make sure the default handler runs too so this window gets
1699 # if the timer is still running then go ahead and show the
1701 if self
.fc
.IsRunning():
1707 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1709 if self
.fc
.IsRunning():
1713 class MyApp(wx
.App
):
1716 Create and show the splash screen. It will then create and show
1717 the main frame when it is time to do so.
1720 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1723 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1725 # Normally when using a SplashScreen you would create it, show
1726 # it and then continue on with the applicaiton's
1727 # initialization, finally creating and showing the main
1728 # application window(s). In this case we have nothing else to
1729 # do so we'll delay showing the main frame until later (see
1730 # ShowMain above) so the users can see the SplashScreen effect.
1731 splash
= MySplashScreen()
1738 #---------------------------------------------------------------------------
1742 demoPath
= os
.path
.dirname(__file__
)
1749 #---------------------------------------------------------------------------
1752 mainOverview
= """<html><body>
1755 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1756 language. It allows Python programmers to create programs with a
1757 robust, highly functional graphical user interface, simply and easily.
1758 It is implemented as a Python extension module (native code) that
1759 wraps the popular wxWindows cross platform GUI library, which is
1762 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1763 means that it is free for anyone to use and the source code is
1764 available for anyone to look at and modify. Or anyone can contribute
1765 fixes or enhancements to the project.
1767 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1768 same program will run on multiple platforms without modification.
1769 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1770 or unix-like systems, and Macintosh OS X. Since the language is
1771 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1774 <p> <b>This demo</b> is not only a collection of test cases for
1775 wxPython, but is also designed to help you learn about and how to use
1776 wxPython. Each sample is listed in the tree control on the left.
1777 When a sample is selected in the tree then a module is loaded and run
1778 (usually in a tab of this notebook,) and the source code of the module
1779 is loaded in another tab for you to browse and learn from.
1784 #----------------------------------------------------------------------------
1785 #----------------------------------------------------------------------------
1787 if __name__
== '__main__':
1791 #----------------------------------------------------------------------------