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', [
59 # managed windows == things with a (optional) caption you can close
60 ('Frames and Dialogs', [
85 # dialogs from libraries
88 'ScrolledMessageDialog',
92 ('Core Windows/Controls', [
129 ('"Book" Controls', [
137 ('Custom Controls', [
150 # controls coming from other libraries
151 ('More Windows/Controls', [
152 'ActiveX_FlashWindow',
153 'ActiveX_IEHtmlWindow',
155 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
158 'CheckListCtrlMixin',
173 'MaskedEditControls',
176 'MultiSplitterWindow',
193 # How to lay out the controls in a frame/dialog
203 'XmlResourceHandler',
204 'XmlResourceSubclass',
208 ('Process and Events', [
215 ##'infoframe', # needs better explanation and some fixing
219 ('Clipboard and DnD', [
241 ##'DialogUnits', # needs more explanations
258 ('Check out the samples dir too', [
265 #---------------------------------------------------------------------------
266 # Show how to derive a custom wxLog class
268 class MyLog(wx
.PyLog
):
269 def __init__(self
, textCtrl
, logTime
=0):
270 wx
.PyLog
.__init
__(self
)
272 self
.logTime
= logTime
274 def DoLogString(self
, message
, timeStamp
):
275 #print message, timeStamp
277 # message = time.strftime("%X", time.localtime(timeStamp)) + \
280 self
.tc
.AppendText(message
+ '\n')
283 class MyTP(wx
.PyTipProvider
):
285 return "This is my tip"
287 #---------------------------------------------------------------------------
288 # A class to be used to simply display a message in the demo pane
289 # rather than running the sample itself.
291 class MessagePanel(wx
.Panel
):
292 def __init__(self
, parent
, message
, caption
='', flags
=0):
293 wx
.Panel
.__init
__(self
, parent
)
298 if flags
& wx
.ICON_EXCLAMATION
:
299 artid
= wx
.ART_WARNING
300 elif flags
& wx
.ICON_ERROR
:
302 elif flags
& wx
.ICON_QUESTION
:
303 artid
= wx
.ART_QUESTION
304 elif flags
& wx
.ICON_INFORMATION
:
305 artid
= wx
.ART_INFORMATION
307 if artid
is not None:
308 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
309 icon
= wx
.StaticBitmap(self
, -1, bmp
)
311 icon
= (32,32) # make a spacer instead
314 caption
= wx
.StaticText(self
, -1, caption
)
315 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
317 message
= wx
.StaticText(self
, -1, message
)
319 # add to sizers for layout
320 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
326 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
333 box
= wx
.BoxSizer(wx
.VERTICAL
)
335 box
.Add(hbox
, 0, wx
.EXPAND
)
342 #---------------------------------------------------------------------------
343 # A class to be used to display source code in the demo. Try using the
344 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
345 # if there is an error, such as the stc module not being present.
349 ##raise ImportError # for testing the alternate implementation
351 from StyledTextCtrl_2
import PythonSTC
353 class DemoCodeEditor(PythonSTC
):
354 def __init__(self
, parent
):
355 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
358 # Some methods to make it compatible with how the wxTextCtrl is used
359 def SetValue(self
, value
):
361 value
= value
.decode('iso8859_1')
363 self
.EmptyUndoBuffer()
366 def IsModified(self
):
367 return self
.GetModify()
372 def SetInsertionPoint(self
, pos
):
373 self
.SetCurrentPos(pos
)
376 def ShowPosition(self
, pos
):
377 line
= self
.LineFromPosition(pos
)
378 #self.EnsureVisible(line)
381 def GetLastPosition(self
):
382 return self
.GetLength()
384 def GetPositionFromLine(self
, line
):
385 return self
.PositionFromLine(line
)
387 def GetRange(self
, start
, end
):
388 return self
.GetTextRange(start
, end
)
390 def GetSelection(self
):
391 return self
.GetAnchor(), self
.GetCurrentPos()
393 def SetSelection(self
, start
, end
):
394 self
.SetSelectionStart(start
)
395 self
.SetSelectionEnd(end
)
397 def SelectLine(self
, line
):
398 start
= self
.PositionFromLine(line
)
399 end
= self
.GetLineEndPosition(line
)
400 self
.SetSelection(start
, end
)
402 def SetUpEditor(self
):
404 This method carries out the work of setting up the demo editor.
405 It's seperate so as not to clutter up the init code.
409 self
.SetLexer(stc
.STC_LEX_PYTHON
)
410 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
413 self
.SetProperty("fold", "1" )
415 # Highlight tab/space mixing (shouldn't be any)
416 self
.SetProperty("tab.timmy.whinge.level", "1")
418 # Set left and right margins
421 # Set up the numbers in the margin for margin #1
422 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
423 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
424 self
.SetMarginWidth(1, 40)
426 # Indentation and tab stuff
427 self
.SetIndent(4) # Proscribed indent size for wx
428 self
.SetIndentationGuides(True) # Show indent guides
429 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
430 self
.SetTabIndents(True) # Tab key indents
431 self
.SetTabWidth(4) # Proscribed tab size for wx
432 self
.SetUseTabs(False) # Use spaces rather than tabs, or
433 # TabTimmy will complain!
435 self
.SetViewWhiteSpace(False) # Don't view white space
437 # EOL: Since we are loading/saving ourselves, and the
438 # strings will always have \n's in them, set the STC to
439 # edit them that way.
440 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
441 self
.SetViewEOL(False)
443 # No right-edge mode indicator
444 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
446 # Setup a margin to hold fold markers
447 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
448 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
449 self
.SetMarginSensitive(2, True)
450 self
.SetMarginWidth(2, 12)
452 # and now set up the fold markers
453 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
454 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
455 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
456 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
457 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
458 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
459 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
461 # Global default style
462 if wx
.Platform
== '__WXMSW__':
463 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
464 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
466 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
467 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
469 # Clear styles and revert to default.
472 # Following style specs only indicate differences from default.
473 # The rest remains unchanged.
475 # Line numbers in margin
476 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
478 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
480 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
482 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
485 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
487 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
488 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
490 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
491 # Strings and characters
492 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
493 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
495 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
497 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
498 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
500 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
502 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
504 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
505 # Identifiers. I leave this as not bold because everything seems
506 # to be an identifier if it doesn't match the above criterae
507 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
510 self
.SetCaretForeground("BLUE")
511 # Selection background
512 self
.SetSelBackground(1, '#66CCFF')
514 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
515 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
517 def RegisterModifiedEvent(self
, eventHandler
):
518 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
522 class DemoCodeEditor(wx
.TextCtrl
):
523 def __init__(self
, parent
):
524 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
525 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
527 def RegisterModifiedEvent(self
, eventHandler
):
528 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
530 def SetReadOnly(self
, flag
):
531 self
.SetEditable(not flag
)
532 # NOTE: STC already has this method
535 return self
.GetValue()
537 def GetPositionFromLine(self
, line
):
538 return self
.XYToPosition(0,line
)
540 def GotoLine(self
, line
):
541 pos
= self
.GetPositionFromLine(line
)
542 self
.SetInsertionPoint(pos
)
543 self
.ShowPosition(pos
)
545 def SelectLine(self
, line
):
546 start
= self
.GetPositionFromLine(line
)
547 end
= start
+ self
.GetLineLength(line
)
548 self
.SetSelection(start
, end
)
551 #---------------------------------------------------------------------------
552 # Constants for module versions
556 modDefault
= modOriginal
558 #---------------------------------------------------------------------------
560 class DemoCodePanel(wx
.Panel
):
561 """Panel for the 'Demo Code' tab"""
562 def __init__(self
, parent
, mainFrame
):
563 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
564 if 'wxMSW' in wx
.PlatformInfo
:
566 self
.mainFrame
= mainFrame
567 self
.editor
= DemoCodeEditor(self
)
568 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
570 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
571 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
572 self
.btnSave
.Enable(False)
573 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
574 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
576 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
577 modModified
: wx
.RadioButton(self
, -1, "Modified") }
579 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
580 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
581 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
582 for modID
, radioButton
in self
.radioButtons
.items():
583 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
584 radioButton
.modID
= modID
# makes it easier for the event handler
585 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
587 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
588 self
.controlBox
.Add(self
.btnRestore
, 0)
590 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
591 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
592 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
593 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
596 self
.SetSizer(self
.box
)
599 # Loads a demo from a DemoModules object
600 def LoadDemo(self
, demoModules
):
601 self
.demoModules
= demoModules
602 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
603 demoModules
.SetActive(modModified
)
605 demoModules
.SetActive(modOriginal
)
606 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
607 self
.ActiveModuleChanged()
610 def ActiveModuleChanged(self
):
611 self
.LoadDemoSource(self
.demoModules
.GetSource())
612 self
.UpdateControlState()
616 def LoadDemoSource(self
, source
):
618 self
.editor
.SetValue(source
)
620 self
.btnSave
.Enable(False)
623 def JumpToLine(self
, line
, highlight
=False):
624 self
.editor
.GotoLine(line
)
625 self
.editor
.SetFocus()
627 self
.editor
.SelectLine(line
)
630 def UpdateControlState(self
):
631 active
= self
.demoModules
.GetActiveID()
632 # Update the radio/restore buttons
633 for moduleID
in self
.radioButtons
:
634 btn
= self
.radioButtons
[moduleID
]
635 if moduleID
== active
:
640 if self
.demoModules
.Exists(moduleID
):
642 if moduleID
== modModified
:
643 self
.btnRestore
.Enable(True)
646 if moduleID
== modModified
:
647 self
.btnRestore
.Enable(False)
650 def OnRadioButton(self
, event
):
651 radioSelected
= event
.GetEventObject()
652 modSelected
= radioSelected
.modID
653 if modSelected
!= self
.demoModules
.GetActiveID():
654 busy
= wx
.BusyInfo("Reloading demo module...")
655 self
.demoModules
.SetActive(modSelected
)
656 self
.ActiveModuleChanged()
659 def ReloadDemo(self
):
660 if self
.demoModules
.name
!= __name__
:
661 self
.mainFrame
.RunModule()
664 def OnCodeModified(self
, event
):
665 self
.btnSave
.Enable(self
.editor
.IsModified())
668 def OnSave(self
, event
):
669 if self
.demoModules
.Exists(modModified
):
670 if self
.demoModules
.GetActiveID() == modOriginal
:
671 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
672 "Do you want to continue?"
673 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
674 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
675 result
= dlg
.ShowModal()
676 if result
== wx
.ID_NO
:
680 self
.demoModules
.SetActive(modModified
)
681 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
683 # Create the demo directory if one doesn't already exist
684 if not os
.path
.exists(GetModifiedDirectory()):
686 os
.makedirs(GetModifiedDirectory())
687 if not os
.path
.exists(GetModifiedDirectory()):
688 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
691 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
694 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
697 f
= open(modifiedFilename
, "wt")
698 source
= self
.editor
.GetText()
704 busy
= wx
.BusyInfo("Reloading demo module...")
705 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
706 self
.ActiveModuleChanged()
709 def OnRestore(self
, event
): # Handles the "Delete Modified" button
710 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
711 self
.demoModules
.Delete(modModified
)
712 os
.unlink(modifiedFilename
) # Delete the modified copy
713 busy
= wx
.BusyInfo("Reloading demo module...")
714 self
.ActiveModuleChanged()
717 #---------------------------------------------------------------------------
720 """Convert paths to the platform-specific separator"""
721 str = apply(os
.path
.join
, tuple(path
.split('/')))
722 # HACK: on Linux, a leading / gets lost...
723 if path
.startswith('/'):
728 def GetModifiedDirectory():
730 Returns the directory where modified versions of the demo files
733 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
736 def GetModifiedFilename(name
):
738 Returns the filename of the modified version of the specified demo
740 if not name
.endswith(".py"):
742 return GetModifiedDirectory() + name
745 def GetOriginalFilename(name
):
747 Returns the filename of the original version of the specified demo
749 if not name
.endswith(".py"):
754 def DoesModifiedExist(name
):
755 """Returns whether the specified demo has a modified copy"""
756 if os
.path
.exists(GetModifiedFilename(name
)):
762 #---------------------------------------------------------------------------
764 class ModuleDictWrapper
:
765 """Emulates a module with a dynamically compiled __dict__"""
766 def __init__(self
, dict):
769 def __getattr__(self
, name
):
770 if name
in self
.dict:
771 return self
.dict[name
]
777 Dynamically manages the original/modified versions of a demo
780 def __init__(self
, name
):
784 # (dict , source , filename , description , error information )
785 # ( 0 , 1 , 2 , 3 , 4 )
786 self
.modules
= [[None, "" , "" , "<original>" , None],
787 [None, "" , "" , "<modified>" , None]]
789 # load original module
790 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
791 self
.SetActive(modOriginal
)
793 # load modified module (if one exists)
794 if DoesModifiedExist(name
):
795 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
798 def LoadFromFile(self
, modID
, filename
):
799 self
.modules
[modID
][2] = filename
800 file = open(filename
, "rt")
801 self
.LoadFromSource(modID
, file.read())
805 def LoadFromSource(self
, modID
, source
):
806 self
.modules
[modID
][1] = source
810 def LoadDict(self
, modID
):
811 if self
.name
!= __name__
:
812 source
= self
.modules
[modID
][1]
813 #description = self.modules[modID][3]
814 description
= self
.modules
[modID
][2]
817 self
.modules
[modID
][0] = {}
818 code
= compile(source
, description
, "exec")
819 exec code
in self
.modules
[modID
][0]
821 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
822 self
.modules
[modID
][0] = None
824 self
.modules
[modID
][4] = None
827 def SetActive(self
, modID
):
828 if modID
!= modOriginal
and modID
!= modModified
:
831 self
.modActive
= modID
835 dict = self
.modules
[self
.modActive
][0]
839 return ModuleDictWrapper(dict)
842 def GetActiveID(self
):
843 return self
.modActive
846 def GetSource(self
, modID
= None):
848 modID
= self
.modActive
849 return self
.modules
[modID
][1]
852 def GetFilename(self
, modID
= None):
854 modID
= self
.modActive
855 return self
.modules
[self
.modActive
][2]
858 def GetErrorInfo(self
, modID
= None):
860 modID
= self
.modActive
861 return self
.modules
[self
.modActive
][4]
864 def Exists(self
, modID
):
865 return self
.modules
[modID
][1] != ""
868 def UpdateFile(self
, modID
= None):
869 """Updates the file from which a module was loaded
870 with (possibly updated) source"""
872 modID
= self
.modActive
874 source
= self
.modules
[modID
][1]
875 filename
= self
.modules
[modID
][2]
878 file = open(filename
, "wt")
884 def Delete(self
, modID
):
885 if self
.modActive
== modID
:
888 self
.modules
[modID
][0] = None
889 self
.modules
[modID
][1] = ""
890 self
.modules
[modID
][2] = ""
893 #---------------------------------------------------------------------------
896 """Wraps and stores information about the current exception"""
897 def __init__(self
, exc_info
):
900 excType
, excValue
= exc_info
[:2]
901 # traceback list entries: (filename, line number, function name, text)
902 self
.traceback
= traceback
.extract_tb(exc_info
[2])
904 # --Based on traceback.py::format_exception_only()--
905 if type(excType
) == types
.ClassType
:
906 self
.exception_type
= excType
.__name
__
908 self
.exception_type
= excType
910 # If it's a syntax error, extra information needs
911 # to be added to the traceback
912 if excType
is SyntaxError:
914 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
919 filename
= "<string>"
921 self
.traceback
.append( (filename
, lineno
, "", line
) )
924 self
.exception_details
= str(excValue
)
926 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
933 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
936 #---------------------------------------------------------------------------
938 class DemoErrorPanel(wx
.Panel
):
939 """Panel put into the demo tab when the demo fails to run due to errors"""
941 def __init__(self
, parent
, codePanel
, demoError
, log
):
942 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
943 self
.codePanel
= codePanel
947 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
950 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
951 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
953 # Exception Information
954 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
955 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
956 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
957 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
958 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
959 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
960 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
961 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
962 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
963 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
965 # Set up the traceback list
966 # This one automatically resizes last column to take up remaining space
967 from ListCtrl
import TestListCtrl
968 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
969 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
970 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
971 self
.list.InsertColumn(0, "Filename")
972 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
973 self
.list.InsertColumn(2, "Function")
974 self
.list.InsertColumn(3, "Code")
975 self
.InsertTraceback(self
.list, demoError
.traceback
)
976 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
977 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
978 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
979 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
980 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
981 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
982 + "Double-click on them to go to the offending line")
983 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
986 self
.SetSizer(self
.box
)
989 def InsertTraceback(self
, list, traceback
):
990 #Add the traceback data
991 for x
in range(len(traceback
)):
993 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
994 list.SetStringItem(x
, 1, str(data
[1])) # Line
995 list.SetStringItem(x
, 2, str(data
[2])) # Function
996 list.SetStringItem(x
, 3, str(data
[3])) # Code
998 # Check whether this entry is from the demo module
999 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1000 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1001 # Give it a blue colour
1002 item
= self
.list.GetItem(x
)
1003 item
.SetTextColour(wx
.BLUE
)
1004 self
.list.SetItem(item
)
1006 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1009 def OnItemSelected(self
, event
):
1010 # This occurs before OnDoubleClick and can be used to set the
1011 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1012 self
.currentItem
= event
.m_itemIndex
1016 def OnDoubleClick(self
, event
):
1017 # If double-clicking on a demo's entry, jump to the line number
1018 line
= self
.list.GetItemData(self
.currentItem
)
1020 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1021 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1025 #---------------------------------------------------------------------------
1027 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1028 TBMENU_RESTORE
= wx
.NewId()
1029 TBMENU_CLOSE
= wx
.NewId()
1030 TBMENU_CHANGE
= wx
.NewId()
1031 TBMENU_REMOVE
= wx
.NewId()
1033 def __init__(self
, frame
):
1034 wx
.TaskBarIcon
.__init
__(self
)
1038 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1039 self
.SetIcon(icon
, "wxPython Demo")
1043 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1044 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1045 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1046 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1047 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1050 def CreatePopupMenu(self
):
1052 This method is called by the base class when it needs to popup
1053 the menu for the default EVT_RIGHT_DOWN event. Just create
1054 the menu how you want it and return it from this function,
1055 the base class takes care of the rest.
1058 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1059 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1060 menu
.AppendSeparator()
1061 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1062 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1066 def MakeIcon(self
, img
):
1068 The various platforms have different requirements for the
1071 if "wxMSW" in wx
.PlatformInfo
:
1072 img
= img
.Scale(16, 16)
1073 elif "wxGTK" in wx
.PlatformInfo
:
1074 img
= img
.Scale(22, 22)
1075 # wxMac can be any size upto 128x128, so leave the source img alone....
1076 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1080 def OnTaskBarActivate(self
, evt
):
1081 if self
.frame
.IsIconized():
1082 self
.frame
.Iconize(False)
1083 if not self
.frame
.IsShown():
1084 self
.frame
.Show(True)
1088 def OnTaskBarClose(self
, evt
):
1092 def OnTaskBarChange(self
, evt
):
1093 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1094 name
= names
[self
.imgidx
]
1096 getFunc
= getattr(images
, "get%sImage" % name
)
1098 if self
.imgidx
>= len(names
):
1101 icon
= self
.MakeIcon(getFunc())
1102 self
.SetIcon(icon
, "This is a new icon: " + name
)
1105 def OnTaskBarRemove(self
, evt
):
1109 #---------------------------------------------------------------------------
1110 class wxPythonDemo(wx
.Frame
):
1111 overviewText
= "wxPython Overview"
1113 def __init__(self
, parent
, title
):
1114 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1115 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1117 self
.SetMinSize((640,480))
1120 self
.cwd
= os
.getcwd()
1121 self
.curOverview
= ""
1122 self
.demoPage
= None
1123 self
.codePage
= None
1125 self
.firstTime
= True
1128 icon
= images
.getWXPdemoIcon()
1131 self
.tbicon
= DemoTaskBarIcon(self
)
1133 wx
.CallAfter(self
.ShowTip
)
1135 self
.otherWin
= None
1136 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1137 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1138 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1139 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1141 self
.Centre(wx
.BOTH
)
1142 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1144 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1145 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1147 def EmptyHandler(evt
): pass
1148 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1149 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1151 # Prevent TreeCtrl from displaying all items after destruction when True
1155 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1158 self
.mainmenu
= wx
.MenuBar()
1160 item
= menu
.Append(-1, '&Redirect Output',
1161 'Redirect print statements to a window',
1163 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1165 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1166 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1167 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1168 self
.mainmenu
.Append(menu
, '&File')
1172 for item
in _treeList
:
1174 for childItem
in item
[1]:
1175 mi
= submenu
.Append(-1, childItem
)
1176 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1177 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1178 self
.mainmenu
.Append(menu
, '&Demo')
1183 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1184 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1185 menu
.AppendSeparator()
1187 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1188 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1189 menu
.AppendSeparator()
1190 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1191 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1193 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1194 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1195 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1196 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1197 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1198 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1199 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1200 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1201 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1202 self
.mainmenu
.Append(menu
, '&Help')
1203 self
.SetMenuBar(self
.mainmenu
)
1205 self
.finddata
= wx
.FindReplaceData()
1206 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1209 # This is another way to set Accelerators, in addition to
1210 # using the '\t<key>' syntax in the menu items.
1211 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1212 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1213 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1214 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1216 self
.SetAcceleratorTable(aTable
)
1222 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1223 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1226 root
= self
.tree
.AddRoot("wxPython Overview")
1228 for item
in _treeList
:
1229 child
= self
.tree
.AppendItem(root
, item
[0])
1230 if not firstChild
: firstChild
= child
1231 for childItem
in item
[1]:
1232 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1233 self
.treeMap
[childItem
] = theDemo
1235 self
.tree
.Expand(root
)
1236 self
.tree
.Expand(firstChild
)
1237 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1238 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1239 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1240 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1242 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1243 # we put it in a panel first because there seems to be a
1244 # refresh bug of some sort (wxGTK) when it is directly in
1247 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1248 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1250 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1251 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1252 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1253 self
.nb
.AddPage(panel
, self
.overviewText
)
1255 def OnOvrSize(evt
, ovr
=self
.ovr
):
1256 ovr
.SetSize(evt
.GetSize())
1257 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1258 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1260 if "gtk2" in wx
.PlatformInfo
:
1261 self
.ovr
.SetStandardFonts()
1262 self
.SetOverview(self
.overviewText
, mainOverview
)
1265 # Set up a log window
1266 self
.log
= wx
.TextCtrl(splitter2
, -1,
1267 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1269 # Set the wxWindows log target to be this textctrl
1270 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1272 # But instead of the above we want to show how to use our own wx.Log class
1273 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1275 # for serious debugging
1276 #wx.Log_SetActiveTarget(wx.LogStderr())
1277 #wx.Log_SetTraceMask(wx.TraceMessages)
1280 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1281 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1283 # add the windows to the splitter and split it.
1284 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1285 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1287 splitter
.SetMinimumPaneSize(120)
1288 splitter2
.SetMinimumPaneSize(60)
1290 # Make the splitter on the right expand the top window when resized
1291 def SplitterOnSize(evt
):
1292 splitter
= evt
.GetEventObject()
1293 sz
= splitter
.GetSize()
1294 splitter
.SetSashPosition(sz
.height
- 160, False)
1297 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1299 # select initial items
1300 self
.nb
.SetSelection(0)
1301 self
.tree
.SelectItem(root
)
1303 # Load 'Main' module
1304 self
.LoadDemo(self
.overviewText
)
1307 # select some other initial module?
1308 if len(sys
.argv
) > 1:
1310 if arg
.endswith('.py'):
1312 selectedDemo
= self
.treeMap
.get(arg
, None)
1314 self
.tree
.SelectItem(selectedDemo
)
1315 self
.tree
.EnsureVisible(selectedDemo
)
1318 #---------------------------------------------
1319 def WriteText(self
, text
):
1320 if text
[-1:] == '\n':
1324 def write(self
, txt
):
1327 #---------------------------------------------
1328 def OnItemExpanded(self
, event
):
1329 item
= event
.GetItem()
1330 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1333 #---------------------------------------------
1334 def OnItemCollapsed(self
, event
):
1335 item
= event
.GetItem()
1336 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1339 #---------------------------------------------
1340 def OnTreeLeftDown(self
, event
):
1341 # reset the overview text if the tree item is clicked on again
1342 pt
= event
.GetPosition();
1343 item
, flags
= self
.tree
.HitTest(pt
)
1344 if item
== self
.tree
.GetSelection():
1345 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1348 #---------------------------------------------
1349 def OnSelChanged(self
, event
):
1350 if self
.dying
or not self
.loaded
:
1353 item
= event
.GetItem()
1354 itemText
= self
.tree
.GetItemText(item
)
1355 self
.LoadDemo(itemText
)
1357 #---------------------------------------------
1358 def LoadDemo(self
, demoName
):
1360 wx
.BeginBusyCursor()
1363 self
.ShutdownDemoModule()
1365 if demoName
== self
.overviewText
:
1366 # User selected the "wxPython Overview" node
1368 # Changing the main window at runtime not yet supported...
1369 self
.demoModules
= DemoModules(__name__
)
1370 self
.SetOverview(self
.overviewText
, mainOverview
)
1371 self
.LoadDemoSource()
1372 self
.UpdateNotebook(0)
1374 if os
.path
.exists(GetOriginalFilename(demoName
)):
1375 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1376 self
.demoModules
= DemoModules(demoName
)
1377 self
.LoadDemoSource()
1380 self
.SetOverview("wxPython", mainOverview
)
1381 self
.codePage
= None
1382 self
.UpdateNotebook(0)
1386 #---------------------------------------------
1387 def LoadDemoSource(self
):
1388 self
.codePage
= None
1389 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1390 self
.codePage
.LoadDemo(self
.demoModules
)
1392 #---------------------------------------------
1393 def RunModule(self
):
1394 """Runs the active module"""
1396 module
= self
.demoModules
.GetActive()
1397 self
.ShutdownDemoModule()
1400 # o The RunTest() for all samples must now return a window that can
1401 # be palced in a tab in the main notebook.
1402 # o If an error occurs (or has occurred before) an error tab is created.
1404 if module
is not None:
1405 wx
.LogMessage("Running demo module...")
1406 if hasattr(module
, "overview"):
1407 overviewText
= module
.overview
1410 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1412 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1413 DemoError(sys
.exc_info()), self
)
1415 assert self
.demoPage
is not None, "runTest must return a window!"
1418 # There was a previous error in compiling or exec-ing
1419 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1420 self
.demoModules
.GetErrorInfo(), self
)
1422 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1425 # cahnge to the demo page the first time a module is run
1426 self
.UpdateNotebook(2)
1427 self
.firstTime
= False
1429 # otherwise just stay on the same tab in case the user has changed to another one
1430 self
.UpdateNotebook()
1432 #---------------------------------------------
1433 def ShutdownDemoModule(self
):
1435 # inform the window that it's time to quit if it cares
1436 if hasattr(self
.demoPage
, "ShutdownDemo"):
1437 self
.demoPage
.ShutdownDemo()
1438 wx
.YieldIfNeeded() # in case the page has pending events
1439 self
.demoPage
= None
1441 #---------------------------------------------
1442 def UpdateNotebook(self
, select
= -1):
1446 def UpdatePage(page
, pageText
):
1449 for i
in range(nb
.GetPageCount()):
1450 if nb
.GetPageText(i
) == pageText
:
1458 nb
.AddPage(page
, pageText
)
1459 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1461 if nb
.GetPage(pagePos
) != page
:
1462 # Reload an existing page
1464 nb
.DeletePage(pagePos
)
1465 nb
.InsertPage(pagePos
, page
, pageText
)
1467 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1469 # Excellent! No redraw/flicker
1470 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1473 nb
.DeletePage(pagePos
)
1474 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1476 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1479 select
= nb
.GetSelection()
1481 UpdatePage(self
.codePage
, "Demo Code")
1482 UpdatePage(self
.demoPage
, "Demo")
1484 if select
>= 0 and select
< nb
.GetPageCount():
1485 nb
.SetSelection(select
)
1487 #---------------------------------------------
1488 def SetOverview(self
, name
, text
):
1489 self
.curOverview
= text
1491 if lead
!= '<html>' and lead
!= '<HTML>':
1492 text
= '<br>'.join(text
.split('\n'))
1494 text
= text
.decode('iso8859_1')
1495 self
.ovr
.SetPage(text
)
1496 self
.nb
.SetPageText(0, name
)
1498 #---------------------------------------------
1500 def OnFileExit(self
, *event
):
1503 def OnToggleRedirect(self
, event
):
1507 print "Print statements and other standard output will now be directed to this window."
1510 print "Print statements and other standard output will now be sent to the usual location."
1512 def OnHelpAbout(self
, event
):
1513 from About
import MyAboutBox
1514 about
= MyAboutBox(self
)
1518 def OnHelpFind(self
, event
):
1519 if self
.finddlg
!= None:
1522 self
.nb
.SetSelection(1)
1523 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1524 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1525 self
.finddlg
.Show(True)
1528 def OnUpdateFindItems(self
, evt
):
1529 evt
.Enable(self
.finddlg
== None)
1532 def OnFind(self
, event
):
1533 editor
= self
.codePage
.editor
1534 self
.nb
.SetSelection(1)
1535 end
= editor
.GetLastPosition()
1536 textstring
= editor
.GetRange(0, end
).lower()
1537 findstring
= self
.finddata
.GetFindString().lower()
1538 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1540 start
= editor
.GetSelection()[0]
1541 loc
= textstring
.rfind(findstring
, 0, start
)
1543 start
= editor
.GetSelection()[1]
1544 loc
= textstring
.find(findstring
, start
)
1545 if loc
== -1 and start
!= 0:
1546 # string not found, start at beginning
1549 loc
= textstring
.rfind(findstring
, 0, start
)
1552 loc
= textstring
.find(findstring
, start
)
1554 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1555 'Find String Not Found in Demo File',
1556 wx
.OK | wx
.ICON_INFORMATION
)
1561 self
.finddlg
.SetFocus()
1564 self
.finddlg
.Destroy()
1566 editor
.ShowPosition(loc
)
1567 editor
.SetSelection(loc
, loc
+ len(findstring
))
1571 def OnFindNext(self
, event
):
1572 if self
.finddata
.GetFindString():
1575 self
.OnHelpFind(event
)
1577 def OnFindClose(self
, event
):
1578 event
.GetDialog().Destroy()
1582 def OnOpenShellWindow(self
, evt
):
1584 # if it already exists then just make sure it's visible
1590 # Make a PyShell window
1592 namespace
= { 'wx' : wx
,
1593 'app' : wx
.GetApp(),
1596 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1597 self
.shell
.SetSize((640,480))
1600 # Hook the close event of the main frame window so that we
1601 # close the shell at the same time if it still exists
1602 def CloseShell(evt
):
1606 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1609 #---------------------------------------------
1610 def OnCloseWindow(self
, event
):
1612 self
.demoPage
= None
1613 self
.codePage
= None
1614 self
.mainmenu
= None
1615 self
.tbicon
.Destroy()
1619 #---------------------------------------------
1620 def OnIdle(self
, event
):
1622 self
.otherWin
.Raise()
1623 self
.demoPage
= self
.otherWin
1624 self
.otherWin
= None
1627 #---------------------------------------------
1630 showTipText
= open(opj("data/showTips")).read()
1631 showTip
, index
= eval(showTipText
)
1633 showTip
, index
= (1, 0)
1635 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1637 showTip
= wx
.ShowTip(self
, tp
)
1638 index
= tp
.GetCurrentTip()
1639 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1642 #---------------------------------------------
1643 def OnDemoMenu(self
, event
):
1645 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1649 self
.tree
.SelectItem(selectedDemo
)
1650 self
.tree
.EnsureVisible(selectedDemo
)
1654 #---------------------------------------------
1655 def OnIconfiy(self
, evt
):
1656 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1659 #---------------------------------------------
1660 def OnMaximize(self
, evt
):
1661 wx
.LogMessage("OnMaximize")
1664 #---------------------------------------------
1665 def OnActivate(self
, evt
):
1666 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1669 #---------------------------------------------
1670 def OnAppActivate(self
, evt
):
1671 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1674 #---------------------------------------------------------------------------
1675 #---------------------------------------------------------------------------
1677 class MySplashScreen(wx
.SplashScreen
):
1679 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1680 wx
.SplashScreen
.__init
__(self
, bmp
,
1681 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1683 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1684 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1687 def OnClose(self
, evt
):
1688 # Make sure the default handler runs too so this window gets
1693 # if the timer is still running then go ahead and show the
1695 if self
.fc
.IsRunning():
1701 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1703 if self
.fc
.IsRunning():
1707 class MyApp(wx
.App
):
1710 Create and show the splash screen. It will then create and show
1711 the main frame when it is time to do so.
1714 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1717 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1719 # Normally when using a SplashScreen you would create it, show
1720 # it and then continue on with the applicaiton's
1721 # initialization, finally creating and showing the main
1722 # application window(s). In this case we have nothing else to
1723 # do so we'll delay showing the main frame until later (see
1724 # ShowMain above) so the users can see the SplashScreen effect.
1725 splash
= MySplashScreen()
1732 #---------------------------------------------------------------------------
1736 demoPath
= os
.path
.dirname(__file__
)
1743 #---------------------------------------------------------------------------
1746 mainOverview
= """<html><body>
1749 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1750 language. It allows Python programmers to create programs with a
1751 robust, highly functional graphical user interface, simply and easily.
1752 It is implemented as a Python extension module (native code) that
1753 wraps the popular wxWindows cross platform GUI library, which is
1756 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1757 means that it is free for anyone to use and the source code is
1758 available for anyone to look at and modify. Or anyone can contribute
1759 fixes or enhancements to the project.
1761 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1762 same program will run on multiple platforms without modification.
1763 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1764 or unix-like systems, and Macintosh OS X. Since the language is
1765 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1768 <p> <b>This demo</b> is not only a collection of test cases for
1769 wxPython, but is also designed to help you learn about and how to use
1770 wxPython. Each sample is listed in the tree control on the left.
1771 When a sample is selected in the tree then a module is loaded and run
1772 (usually in a tab of this notebook,) and the source code of the module
1773 is loaded in another tab for you to browse and learn from.
1778 #----------------------------------------------------------------------------
1779 #----------------------------------------------------------------------------
1781 if __name__
== '__main__':
1785 #----------------------------------------------------------------------------