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', [
56 # managed windows == things with a (optional) caption you can close
57 ('Frames and Dialogs', [
81 # dialogs from libraries
84 'ScrolledMessageDialog',
88 ('Core Windows/Controls', [
125 ('"Book" Controls', [
133 ('Custom Controls', [
146 # controls coming from other libraries
147 ('More Windows/Controls', [
148 'ActiveX_FlashWindow',
149 'ActiveX_IEHtmlWindow',
151 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
154 'CheckListCtrlMixin',
169 'MaskedEditControls',
172 'MultiSplitterWindow',
187 # How to lay out the controls in a frame/dialog
197 'XmlResourceHandler',
198 'XmlResourceSubclass',
202 ('Process and Events', [
209 ##'infoframe', # needs better explanation and some fixing
213 ('Clipboard and DnD', [
235 ##'DialogUnits', # needs more explanations
252 ('Check out the samples dir too', [
259 #---------------------------------------------------------------------------
260 # Show how to derive a custom wxLog class
262 class MyLog(wx
.PyLog
):
263 def __init__(self
, textCtrl
, logTime
=0):
264 wx
.PyLog
.__init
__(self
)
266 self
.logTime
= logTime
268 def DoLogString(self
, message
, timeStamp
):
269 #print message, timeStamp
271 # message = time.strftime("%X", time.localtime(timeStamp)) + \
274 self
.tc
.AppendText(message
+ '\n')
277 class MyTP(wx
.PyTipProvider
):
279 return "This is my tip"
281 #---------------------------------------------------------------------------
282 # A class to be used to simply display a message in the demo pane
283 # rather than running the sample itself.
285 class MessagePanel(wx
.Panel
):
286 def __init__(self
, parent
, message
, caption
='', flags
=0):
287 wx
.Panel
.__init
__(self
, parent
)
292 if flags
& wx
.ICON_EXCLAMATION
:
293 artid
= wx
.ART_WARNING
294 elif flags
& wx
.ICON_ERROR
:
296 elif flags
& wx
.ICON_QUESTION
:
297 artid
= wx
.ART_QUESTION
298 elif flags
& wx
.ICON_INFORMATION
:
299 artid
= wx
.ART_INFORMATION
301 if artid
is not None:
302 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
303 icon
= wx
.StaticBitmap(self
, -1, bmp
)
305 icon
= (32,32) # make a spacer instead
308 caption
= wx
.StaticText(self
, -1, caption
)
309 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
311 message
= wx
.StaticText(self
, -1, message
)
313 # add to sizers for layout
314 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
320 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
327 box
= wx
.BoxSizer(wx
.VERTICAL
)
329 box
.Add(hbox
, 0, wx
.EXPAND
)
336 #---------------------------------------------------------------------------
337 # A class to be used to display source code in the demo. Try using the
338 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
339 # if there is an error, such as the stc module not being present.
343 ##raise ImportError # for testing the alternate implementation
345 from StyledTextCtrl_2
import PythonSTC
347 class DemoCodeEditor(PythonSTC
):
348 def __init__(self
, parent
):
349 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
352 # Some methods to make it compatible with how the wxTextCtrl is used
353 def SetValue(self
, value
):
355 value
= value
.decode('iso8859_1')
357 self
.EmptyUndoBuffer()
360 def IsModified(self
):
361 return self
.GetModify()
366 def SetInsertionPoint(self
, pos
):
367 self
.SetCurrentPos(pos
)
370 def ShowPosition(self
, pos
):
371 line
= self
.LineFromPosition(pos
)
372 #self.EnsureVisible(line)
375 def GetLastPosition(self
):
376 return self
.GetLength()
378 def GetPositionFromLine(self
, line
):
379 return self
.PositionFromLine(line
)
381 def GetRange(self
, start
, end
):
382 return self
.GetTextRange(start
, end
)
384 def GetSelection(self
):
385 return self
.GetAnchor(), self
.GetCurrentPos()
387 def SetSelection(self
, start
, end
):
388 self
.SetSelectionStart(start
)
389 self
.SetSelectionEnd(end
)
391 def SelectLine(self
, line
):
392 start
= self
.PositionFromLine(line
)
393 end
= self
.GetLineEndPosition(line
)
394 self
.SetSelection(start
, end
)
396 def SetUpEditor(self
):
398 This method carries out the work of setting up the demo editor.
399 It's seperate so as not to clutter up the init code.
403 self
.SetLexer(stc
.STC_LEX_PYTHON
)
404 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
407 self
.SetProperty("fold", "1" )
409 # Highlight tab/space mixing (shouldn't be any)
410 self
.SetProperty("tab.timmy.whinge.level", "1")
412 # Set left and right margins
415 # Set up the numbers in the margin for margin #1
416 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
417 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
418 self
.SetMarginWidth(1, 40)
420 # Indentation and tab stuff
421 self
.SetIndent(4) # Proscribed indent size for wx
422 self
.SetIndentationGuides(True) # Show indent guides
423 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
424 self
.SetTabIndents(True) # Tab key indents
425 self
.SetTabWidth(4) # Proscribed tab size for wx
426 self
.SetUseTabs(False) # Use spaces rather than tabs, or
427 # TabTimmy will complain!
429 self
.SetViewWhiteSpace(False) # Don't view white space
431 # EOL: Since we are loading/saving ourselves, and the
432 # strings will always have \n's in them, set the STC to
433 # edit them that way.
434 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
435 self
.SetViewEOL(False)
437 # No right-edge mode indicator
438 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
440 # Setup a margin to hold fold markers
441 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
442 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
443 self
.SetMarginSensitive(2, True)
444 self
.SetMarginWidth(2, 12)
446 # and now set up the fold markers
447 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
448 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
449 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
450 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
451 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
452 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
453 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
455 # Global default style
456 if wx
.Platform
== '__WXMSW__':
457 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
458 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
460 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
461 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
463 # Clear styles and revert to default.
466 # Following style specs only indicate differences from default.
467 # The rest remains unchanged.
469 # Line numbers in margin
470 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
472 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
474 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
476 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
479 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
481 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
482 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
484 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
485 # Strings and characters
486 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
487 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
489 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
491 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
492 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
494 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
496 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
498 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
499 # Identifiers. I leave this as not bold because everything seems
500 # to be an identifier if it doesn't match the above criterae
501 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
504 self
.SetCaretForeground("BLUE")
505 # Selection background
506 self
.SetSelBackground(1, '#66CCFF')
508 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
509 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
511 def RegisterModifiedEvent(self
, eventHandler
):
512 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
516 class DemoCodeEditor(wx
.TextCtrl
):
517 def __init__(self
, parent
):
518 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
519 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
521 def RegisterModifiedEvent(self
, eventHandler
):
522 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
524 def SetReadOnly(self
, flag
):
525 self
.SetEditable(not flag
)
526 # NOTE: STC already has this method
529 return self
.GetValue()
531 def GetPositionFromLine(self
, line
):
532 return self
.XYToPosition(0,line
)
534 def GotoLine(self
, line
):
535 pos
= self
.GetPositionFromLine(line
)
536 self
.SetInsertionPoint(pos
)
537 self
.ShowPosition(pos
)
539 def SelectLine(self
, line
):
540 start
= self
.GetPositionFromLine(line
)
541 end
= start
+ self
.GetLineLength(line
)
542 self
.SetSelection(start
, end
)
545 #---------------------------------------------------------------------------
546 # Constants for module versions
550 modDefault
= modOriginal
552 #---------------------------------------------------------------------------
554 class DemoCodePanel(wx
.Panel
):
555 """Panel for the 'Demo Code' tab"""
556 def __init__(self
, parent
, mainFrame
):
557 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
558 if 'wxMSW' in wx
.PlatformInfo
:
560 self
.mainFrame
= mainFrame
561 self
.editor
= DemoCodeEditor(self
)
562 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
564 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
565 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
566 self
.btnSave
.Enable(False)
567 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
568 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
570 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
571 modModified
: wx
.RadioButton(self
, -1, "Modified") }
573 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
574 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
575 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
576 for modID
, radioButton
in self
.radioButtons
.items():
577 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
578 radioButton
.modID
= modID
# makes it easier for the event handler
579 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
581 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
582 self
.controlBox
.Add(self
.btnRestore
, 0)
584 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
585 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
586 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
587 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
590 self
.SetSizer(self
.box
)
593 # Loads a demo from a DemoModules object
594 def LoadDemo(self
, demoModules
):
595 self
.demoModules
= demoModules
596 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
597 demoModules
.SetActive(modModified
)
599 demoModules
.SetActive(modOriginal
)
600 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
601 self
.ActiveModuleChanged()
604 def ActiveModuleChanged(self
):
605 self
.LoadDemoSource(self
.demoModules
.GetSource())
606 self
.UpdateControlState()
610 def LoadDemoSource(self
, source
):
612 self
.editor
.SetValue(source
)
614 self
.btnSave
.Enable(False)
617 def JumpToLine(self
, line
, highlight
=False):
618 self
.editor
.GotoLine(line
)
619 self
.editor
.SetFocus()
621 self
.editor
.SelectLine(line
)
624 def UpdateControlState(self
):
625 active
= self
.demoModules
.GetActiveID()
626 # Update the radio/restore buttons
627 for moduleID
in self
.radioButtons
:
628 btn
= self
.radioButtons
[moduleID
]
629 if moduleID
== active
:
634 if self
.demoModules
.Exists(moduleID
):
636 if moduleID
== modModified
:
637 self
.btnRestore
.Enable(True)
640 if moduleID
== modModified
:
641 self
.btnRestore
.Enable(False)
644 def OnRadioButton(self
, event
):
645 radioSelected
= event
.GetEventObject()
646 modSelected
= radioSelected
.modID
647 if modSelected
!= self
.demoModules
.GetActiveID():
648 busy
= wx
.BusyInfo("Reloading demo module...")
649 self
.demoModules
.SetActive(modSelected
)
650 self
.ActiveModuleChanged()
653 def ReloadDemo(self
):
654 if self
.demoModules
.name
!= __name__
:
655 self
.mainFrame
.RunModule()
658 def OnCodeModified(self
, event
):
659 self
.btnSave
.Enable(self
.editor
.IsModified())
662 def OnSave(self
, event
):
663 if self
.demoModules
.Exists(modModified
):
664 if self
.demoModules
.GetActiveID() == modOriginal
:
665 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
666 "Do you want to continue?"
667 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
668 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
669 result
= dlg
.ShowModal()
670 if result
== wx
.ID_NO
:
674 self
.demoModules
.SetActive(modModified
)
675 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
677 # Create the demo directory if one doesn't already exist
678 if not os
.path
.exists(GetModifiedDirectory()):
680 os
.makedirs(GetModifiedDirectory())
681 if not os
.path
.exists(GetModifiedDirectory()):
682 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
685 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
688 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
691 f
= open(modifiedFilename
, "wt")
692 source
= self
.editor
.GetText()
698 busy
= wx
.BusyInfo("Reloading demo module...")
699 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
700 self
.ActiveModuleChanged()
703 def OnRestore(self
, event
): # Handles the "Delete Modified" button
704 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
705 self
.demoModules
.Delete(modModified
)
706 os
.unlink(modifiedFilename
) # Delete the modified copy
707 busy
= wx
.BusyInfo("Reloading demo module...")
708 self
.ActiveModuleChanged()
711 #---------------------------------------------------------------------------
714 """Convert paths to the platform-specific separator"""
715 str = apply(os
.path
.join
, tuple(path
.split('/')))
716 # HACK: on Linux, a leading / gets lost...
717 if path
.startswith('/'):
722 def GetModifiedDirectory():
724 Returns the directory where modified versions of the demo files
727 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
730 def GetModifiedFilename(name
):
732 Returns the filename of the modified version of the specified demo
734 if not name
.endswith(".py"):
736 return GetModifiedDirectory() + name
739 def GetOriginalFilename(name
):
741 Returns the filename of the original version of the specified demo
743 if not name
.endswith(".py"):
748 def DoesModifiedExist(name
):
749 """Returns whether the specified demo has a modified copy"""
750 if os
.path
.exists(GetModifiedFilename(name
)):
756 #---------------------------------------------------------------------------
758 class ModuleDictWrapper
:
759 """Emulates a module with a dynamically compiled __dict__"""
760 def __init__(self
, dict):
763 def __getattr__(self
, name
):
764 if name
in self
.dict:
765 return self
.dict[name
]
771 Dynamically manages the original/modified versions of a demo
774 def __init__(self
, name
):
778 # (dict , source , filename , description , error information )
779 # ( 0 , 1 , 2 , 3 , 4 )
780 self
.modules
= [[None, "" , "" , "<original>" , None],
781 [None, "" , "" , "<modified>" , None]]
783 # load original module
784 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
785 self
.SetActive(modOriginal
)
787 # load modified module (if one exists)
788 if DoesModifiedExist(name
):
789 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
792 def LoadFromFile(self
, modID
, filename
):
793 self
.modules
[modID
][2] = filename
794 file = open(filename
, "rt")
795 self
.LoadFromSource(modID
, file.read())
799 def LoadFromSource(self
, modID
, source
):
800 self
.modules
[modID
][1] = source
804 def LoadDict(self
, modID
):
805 if self
.name
!= __name__
:
806 source
= self
.modules
[modID
][1]
807 #description = self.modules[modID][3]
808 description
= self
.modules
[modID
][2]
811 self
.modules
[modID
][0] = {}
812 code
= compile(source
, description
, "exec")
813 exec code
in self
.modules
[modID
][0]
815 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
816 self
.modules
[modID
][0] = None
818 self
.modules
[modID
][4] = None
821 def SetActive(self
, modID
):
822 if modID
!= modOriginal
and modID
!= modModified
:
825 self
.modActive
= modID
829 dict = self
.modules
[self
.modActive
][0]
833 return ModuleDictWrapper(dict)
836 def GetActiveID(self
):
837 return self
.modActive
840 def GetSource(self
, modID
= None):
842 modID
= self
.modActive
843 return self
.modules
[modID
][1]
846 def GetFilename(self
, modID
= None):
848 modID
= self
.modActive
849 return self
.modules
[self
.modActive
][2]
852 def GetErrorInfo(self
, modID
= None):
854 modID
= self
.modActive
855 return self
.modules
[self
.modActive
][4]
858 def Exists(self
, modID
):
859 return self
.modules
[modID
][1] != ""
862 def UpdateFile(self
, modID
= None):
863 """Updates the file from which a module was loaded
864 with (possibly updated) source"""
866 modID
= self
.modActive
868 source
= self
.modules
[modID
][1]
869 filename
= self
.modules
[modID
][2]
872 file = open(filename
, "wt")
878 def Delete(self
, modID
):
879 if self
.modActive
== modID
:
882 self
.modules
[modID
][0] = None
883 self
.modules
[modID
][1] = ""
884 self
.modules
[modID
][2] = ""
887 #---------------------------------------------------------------------------
890 """Wraps and stores information about the current exception"""
891 def __init__(self
, exc_info
):
894 excType
, excValue
= exc_info
[:2]
895 # traceback list entries: (filename, line number, function name, text)
896 self
.traceback
= traceback
.extract_tb(exc_info
[2])
898 # --Based on traceback.py::format_exception_only()--
899 if type(excType
) == types
.ClassType
:
900 self
.exception_type
= excType
.__name
__
902 self
.exception_type
= excType
904 # If it's a syntax error, extra information needs
905 # to be added to the traceback
906 if excType
is SyntaxError:
908 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
913 filename
= "<string>"
915 self
.traceback
.append( (filename
, lineno
, "", line
) )
918 self
.exception_details
= str(excValue
)
920 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
927 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
930 #---------------------------------------------------------------------------
932 class DemoErrorPanel(wx
.Panel
):
933 """Panel put into the demo tab when the demo fails to run due to errors"""
935 def __init__(self
, parent
, codePanel
, demoError
, log
):
936 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
937 self
.codePanel
= codePanel
941 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
944 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
945 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
947 # Exception Information
948 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
949 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
950 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
951 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
952 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
953 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
954 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
955 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
956 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
957 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
959 # Set up the traceback list
960 # This one automatically resizes last column to take up remaining space
961 from ListCtrl
import TestListCtrl
962 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
963 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
964 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
965 self
.list.InsertColumn(0, "Filename")
966 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
967 self
.list.InsertColumn(2, "Function")
968 self
.list.InsertColumn(3, "Code")
969 self
.InsertTraceback(self
.list, demoError
.traceback
)
970 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
971 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
972 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
973 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
974 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
975 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
976 + "Double-click on them to go to the offending line")
977 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
980 self
.SetSizer(self
.box
)
983 def InsertTraceback(self
, list, traceback
):
984 #Add the traceback data
985 for x
in range(len(traceback
)):
987 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
988 list.SetStringItem(x
, 1, str(data
[1])) # Line
989 list.SetStringItem(x
, 2, str(data
[2])) # Function
990 list.SetStringItem(x
, 3, str(data
[3])) # Code
992 # Check whether this entry is from the demo module
993 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
994 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
995 # Give it a blue colour
996 item
= self
.list.GetItem(x
)
997 item
.SetTextColour(wx
.BLUE
)
998 self
.list.SetItem(item
)
1000 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1003 def OnItemSelected(self
, event
):
1004 # This occurs before OnDoubleClick and can be used to set the
1005 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1006 self
.currentItem
= event
.m_itemIndex
1010 def OnDoubleClick(self
, event
):
1011 # If double-clicking on a demo's entry, jump to the line number
1012 line
= self
.list.GetItemData(self
.currentItem
)
1014 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1015 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1019 #---------------------------------------------------------------------------
1021 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1022 TBMENU_RESTORE
= wx
.NewId()
1023 TBMENU_CLOSE
= wx
.NewId()
1024 TBMENU_CHANGE
= wx
.NewId()
1025 TBMENU_REMOVE
= wx
.NewId()
1027 def __init__(self
, frame
):
1028 wx
.TaskBarIcon
.__init
__(self
)
1032 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1033 self
.SetIcon(icon
, "wxPython Demo")
1037 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1038 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1039 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1040 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1041 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1044 def CreatePopupMenu(self
):
1046 This method is called by the base class when it needs to popup
1047 the menu for the default EVT_RIGHT_DOWN event. Just create
1048 the menu how you want it and return it from this function,
1049 the base class takes care of the rest.
1052 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1053 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1054 menu
.AppendSeparator()
1055 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1056 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1060 def MakeIcon(self
, img
):
1062 The various platforms have different requirements for the
1065 if "wxMSW" in wx
.PlatformInfo
:
1066 img
= img
.Scale(16, 16)
1067 elif "wxGTK" in wx
.PlatformInfo
:
1068 img
= img
.Scale(22, 22)
1069 # wxMac can be any size upto 128x128, so leave the source img alone....
1070 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1074 def OnTaskBarActivate(self
, evt
):
1075 if self
.frame
.IsIconized():
1076 self
.frame
.Iconize(False)
1077 if not self
.frame
.IsShown():
1078 self
.frame
.Show(True)
1082 def OnTaskBarClose(self
, evt
):
1086 def OnTaskBarChange(self
, evt
):
1087 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1088 name
= names
[self
.imgidx
]
1090 getFunc
= getattr(images
, "get%sImage" % name
)
1092 if self
.imgidx
>= len(names
):
1095 icon
= self
.MakeIcon(getFunc())
1096 self
.SetIcon(icon
, "This is a new icon: " + name
)
1099 def OnTaskBarRemove(self
, evt
):
1103 #---------------------------------------------------------------------------
1104 class wxPythonDemo(wx
.Frame
):
1105 overviewText
= "wxPython Overview"
1107 def __init__(self
, parent
, title
):
1108 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1109 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1111 self
.SetMinSize((640,480))
1114 self
.cwd
= os
.getcwd()
1115 self
.curOverview
= ""
1116 self
.demoPage
= None
1117 self
.codePage
= None
1119 self
.firstTime
= True
1122 icon
= images
.getWXPdemoIcon()
1125 self
.tbicon
= DemoTaskBarIcon(self
)
1127 wx
.CallAfter(self
.ShowTip
)
1129 self
.otherWin
= None
1130 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1131 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1132 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1133 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1135 self
.Centre(wx
.BOTH
)
1136 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1138 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1139 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1141 def EmptyHandler(evt
): pass
1142 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1143 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1145 # Prevent TreeCtrl from displaying all items after destruction when True
1149 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1152 self
.mainmenu
= wx
.MenuBar()
1154 item
= menu
.Append(-1, '&Redirect Output',
1155 'Redirect print statements to a window',
1157 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1159 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1160 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1161 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1162 self
.mainmenu
.Append(menu
, '&File')
1166 for item
in _treeList
:
1168 for childItem
in item
[1]:
1169 mi
= submenu
.Append(-1, childItem
)
1170 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1171 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1172 self
.mainmenu
.Append(menu
, '&Demo')
1174 # Make a Demo Code menu
1175 #TODO: Add new menu items
1176 # Like the option-enabled entries to select the
1178 #TODO: should we bother?
1181 #saveID = wx.NewId()
1182 #restoreID = wx.NewId()
1184 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1185 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1186 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1187 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1188 #self.mainmenu.Append(menu, 'Demo &Code')
1193 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1194 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1195 menu
.AppendSeparator()
1197 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1198 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1199 menu
.AppendSeparator()
1200 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1201 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1203 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1204 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1205 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1206 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1207 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1208 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1209 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1210 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1211 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1212 self
.mainmenu
.Append(menu
, '&Help')
1213 self
.SetMenuBar(self
.mainmenu
)
1215 self
.finddata
= wx
.FindReplaceData()
1216 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1219 # This is another way to set Accelerators, in addition to
1220 # using the '\t<key>' syntax in the menu items.
1221 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1222 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1223 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1224 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1226 self
.SetAcceleratorTable(aTable
)
1232 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1233 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1236 root
= self
.tree
.AddRoot("wxPython Overview")
1238 for item
in _treeList
:
1239 child
= self
.tree
.AppendItem(root
, item
[0])
1240 if not firstChild
: firstChild
= child
1241 for childItem
in item
[1]:
1242 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1243 self
.treeMap
[childItem
] = theDemo
1245 self
.tree
.Expand(root
)
1246 self
.tree
.Expand(firstChild
)
1247 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1248 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1249 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1250 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1252 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1253 # we put it in a panel first because there seems to be a
1254 # refresh bug of some sort (wxGTK) when it is directly in
1257 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1258 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1260 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1261 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1262 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1263 self
.nb
.AddPage(panel
, self
.overviewText
)
1265 def OnOvrSize(evt
, ovr
=self
.ovr
):
1266 ovr
.SetSize(evt
.GetSize())
1267 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1268 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1270 if "gtk2" in wx
.PlatformInfo
:
1271 self
.ovr
.SetStandardFonts()
1272 self
.SetOverview(self
.overviewText
, mainOverview
)
1275 # Set up a log window
1276 self
.log
= wx
.TextCtrl(splitter2
, -1,
1277 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1279 # Set the wxWindows log target to be this textctrl
1280 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1282 # But instead of the above we want to show how to use our own wx.Log class
1283 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1285 # for serious debugging
1286 #wx.Log_SetActiveTarget(wx.LogStderr())
1287 #wx.Log_SetTraceMask(wx.TraceMessages)
1290 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1291 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1293 # add the windows to the splitter and split it.
1294 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1295 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1297 splitter
.SetMinimumPaneSize(120)
1298 splitter2
.SetMinimumPaneSize(60)
1300 # Make the splitter on the right expand the top window when resized
1301 def SplitterOnSize(evt
):
1302 splitter
= evt
.GetEventObject()
1303 sz
= splitter
.GetSize()
1304 splitter
.SetSashPosition(sz
.height
- 160, False)
1307 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1309 # select initial items
1310 self
.nb
.SetSelection(0)
1311 self
.tree
.SelectItem(root
)
1313 # Load 'Main' module
1314 self
.LoadDemo(self
.overviewText
)
1317 # select some other initial module?
1318 if len(sys
.argv
) > 1:
1320 if arg
.endswith('.py'):
1322 selectedDemo
= self
.treeMap
.get(arg
, None)
1324 self
.tree
.SelectItem(selectedDemo
)
1325 self
.tree
.EnsureVisible(selectedDemo
)
1328 #---------------------------------------------
1329 def WriteText(self
, text
):
1330 if text
[-1:] == '\n':
1334 def write(self
, txt
):
1337 #---------------------------------------------
1338 def OnItemExpanded(self
, event
):
1339 item
= event
.GetItem()
1340 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1343 #---------------------------------------------
1344 def OnItemCollapsed(self
, event
):
1345 item
= event
.GetItem()
1346 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1349 #---------------------------------------------
1350 def OnTreeLeftDown(self
, event
):
1351 # reset the overview text if the tree item is clicked on again
1352 pt
= event
.GetPosition();
1353 item
, flags
= self
.tree
.HitTest(pt
)
1354 if item
== self
.tree
.GetSelection():
1355 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1358 #---------------------------------------------
1359 def OnSelChanged(self
, event
):
1360 if self
.dying
or not self
.loaded
:
1363 item
= event
.GetItem()
1364 itemText
= self
.tree
.GetItemText(item
)
1365 self
.LoadDemo(itemText
)
1367 #---------------------------------------------
1368 def LoadDemo(self
, demoName
):
1370 wx
.BeginBusyCursor()
1373 self
.ShutdownDemoModule()
1375 if demoName
== self
.overviewText
:
1376 # User selected the "wxPython Overview" node
1378 # Changing the main window at runtime not yet supported...
1379 self
.demoModules
= DemoModules(__name__
)
1380 self
.SetOverview(self
.overviewText
, mainOverview
)
1381 self
.LoadDemoSource()
1382 self
.UpdateNotebook(0)
1384 if os
.path
.exists(GetOriginalFilename(demoName
)):
1385 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1386 self
.demoModules
= DemoModules(demoName
)
1387 self
.LoadDemoSource()
1390 self
.SetOverview("wxPython", mainOverview
)
1391 self
.codePage
= None
1392 self
.UpdateNotebook(0)
1396 #---------------------------------------------
1397 def LoadDemoSource(self
):
1398 self
.codePage
= None
1399 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1400 self
.codePage
.LoadDemo(self
.demoModules
)
1402 #---------------------------------------------
1403 def RunModule(self
):
1404 """Runs the active module"""
1406 module
= self
.demoModules
.GetActive()
1407 self
.ShutdownDemoModule()
1410 # o The RunTest() for all samples must now return a window that can
1411 # be palced in a tab in the main notebook.
1412 # o If an error occurs (or has occurred before) an error tab is created.
1414 if module
is not None:
1415 wx
.LogMessage("Running demo module...")
1416 if hasattr(module
, "overview"):
1417 overviewText
= module
.overview
1420 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1422 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1423 DemoError(sys
.exc_info()), self
)
1425 assert self
.demoPage
is not None, "runTest must return a window!"
1428 # There was a previous error in compiling or exec-ing
1429 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1430 self
.demoModules
.GetErrorInfo(), self
)
1432 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1435 # cahnge to the demo page the first time a module is run
1436 self
.UpdateNotebook(2)
1437 self
.firstTime
= False
1439 # otherwise just stay on the same tab in case the user has changed to another one
1440 self
.UpdateNotebook()
1442 #---------------------------------------------
1443 def ShutdownDemoModule(self
):
1445 # inform the window that it's time to quit if it cares
1446 if hasattr(self
.demoPage
, "ShutdownDemo"):
1447 self
.demoPage
.ShutdownDemo()
1448 wx
.YieldIfNeeded() # in case the page has pending events
1449 self
.demoPage
= None
1451 #---------------------------------------------
1452 def UpdateNotebook(self
, select
= -1):
1456 def UpdatePage(page
, pageText
):
1459 for i
in range(nb
.GetPageCount()):
1460 if nb
.GetPageText(i
) == pageText
:
1468 nb
.AddPage(page
, pageText
)
1469 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1471 if nb
.GetPage(pagePos
) != page
:
1472 # Reload an existing page
1474 nb
.DeletePage(pagePos
)
1475 nb
.InsertPage(pagePos
, page
, pageText
)
1477 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1479 # Excellent! No redraw/flicker
1480 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1483 nb
.DeletePage(pagePos
)
1484 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1486 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1489 select
= nb
.GetSelection()
1491 UpdatePage(self
.codePage
, "Demo Code")
1492 UpdatePage(self
.demoPage
, "Demo")
1494 if select
>= 0 and select
< nb
.GetPageCount():
1495 nb
.SetSelection(select
)
1497 #---------------------------------------------
1498 def SetOverview(self
, name
, text
):
1499 self
.curOverview
= text
1501 if lead
!= '<html>' and lead
!= '<HTML>':
1502 text
= '<br>'.join(text
.split('\n'))
1504 text
= text
.decode('iso8859_1')
1505 self
.ovr
.SetPage(text
)
1506 self
.nb
.SetPageText(0, name
)
1508 #---------------------------------------------
1510 def OnFileExit(self
, *event
):
1513 def OnToggleRedirect(self
, event
):
1517 print "Print statements and other standard output will now be directed to this window."
1520 print "Print statements and other standard output will now be sent to the usual location."
1522 def OnHelpAbout(self
, event
):
1523 from About
import MyAboutBox
1524 about
= MyAboutBox(self
)
1528 def OnHelpFind(self
, event
):
1529 if self
.finddlg
!= None:
1532 self
.nb
.SetSelection(1)
1533 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1534 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1535 self
.finddlg
.Show(True)
1538 def OnUpdateFindItems(self
, evt
):
1539 evt
.Enable(self
.finddlg
== None)
1542 def OnFind(self
, event
):
1543 editor
= self
.codePage
.editor
1544 self
.nb
.SetSelection(1)
1545 end
= editor
.GetLastPosition()
1546 textstring
= editor
.GetRange(0, end
).lower()
1547 findstring
= self
.finddata
.GetFindString().lower()
1548 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1550 start
= editor
.GetSelection()[0]
1551 loc
= textstring
.rfind(findstring
, 0, start
)
1553 start
= editor
.GetSelection()[1]
1554 loc
= textstring
.find(findstring
, start
)
1555 if loc
== -1 and start
!= 0:
1556 # string not found, start at beginning
1559 loc
= textstring
.rfind(findstring
, 0, start
)
1562 loc
= textstring
.find(findstring
, start
)
1564 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1565 'Find String Not Found in Demo File',
1566 wx
.OK | wx
.ICON_INFORMATION
)
1571 self
.finddlg
.SetFocus()
1574 self
.finddlg
.Destroy()
1576 editor
.ShowPosition(loc
)
1577 editor
.SetSelection(loc
, loc
+ len(findstring
))
1581 def OnFindNext(self
, event
):
1582 if self
.finddata
.GetFindString():
1585 self
.OnHelpFind(event
)
1587 def OnFindClose(self
, event
):
1588 event
.GetDialog().Destroy()
1592 def OnOpenShellWindow(self
, evt
):
1594 # if it already exists then just make sure it's visible
1600 # Make a PyShell window
1602 namespace
= { 'wx' : wx
,
1603 'app' : wx
.GetApp(),
1606 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1607 self
.shell
.SetSize((640,480))
1610 # Hook the close event of the main frame window so that we
1611 # close the shell at the same time if it still exists
1612 def CloseShell(evt
):
1616 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1619 #---------------------------------------------
1620 def OnCloseWindow(self
, event
):
1622 self
.demoPage
= None
1623 self
.codePage
= None
1624 self
.mainmenu
= None
1625 self
.tbicon
.Destroy()
1629 #---------------------------------------------
1630 def OnIdle(self
, event
):
1632 self
.otherWin
.Raise()
1633 self
.demoPage
= self
.otherWin
1634 self
.otherWin
= None
1637 #---------------------------------------------
1640 showTipText
= open(opj("data/showTips")).read()
1641 showTip
, index
= eval(showTipText
)
1643 showTip
, index
= (1, 0)
1645 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1647 showTip
= wx
.ShowTip(self
, tp
)
1648 index
= tp
.GetCurrentTip()
1649 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1652 #---------------------------------------------
1653 def OnDemoMenu(self
, event
):
1655 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1659 self
.tree
.SelectItem(selectedDemo
)
1660 self
.tree
.EnsureVisible(selectedDemo
)
1664 #---------------------------------------------
1665 def OnIconfiy(self
, evt
):
1666 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1669 #---------------------------------------------
1670 def OnMaximize(self
, evt
):
1671 wx
.LogMessage("OnMaximize")
1674 #---------------------------------------------
1675 def OnActivate(self
, evt
):
1676 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1679 #---------------------------------------------
1680 def OnAppActivate(self
, evt
):
1681 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1684 #---------------------------------------------------------------------------
1685 #---------------------------------------------------------------------------
1687 class MySplashScreen(wx
.SplashScreen
):
1689 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1690 wx
.SplashScreen
.__init
__(self
, bmp
,
1691 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1693 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1694 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1697 def OnClose(self
, evt
):
1698 # Make sure the default handler runs too so this window gets
1703 # if the timer is still running then go ahead and show the
1705 if self
.fc
.IsRunning():
1711 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1713 if self
.fc
.IsRunning():
1717 class MyApp(wx
.App
):
1720 Create and show the splash screen. It will then create and show
1721 the main frame when it is time to do so.
1724 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1727 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1729 # Normally when using a SplashScreen you would create it, show
1730 # it and then continue on with the applicaiton's
1731 # initialization, finally creating and showing the main
1732 # application window(s). In this case we have nothing else to
1733 # do so we'll delay showing the main frame until later (see
1734 # ShowMain above) so the users can see the SplashScreen effect.
1735 splash
= MySplashScreen()
1742 #---------------------------------------------------------------------------
1746 demoPath
= os
.path
.dirname(__file__
)
1753 #---------------------------------------------------------------------------
1756 mainOverview
= """<html><body>
1759 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1760 language. It allows Python programmers to create programs with a
1761 robust, highly functional graphical user interface, simply and easily.
1762 It is implemented as a Python extension module (native code) that
1763 wraps the popular wxWindows cross platform GUI library, which is
1766 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1767 means that it is free for anyone to use and the source code is
1768 available for anyone to look at and modify. Or anyone can contribute
1769 fixes or enhancements to the project.
1771 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1772 same program will run on multiple platforms without modification.
1773 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1774 or unix-like systems, and Macintosh OS X. Since the language is
1775 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1778 <p> <b>This demo</b> is not only a collection of test cases for
1779 wxPython, but is also designed to help you learn about and how to use
1780 wxPython. Each sample is listed in the tree control on the left.
1781 When a sample is selected in the tree then a module is loaded and run
1782 (usually in a tab of this notebook,) and the source code of the module
1783 is loaded in another tab for you to browse and learn from.
1788 #----------------------------------------------------------------------------
1789 #----------------------------------------------------------------------------
1791 if __name__
== '__main__':
1795 #----------------------------------------------------------------------------