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', [
60 # managed windows == things with a (optional) caption you can close
61 ('Frames and Dialogs', [
86 # dialogs from libraries
89 'ScrolledMessageDialog',
93 ('Core Windows/Controls', [
130 ('"Book" Controls', [
138 ('Custom Controls', [
151 # controls coming from other libraries
152 ('More Windows/Controls', [
153 'ActiveX_FlashWindow',
154 'ActiveX_IEHtmlWindow',
156 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
159 'CheckListCtrlMixin',
174 'MaskedEditControls',
177 'MultiSplitterWindow',
194 # How to lay out the controls in a frame/dialog
204 'XmlResourceHandler',
205 'XmlResourceSubclass',
209 ('Process and Events', [
216 ##'infoframe', # needs better explanation and some fixing
220 ('Clipboard and DnD', [
242 ##'DialogUnits', # needs more explanations
260 ('Check out the samples dir too', [
267 #---------------------------------------------------------------------------
268 # Show how to derive a custom wxLog class
270 class MyLog(wx
.PyLog
):
271 def __init__(self
, textCtrl
, logTime
=0):
272 wx
.PyLog
.__init
__(self
)
274 self
.logTime
= logTime
276 def DoLogString(self
, message
, timeStamp
):
277 #print message, timeStamp
279 # message = time.strftime("%X", time.localtime(timeStamp)) + \
282 self
.tc
.AppendText(message
+ '\n')
285 class MyTP(wx
.PyTipProvider
):
287 return "This is my tip"
289 #---------------------------------------------------------------------------
290 # A class to be used to simply display a message in the demo pane
291 # rather than running the sample itself.
293 class MessagePanel(wx
.Panel
):
294 def __init__(self
, parent
, message
, caption
='', flags
=0):
295 wx
.Panel
.__init
__(self
, parent
)
300 if flags
& wx
.ICON_EXCLAMATION
:
301 artid
= wx
.ART_WARNING
302 elif flags
& wx
.ICON_ERROR
:
304 elif flags
& wx
.ICON_QUESTION
:
305 artid
= wx
.ART_QUESTION
306 elif flags
& wx
.ICON_INFORMATION
:
307 artid
= wx
.ART_INFORMATION
309 if artid
is not None:
310 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
311 icon
= wx
.StaticBitmap(self
, -1, bmp
)
313 icon
= (32,32) # make a spacer instead
316 caption
= wx
.StaticText(self
, -1, caption
)
317 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
319 message
= wx
.StaticText(self
, -1, message
)
321 # add to sizers for layout
322 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
328 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
335 box
= wx
.BoxSizer(wx
.VERTICAL
)
337 box
.Add(hbox
, 0, wx
.EXPAND
)
344 #---------------------------------------------------------------------------
345 # A class to be used to display source code in the demo. Try using the
346 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
347 # if there is an error, such as the stc module not being present.
351 ##raise ImportError # for testing the alternate implementation
353 from StyledTextCtrl_2
import PythonSTC
355 class DemoCodeEditor(PythonSTC
):
356 def __init__(self
, parent
):
357 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
360 # Some methods to make it compatible with how the wxTextCtrl is used
361 def SetValue(self
, value
):
363 value
= value
.decode('iso8859_1')
365 self
.EmptyUndoBuffer()
368 def IsModified(self
):
369 return self
.GetModify()
374 def SetInsertionPoint(self
, pos
):
375 self
.SetCurrentPos(pos
)
378 def ShowPosition(self
, pos
):
379 line
= self
.LineFromPosition(pos
)
380 #self.EnsureVisible(line)
383 def GetLastPosition(self
):
384 return self
.GetLength()
386 def GetPositionFromLine(self
, line
):
387 return self
.PositionFromLine(line
)
389 def GetRange(self
, start
, end
):
390 return self
.GetTextRange(start
, end
)
392 def GetSelection(self
):
393 return self
.GetAnchor(), self
.GetCurrentPos()
395 def SetSelection(self
, start
, end
):
396 self
.SetSelectionStart(start
)
397 self
.SetSelectionEnd(end
)
399 def SelectLine(self
, line
):
400 start
= self
.PositionFromLine(line
)
401 end
= self
.GetLineEndPosition(line
)
402 self
.SetSelection(start
, end
)
404 def SetUpEditor(self
):
406 This method carries out the work of setting up the demo editor.
407 It's seperate so as not to clutter up the init code.
411 self
.SetLexer(stc
.STC_LEX_PYTHON
)
412 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
415 self
.SetProperty("fold", "1" )
417 # Highlight tab/space mixing (shouldn't be any)
418 self
.SetProperty("tab.timmy.whinge.level", "1")
420 # Set left and right margins
423 # Set up the numbers in the margin for margin #1
424 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
425 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
426 self
.SetMarginWidth(1, 40)
428 # Indentation and tab stuff
429 self
.SetIndent(4) # Proscribed indent size for wx
430 self
.SetIndentationGuides(True) # Show indent guides
431 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
432 self
.SetTabIndents(True) # Tab key indents
433 self
.SetTabWidth(4) # Proscribed tab size for wx
434 self
.SetUseTabs(False) # Use spaces rather than tabs, or
435 # TabTimmy will complain!
437 self
.SetViewWhiteSpace(False) # Don't view white space
439 # EOL: Since we are loading/saving ourselves, and the
440 # strings will always have \n's in them, set the STC to
441 # edit them that way.
442 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
443 self
.SetViewEOL(False)
445 # No right-edge mode indicator
446 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
448 # Setup a margin to hold fold markers
449 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
450 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
451 self
.SetMarginSensitive(2, True)
452 self
.SetMarginWidth(2, 12)
454 # and now set up the fold markers
455 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
456 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
457 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
458 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
459 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
460 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
461 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
463 # Global default style
464 if wx
.Platform
== '__WXMSW__':
465 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
466 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
468 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
469 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
471 # Clear styles and revert to default.
474 # Following style specs only indicate differences from default.
475 # The rest remains unchanged.
477 # Line numbers in margin
478 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
480 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
482 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
484 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
487 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
489 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
490 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
492 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
493 # Strings and characters
494 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
495 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
497 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
499 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
500 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
502 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
504 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
506 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
507 # Identifiers. I leave this as not bold because everything seems
508 # to be an identifier if it doesn't match the above criterae
509 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
512 self
.SetCaretForeground("BLUE")
513 # Selection background
514 self
.SetSelBackground(1, '#66CCFF')
516 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
517 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
519 def RegisterModifiedEvent(self
, eventHandler
):
520 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
524 class DemoCodeEditor(wx
.TextCtrl
):
525 def __init__(self
, parent
):
526 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
527 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
529 def RegisterModifiedEvent(self
, eventHandler
):
530 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
532 def SetReadOnly(self
, flag
):
533 self
.SetEditable(not flag
)
534 # NOTE: STC already has this method
537 return self
.GetValue()
539 def GetPositionFromLine(self
, line
):
540 return self
.XYToPosition(0,line
)
542 def GotoLine(self
, line
):
543 pos
= self
.GetPositionFromLine(line
)
544 self
.SetInsertionPoint(pos
)
545 self
.ShowPosition(pos
)
547 def SelectLine(self
, line
):
548 start
= self
.GetPositionFromLine(line
)
549 end
= start
+ self
.GetLineLength(line
)
550 self
.SetSelection(start
, end
)
553 #---------------------------------------------------------------------------
554 # Constants for module versions
558 modDefault
= modOriginal
560 #---------------------------------------------------------------------------
562 class DemoCodePanel(wx
.Panel
):
563 """Panel for the 'Demo Code' tab"""
564 def __init__(self
, parent
, mainFrame
):
565 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
566 if 'wxMSW' in wx
.PlatformInfo
:
568 self
.mainFrame
= mainFrame
569 self
.editor
= DemoCodeEditor(self
)
570 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
572 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
573 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
574 self
.btnSave
.Enable(False)
575 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
576 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
578 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
579 modModified
: wx
.RadioButton(self
, -1, "Modified") }
581 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
582 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
583 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
584 for modID
, radioButton
in self
.radioButtons
.items():
585 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
586 radioButton
.modID
= modID
# makes it easier for the event handler
587 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
589 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
590 self
.controlBox
.Add(self
.btnRestore
, 0)
592 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
593 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
594 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
595 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
598 self
.SetSizer(self
.box
)
601 # Loads a demo from a DemoModules object
602 def LoadDemo(self
, demoModules
):
603 self
.demoModules
= demoModules
604 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
605 demoModules
.SetActive(modModified
)
607 demoModules
.SetActive(modOriginal
)
608 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
609 self
.ActiveModuleChanged()
612 def ActiveModuleChanged(self
):
613 self
.LoadDemoSource(self
.demoModules
.GetSource())
614 self
.UpdateControlState()
618 def LoadDemoSource(self
, source
):
620 self
.editor
.SetValue(source
)
622 self
.btnSave
.Enable(False)
625 def JumpToLine(self
, line
, highlight
=False):
626 self
.editor
.GotoLine(line
)
627 self
.editor
.SetFocus()
629 self
.editor
.SelectLine(line
)
632 def UpdateControlState(self
):
633 active
= self
.demoModules
.GetActiveID()
634 # Update the radio/restore buttons
635 for moduleID
in self
.radioButtons
:
636 btn
= self
.radioButtons
[moduleID
]
637 if moduleID
== active
:
642 if self
.demoModules
.Exists(moduleID
):
644 if moduleID
== modModified
:
645 self
.btnRestore
.Enable(True)
648 if moduleID
== modModified
:
649 self
.btnRestore
.Enable(False)
652 def OnRadioButton(self
, event
):
653 radioSelected
= event
.GetEventObject()
654 modSelected
= radioSelected
.modID
655 if modSelected
!= self
.demoModules
.GetActiveID():
656 busy
= wx
.BusyInfo("Reloading demo module...")
657 self
.demoModules
.SetActive(modSelected
)
658 self
.ActiveModuleChanged()
661 def ReloadDemo(self
):
662 if self
.demoModules
.name
!= __name__
:
663 self
.mainFrame
.RunModule()
666 def OnCodeModified(self
, event
):
667 self
.btnSave
.Enable(self
.editor
.IsModified())
670 def OnSave(self
, event
):
671 if self
.demoModules
.Exists(modModified
):
672 if self
.demoModules
.GetActiveID() == modOriginal
:
673 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
674 "Do you want to continue?"
675 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
676 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
677 result
= dlg
.ShowModal()
678 if result
== wx
.ID_NO
:
682 self
.demoModules
.SetActive(modModified
)
683 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
685 # Create the demo directory if one doesn't already exist
686 if not os
.path
.exists(GetModifiedDirectory()):
688 os
.makedirs(GetModifiedDirectory())
689 if not os
.path
.exists(GetModifiedDirectory()):
690 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
693 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
696 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
699 f
= open(modifiedFilename
, "wt")
700 source
= self
.editor
.GetText()
706 busy
= wx
.BusyInfo("Reloading demo module...")
707 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
708 self
.ActiveModuleChanged()
711 def OnRestore(self
, event
): # Handles the "Delete Modified" button
712 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
713 self
.demoModules
.Delete(modModified
)
714 os
.unlink(modifiedFilename
) # Delete the modified copy
715 busy
= wx
.BusyInfo("Reloading demo module...")
716 self
.ActiveModuleChanged()
719 #---------------------------------------------------------------------------
722 """Convert paths to the platform-specific separator"""
723 str = apply(os
.path
.join
, tuple(path
.split('/')))
724 # HACK: on Linux, a leading / gets lost...
725 if path
.startswith('/'):
730 def GetModifiedDirectory():
732 Returns the directory where modified versions of the demo files
735 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
738 def GetModifiedFilename(name
):
740 Returns the filename of the modified version of the specified demo
742 if not name
.endswith(".py"):
744 return GetModifiedDirectory() + name
747 def GetOriginalFilename(name
):
749 Returns the filename of the original version of the specified demo
751 if not name
.endswith(".py"):
756 def DoesModifiedExist(name
):
757 """Returns whether the specified demo has a modified copy"""
758 if os
.path
.exists(GetModifiedFilename(name
)):
764 #---------------------------------------------------------------------------
766 class ModuleDictWrapper
:
767 """Emulates a module with a dynamically compiled __dict__"""
768 def __init__(self
, dict):
771 def __getattr__(self
, name
):
772 if name
in self
.dict:
773 return self
.dict[name
]
779 Dynamically manages the original/modified versions of a demo
782 def __init__(self
, name
):
786 # (dict , source , filename , description , error information )
787 # ( 0 , 1 , 2 , 3 , 4 )
788 self
.modules
= [[None, "" , "" , "<original>" , None],
789 [None, "" , "" , "<modified>" , None]]
791 # load original module
792 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
793 self
.SetActive(modOriginal
)
795 # load modified module (if one exists)
796 if DoesModifiedExist(name
):
797 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
800 def LoadFromFile(self
, modID
, filename
):
801 self
.modules
[modID
][2] = filename
802 file = open(filename
, "rt")
803 self
.LoadFromSource(modID
, file.read())
807 def LoadFromSource(self
, modID
, source
):
808 self
.modules
[modID
][1] = source
812 def LoadDict(self
, modID
):
813 if self
.name
!= __name__
:
814 source
= self
.modules
[modID
][1]
815 #description = self.modules[modID][3]
816 description
= self
.modules
[modID
][2]
819 self
.modules
[modID
][0] = {}
820 code
= compile(source
, description
, "exec")
821 exec code
in self
.modules
[modID
][0]
823 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
824 self
.modules
[modID
][0] = None
826 self
.modules
[modID
][4] = None
829 def SetActive(self
, modID
):
830 if modID
!= modOriginal
and modID
!= modModified
:
833 self
.modActive
= modID
837 dict = self
.modules
[self
.modActive
][0]
841 return ModuleDictWrapper(dict)
844 def GetActiveID(self
):
845 return self
.modActive
848 def GetSource(self
, modID
= None):
850 modID
= self
.modActive
851 return self
.modules
[modID
][1]
854 def GetFilename(self
, modID
= None):
856 modID
= self
.modActive
857 return self
.modules
[self
.modActive
][2]
860 def GetErrorInfo(self
, modID
= None):
862 modID
= self
.modActive
863 return self
.modules
[self
.modActive
][4]
866 def Exists(self
, modID
):
867 return self
.modules
[modID
][1] != ""
870 def UpdateFile(self
, modID
= None):
871 """Updates the file from which a module was loaded
872 with (possibly updated) source"""
874 modID
= self
.modActive
876 source
= self
.modules
[modID
][1]
877 filename
= self
.modules
[modID
][2]
880 file = open(filename
, "wt")
886 def Delete(self
, modID
):
887 if self
.modActive
== modID
:
890 self
.modules
[modID
][0] = None
891 self
.modules
[modID
][1] = ""
892 self
.modules
[modID
][2] = ""
895 #---------------------------------------------------------------------------
898 """Wraps and stores information about the current exception"""
899 def __init__(self
, exc_info
):
902 excType
, excValue
= exc_info
[:2]
903 # traceback list entries: (filename, line number, function name, text)
904 self
.traceback
= traceback
.extract_tb(exc_info
[2])
906 # --Based on traceback.py::format_exception_only()--
907 if type(excType
) == types
.ClassType
:
908 self
.exception_type
= excType
.__name
__
910 self
.exception_type
= excType
912 # If it's a syntax error, extra information needs
913 # to be added to the traceback
914 if excType
is SyntaxError:
916 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
921 filename
= "<string>"
923 self
.traceback
.append( (filename
, lineno
, "", line
) )
926 self
.exception_details
= str(excValue
)
928 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
935 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
938 #---------------------------------------------------------------------------
940 class DemoErrorPanel(wx
.Panel
):
941 """Panel put into the demo tab when the demo fails to run due to errors"""
943 def __init__(self
, parent
, codePanel
, demoError
, log
):
944 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
945 self
.codePanel
= codePanel
949 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
952 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
953 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
955 # Exception Information
956 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
957 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
958 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
959 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
960 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
961 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
962 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
963 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
964 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
965 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
967 # Set up the traceback list
968 # This one automatically resizes last column to take up remaining space
969 from ListCtrl
import TestListCtrl
970 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
971 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
972 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
973 self
.list.InsertColumn(0, "Filename")
974 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
975 self
.list.InsertColumn(2, "Function")
976 self
.list.InsertColumn(3, "Code")
977 self
.InsertTraceback(self
.list, demoError
.traceback
)
978 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
979 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
980 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
981 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
982 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
983 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
984 + "Double-click on them to go to the offending line")
985 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
988 self
.SetSizer(self
.box
)
991 def InsertTraceback(self
, list, traceback
):
992 #Add the traceback data
993 for x
in range(len(traceback
)):
995 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
996 list.SetStringItem(x
, 1, str(data
[1])) # Line
997 list.SetStringItem(x
, 2, str(data
[2])) # Function
998 list.SetStringItem(x
, 3, str(data
[3])) # Code
1000 # Check whether this entry is from the demo module
1001 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
1002 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
1003 # Give it a blue colour
1004 item
= self
.list.GetItem(x
)
1005 item
.SetTextColour(wx
.BLUE
)
1006 self
.list.SetItem(item
)
1008 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1011 def OnItemSelected(self
, event
):
1012 # This occurs before OnDoubleClick and can be used to set the
1013 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1014 self
.currentItem
= event
.m_itemIndex
1018 def OnDoubleClick(self
, event
):
1019 # If double-clicking on a demo's entry, jump to the line number
1020 line
= self
.list.GetItemData(self
.currentItem
)
1022 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1023 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1027 #---------------------------------------------------------------------------
1029 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1030 TBMENU_RESTORE
= wx
.NewId()
1031 TBMENU_CLOSE
= wx
.NewId()
1032 TBMENU_CHANGE
= wx
.NewId()
1033 TBMENU_REMOVE
= wx
.NewId()
1035 def __init__(self
, frame
):
1036 wx
.TaskBarIcon
.__init
__(self
)
1040 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1041 self
.SetIcon(icon
, "wxPython Demo")
1045 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1046 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1047 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1048 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1049 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1052 def CreatePopupMenu(self
):
1054 This method is called by the base class when it needs to popup
1055 the menu for the default EVT_RIGHT_DOWN event. Just create
1056 the menu how you want it and return it from this function,
1057 the base class takes care of the rest.
1060 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1061 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1062 menu
.AppendSeparator()
1063 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1064 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1068 def MakeIcon(self
, img
):
1070 The various platforms have different requirements for the
1073 if "wxMSW" in wx
.PlatformInfo
:
1074 img
= img
.Scale(16, 16)
1075 elif "wxGTK" in wx
.PlatformInfo
:
1076 img
= img
.Scale(22, 22)
1077 # wxMac can be any size upto 128x128, so leave the source img alone....
1078 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1082 def OnTaskBarActivate(self
, evt
):
1083 if self
.frame
.IsIconized():
1084 self
.frame
.Iconize(False)
1085 if not self
.frame
.IsShown():
1086 self
.frame
.Show(True)
1090 def OnTaskBarClose(self
, evt
):
1094 def OnTaskBarChange(self
, evt
):
1095 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1096 name
= names
[self
.imgidx
]
1098 getFunc
= getattr(images
, "get%sImage" % name
)
1100 if self
.imgidx
>= len(names
):
1103 icon
= self
.MakeIcon(getFunc())
1104 self
.SetIcon(icon
, "This is a new icon: " + name
)
1107 def OnTaskBarRemove(self
, evt
):
1111 #---------------------------------------------------------------------------
1112 class wxPythonDemo(wx
.Frame
):
1113 overviewText
= "wxPython Overview"
1115 def __init__(self
, parent
, title
):
1116 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1117 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1119 self
.SetMinSize((640,480))
1122 self
.cwd
= os
.getcwd()
1123 self
.curOverview
= ""
1124 self
.demoPage
= None
1125 self
.codePage
= None
1127 self
.firstTime
= True
1130 icon
= images
.getWXPdemoIcon()
1133 self
.tbicon
= DemoTaskBarIcon(self
)
1135 wx
.CallAfter(self
.ShowTip
)
1137 self
.otherWin
= None
1138 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1139 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1140 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1141 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1143 self
.Centre(wx
.BOTH
)
1144 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1146 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1147 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1149 def EmptyHandler(evt
): pass
1150 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1151 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1153 # Prevent TreeCtrl from displaying all items after destruction when True
1157 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1160 self
.mainmenu
= wx
.MenuBar()
1162 item
= menu
.Append(-1, '&Redirect Output',
1163 'Redirect print statements to a window',
1165 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1167 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1168 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1169 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1170 self
.mainmenu
.Append(menu
, '&File')
1174 for item
in _treeList
:
1176 for childItem
in item
[1]:
1177 mi
= submenu
.Append(-1, childItem
)
1178 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1179 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1180 self
.mainmenu
.Append(menu
, '&Demo')
1185 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1186 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1187 menu
.AppendSeparator()
1189 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1190 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1191 menu
.AppendSeparator()
1192 helpItem
= menu
.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
1193 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1195 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1196 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1197 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1198 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1199 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1200 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1201 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1202 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1203 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1204 self
.mainmenu
.Append(menu
, '&Help')
1205 self
.SetMenuBar(self
.mainmenu
)
1207 self
.finddata
= wx
.FindReplaceData()
1208 self
.finddata
.SetFlags(wx
.FR_DOWN
)
1211 # This is another way to set Accelerators, in addition to
1212 # using the '\t<key>' syntax in the menu items.
1213 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1214 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1215 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1216 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1218 self
.SetAcceleratorTable(aTable
)
1224 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1225 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1228 root
= self
.tree
.AddRoot("wxPython Overview")
1230 for item
in _treeList
:
1231 child
= self
.tree
.AppendItem(root
, item
[0])
1232 if not firstChild
: firstChild
= child
1233 for childItem
in item
[1]:
1234 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1235 self
.treeMap
[childItem
] = theDemo
1237 self
.tree
.Expand(root
)
1238 self
.tree
.Expand(firstChild
)
1239 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1240 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1241 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1242 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1244 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1245 # we put it in a panel first because there seems to be a
1246 # refresh bug of some sort (wxGTK) when it is directly in
1249 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1250 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1252 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1253 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1254 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1255 self
.nb
.AddPage(panel
, self
.overviewText
)
1257 def OnOvrSize(evt
, ovr
=self
.ovr
):
1258 ovr
.SetSize(evt
.GetSize())
1259 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1260 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1262 if "gtk2" in wx
.PlatformInfo
:
1263 self
.ovr
.SetStandardFonts()
1264 self
.SetOverview(self
.overviewText
, mainOverview
)
1267 # Set up a log window
1268 self
.log
= wx
.TextCtrl(splitter2
, -1,
1269 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1271 # Set the wxWindows log target to be this textctrl
1272 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1274 # But instead of the above we want to show how to use our own wx.Log class
1275 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1277 # for serious debugging
1278 #wx.Log_SetActiveTarget(wx.LogStderr())
1279 #wx.Log_SetTraceMask(wx.TraceMessages)
1282 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1283 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1285 # add the windows to the splitter and split it.
1286 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1287 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1289 splitter
.SetMinimumPaneSize(120)
1290 splitter2
.SetMinimumPaneSize(60)
1292 # Make the splitter on the right expand the top window when resized
1293 def SplitterOnSize(evt
):
1294 splitter
= evt
.GetEventObject()
1295 sz
= splitter
.GetSize()
1296 splitter
.SetSashPosition(sz
.height
- 160, False)
1299 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1301 # select initial items
1302 self
.nb
.SetSelection(0)
1303 self
.tree
.SelectItem(root
)
1305 # Load 'Main' module
1306 self
.LoadDemo(self
.overviewText
)
1309 # select some other initial module?
1310 if len(sys
.argv
) > 1:
1312 if arg
.endswith('.py'):
1314 selectedDemo
= self
.treeMap
.get(arg
, None)
1316 self
.tree
.SelectItem(selectedDemo
)
1317 self
.tree
.EnsureVisible(selectedDemo
)
1320 #---------------------------------------------
1321 def WriteText(self
, text
):
1322 if text
[-1:] == '\n':
1326 def write(self
, txt
):
1329 #---------------------------------------------
1330 def OnItemExpanded(self
, event
):
1331 item
= event
.GetItem()
1332 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1335 #---------------------------------------------
1336 def OnItemCollapsed(self
, event
):
1337 item
= event
.GetItem()
1338 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1341 #---------------------------------------------
1342 def OnTreeLeftDown(self
, event
):
1343 # reset the overview text if the tree item is clicked on again
1344 pt
= event
.GetPosition();
1345 item
, flags
= self
.tree
.HitTest(pt
)
1346 if item
== self
.tree
.GetSelection():
1347 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1350 #---------------------------------------------
1351 def OnSelChanged(self
, event
):
1352 if self
.dying
or not self
.loaded
:
1355 item
= event
.GetItem()
1356 itemText
= self
.tree
.GetItemText(item
)
1357 self
.LoadDemo(itemText
)
1359 #---------------------------------------------
1360 def LoadDemo(self
, demoName
):
1362 wx
.BeginBusyCursor()
1365 self
.ShutdownDemoModule()
1367 if demoName
== self
.overviewText
:
1368 # User selected the "wxPython Overview" node
1370 # Changing the main window at runtime not yet supported...
1371 self
.demoModules
= DemoModules(__name__
)
1372 self
.SetOverview(self
.overviewText
, mainOverview
)
1373 self
.LoadDemoSource()
1374 self
.UpdateNotebook(0)
1376 if os
.path
.exists(GetOriginalFilename(demoName
)):
1377 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1378 self
.demoModules
= DemoModules(demoName
)
1379 self
.LoadDemoSource()
1382 self
.SetOverview("wxPython", mainOverview
)
1383 self
.codePage
= None
1384 self
.UpdateNotebook(0)
1388 #---------------------------------------------
1389 def LoadDemoSource(self
):
1390 self
.codePage
= None
1391 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1392 self
.codePage
.LoadDemo(self
.demoModules
)
1394 #---------------------------------------------
1395 def RunModule(self
):
1396 """Runs the active module"""
1398 module
= self
.demoModules
.GetActive()
1399 self
.ShutdownDemoModule()
1402 # o The RunTest() for all samples must now return a window that can
1403 # be palced in a tab in the main notebook.
1404 # o If an error occurs (or has occurred before) an error tab is created.
1406 if module
is not None:
1407 wx
.LogMessage("Running demo module...")
1408 if hasattr(module
, "overview"):
1409 overviewText
= module
.overview
1412 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1414 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1415 DemoError(sys
.exc_info()), self
)
1417 assert self
.demoPage
is not None, "runTest must return a window!"
1420 # There was a previous error in compiling or exec-ing
1421 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1422 self
.demoModules
.GetErrorInfo(), self
)
1424 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1427 # cahnge to the demo page the first time a module is run
1428 self
.UpdateNotebook(2)
1429 self
.firstTime
= False
1431 # otherwise just stay on the same tab in case the user has changed to another one
1432 self
.UpdateNotebook()
1434 #---------------------------------------------
1435 def ShutdownDemoModule(self
):
1437 # inform the window that it's time to quit if it cares
1438 if hasattr(self
.demoPage
, "ShutdownDemo"):
1439 self
.demoPage
.ShutdownDemo()
1440 wx
.YieldIfNeeded() # in case the page has pending events
1441 self
.demoPage
= None
1443 #---------------------------------------------
1444 def UpdateNotebook(self
, select
= -1):
1448 def UpdatePage(page
, pageText
):
1451 for i
in range(nb
.GetPageCount()):
1452 if nb
.GetPageText(i
) == pageText
:
1460 nb
.AddPage(page
, pageText
)
1461 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1463 if nb
.GetPage(pagePos
) != page
:
1464 # Reload an existing page
1466 nb
.DeletePage(pagePos
)
1467 nb
.InsertPage(pagePos
, page
, pageText
)
1469 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1471 # Excellent! No redraw/flicker
1472 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1475 nb
.DeletePage(pagePos
)
1476 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1478 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1481 select
= nb
.GetSelection()
1483 UpdatePage(self
.codePage
, "Demo Code")
1484 UpdatePage(self
.demoPage
, "Demo")
1486 if select
>= 0 and select
< nb
.GetPageCount():
1487 nb
.SetSelection(select
)
1489 #---------------------------------------------
1490 def SetOverview(self
, name
, text
):
1491 self
.curOverview
= text
1493 if lead
!= '<html>' and lead
!= '<HTML>':
1494 text
= '<br>'.join(text
.split('\n'))
1496 text
= text
.decode('iso8859_1')
1497 self
.ovr
.SetPage(text
)
1498 self
.nb
.SetPageText(0, name
)
1500 #---------------------------------------------
1502 def OnFileExit(self
, *event
):
1505 def OnToggleRedirect(self
, event
):
1509 print "Print statements and other standard output will now be directed to this window."
1512 print "Print statements and other standard output will now be sent to the usual location."
1514 def OnHelpAbout(self
, event
):
1515 from About
import MyAboutBox
1516 about
= MyAboutBox(self
)
1520 def OnHelpFind(self
, event
):
1521 if self
.finddlg
!= None:
1524 self
.nb
.SetSelection(1)
1525 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1526 wx
.FR_NOMATCHCASE | wx
.FR_NOWHOLEWORD
)
1527 self
.finddlg
.Show(True)
1530 def OnUpdateFindItems(self
, evt
):
1531 evt
.Enable(self
.finddlg
== None)
1534 def OnFind(self
, event
):
1535 editor
= self
.codePage
.editor
1536 self
.nb
.SetSelection(1)
1537 end
= editor
.GetLastPosition()
1538 textstring
= editor
.GetRange(0, end
).lower()
1539 findstring
= self
.finddata
.GetFindString().lower()
1540 backward
= not (self
.finddata
.GetFlags() & wx
.FR_DOWN
)
1542 start
= editor
.GetSelection()[0]
1543 loc
= textstring
.rfind(findstring
, 0, start
)
1545 start
= editor
.GetSelection()[1]
1546 loc
= textstring
.find(findstring
, start
)
1547 if loc
== -1 and start
!= 0:
1548 # string not found, start at beginning
1551 loc
= textstring
.rfind(findstring
, 0, start
)
1554 loc
= textstring
.find(findstring
, start
)
1556 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1557 'Find String Not Found in Demo File',
1558 wx
.OK | wx
.ICON_INFORMATION
)
1563 self
.finddlg
.SetFocus()
1566 self
.finddlg
.Destroy()
1568 editor
.ShowPosition(loc
)
1569 editor
.SetSelection(loc
, loc
+ len(findstring
))
1573 def OnFindNext(self
, event
):
1574 if self
.finddata
.GetFindString():
1577 self
.OnHelpFind(event
)
1579 def OnFindClose(self
, event
):
1580 event
.GetDialog().Destroy()
1584 def OnOpenShellWindow(self
, evt
):
1586 # if it already exists then just make sure it's visible
1592 # Make a PyShell window
1594 namespace
= { 'wx' : wx
,
1595 'app' : wx
.GetApp(),
1598 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1599 self
.shell
.SetSize((640,480))
1602 # Hook the close event of the main frame window so that we
1603 # close the shell at the same time if it still exists
1604 def CloseShell(evt
):
1608 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1611 #---------------------------------------------
1612 def OnCloseWindow(self
, event
):
1614 self
.demoPage
= None
1615 self
.codePage
= None
1616 self
.mainmenu
= None
1617 self
.tbicon
.Destroy()
1621 #---------------------------------------------
1622 def OnIdle(self
, event
):
1624 self
.otherWin
.Raise()
1625 self
.demoPage
= self
.otherWin
1626 self
.otherWin
= None
1629 #---------------------------------------------
1632 showTipText
= open(opj("data/showTips")).read()
1633 showTip
, index
= eval(showTipText
)
1635 showTip
, index
= (1, 0)
1637 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1639 showTip
= wx
.ShowTip(self
, tp
)
1640 index
= tp
.GetCurrentTip()
1641 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1644 #---------------------------------------------
1645 def OnDemoMenu(self
, event
):
1647 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1651 self
.tree
.SelectItem(selectedDemo
)
1652 self
.tree
.EnsureVisible(selectedDemo
)
1656 #---------------------------------------------
1657 def OnIconfiy(self
, evt
):
1658 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1661 #---------------------------------------------
1662 def OnMaximize(self
, evt
):
1663 wx
.LogMessage("OnMaximize")
1666 #---------------------------------------------
1667 def OnActivate(self
, evt
):
1668 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1671 #---------------------------------------------
1672 def OnAppActivate(self
, evt
):
1673 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1676 #---------------------------------------------------------------------------
1677 #---------------------------------------------------------------------------
1679 class MySplashScreen(wx
.SplashScreen
):
1681 bmp
= wx
.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1682 wx
.SplashScreen
.__init
__(self
, bmp
,
1683 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1685 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1686 self
.fc
= wx
.FutureCall(2000, self
.ShowMain
)
1689 def OnClose(self
, evt
):
1690 # Make sure the default handler runs too so this window gets
1695 # if the timer is still running then go ahead and show the
1697 if self
.fc
.IsRunning():
1703 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1705 if self
.fc
.IsRunning():
1709 class MyApp(wx
.App
):
1712 Create and show the splash screen. It will then create and show
1713 the main frame when it is time to do so.
1716 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1719 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1721 # Normally when using a SplashScreen you would create it, show
1722 # it and then continue on with the applicaiton's
1723 # initialization, finally creating and showing the main
1724 # application window(s). In this case we have nothing else to
1725 # do so we'll delay showing the main frame until later (see
1726 # ShowMain above) so the users can see the SplashScreen effect.
1727 splash
= MySplashScreen()
1734 #---------------------------------------------------------------------------
1738 demoPath
= os
.path
.dirname(__file__
)
1745 #---------------------------------------------------------------------------
1748 mainOverview
= """<html><body>
1751 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1752 language. It allows Python programmers to create programs with a
1753 robust, highly functional graphical user interface, simply and easily.
1754 It is implemented as a Python extension module (native code) that
1755 wraps the popular wxWindows cross platform GUI library, which is
1758 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1759 means that it is free for anyone to use and the source code is
1760 available for anyone to look at and modify. Or anyone can contribute
1761 fixes or enhancements to the project.
1763 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1764 same program will run on multiple platforms without modification.
1765 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1766 or unix-like systems, and Macintosh OS X. Since the language is
1767 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1770 <p> <b>This demo</b> is not only a collection of test cases for
1771 wxPython, but is also designed to help you learn about and how to use
1772 wxPython. Each sample is listed in the tree control on the left.
1773 When a sample is selected in the tree then a module is loaded and run
1774 (usually in a tab of this notebook,) and the source code of the module
1775 is loaded in another tab for you to browse and learn from.
1780 #----------------------------------------------------------------------------
1781 #----------------------------------------------------------------------------
1783 if __name__
== '__main__':
1787 #----------------------------------------------------------------------------