2 #----------------------------------------------------------------------------
4 # Purpose: Testing lots of stuff, controls, window types, etc.
8 # Created: A long time ago, in a galaxy far, far away...
10 # Copyright: (c) 1999 by Total Control Software
11 # Licence: wxWindows license
12 #----------------------------------------------------------------------------
15 # * Problems with flickering related to ERASE_BACKGROUND
16 # and the splitters. Might be a problem with this 2.5 beta...?
17 # UPDATE: can't see on 2.5.2 GTK - maybe just a faster machine :)
19 # * Annoying switching between tabs and resulting flicker
20 # how to replace a page in the notebook without deleting/adding?
21 # Where is SetPage!? tried freeze...tried reparent of dummy panel....
24 # * UI design more prefessional
25 # * save file positions (new field in demoModules) (@ LoadDemoSource)
26 # * Update main overview
28 # * Why don't we move _treeList into a separate module
30 import sys
, os
, time
, traceback
, types
32 import wx
# This module uses the new wx namespace
39 ##print "wx.VERSION_STRING = ", wx.VERSION_STRING
41 ##raw_input("Press Enter...")
44 #---------------------------------------------------------------------------
49 ('Recent Additions/Updates', [
55 # managed windows == things with a (optional) caption you can close
56 ('Frames and Dialogs', [
80 # dialogs from libraries
83 'MultipleChoiceDialog',
84 'ScrolledMessageDialog',
88 ('Core Windows/Controls', [
128 ('Custom Controls', [
141 # controls coming from other libraries
142 ('More Windows/Controls', [
143 'ActiveX_FlashWindow',
144 'ActiveX_IEHtmlWindow',
146 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
164 'MaskedEditControls',
181 # How to lay out the controls in a frame/dialog
191 'XmlResourceHandler',
192 'XmlResourceSubclass',
196 ('Process and Events', [
203 ##'infoframe', # needs better explanation and some fixing
207 ('Clipboard and DnD', [
229 ##'DialogUnits', # needs more explanations
243 # need libs not coming with the demo
244 ('Samples using an external library', [
249 ('Check out the samples dir too', [
256 #---------------------------------------------------------------------------
257 # Show how to derive a custom wxLog class
259 class MyLog(wx
.PyLog
):
260 def __init__(self
, textCtrl
, logTime
=0):
261 wx
.PyLog
.__init
__(self
)
263 self
.logTime
= logTime
265 def DoLogString(self
, message
, timeStamp
):
266 #print message, timeStamp
268 # message = time.strftime("%X", time.localtime(timeStamp)) + \
271 self
.tc
.AppendText(message
+ '\n')
274 class MyTP(wx
.PyTipProvider
):
276 return "This is my tip"
278 #---------------------------------------------------------------------------
279 # A class to be used to simply display a message in the demo pane
280 # rather than running the sample itself.
282 class MessagePanel(wx
.Panel
):
283 def __init__(self
, parent
, message
, caption
='', flags
=0):
284 wx
.Panel
.__init
__(self
, parent
)
289 if flags
& wx
.ICON_EXCLAMATION
:
290 artid
= wx
.ART_WARNING
291 elif flags
& wx
.ICON_ERROR
:
293 elif flags
& wx
.ICON_QUESTION
:
294 artid
= wx
.ART_QUESTION
295 elif flags
& wx
.ICON_INFORMATION
:
296 artid
= wx
.ART_INFORMATION
298 if artid
is not None:
299 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
300 icon
= wx
.StaticBitmap(self
, -1, bmp
)
302 icon
= (32,32) # make a spacer instead
305 caption
= wx
.StaticText(self
, -1, caption
)
306 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
308 message
= wx
.StaticText(self
, -1, message
)
310 # add to sizers for layout
311 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
317 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
324 box
= wx
.BoxSizer(wx
.VERTICAL
)
326 box
.Add(hbox
, 0, wx
.EXPAND
)
333 #---------------------------------------------------------------------------
334 # A class to be used to display source code in the demo. Try using the
335 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
336 # if there is an error, such as the stc module not being present.
340 ##raise ImportError # for testing the alternate implementation
342 from StyledTextCtrl_2
import PythonSTC
344 class DemoCodeEditor(PythonSTC
):
345 def __init__(self
, parent
):
346 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
349 # Some methods to make it compatible with how the wxTextCtrl is used
350 def SetValue(self
, value
):
352 value
= value
.decode('iso8859_1')
354 self
.EmptyUndoBuffer()
357 def IsModified(self
):
358 return self
.GetModify()
363 def SetInsertionPoint(self
, pos
):
364 self
.SetCurrentPos(pos
)
367 def ShowPosition(self
, pos
):
368 line
= self
.LineFromPosition(pos
)
369 #self.EnsureVisible(line)
372 def GetLastPosition(self
):
373 return self
.GetLength()
375 def GetPositionFromLine(self
, line
):
376 return self
.PositionFromLine(line
)
378 def GetRange(self
, start
, end
):
379 return self
.GetTextRange(start
, end
)
381 def GetSelection(self
):
382 return self
.GetAnchor(), self
.GetCurrentPos()
384 def SetSelection(self
, start
, end
):
385 self
.SetSelectionStart(start
)
386 self
.SetSelectionEnd(end
)
388 def SelectLine(self
, line
):
389 start
= self
.PositionFromLine(line
)
390 end
= self
.GetLineEndPosition(line
)
391 self
.SetSelection(start
, end
)
393 def SetUpEditor(self
):
395 This method carries out the work of setting up the demo editor.
396 It's seperate so as not to clutter up the init code.
400 self
.SetLexer(stc
.STC_LEX_PYTHON
)
401 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
404 self
.SetProperty("fold", "1" )
406 # Highlight tab/space mixing (shouldn't be any)
407 self
.SetProperty("tab.timmy.whinge.level", "1")
409 # Set left and right margins
412 # Set up the numbers in the margin for margin #1
413 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
414 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
415 self
.SetMarginWidth(1, 40)
417 # Indentation and tab stuff
418 self
.SetIndent(4) # Proscribed indent size for wx
419 self
.SetIndentationGuides(True) # Show indent guides
420 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
421 self
.SetTabIndents(True) # Tab key indents
422 self
.SetTabWidth(4) # Proscribed tab size for wx
423 self
.SetUseTabs(False) # Use spaces rather than tabs, or
424 # TabTimmy will complain!
426 self
.SetViewWhiteSpace(False) # Don't view white space
428 # EOL: Since we are loading/saving ourselves, and the
429 # strings will always have \n's in them, set the STC to
430 # edit them that way.
431 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
432 self
.SetViewEOL(False)
434 # No right-edge mode indicator
435 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
437 # Setup a margin to hold fold markers
438 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
439 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
440 self
.SetMarginSensitive(2, True)
441 self
.SetMarginWidth(2, 12)
443 # and now set up the fold markers
444 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
445 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
446 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
447 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
448 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
449 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
450 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
452 # Global default style
453 if wx
.Platform
== '__WXMSW__':
454 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
455 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
457 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
458 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
460 # Clear styles and revert to default.
463 # Following style specs only indicate differences from default.
464 # The rest remains unchanged.
466 # Line numbers in margin
467 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
469 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
471 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
473 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
476 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
478 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
479 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
481 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
482 # Strings and characters
483 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
484 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
486 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
488 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
489 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
491 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
493 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
495 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
496 # Identifiers. I leave this as not bold because everything seems
497 # to be an identifier if it doesn't match the above criterae
498 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
501 self
.SetCaretForeground("BLUE")
502 # Selection background
503 self
.SetSelBackground(1, '#66CCFF')
505 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
506 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
508 def RegisterModifiedEvent(self
, eventHandler
):
509 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
513 class DemoCodeEditor(wx
.TextCtrl
):
514 def __init__(self
, parent
):
515 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
516 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
518 def RegisterModifiedEvent(self
, eventHandler
):
519 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
521 def SetReadOnly(self
, flag
):
522 self
.SetEditable(not flag
)
523 # NOTE: STC already has this method
526 return self
.GetValue()
528 def GetPositionFromLine(self
, line
):
529 return self
.XYToPosition(0,line
)
531 def GotoLine(self
, line
):
532 pos
= self
.GetPositionFromLine(line
)
533 self
.SetInsertionPoint(pos
)
534 self
.ShowPosition(pos
)
536 def SelectLine(self
, line
):
537 start
= self
.GetPositionFromLine(line
)
538 end
= start
+ self
.GetLineLength(line
)
539 self
.SetSelection(start
, end
)
542 #---------------------------------------------------------------------------
543 # Constants for module versions
547 modDefault
= modOriginal
549 #---------------------------------------------------------------------------
551 class DemoCodePanel(wx
.Panel
):
552 """Panel for the 'Demo Code' tab"""
553 def __init__(self
, parent
, mainFrame
):
554 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
555 if 'wxMSW' in wx
.PlatformInfo
:
557 self
.mainFrame
= mainFrame
558 self
.editor
= DemoCodeEditor(self
)
559 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
561 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
562 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
563 self
.btnSave
.Enable(False)
564 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
565 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
567 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
568 modModified
: wx
.RadioButton(self
, -1, "Modified") }
570 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
571 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
572 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
573 for modID
, radioButton
in self
.radioButtons
.items():
574 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
575 radioButton
.modID
= modID
# makes it easier for the event handler
576 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
578 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
579 self
.controlBox
.Add(self
.btnRestore
, 0)
581 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
582 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
583 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
584 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
587 self
.SetSizer(self
.box
)
590 # Loads a demo from a DemoModules object
591 def LoadDemo(self
, demoModules
):
592 self
.demoModules
= demoModules
593 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
594 demoModules
.SetActive(modModified
)
596 demoModules
.SetActive(modOriginal
)
597 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
598 self
.ActiveModuleChanged()
601 def ActiveModuleChanged(self
):
602 self
.LoadDemoSource(self
.demoModules
.GetSource())
603 self
.UpdateControlState()
607 def LoadDemoSource(self
, source
):
609 self
.editor
.SetValue(source
)
611 self
.btnSave
.Enable(False)
614 def JumpToLine(self
, line
, highlight
=False):
615 self
.editor
.GotoLine(line
)
616 self
.editor
.SetFocus()
618 self
.editor
.SelectLine(line
)
621 def UpdateControlState(self
):
622 active
= self
.demoModules
.GetActiveID()
623 # Update the radio/restore buttons
624 for moduleID
in self
.radioButtons
:
625 btn
= self
.radioButtons
[moduleID
]
626 if moduleID
== active
:
631 if self
.demoModules
.Exists(moduleID
):
633 if moduleID
== modModified
:
634 self
.btnRestore
.Enable(True)
637 if moduleID
== modModified
:
638 self
.btnRestore
.Enable(False)
641 def OnRadioButton(self
, event
):
642 radioSelected
= event
.GetEventObject()
643 modSelected
= radioSelected
.modID
644 if modSelected
!= self
.demoModules
.GetActiveID():
645 busy
= wx
.BusyInfo("Reloading demo module...")
646 self
.demoModules
.SetActive(modSelected
)
647 self
.ActiveModuleChanged()
650 def ReloadDemo(self
):
651 if self
.demoModules
.name
!= __name__
:
652 self
.mainFrame
.RunModule()
655 def OnCodeModified(self
, event
):
656 self
.btnSave
.Enable(self
.editor
.IsModified())
659 def OnSave(self
, event
):
660 if self
.demoModules
.Exists(modModified
):
661 if self
.demoModules
.GetActiveID() == modOriginal
:
662 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
663 "Do you want to continue?"
664 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
665 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
666 result
= dlg
.ShowModal()
667 if result
== wx
.ID_NO
:
671 self
.demoModules
.SetActive(modModified
)
672 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
674 # Create the demo directory if one doesn't already exist
675 if not os
.path
.exists(GetModifiedDirectory()):
677 os
.makedirs(GetModifiedDirectory())
678 if not os
.path
.exists(GetModifiedDirectory()):
679 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
682 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
685 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
688 f
= open(modifiedFilename
, "wt")
689 source
= self
.editor
.GetText()
695 busy
= wx
.BusyInfo("Reloading demo module...")
696 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
697 self
.ActiveModuleChanged()
700 def OnRestore(self
, event
): # Handles the "Delete Modified" button
701 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
702 self
.demoModules
.Delete(modModified
)
703 os
.unlink(modifiedFilename
) # Delete the modified copy
704 busy
= wx
.BusyInfo("Reloading demo module...")
705 self
.ActiveModuleChanged()
708 #---------------------------------------------------------------------------
711 """Convert paths to the platform-specific separator"""
712 str = apply(os
.path
.join
, tuple(path
.split('/')))
713 # HACK: on Linux, a leading / gets lost...
714 if path
.startswith('/'):
719 def GetModifiedDirectory():
721 Returns the directory where modified versions of the demo files
724 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
727 def GetModifiedFilename(name
):
729 Returns the filename of the modified version of the specified demo
731 if not name
.endswith(".py"):
733 return GetModifiedDirectory() + name
736 def GetOriginalFilename(name
):
738 Returns the filename of the original version of the specified demo
740 if not name
.endswith(".py"):
745 def DoesModifiedExist(name
):
746 """Returns whether the specified demo has a modified copy"""
747 if os
.path
.exists(GetModifiedFilename(name
)):
753 #---------------------------------------------------------------------------
755 class ModuleDictWrapper
:
756 """Emulates a module with a dynamically compiled __dict__"""
757 def __init__(self
, dict):
760 def __getattr__(self
, name
):
761 if name
in self
.dict:
762 return self
.dict[name
]
768 Dynamically manages the original/modified versions of a demo
771 def __init__(self
, name
):
775 # (dict , source , filename , description , error information )
776 # ( 0 , 1 , 2 , 3 , 4 )
777 self
.modules
= [[None, "" , "" , "<original>" , None],
778 [None, "" , "" , "<modified>" , None]]
780 # load original module
781 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
782 self
.SetActive(modOriginal
)
784 # load modified module (if one exists)
785 if DoesModifiedExist(name
):
786 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
789 def LoadFromFile(self
, modID
, filename
):
790 self
.modules
[modID
][2] = filename
791 file = open(filename
, "rt")
792 self
.LoadFromSource(modID
, file.read())
796 def LoadFromSource(self
, modID
, source
):
797 self
.modules
[modID
][1] = source
801 def LoadDict(self
, modID
):
802 if self
.name
!= __name__
:
803 source
= self
.modules
[modID
][1]
804 description
= self
.modules
[modID
][3]
807 self
.modules
[modID
][0] = {}
808 code
= compile(source
, description
, "exec")
809 exec code
in self
.modules
[modID
][0]
811 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
812 self
.modules
[modID
][0] = None
814 self
.modules
[modID
][4] = None
817 def SetActive(self
, modID
):
818 if modID
!= modOriginal
and modID
!= modModified
:
821 self
.modActive
= modID
825 dict = self
.modules
[self
.modActive
][0]
829 return ModuleDictWrapper(dict)
832 def GetActiveID(self
):
833 return self
.modActive
836 def GetSource(self
, modID
= None):
838 modID
= self
.modActive
839 return self
.modules
[modID
][1]
842 def GetFilename(self
, modID
= None):
844 modID
= self
.modActive
845 return self
.modules
[self
.modActive
][2]
848 def GetErrorInfo(self
, modID
= None):
850 modID
= self
.modActive
851 return self
.modules
[self
.modActive
][4]
854 def Exists(self
, modID
):
855 return self
.modules
[modID
][1] != ""
858 def UpdateFile(self
, modID
= None):
859 """Updates the file from which a module was loaded
860 with (possibly updated) source"""
862 modID
= self
.modActive
864 source
= self
.modules
[modID
][1]
865 filename
= self
.modules
[modID
][2]
868 file = open(filename
, "wt")
874 def Delete(self
, modID
):
875 if self
.modActive
== modID
:
878 self
.modules
[modID
][0] = None
879 self
.modules
[modID
][1] = ""
880 self
.modules
[modID
][2] = ""
883 #---------------------------------------------------------------------------
886 """Wraps and stores information about the current exception"""
887 def __init__(self
, exc_info
):
890 excType
, excValue
= exc_info
[:2]
891 # traceback list entries: (filename, line number, function name, text)
892 self
.traceback
= traceback
.extract_tb(exc_info
[2])
894 # --Based on traceback.py::format_exception_only()--
895 if type(excType
) == types
.ClassType
:
896 self
.exception_type
= excType
.__name
__
898 self
.exception_type
= excType
900 # If it's a syntax error, extra information needs
901 # to be added to the traceback
902 if excType
is SyntaxError:
904 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
909 filename
= "<string>"
911 self
.traceback
.append( (filename
, lineno
, "", line
) )
914 self
.exception_details
= str(excValue
)
916 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
923 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
926 #---------------------------------------------------------------------------
928 class DemoErrorPanel(wx
.Panel
):
929 """Panel put into the demo tab when the demo fails to run due to errors"""
931 def __init__(self
, parent
, codePanel
, demoError
, log
):
932 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
933 self
.codePanel
= codePanel
937 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
940 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
941 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
943 # Exception Information
944 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
945 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
946 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
947 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
948 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
949 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
950 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
951 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
952 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
953 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
955 # Set up the traceback list
956 # This one automatically resizes last column to take up remaining space
957 from ListCtrl
import TestListCtrl
958 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
959 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
960 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
961 self
.list.InsertColumn(0, "Filename")
962 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
963 self
.list.InsertColumn(2, "Function")
964 self
.list.InsertColumn(3, "Code")
965 self
.InsertTraceback(self
.list, demoError
.traceback
)
966 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
967 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
968 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
969 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
970 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
971 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
972 + "Double-click on them to go to the offending line")
973 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
976 self
.SetSizer(self
.box
)
979 def InsertTraceback(self
, list, traceback
):
980 #Add the traceback data
981 for x
in range(len(traceback
)):
983 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
984 list.SetStringItem(x
, 1, str(data
[1])) # Line
985 list.SetStringItem(x
, 2, str(data
[2])) # Function
986 list.SetStringItem(x
, 3, str(data
[3])) # Code
988 # Check whether this entry is from the demo module
989 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
990 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
991 # Give it a blue colour
992 item
= self
.list.GetItem(x
)
993 item
.SetTextColour(wx
.BLUE
)
994 self
.list.SetItem(item
)
996 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
999 def OnItemSelected(self
, event
):
1000 # This occurs before OnDoubleClick and can be used to set the
1001 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1002 self
.currentItem
= event
.m_itemIndex
1006 def OnDoubleClick(self
, event
):
1007 # If double-clicking on a demo's entry, jump to the line number
1008 line
= self
.list.GetItemData(self
.currentItem
)
1010 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1011 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1015 #---------------------------------------------------------------------------
1017 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1018 TBMENU_RESTORE
= wx
.NewId()
1019 TBMENU_CLOSE
= wx
.NewId()
1020 TBMENU_CHANGE
= wx
.NewId()
1021 TBMENU_REMOVE
= wx
.NewId()
1023 def __init__(self
, frame
):
1024 wx
.TaskBarIcon
.__init
__(self
)
1028 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1029 self
.SetIcon(icon
, "wxPython Demo")
1033 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1034 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1035 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1036 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1037 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1040 def CreatePopupMenu(self
):
1042 This method is called by the base class when it needs to popup
1043 the menu for the default EVT_RIGHT_DOWN event. Just create
1044 the menu how you want it and return it from this function,
1045 the base class takes care of the rest.
1048 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1049 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1050 menu
.AppendSeparator()
1051 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1052 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1056 def MakeIcon(self
, img
):
1058 The various platforms have different requirements for the
1061 if "wxMSW" in wx
.PlatformInfo
:
1062 img
= img
.Scale(16, 16)
1063 elif "wxGTK" in wx
.PlatformInfo
:
1064 img
= img
.Scale(22, 22)
1065 # wxMac can be any size upto 128x128, so leave the source img alone....
1066 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1070 def OnTaskBarActivate(self
, evt
):
1071 if self
.frame
.IsIconized():
1072 self
.frame
.Iconize(False)
1073 if not self
.frame
.IsShown():
1074 self
.frame
.Show(True)
1078 def OnTaskBarClose(self
, evt
):
1082 def OnTaskBarChange(self
, evt
):
1083 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1084 name
= names
[self
.imgidx
]
1086 getFunc
= getattr(images
, "get%sImage" % name
)
1088 if self
.imgidx
>= len(names
):
1091 icon
= self
.MakeIcon(getFunc())
1092 self
.SetIcon(icon
, "This is a new icon: " + name
)
1095 def OnTaskBarRemove(self
, evt
):
1099 #---------------------------------------------------------------------------
1100 class wxPythonDemo(wx
.Frame
):
1101 overviewText
= "wxPython Overview"
1103 def __init__(self
, parent
, title
):
1104 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1105 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1107 self
.SetMinSize((640,480))
1110 self
.cwd
= os
.getcwd()
1111 self
.curOverview
= ""
1112 self
.demoPage
= None
1113 self
.codePage
= None
1115 self
.firstTime
= True
1118 icon
= images
.getWXPdemoIcon()
1121 self
.tbicon
= DemoTaskBarIcon(self
)
1123 wx
.CallAfter(self
.ShowTip
)
1125 self
.otherWin
= None
1126 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1127 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1128 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1129 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1131 self
.Centre(wx
.BOTH
)
1132 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1134 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1135 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1137 def EmptyHandler(evt
): pass
1138 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1139 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1141 # Prevent TreeCtrl from displaying all items after destruction when True
1145 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1148 self
.mainmenu
= wx
.MenuBar()
1150 item
= menu
.Append(-1, '&Redirect Output',
1151 'Redirect print statements to a window',
1153 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1155 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1156 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1157 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1158 self
.mainmenu
.Append(menu
, '&File')
1162 for item
in _treeList
:
1164 for childItem
in item
[1]:
1165 mi
= submenu
.Append(-1, childItem
)
1166 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1167 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1168 self
.mainmenu
.Append(menu
, '&Demo')
1170 # Make a Demo Code menu
1171 #TODO: Add new menu items
1172 # Like the option-enabled entries to select the
1174 #TODO: should we bother?
1177 #saveID = wx.NewId()
1178 #restoreID = wx.NewId()
1180 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1181 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1182 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1183 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1184 #self.mainmenu.Append(menu, 'Demo &Code')
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\tCtrl-H', '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()
1214 # This is another way to set Accelerators, in addition to
1215 # using the '\t<key>' syntax in the menu items.
1216 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1217 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1218 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1219 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1221 self
.SetAcceleratorTable(aTable
)
1227 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1228 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1231 root
= self
.tree
.AddRoot("wxPython Overview")
1233 for item
in _treeList
:
1234 child
= self
.tree
.AppendItem(root
, item
[0])
1235 if not firstChild
: firstChild
= child
1236 for childItem
in item
[1]:
1237 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1238 self
.treeMap
[childItem
] = theDemo
1240 self
.tree
.Expand(root
)
1241 self
.tree
.Expand(firstChild
)
1242 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1243 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1244 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1245 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1247 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1248 # we put it in a panel first because there seems to be a
1249 # refresh bug of some sort (wxGTK) when it is directly in
1252 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1253 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1255 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1256 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1257 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1258 self
.nb
.AddPage(panel
, self
.overviewText
)
1260 def OnOvrSize(evt
, ovr
=self
.ovr
):
1261 ovr
.SetSize(evt
.GetSize())
1262 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1263 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1265 if "gtk2" in wx
.PlatformInfo
:
1266 self
.ovr
.SetStandardFonts()
1267 self
.SetOverview(self
.overviewText
, mainOverview
)
1270 # Set up a log window
1271 self
.log
= wx
.TextCtrl(splitter2
, -1,
1272 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1274 # Set the wxWindows log target to be this textctrl
1275 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1277 # But instead of the above we want to show how to use our own wx.Log class
1278 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1280 # for serious debugging
1281 #wx.Log_SetActiveTarget(wx.LogStderr())
1282 #wx.Log_SetTraceMask(wx.TraceMessages)
1285 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1286 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1288 # add the windows to the splitter and split it.
1289 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1290 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1292 splitter
.SetMinimumPaneSize(120)
1293 splitter2
.SetMinimumPaneSize(60)
1295 # Make the splitter on the right expand the top window when resized
1296 def SplitterOnSize(evt
):
1297 splitter
= evt
.GetEventObject()
1298 sz
= splitter
.GetSize()
1299 splitter
.SetSashPosition(sz
.height
- 160, False)
1302 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1304 # select initial items
1305 self
.nb
.SetSelection(0)
1306 self
.tree
.SelectItem(root
)
1308 # Load 'Main' module
1309 self
.LoadDemo(self
.overviewText
)
1312 # select some other initial module?
1313 if len(sys
.argv
) > 1:
1315 if arg
.endswith('.py'):
1317 selectedDemo
= self
.treeMap
.get(arg
, None)
1319 self
.tree
.SelectItem(selectedDemo
)
1320 self
.tree
.EnsureVisible(selectedDemo
)
1323 #---------------------------------------------
1324 def WriteText(self
, text
):
1325 if text
[-1:] == '\n':
1329 def write(self
, txt
):
1332 #---------------------------------------------
1333 def OnItemExpanded(self
, event
):
1334 item
= event
.GetItem()
1335 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1338 #---------------------------------------------
1339 def OnItemCollapsed(self
, event
):
1340 item
= event
.GetItem()
1341 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1344 #---------------------------------------------
1345 def OnTreeLeftDown(self
, event
):
1346 # reset the overview text if the tree item is clicked on again
1347 pt
= event
.GetPosition();
1348 item
, flags
= self
.tree
.HitTest(pt
)
1349 if item
== self
.tree
.GetSelection():
1350 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1353 #---------------------------------------------
1354 def OnSelChanged(self
, event
):
1355 if self
.dying
or not self
.loaded
:
1358 item
= event
.GetItem()
1359 itemText
= self
.tree
.GetItemText(item
)
1360 self
.LoadDemo(itemText
)
1362 #---------------------------------------------
1363 def LoadDemo(self
, demoName
):
1365 wx
.BeginBusyCursor()
1368 self
.ShutdownDemoModule()
1370 if demoName
== self
.overviewText
:
1371 # User selected the "wxPython Overview" node
1373 # Changing the main window at runtime not yet supported...
1374 self
.demoModules
= DemoModules(__name__
)
1375 self
.SetOverview(self
.overviewText
, mainOverview
)
1376 self
.LoadDemoSource()
1377 self
.UpdateNotebook(0)
1379 if os
.path
.exists(GetOriginalFilename(demoName
)):
1380 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1381 self
.demoModules
= DemoModules(demoName
)
1382 self
.LoadDemoSource()
1385 self
.SetOverview("wxPython", mainOverview
)
1386 self
.codePage
= None
1387 self
.UpdateNotebook(0)
1391 #---------------------------------------------
1392 def LoadDemoSource(self
):
1393 self
.codePage
= None
1394 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1395 self
.codePage
.LoadDemo(self
.demoModules
)
1397 #---------------------------------------------
1398 def RunModule(self
):
1399 """Runs the active module"""
1401 module
= self
.demoModules
.GetActive()
1402 self
.ShutdownDemoModule()
1405 # o The RunTest() for all samples must now return a window that can
1406 # be palced in a tab in the main notebook.
1407 # o If an error occurs (or has occured before) an error tab is created.
1409 if module
is not None:
1410 wx
.LogMessage("Running demo module...")
1411 if hasattr(module
, "overview"):
1412 overviewText
= module
.overview
1415 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1417 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1418 DemoError(sys
.exc_info()), self
)
1420 assert self
.demoPage
is not None, "runTest must return a window!"
1423 # There was a previous error in compiling or exec-ing
1424 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1425 self
.demoModules
.GetErrorInfo(), self
)
1427 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1430 # cahnge to the demo page the first time a module is run
1431 self
.UpdateNotebook(2)
1432 self
.firstTime
= False
1434 # otherwise just stay on the same tab in case the user has changed to another one
1435 self
.UpdateNotebook()
1437 #---------------------------------------------
1438 def ShutdownDemoModule(self
):
1440 # inform the window that it's time to quit if it cares
1441 if hasattr(self
.demoPage
, "ShutdownDemo"):
1442 self
.demoPage
.ShutdownDemo()
1443 wx
.YieldIfNeeded() # in case the page has pending events
1444 self
.demoPage
= None
1446 #---------------------------------------------
1447 def UpdateNotebook(self
, select
= -1):
1451 def UpdatePage(page
, pageText
):
1454 for i
in range(nb
.GetPageCount()):
1455 if nb
.GetPageText(i
) == pageText
:
1463 nb
.AddPage(page
, pageText
)
1464 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1466 if nb
.GetPage(pagePos
) != page
:
1467 # Reload an existing page
1469 nb
.DeletePage(pagePos
)
1470 nb
.InsertPage(pagePos
, page
, pageText
)
1472 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1474 # Excellent! No redraw/flicker
1475 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1478 nb
.DeletePage(pagePos
)
1479 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1481 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1484 select
= nb
.GetSelection()
1486 UpdatePage(self
.codePage
, "Demo Code")
1487 UpdatePage(self
.demoPage
, "Demo")
1489 if select
>= 0 and select
< nb
.GetPageCount():
1490 nb
.SetSelection(select
)
1492 #---------------------------------------------
1493 def SetOverview(self
, name
, text
):
1494 self
.curOverview
= text
1496 if lead
!= '<html>' and lead
!= '<HTML>':
1497 text
= '<br>'.join(text
.split('\n'))
1499 text
= text
.decode('iso8859_1')
1500 self
.ovr
.SetPage(text
)
1501 self
.nb
.SetPageText(0, name
)
1503 #---------------------------------------------
1505 def OnFileExit(self
, *event
):
1508 def OnToggleRedirect(self
, event
):
1512 print "Print statements and other standard output will now be directed to this window."
1515 print "Print statements and other standard output will now be sent to the usual location."
1517 def OnHelpAbout(self
, event
):
1518 from About
import MyAboutBox
1519 about
= MyAboutBox(self
)
1523 def OnHelpFind(self
, event
):
1524 if self
.finddlg
!= None:
1527 self
.nb
.SetSelection(1)
1528 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1532 self
.finddlg
.Show(True)
1535 def OnUpdateFindItems(self
, evt
):
1536 evt
.Enable(self
.finddlg
== None)
1539 def OnFind(self
, event
):
1540 editor
= self
.codePage
.editor
1541 self
.nb
.SetSelection(1)
1542 end
= editor
.GetLastPosition()
1543 textstring
= editor
.GetRange(0, end
).lower()
1544 start
= editor
.GetSelection()[1]
1545 findstring
= self
.finddata
.GetFindString().lower()
1546 loc
= textstring
.find(findstring
, start
)
1547 if loc
== -1 and start
!= 0:
1548 # string not found, start at beginning
1550 loc
= textstring
.find(findstring
, start
)
1552 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1553 'Find String Not Found in Demo File',
1554 wx
.OK | wx
.ICON_INFORMATION
)
1559 self
.finddlg
.SetFocus()
1562 self
.finddlg
.Destroy()
1564 editor
.ShowPosition(loc
)
1565 editor
.SetSelection(loc
, loc
+ len(findstring
))
1569 def OnFindNext(self
, event
):
1570 if self
.finddata
.GetFindString():
1573 self
.OnHelpFind(event
)
1575 def OnFindClose(self
, event
):
1576 event
.GetDialog().Destroy()
1580 def OnOpenShellWindow(self
, evt
):
1582 # if it already exists then just make sure it's visible
1588 # Make a PyShell window
1590 namespace
= { 'wx' : wx
,
1591 'app' : wx
.GetApp(),
1594 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1595 self
.shell
.SetSize((640,480))
1598 # Hook the close event of the main frame window so that we
1599 # close the shell at the same time if it still exists
1600 def CloseShell(evt
):
1604 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1607 #---------------------------------------------
1608 def OnCloseWindow(self
, event
):
1610 self
.demoPage
= None
1611 self
.codePage
= None
1612 self
.mainmenu
= None
1613 self
.tbicon
.Destroy()
1617 #---------------------------------------------
1618 def OnIdle(self
, event
):
1620 self
.otherWin
.Raise()
1621 self
.demoPage
= self
.otherWin
1622 self
.otherWin
= None
1625 #---------------------------------------------
1628 showTipText
= open(opj("data/showTips")).read()
1629 showTip
, index
= eval(showTipText
)
1631 showTip
, index
= (1, 0)
1633 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1635 showTip
= wx
.ShowTip(self
, tp
)
1636 index
= tp
.GetCurrentTip()
1637 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1640 #---------------------------------------------
1641 def OnDemoMenu(self
, event
):
1643 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1647 self
.tree
.SelectItem(selectedDemo
)
1648 self
.tree
.EnsureVisible(selectedDemo
)
1652 #---------------------------------------------
1653 def OnIconfiy(self
, evt
):
1654 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1657 #---------------------------------------------
1658 def OnMaximize(self
, evt
):
1659 wx
.LogMessage("OnMaximize")
1662 #---------------------------------------------
1663 def OnActivate(self
, evt
):
1664 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1667 #---------------------------------------------
1668 def OnAppActivate(self
, evt
):
1669 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1672 #---------------------------------------------------------------------------
1673 #---------------------------------------------------------------------------
1675 class MySplashScreen(wx
.SplashScreen
):
1677 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1678 wx
.SplashScreen
.__init
__(self
, bmp
,
1679 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1681 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1682 wx
.FutureCall(2000, self
.ShowMain
)
1684 def OnClose(self
, evt
):
1686 evt
.Skip() # Make sure the default handler runs too...
1689 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1694 class MyApp(wx
.App
):
1697 Create and show the splash screen. It will then create and show
1698 the main frame when it is time to do so.
1701 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1704 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1706 # Normally when using a SplashScreen you would create it, show
1707 # it and then continue on with the applicaiton's
1708 # initialization, finally creating and showing the main
1709 # application window(s). In this case we have nothing else to
1710 # do so we'll delay showing the main frame until later (see
1711 # ShowMain above) so the users can see the SplashScreen effect.
1712 splash
= MySplashScreen()
1719 #---------------------------------------------------------------------------
1723 demoPath
= os
.path
.dirname(__file__
)
1730 #---------------------------------------------------------------------------
1733 mainOverview
= """<html><body>
1736 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1737 language. It allows Python programmers to create programs with a
1738 robust, highly functional graphical user interface, simply and easily.
1739 It is implemented as a Python extension module (native code) that
1740 wraps the popular wxWindows cross platform GUI library, which is
1743 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1744 means that it is free for anyone to use and the source code is
1745 available for anyone to look at and modify. Or anyone can contribute
1746 fixes or enhancements to the project.
1748 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1749 same program will run on multiple platforms without modification.
1750 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1751 or unix-like systems, and Macintosh OS X. Since the language is
1752 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1755 <p> <b>This demo</b> is not only a collection of test cases for
1756 wxPython, but is also designed to help you learn about and how to use
1757 wxPython. Each sample is listed in the tree control on the left.
1758 When a sample is selected in the tree then a module is loaded and run
1759 (usually in a tab of this notebook,) and the source code of the module
1760 is loaded in another tab for you to browse and learn from.
1765 #----------------------------------------------------------------------------
1766 #----------------------------------------------------------------------------
1768 if __name__
== '__main__':
1772 #----------------------------------------------------------------------------