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', [
57 # managed windows == things with a (optional) caption you can close
58 ('Frames and Dialogs', [
82 # dialogs from libraries
85 'ScrolledMessageDialog',
89 ('Core Windows/Controls', [
126 ('"Book" Controls', [
134 ('Custom Controls', [
147 # controls coming from other libraries
148 ('More Windows/Controls', [
149 'ActiveX_FlashWindow',
150 'ActiveX_IEHtmlWindow',
152 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
155 'CheckListCtrlMixin',
170 'MaskedEditControls',
173 'MultiSplitterWindow',
189 # How to lay out the controls in a frame/dialog
199 'XmlResourceHandler',
200 'XmlResourceSubclass',
204 ('Process and Events', [
211 ##'infoframe', # needs better explanation and some fixing
215 ('Clipboard and DnD', [
237 ##'DialogUnits', # needs more explanations
254 ('Check out the samples dir too', [
261 #---------------------------------------------------------------------------
262 # Show how to derive a custom wxLog class
264 class MyLog(wx
.PyLog
):
265 def __init__(self
, textCtrl
, logTime
=0):
266 wx
.PyLog
.__init
__(self
)
268 self
.logTime
= logTime
270 def DoLogString(self
, message
, timeStamp
):
271 #print message, timeStamp
273 # message = time.strftime("%X", time.localtime(timeStamp)) + \
276 self
.tc
.AppendText(message
+ '\n')
279 class MyTP(wx
.PyTipProvider
):
281 return "This is my tip"
283 #---------------------------------------------------------------------------
284 # A class to be used to simply display a message in the demo pane
285 # rather than running the sample itself.
287 class MessagePanel(wx
.Panel
):
288 def __init__(self
, parent
, message
, caption
='', flags
=0):
289 wx
.Panel
.__init
__(self
, parent
)
294 if flags
& wx
.ICON_EXCLAMATION
:
295 artid
= wx
.ART_WARNING
296 elif flags
& wx
.ICON_ERROR
:
298 elif flags
& wx
.ICON_QUESTION
:
299 artid
= wx
.ART_QUESTION
300 elif flags
& wx
.ICON_INFORMATION
:
301 artid
= wx
.ART_INFORMATION
303 if artid
is not None:
304 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
305 icon
= wx
.StaticBitmap(self
, -1, bmp
)
307 icon
= (32,32) # make a spacer instead
310 caption
= wx
.StaticText(self
, -1, caption
)
311 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
313 message
= wx
.StaticText(self
, -1, message
)
315 # add to sizers for layout
316 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
322 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
329 box
= wx
.BoxSizer(wx
.VERTICAL
)
331 box
.Add(hbox
, 0, wx
.EXPAND
)
338 #---------------------------------------------------------------------------
339 # A class to be used to display source code in the demo. Try using the
340 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
341 # if there is an error, such as the stc module not being present.
345 ##raise ImportError # for testing the alternate implementation
347 from StyledTextCtrl_2
import PythonSTC
349 class DemoCodeEditor(PythonSTC
):
350 def __init__(self
, parent
):
351 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
354 # Some methods to make it compatible with how the wxTextCtrl is used
355 def SetValue(self
, value
):
357 value
= value
.decode('iso8859_1')
359 self
.EmptyUndoBuffer()
362 def IsModified(self
):
363 return self
.GetModify()
368 def SetInsertionPoint(self
, pos
):
369 self
.SetCurrentPos(pos
)
372 def ShowPosition(self
, pos
):
373 line
= self
.LineFromPosition(pos
)
374 #self.EnsureVisible(line)
377 def GetLastPosition(self
):
378 return self
.GetLength()
380 def GetPositionFromLine(self
, line
):
381 return self
.PositionFromLine(line
)
383 def GetRange(self
, start
, end
):
384 return self
.GetTextRange(start
, end
)
386 def GetSelection(self
):
387 return self
.GetAnchor(), self
.GetCurrentPos()
389 def SetSelection(self
, start
, end
):
390 self
.SetSelectionStart(start
)
391 self
.SetSelectionEnd(end
)
393 def SelectLine(self
, line
):
394 start
= self
.PositionFromLine(line
)
395 end
= self
.GetLineEndPosition(line
)
396 self
.SetSelection(start
, end
)
398 def SetUpEditor(self
):
400 This method carries out the work of setting up the demo editor.
401 It's seperate so as not to clutter up the init code.
405 self
.SetLexer(stc
.STC_LEX_PYTHON
)
406 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
409 self
.SetProperty("fold", "1" )
411 # Highlight tab/space mixing (shouldn't be any)
412 self
.SetProperty("tab.timmy.whinge.level", "1")
414 # Set left and right margins
417 # Set up the numbers in the margin for margin #1
418 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
419 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
420 self
.SetMarginWidth(1, 40)
422 # Indentation and tab stuff
423 self
.SetIndent(4) # Proscribed indent size for wx
424 self
.SetIndentationGuides(True) # Show indent guides
425 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
426 self
.SetTabIndents(True) # Tab key indents
427 self
.SetTabWidth(4) # Proscribed tab size for wx
428 self
.SetUseTabs(False) # Use spaces rather than tabs, or
429 # TabTimmy will complain!
431 self
.SetViewWhiteSpace(False) # Don't view white space
433 # EOL: Since we are loading/saving ourselves, and the
434 # strings will always have \n's in them, set the STC to
435 # edit them that way.
436 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
437 self
.SetViewEOL(False)
439 # No right-edge mode indicator
440 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
442 # Setup a margin to hold fold markers
443 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
444 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
445 self
.SetMarginSensitive(2, True)
446 self
.SetMarginWidth(2, 12)
448 # and now set up the fold markers
449 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
450 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
451 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
452 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
453 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
454 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
455 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
457 # Global default style
458 if wx
.Platform
== '__WXMSW__':
459 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
460 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
462 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
463 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
465 # Clear styles and revert to default.
468 # Following style specs only indicate differences from default.
469 # The rest remains unchanged.
471 # Line numbers in margin
472 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
474 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
476 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
478 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
481 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
483 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
484 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
486 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
487 # Strings and characters
488 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
489 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
491 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
493 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
494 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
496 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
498 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
500 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
501 # Identifiers. I leave this as not bold because everything seems
502 # to be an identifier if it doesn't match the above criterae
503 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
506 self
.SetCaretForeground("BLUE")
507 # Selection background
508 self
.SetSelBackground(1, '#66CCFF')
510 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
511 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
513 def RegisterModifiedEvent(self
, eventHandler
):
514 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
518 class DemoCodeEditor(wx
.TextCtrl
):
519 def __init__(self
, parent
):
520 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
521 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
523 def RegisterModifiedEvent(self
, eventHandler
):
524 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
526 def SetReadOnly(self
, flag
):
527 self
.SetEditable(not flag
)
528 # NOTE: STC already has this method
531 return self
.GetValue()
533 def GetPositionFromLine(self
, line
):
534 return self
.XYToPosition(0,line
)
536 def GotoLine(self
, line
):
537 pos
= self
.GetPositionFromLine(line
)
538 self
.SetInsertionPoint(pos
)
539 self
.ShowPosition(pos
)
541 def SelectLine(self
, line
):
542 start
= self
.GetPositionFromLine(line
)
543 end
= start
+ self
.GetLineLength(line
)
544 self
.SetSelection(start
, end
)
547 #---------------------------------------------------------------------------
548 # Constants for module versions
552 modDefault
= modOriginal
554 #---------------------------------------------------------------------------
556 class DemoCodePanel(wx
.Panel
):
557 """Panel for the 'Demo Code' tab"""
558 def __init__(self
, parent
, mainFrame
):
559 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
560 if 'wxMSW' in wx
.PlatformInfo
:
562 self
.mainFrame
= mainFrame
563 self
.editor
= DemoCodeEditor(self
)
564 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
566 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
567 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
568 self
.btnSave
.Enable(False)
569 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
570 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
572 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
573 modModified
: wx
.RadioButton(self
, -1, "Modified") }
575 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
576 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
577 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
578 for modID
, radioButton
in self
.radioButtons
.items():
579 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
580 radioButton
.modID
= modID
# makes it easier for the event handler
581 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
583 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
584 self
.controlBox
.Add(self
.btnRestore
, 0)
586 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
587 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
588 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
589 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
592 self
.SetSizer(self
.box
)
595 # Loads a demo from a DemoModules object
596 def LoadDemo(self
, demoModules
):
597 self
.demoModules
= demoModules
598 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
599 demoModules
.SetActive(modModified
)
601 demoModules
.SetActive(modOriginal
)
602 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
603 self
.ActiveModuleChanged()
606 def ActiveModuleChanged(self
):
607 self
.LoadDemoSource(self
.demoModules
.GetSource())
608 self
.UpdateControlState()
612 def LoadDemoSource(self
, source
):
614 self
.editor
.SetValue(source
)
616 self
.btnSave
.Enable(False)
619 def JumpToLine(self
, line
, highlight
=False):
620 self
.editor
.GotoLine(line
)
621 self
.editor
.SetFocus()
623 self
.editor
.SelectLine(line
)
626 def UpdateControlState(self
):
627 active
= self
.demoModules
.GetActiveID()
628 # Update the radio/restore buttons
629 for moduleID
in self
.radioButtons
:
630 btn
= self
.radioButtons
[moduleID
]
631 if moduleID
== active
:
636 if self
.demoModules
.Exists(moduleID
):
638 if moduleID
== modModified
:
639 self
.btnRestore
.Enable(True)
642 if moduleID
== modModified
:
643 self
.btnRestore
.Enable(False)
646 def OnRadioButton(self
, event
):
647 radioSelected
= event
.GetEventObject()
648 modSelected
= radioSelected
.modID
649 if modSelected
!= self
.demoModules
.GetActiveID():
650 busy
= wx
.BusyInfo("Reloading demo module...")
651 self
.demoModules
.SetActive(modSelected
)
652 self
.ActiveModuleChanged()
655 def ReloadDemo(self
):
656 if self
.demoModules
.name
!= __name__
:
657 self
.mainFrame
.RunModule()
660 def OnCodeModified(self
, event
):
661 self
.btnSave
.Enable(self
.editor
.IsModified())
664 def OnSave(self
, event
):
665 if self
.demoModules
.Exists(modModified
):
666 if self
.demoModules
.GetActiveID() == modOriginal
:
667 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
668 "Do you want to continue?"
669 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
670 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
671 result
= dlg
.ShowModal()
672 if result
== wx
.ID_NO
:
676 self
.demoModules
.SetActive(modModified
)
677 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
679 # Create the demo directory if one doesn't already exist
680 if not os
.path
.exists(GetModifiedDirectory()):
682 os
.makedirs(GetModifiedDirectory())
683 if not os
.path
.exists(GetModifiedDirectory()):
684 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
687 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
690 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
693 f
= open(modifiedFilename
, "wt")
694 source
= self
.editor
.GetText()
700 busy
= wx
.BusyInfo("Reloading demo module...")
701 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
702 self
.ActiveModuleChanged()
705 def OnRestore(self
, event
): # Handles the "Delete Modified" button
706 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
707 self
.demoModules
.Delete(modModified
)
708 os
.unlink(modifiedFilename
) # Delete the modified copy
709 busy
= wx
.BusyInfo("Reloading demo module...")
710 self
.ActiveModuleChanged()
713 #---------------------------------------------------------------------------
716 """Convert paths to the platform-specific separator"""
717 str = apply(os
.path
.join
, tuple(path
.split('/')))
718 # HACK: on Linux, a leading / gets lost...
719 if path
.startswith('/'):
724 def GetModifiedDirectory():
726 Returns the directory where modified versions of the demo files
729 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
732 def GetModifiedFilename(name
):
734 Returns the filename of the modified version of the specified demo
736 if not name
.endswith(".py"):
738 return GetModifiedDirectory() + name
741 def GetOriginalFilename(name
):
743 Returns the filename of the original version of the specified demo
745 if not name
.endswith(".py"):
750 def DoesModifiedExist(name
):
751 """Returns whether the specified demo has a modified copy"""
752 if os
.path
.exists(GetModifiedFilename(name
)):
758 #---------------------------------------------------------------------------
760 class ModuleDictWrapper
:
761 """Emulates a module with a dynamically compiled __dict__"""
762 def __init__(self
, dict):
765 def __getattr__(self
, name
):
766 if name
in self
.dict:
767 return self
.dict[name
]
773 Dynamically manages the original/modified versions of a demo
776 def __init__(self
, name
):
780 # (dict , source , filename , description , error information )
781 # ( 0 , 1 , 2 , 3 , 4 )
782 self
.modules
= [[None, "" , "" , "<original>" , None],
783 [None, "" , "" , "<modified>" , None]]
785 # load original module
786 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
787 self
.SetActive(modOriginal
)
789 # load modified module (if one exists)
790 if DoesModifiedExist(name
):
791 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
794 def LoadFromFile(self
, modID
, filename
):
795 self
.modules
[modID
][2] = filename
796 file = open(filename
, "rt")
797 self
.LoadFromSource(modID
, file.read())
801 def LoadFromSource(self
, modID
, source
):
802 self
.modules
[modID
][1] = source
806 def LoadDict(self
, modID
):
807 if self
.name
!= __name__
:
808 source
= self
.modules
[modID
][1]
809 #description = self.modules[modID][3]
810 description
= self
.modules
[modID
][2]
813 self
.modules
[modID
][0] = {}
814 code
= compile(source
, description
, "exec")
815 exec code
in self
.modules
[modID
][0]
817 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
818 self
.modules
[modID
][0] = None
820 self
.modules
[modID
][4] = None
823 def SetActive(self
, modID
):
824 if modID
!= modOriginal
and modID
!= modModified
:
827 self
.modActive
= modID
831 dict = self
.modules
[self
.modActive
][0]
835 return ModuleDictWrapper(dict)
838 def GetActiveID(self
):
839 return self
.modActive
842 def GetSource(self
, modID
= None):
844 modID
= self
.modActive
845 return self
.modules
[modID
][1]
848 def GetFilename(self
, modID
= None):
850 modID
= self
.modActive
851 return self
.modules
[self
.modActive
][2]
854 def GetErrorInfo(self
, modID
= None):
856 modID
= self
.modActive
857 return self
.modules
[self
.modActive
][4]
860 def Exists(self
, modID
):
861 return self
.modules
[modID
][1] != ""
864 def UpdateFile(self
, modID
= None):
865 """Updates the file from which a module was loaded
866 with (possibly updated) source"""
868 modID
= self
.modActive
870 source
= self
.modules
[modID
][1]
871 filename
= self
.modules
[modID
][2]
874 file = open(filename
, "wt")
880 def Delete(self
, modID
):
881 if self
.modActive
== modID
:
884 self
.modules
[modID
][0] = None
885 self
.modules
[modID
][1] = ""
886 self
.modules
[modID
][2] = ""
889 #---------------------------------------------------------------------------
892 """Wraps and stores information about the current exception"""
893 def __init__(self
, exc_info
):
896 excType
, excValue
= exc_info
[:2]
897 # traceback list entries: (filename, line number, function name, text)
898 self
.traceback
= traceback
.extract_tb(exc_info
[2])
900 # --Based on traceback.py::format_exception_only()--
901 if type(excType
) == types
.ClassType
:
902 self
.exception_type
= excType
.__name
__
904 self
.exception_type
= excType
906 # If it's a syntax error, extra information needs
907 # to be added to the traceback
908 if excType
is SyntaxError:
910 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
915 filename
= "<string>"
917 self
.traceback
.append( (filename
, lineno
, "", line
) )
920 self
.exception_details
= str(excValue
)
922 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
929 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
932 #---------------------------------------------------------------------------
934 class DemoErrorPanel(wx
.Panel
):
935 """Panel put into the demo tab when the demo fails to run due to errors"""
937 def __init__(self
, parent
, codePanel
, demoError
, log
):
938 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
939 self
.codePanel
= codePanel
943 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
946 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
947 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
949 # Exception Information
950 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
951 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
952 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
953 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
954 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
955 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
956 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
957 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
958 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
959 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
961 # Set up the traceback list
962 # This one automatically resizes last column to take up remaining space
963 from ListCtrl
import TestListCtrl
964 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
965 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
966 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
967 self
.list.InsertColumn(0, "Filename")
968 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
969 self
.list.InsertColumn(2, "Function")
970 self
.list.InsertColumn(3, "Code")
971 self
.InsertTraceback(self
.list, demoError
.traceback
)
972 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
973 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
974 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
975 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
976 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
977 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
978 + "Double-click on them to go to the offending line")
979 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
982 self
.SetSizer(self
.box
)
985 def InsertTraceback(self
, list, traceback
):
986 #Add the traceback data
987 for x
in range(len(traceback
)):
989 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
990 list.SetStringItem(x
, 1, str(data
[1])) # Line
991 list.SetStringItem(x
, 2, str(data
[2])) # Function
992 list.SetStringItem(x
, 3, str(data
[3])) # Code
994 # Check whether this entry is from the demo module
995 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
996 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
997 # Give it a blue colour
998 item
= self
.list.GetItem(x
)
999 item
.SetTextColour(wx
.BLUE
)
1000 self
.list.SetItem(item
)
1002 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1005 def OnItemSelected(self
, event
):
1006 # This occurs before OnDoubleClick and can be used to set the
1007 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1008 self
.currentItem
= event
.m_itemIndex
1012 def OnDoubleClick(self
, event
):
1013 # If double-clicking on a demo's entry, jump to the line number
1014 line
= self
.list.GetItemData(self
.currentItem
)
1016 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1017 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1021 #---------------------------------------------------------------------------
1023 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1024 TBMENU_RESTORE
= wx
.NewId()
1025 TBMENU_CLOSE
= wx
.NewId()
1026 TBMENU_CHANGE
= wx
.NewId()
1027 TBMENU_REMOVE
= wx
.NewId()
1029 def __init__(self
, frame
):
1030 wx
.TaskBarIcon
.__init
__(self
)
1034 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1035 self
.SetIcon(icon
, "wxPython Demo")
1039 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1040 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1041 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1042 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1043 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1046 def CreatePopupMenu(self
):
1048 This method is called by the base class when it needs to popup
1049 the menu for the default EVT_RIGHT_DOWN event. Just create
1050 the menu how you want it and return it from this function,
1051 the base class takes care of the rest.
1054 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1055 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1056 menu
.AppendSeparator()
1057 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1058 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1062 def MakeIcon(self
, img
):
1064 The various platforms have different requirements for the
1067 if "wxMSW" in wx
.PlatformInfo
:
1068 img
= img
.Scale(16, 16)
1069 elif "wxGTK" in wx
.PlatformInfo
:
1070 img
= img
.Scale(22, 22)
1071 # wxMac can be any size upto 128x128, so leave the source img alone....
1072 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1076 def OnTaskBarActivate(self
, evt
):
1077 if self
.frame
.IsIconized():
1078 self
.frame
.Iconize(False)
1079 if not self
.frame
.IsShown():
1080 self
.frame
.Show(True)
1084 def OnTaskBarClose(self
, evt
):
1088 def OnTaskBarChange(self
, evt
):
1089 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1090 name
= names
[self
.imgidx
]
1092 getFunc
= getattr(images
, "get%sImage" % name
)
1094 if self
.imgidx
>= len(names
):
1097 icon
= self
.MakeIcon(getFunc())
1098 self
.SetIcon(icon
, "This is a new icon: " + name
)
1101 def OnTaskBarRemove(self
, evt
):
1105 #---------------------------------------------------------------------------
1106 class wxPythonDemo(wx
.Frame
):
1107 overviewText
= "wxPython Overview"
1109 def __init__(self
, parent
, title
):
1110 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1111 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1113 self
.SetMinSize((640,480))
1116 self
.cwd
= os
.getcwd()
1117 self
.curOverview
= ""
1118 self
.demoPage
= None
1119 self
.codePage
= None
1121 self
.firstTime
= True
1124 icon
= images
.getWXPdemoIcon()
1127 self
.tbicon
= DemoTaskBarIcon(self
)
1129 wx
.CallAfter(self
.ShowTip
)
1131 self
.otherWin
= None
1132 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1133 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1134 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1135 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1137 self
.Centre(wx
.BOTH
)
1138 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1140 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1141 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1143 def EmptyHandler(evt
): pass
1144 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1145 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1147 # Prevent TreeCtrl from displaying all items after destruction when True
1151 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1154 self
.mainmenu
= wx
.MenuBar()
1156 item
= menu
.Append(-1, '&Redirect Output',
1157 'Redirect print statements to a window',
1159 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1161 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1162 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1163 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1164 self
.mainmenu
.Append(menu
, '&File')
1168 for item
in _treeList
:
1170 for childItem
in item
[1]:
1171 mi
= submenu
.Append(-1, childItem
)
1172 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1173 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1174 self
.mainmenu
.Append(menu
, '&Demo')
1176 # Make a Demo Code menu
1177 #TODO: Add new menu items
1178 # Like the option-enabled entries to select the
1180 #TODO: should we bother?
1183 #saveID = wx.NewId()
1184 #restoreID = wx.NewId()
1186 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1187 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1188 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1189 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1190 #self.mainmenu.Append(menu, 'Demo &Code')
1195 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1196 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1197 menu
.AppendSeparator()
1199 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1200 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1201 menu
.AppendSeparator()
1202 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1203 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1205 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1206 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1207 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1208 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1209 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1210 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1211 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1212 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1213 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1214 self
.mainmenu
.Append(menu
, '&Help')
1215 self
.SetMenuBar(self
.mainmenu
)
1217 self
.finddata
= wx
.FindReplaceData()
1218 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1221 # This is another way to set Accelerators, in addition to
1222 # using the '\t<key>' syntax in the menu items.
1223 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1224 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1225 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1226 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1228 self
.SetAcceleratorTable(aTable
)
1234 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1235 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1238 root
= self
.tree
.AddRoot("wxPython Overview")
1240 for item
in _treeList
:
1241 child
= self
.tree
.AppendItem(root
, item
[0])
1242 if not firstChild
: firstChild
= child
1243 for childItem
in item
[1]:
1244 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1245 self
.treeMap
[childItem
] = theDemo
1247 self
.tree
.Expand(root
)
1248 self
.tree
.Expand(firstChild
)
1249 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1250 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1251 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1252 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1254 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1255 # we put it in a panel first because there seems to be a
1256 # refresh bug of some sort (wxGTK) when it is directly in
1259 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1260 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1262 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1263 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1264 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1265 self
.nb
.AddPage(panel
, self
.overviewText
)
1267 def OnOvrSize(evt
, ovr
=self
.ovr
):
1268 ovr
.SetSize(evt
.GetSize())
1269 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1270 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1272 if "gtk2" in wx
.PlatformInfo
:
1273 self
.ovr
.SetStandardFonts()
1274 self
.SetOverview(self
.overviewText
, mainOverview
)
1277 # Set up a log window
1278 self
.log
= wx
.TextCtrl(splitter2
, -1,
1279 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1281 # Set the wxWindows log target to be this textctrl
1282 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1284 # But instead of the above we want to show how to use our own wx.Log class
1285 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1287 # for serious debugging
1288 #wx.Log_SetActiveTarget(wx.LogStderr())
1289 #wx.Log_SetTraceMask(wx.TraceMessages)
1292 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1293 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1295 # add the windows to the splitter and split it.
1296 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1297 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1299 splitter
.SetMinimumPaneSize(120)
1300 splitter2
.SetMinimumPaneSize(60)
1302 # Make the splitter on the right expand the top window when resized
1303 def SplitterOnSize(evt
):
1304 splitter
= evt
.GetEventObject()
1305 sz
= splitter
.GetSize()
1306 splitter
.SetSashPosition(sz
.height
- 160, False)
1309 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1311 # select initial items
1312 self
.nb
.SetSelection(0)
1313 self
.tree
.SelectItem(root
)
1315 # Load 'Main' module
1316 self
.LoadDemo(self
.overviewText
)
1319 # select some other initial module?
1320 if len(sys
.argv
) > 1:
1322 if arg
.endswith('.py'):
1324 selectedDemo
= self
.treeMap
.get(arg
, None)
1326 self
.tree
.SelectItem(selectedDemo
)
1327 self
.tree
.EnsureVisible(selectedDemo
)
1330 #---------------------------------------------
1331 def WriteText(self
, text
):
1332 if text
[-1:] == '\n':
1336 def write(self
, txt
):
1339 #---------------------------------------------
1340 def OnItemExpanded(self
, event
):
1341 item
= event
.GetItem()
1342 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1345 #---------------------------------------------
1346 def OnItemCollapsed(self
, event
):
1347 item
= event
.GetItem()
1348 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1351 #---------------------------------------------
1352 def OnTreeLeftDown(self
, event
):
1353 # reset the overview text if the tree item is clicked on again
1354 pt
= event
.GetPosition();
1355 item
, flags
= self
.tree
.HitTest(pt
)
1356 if item
== self
.tree
.GetSelection():
1357 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1360 #---------------------------------------------
1361 def OnSelChanged(self
, event
):
1362 if self
.dying
or not self
.loaded
:
1365 item
= event
.GetItem()
1366 itemText
= self
.tree
.GetItemText(item
)
1367 self
.LoadDemo(itemText
)
1369 #---------------------------------------------
1370 def LoadDemo(self
, demoName
):
1372 wx
.BeginBusyCursor()
1375 self
.ShutdownDemoModule()
1377 if demoName
== self
.overviewText
:
1378 # User selected the "wxPython Overview" node
1380 # Changing the main window at runtime not yet supported...
1381 self
.demoModules
= DemoModules(__name__
)
1382 self
.SetOverview(self
.overviewText
, mainOverview
)
1383 self
.LoadDemoSource()
1384 self
.UpdateNotebook(0)
1386 if os
.path
.exists(GetOriginalFilename(demoName
)):
1387 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1388 self
.demoModules
= DemoModules(demoName
)
1389 self
.LoadDemoSource()
1392 self
.SetOverview("wxPython", mainOverview
)
1393 self
.codePage
= None
1394 self
.UpdateNotebook(0)
1398 #---------------------------------------------
1399 def LoadDemoSource(self
):
1400 self
.codePage
= None
1401 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1402 self
.codePage
.LoadDemo(self
.demoModules
)
1404 #---------------------------------------------
1405 def RunModule(self
):
1406 """Runs the active module"""
1408 module
= self
.demoModules
.GetActive()
1409 self
.ShutdownDemoModule()
1412 # o The RunTest() for all samples must now return a window that can
1413 # be palced in a tab in the main notebook.
1414 # o If an error occurs (or has occurred before) an error tab is created.
1416 if module
is not None:
1417 wx
.LogMessage("Running demo module...")
1418 if hasattr(module
, "overview"):
1419 overviewText
= module
.overview
1422 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1424 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1425 DemoError(sys
.exc_info()), self
)
1427 assert self
.demoPage
is not None, "runTest must return a window!"
1430 # There was a previous error in compiling or exec-ing
1431 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1432 self
.demoModules
.GetErrorInfo(), self
)
1434 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1437 # cahnge to the demo page the first time a module is run
1438 self
.UpdateNotebook(2)
1439 self
.firstTime
= False
1441 # otherwise just stay on the same tab in case the user has changed to another one
1442 self
.UpdateNotebook()
1444 #---------------------------------------------
1445 def ShutdownDemoModule(self
):
1447 # inform the window that it's time to quit if it cares
1448 if hasattr(self
.demoPage
, "ShutdownDemo"):
1449 self
.demoPage
.ShutdownDemo()
1450 wx
.YieldIfNeeded() # in case the page has pending events
1451 self
.demoPage
= None
1453 #---------------------------------------------
1454 def UpdateNotebook(self
, select
= -1):
1458 def UpdatePage(page
, pageText
):
1461 for i
in range(nb
.GetPageCount()):
1462 if nb
.GetPageText(i
) == pageText
:
1470 nb
.AddPage(page
, pageText
)
1471 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1473 if nb
.GetPage(pagePos
) != page
:
1474 # Reload an existing page
1476 nb
.DeletePage(pagePos
)
1477 nb
.InsertPage(pagePos
, page
, pageText
)
1479 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1481 # Excellent! No redraw/flicker
1482 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1485 nb
.DeletePage(pagePos
)
1486 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1488 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1491 select
= nb
.GetSelection()
1493 UpdatePage(self
.codePage
, "Demo Code")
1494 UpdatePage(self
.demoPage
, "Demo")
1496 if select
>= 0 and select
< nb
.GetPageCount():
1497 nb
.SetSelection(select
)
1499 #---------------------------------------------
1500 def SetOverview(self
, name
, text
):
1501 self
.curOverview
= text
1503 if lead
!= '<html>' and lead
!= '<HTML>':
1504 text
= '<br>'.join(text
.split('\n'))
1506 text
= text
.decode('iso8859_1')
1507 self
.ovr
.SetPage(text
)
1508 self
.nb
.SetPageText(0, name
)
1510 #---------------------------------------------
1512 def OnFileExit(self
, *event
):
1515 def OnToggleRedirect(self
, event
):
1519 print "Print statements and other standard output will now be directed to this window."
1522 print "Print statements and other standard output will now be sent to the usual location."
1524 def OnHelpAbout(self
, event
):
1525 from About
import MyAboutBox
1526 about
= MyAboutBox(self
)
1530 def OnHelpFind(self
, event
):
1531 if self
.finddlg
!= None:
1534 self
.nb
.SetSelection(1)
1535 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1536 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1537 self
.finddlg
.Show(True)
1540 def OnUpdateFindItems(self
, evt
):
1541 evt
.Enable(self
.finddlg
== None)
1544 def OnFind(self
, event
):
1545 editor
= self
.codePage
.editor
1546 self
.nb
.SetSelection(1)
1547 end
= editor
.GetLastPosition()
1548 textstring
= editor
.GetRange(0, end
).lower()
1549 findstring
= self
.finddata
.GetFindString().lower()
1550 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1552 start
= editor
.GetSelection()[0]
1553 loc
= textstring
.rfind(findstring
, 0, start
)
1555 start
= editor
.GetSelection()[1]
1556 loc
= textstring
.find(findstring
, start
)
1557 if loc
== -1 and start
!= 0:
1558 # string not found, start at beginning
1561 loc
= textstring
.rfind(findstring
, 0, start
)
1564 loc
= textstring
.find(findstring
, start
)
1566 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1567 'Find String Not Found in Demo File',
1568 wx
.OK | wx
.ICON_INFORMATION
)
1573 self
.finddlg
.SetFocus()
1576 self
.finddlg
.Destroy()
1578 editor
.ShowPosition(loc
)
1579 editor
.SetSelection(loc
, loc
+ len(findstring
))
1583 def OnFindNext(self
, event
):
1584 if self
.finddata
.GetFindString():
1587 self
.OnHelpFind(event
)
1589 def OnFindClose(self
, event
):
1590 event
.GetDialog().Destroy()
1594 def OnOpenShellWindow(self
, evt
):
1596 # if it already exists then just make sure it's visible
1602 # Make a PyShell window
1604 namespace
= { 'wx' : wx
,
1605 'app' : wx
.GetApp(),
1608 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1609 self
.shell
.SetSize((640,480))
1612 # Hook the close event of the main frame window so that we
1613 # close the shell at the same time if it still exists
1614 def CloseShell(evt
):
1618 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1621 #---------------------------------------------
1622 def OnCloseWindow(self
, event
):
1624 self
.demoPage
= None
1625 self
.codePage
= None
1626 self
.mainmenu
= None
1627 self
.tbicon
.Destroy()
1631 #---------------------------------------------
1632 def OnIdle(self
, event
):
1634 self
.otherWin
.Raise()
1635 self
.demoPage
= self
.otherWin
1636 self
.otherWin
= None
1639 #---------------------------------------------
1642 showTipText
= open(opj("data/showTips")).read()
1643 showTip
, index
= eval(showTipText
)
1645 showTip
, index
= (1, 0)
1647 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1649 showTip
= wx
.ShowTip(self
, tp
)
1650 index
= tp
.GetCurrentTip()
1651 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1654 #---------------------------------------------
1655 def OnDemoMenu(self
, event
):
1657 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1661 self
.tree
.SelectItem(selectedDemo
)
1662 self
.tree
.EnsureVisible(selectedDemo
)
1666 #---------------------------------------------
1667 def OnIconfiy(self
, evt
):
1668 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1671 #---------------------------------------------
1672 def OnMaximize(self
, evt
):
1673 wx
.LogMessage("OnMaximize")
1676 #---------------------------------------------
1677 def OnActivate(self
, evt
):
1678 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1681 #---------------------------------------------
1682 def OnAppActivate(self
, evt
):
1683 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1686 #---------------------------------------------------------------------------
1687 #---------------------------------------------------------------------------
1689 class MySplashScreen(wx
.SplashScreen
):
1691 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1692 wx
.SplashScreen
.__init
__(self
, bmp
,
1693 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1695 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1696 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1699 def OnClose(self
, evt
):
1700 # Make sure the default handler runs too so this window gets
1705 # if the timer is still running then go ahead and show the
1707 if self
.fc
.IsRunning():
1713 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1715 if self
.fc
.IsRunning():
1719 class MyApp(wx
.App
):
1722 Create and show the splash screen. It will then create and show
1723 the main frame when it is time to do so.
1726 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1729 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1731 # Normally when using a SplashScreen you would create it, show
1732 # it and then continue on with the applicaiton's
1733 # initialization, finally creating and showing the main
1734 # application window(s). In this case we have nothing else to
1735 # do so we'll delay showing the main frame until later (see
1736 # ShowMain above) so the users can see the SplashScreen effect.
1737 splash
= MySplashScreen()
1744 #---------------------------------------------------------------------------
1748 demoPath
= os
.path
.dirname(__file__
)
1755 #---------------------------------------------------------------------------
1758 mainOverview
= """<html><body>
1761 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1762 language. It allows Python programmers to create programs with a
1763 robust, highly functional graphical user interface, simply and easily.
1764 It is implemented as a Python extension module (native code) that
1765 wraps the popular wxWindows cross platform GUI library, which is
1768 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1769 means that it is free for anyone to use and the source code is
1770 available for anyone to look at and modify. Or anyone can contribute
1771 fixes or enhancements to the project.
1773 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1774 same program will run on multiple platforms without modification.
1775 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1776 or unix-like systems, and Macintosh OS X. Since the language is
1777 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1780 <p> <b>This demo</b> is not only a collection of test cases for
1781 wxPython, but is also designed to help you learn about and how to use
1782 wxPython. Each sample is listed in the tree control on the left.
1783 When a sample is selected in the tree then a module is loaded and run
1784 (usually in a tab of this notebook,) and the source code of the module
1785 is loaded in another tab for you to browse and learn from.
1790 #----------------------------------------------------------------------------
1791 #----------------------------------------------------------------------------
1793 if __name__
== '__main__':
1797 #----------------------------------------------------------------------------