2 #----------------------------------------------------------------------------
4 # Purpose: Testing lots of stuff, controls, window types, etc.
8 # Created: A long time ago, in a galaxy far, far away...
10 # Copyright: (c) 1999 by Total Control Software
11 # Licence: wxWindows license
12 #----------------------------------------------------------------------------
15 # * Problems with flickering related to ERASE_BACKGROUND
16 # and the splitters. Might be a problem with this 2.5 beta...?
17 # UPDATE: can't see on 2.5.2 GTK - maybe just a faster machine :)
19 # * Annoying switching between tabs and resulting flicker
20 # how to replace a page in the notebook without deleting/adding?
21 # Where is SetPage!? tried freeze...tried reparent of dummy panel....
24 # * UI design more prefessional
25 # * save file positions (new field in demoModules) (@ LoadDemoSource)
26 # * Update main overview
28 # * Why don't we move _treeList into a separate module
30 import sys
, os
, time
, traceback
, types
32 import wx
# This module uses the new wx namespace
39 ##print "wx.VERSION_STRING = ", wx.VERSION_STRING
41 ##raw_input("Press Enter...")
44 #---------------------------------------------------------------------------
49 ('Recent Additions/Updates', [
53 'MultiSplitterWindow',
56 # managed windows == things with a (optional) caption you can close
57 ('Frames and Dialogs', [
81 # dialogs from libraries
84 'MultipleChoiceDialog',
85 'ScrolledMessageDialog',
89 ('Core Windows/Controls', [
129 ('Custom Controls', [
142 # controls coming from other libraries
143 ('More Windows/Controls', [
144 'ActiveX_FlashWindow',
145 'ActiveX_IEHtmlWindow',
147 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
164 'MultiSplitterWindow',
166 'MaskedEditControls',
183 # How to lay out the controls in a frame/dialog
193 'XmlResourceHandler',
194 'XmlResourceSubclass',
198 ('Process and Events', [
205 ##'infoframe', # needs better explanation and some fixing
209 ('Clipboard and DnD', [
231 ##'DialogUnits', # needs more explanations
245 # need libs not coming with the demo
246 ('Samples using an external library', [
251 ('Check out the samples dir too', [
258 #---------------------------------------------------------------------------
259 # Show how to derive a custom wxLog class
261 class MyLog(wx
.PyLog
):
262 def __init__(self
, textCtrl
, logTime
=0):
263 wx
.PyLog
.__init
__(self
)
265 self
.logTime
= logTime
267 def DoLogString(self
, message
, timeStamp
):
268 #print message, timeStamp
270 # message = time.strftime("%X", time.localtime(timeStamp)) + \
273 self
.tc
.AppendText(message
+ '\n')
276 class MyTP(wx
.PyTipProvider
):
278 return "This is my tip"
280 #---------------------------------------------------------------------------
281 # A class to be used to simply display a message in the demo pane
282 # rather than running the sample itself.
284 class MessagePanel(wx
.Panel
):
285 def __init__(self
, parent
, message
, caption
='', flags
=0):
286 wx
.Panel
.__init
__(self
, parent
)
291 if flags
& wx
.ICON_EXCLAMATION
:
292 artid
= wx
.ART_WARNING
293 elif flags
& wx
.ICON_ERROR
:
295 elif flags
& wx
.ICON_QUESTION
:
296 artid
= wx
.ART_QUESTION
297 elif flags
& wx
.ICON_INFORMATION
:
298 artid
= wx
.ART_INFORMATION
300 if artid
is not None:
301 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
302 icon
= wx
.StaticBitmap(self
, -1, bmp
)
304 icon
= (32,32) # make a spacer instead
307 caption
= wx
.StaticText(self
, -1, caption
)
308 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
310 message
= wx
.StaticText(self
, -1, message
)
312 # add to sizers for layout
313 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
319 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
326 box
= wx
.BoxSizer(wx
.VERTICAL
)
328 box
.Add(hbox
, 0, wx
.EXPAND
)
335 #---------------------------------------------------------------------------
336 # A class to be used to display source code in the demo. Try using the
337 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
338 # if there is an error, such as the stc module not being present.
342 ##raise ImportError # for testing the alternate implementation
344 from StyledTextCtrl_2
import PythonSTC
346 class DemoCodeEditor(PythonSTC
):
347 def __init__(self
, parent
):
348 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
351 # Some methods to make it compatible with how the wxTextCtrl is used
352 def SetValue(self
, value
):
354 value
= value
.decode('iso8859_1')
356 self
.EmptyUndoBuffer()
359 def IsModified(self
):
360 return self
.GetModify()
365 def SetInsertionPoint(self
, pos
):
366 self
.SetCurrentPos(pos
)
369 def ShowPosition(self
, pos
):
370 line
= self
.LineFromPosition(pos
)
371 #self.EnsureVisible(line)
374 def GetLastPosition(self
):
375 return self
.GetLength()
377 def GetPositionFromLine(self
, line
):
378 return self
.PositionFromLine(line
)
380 def GetRange(self
, start
, end
):
381 return self
.GetTextRange(start
, end
)
383 def GetSelection(self
):
384 return self
.GetAnchor(), self
.GetCurrentPos()
386 def SetSelection(self
, start
, end
):
387 self
.SetSelectionStart(start
)
388 self
.SetSelectionEnd(end
)
390 def SelectLine(self
, line
):
391 start
= self
.PositionFromLine(line
)
392 end
= self
.GetLineEndPosition(line
)
393 self
.SetSelection(start
, end
)
395 def SetUpEditor(self
):
397 This method carries out the work of setting up the demo editor.
398 It's seperate so as not to clutter up the init code.
402 self
.SetLexer(stc
.STC_LEX_PYTHON
)
403 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
406 self
.SetProperty("fold", "1" )
408 # Highlight tab/space mixing (shouldn't be any)
409 self
.SetProperty("tab.timmy.whinge.level", "1")
411 # Set left and right margins
414 # Set up the numbers in the margin for margin #1
415 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
416 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
417 self
.SetMarginWidth(1, 40)
419 # Indentation and tab stuff
420 self
.SetIndent(4) # Proscribed indent size for wx
421 self
.SetIndentationGuides(True) # Show indent guides
422 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
423 self
.SetTabIndents(True) # Tab key indents
424 self
.SetTabWidth(4) # Proscribed tab size for wx
425 self
.SetUseTabs(False) # Use spaces rather than tabs, or
426 # TabTimmy will complain!
428 self
.SetViewWhiteSpace(False) # Don't view white space
430 # EOL: Since we are loading/saving ourselves, and the
431 # strings will always have \n's in them, set the STC to
432 # edit them that way.
433 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
434 self
.SetViewEOL(False)
436 # No right-edge mode indicator
437 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
439 # Setup a margin to hold fold markers
440 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
441 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
442 self
.SetMarginSensitive(2, True)
443 self
.SetMarginWidth(2, 12)
445 # and now set up the fold markers
446 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
447 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
448 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
449 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
450 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
451 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
452 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
454 # Global default style
455 if wx
.Platform
== '__WXMSW__':
456 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
457 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
459 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
460 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
462 # Clear styles and revert to default.
465 # Following style specs only indicate differences from default.
466 # The rest remains unchanged.
468 # Line numbers in margin
469 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
471 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
473 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
475 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
478 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
480 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
481 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
483 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
484 # Strings and characters
485 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
486 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
488 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
490 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
491 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
493 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
495 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
497 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
498 # Identifiers. I leave this as not bold because everything seems
499 # to be an identifier if it doesn't match the above criterae
500 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
503 self
.SetCaretForeground("BLUE")
504 # Selection background
505 self
.SetSelBackground(1, '#66CCFF')
507 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
508 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
510 def RegisterModifiedEvent(self
, eventHandler
):
511 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
515 class DemoCodeEditor(wx
.TextCtrl
):
516 def __init__(self
, parent
):
517 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
518 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
520 def RegisterModifiedEvent(self
, eventHandler
):
521 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
523 def SetReadOnly(self
, flag
):
524 self
.SetEditable(not flag
)
525 # NOTE: STC already has this method
528 return self
.GetValue()
530 def GetPositionFromLine(self
, line
):
531 return self
.XYToPosition(0,line
)
533 def GotoLine(self
, line
):
534 pos
= self
.GetPositionFromLine(line
)
535 self
.SetInsertionPoint(pos
)
536 self
.ShowPosition(pos
)
538 def SelectLine(self
, line
):
539 start
= self
.GetPositionFromLine(line
)
540 end
= start
+ self
.GetLineLength(line
)
541 self
.SetSelection(start
, end
)
544 #---------------------------------------------------------------------------
545 # Constants for module versions
549 modDefault
= modOriginal
551 #---------------------------------------------------------------------------
553 class DemoCodePanel(wx
.Panel
):
554 """Panel for the 'Demo Code' tab"""
555 def __init__(self
, parent
, mainFrame
):
556 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
557 if 'wxMSW' in wx
.PlatformInfo
:
559 self
.mainFrame
= mainFrame
560 self
.editor
= DemoCodeEditor(self
)
561 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
563 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
564 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
565 self
.btnSave
.Enable(False)
566 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
567 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
569 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
570 modModified
: wx
.RadioButton(self
, -1, "Modified") }
572 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
573 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
574 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
575 for modID
, radioButton
in self
.radioButtons
.items():
576 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
577 radioButton
.modID
= modID
# makes it easier for the event handler
578 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
580 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
581 self
.controlBox
.Add(self
.btnRestore
, 0)
583 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
584 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
585 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
586 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
589 self
.SetSizer(self
.box
)
592 # Loads a demo from a DemoModules object
593 def LoadDemo(self
, demoModules
):
594 self
.demoModules
= demoModules
595 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
596 demoModules
.SetActive(modModified
)
598 demoModules
.SetActive(modOriginal
)
599 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
600 self
.ActiveModuleChanged()
603 def ActiveModuleChanged(self
):
604 self
.LoadDemoSource(self
.demoModules
.GetSource())
605 self
.UpdateControlState()
609 def LoadDemoSource(self
, source
):
611 self
.editor
.SetValue(source
)
613 self
.btnSave
.Enable(False)
616 def JumpToLine(self
, line
, highlight
=False):
617 self
.editor
.GotoLine(line
)
618 self
.editor
.SetFocus()
620 self
.editor
.SelectLine(line
)
623 def UpdateControlState(self
):
624 active
= self
.demoModules
.GetActiveID()
625 # Update the radio/restore buttons
626 for moduleID
in self
.radioButtons
:
627 btn
= self
.radioButtons
[moduleID
]
628 if moduleID
== active
:
633 if self
.demoModules
.Exists(moduleID
):
635 if moduleID
== modModified
:
636 self
.btnRestore
.Enable(True)
639 if moduleID
== modModified
:
640 self
.btnRestore
.Enable(False)
643 def OnRadioButton(self
, event
):
644 radioSelected
= event
.GetEventObject()
645 modSelected
= radioSelected
.modID
646 if modSelected
!= self
.demoModules
.GetActiveID():
647 busy
= wx
.BusyInfo("Reloading demo module...")
648 self
.demoModules
.SetActive(modSelected
)
649 self
.ActiveModuleChanged()
652 def ReloadDemo(self
):
653 if self
.demoModules
.name
!= __name__
:
654 self
.mainFrame
.RunModule()
657 def OnCodeModified(self
, event
):
658 self
.btnSave
.Enable(self
.editor
.IsModified())
661 def OnSave(self
, event
):
662 if self
.demoModules
.Exists(modModified
):
663 if self
.demoModules
.GetActiveID() == modOriginal
:
664 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
665 "Do you want to continue?"
666 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
667 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
668 result
= dlg
.ShowModal()
669 if result
== wx
.ID_NO
:
673 self
.demoModules
.SetActive(modModified
)
674 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
676 # Create the demo directory if one doesn't already exist
677 if not os
.path
.exists(GetModifiedDirectory()):
679 os
.makedirs(GetModifiedDirectory())
680 if not os
.path
.exists(GetModifiedDirectory()):
681 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
684 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
687 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
690 f
= open(modifiedFilename
, "wt")
691 source
= self
.editor
.GetText()
697 busy
= wx
.BusyInfo("Reloading demo module...")
698 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
699 self
.ActiveModuleChanged()
702 def OnRestore(self
, event
): # Handles the "Delete Modified" button
703 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
704 self
.demoModules
.Delete(modModified
)
705 os
.unlink(modifiedFilename
) # Delete the modified copy
706 busy
= wx
.BusyInfo("Reloading demo module...")
707 self
.ActiveModuleChanged()
710 #---------------------------------------------------------------------------
713 """Convert paths to the platform-specific separator"""
714 str = apply(os
.path
.join
, tuple(path
.split('/')))
715 # HACK: on Linux, a leading / gets lost...
716 if path
.startswith('/'):
721 def GetModifiedDirectory():
723 Returns the directory where modified versions of the demo files
726 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
729 def GetModifiedFilename(name
):
731 Returns the filename of the modified version of the specified demo
733 if not name
.endswith(".py"):
735 return GetModifiedDirectory() + name
738 def GetOriginalFilename(name
):
740 Returns the filename of the original version of the specified demo
742 if not name
.endswith(".py"):
747 def DoesModifiedExist(name
):
748 """Returns whether the specified demo has a modified copy"""
749 if os
.path
.exists(GetModifiedFilename(name
)):
755 #---------------------------------------------------------------------------
757 class ModuleDictWrapper
:
758 """Emulates a module with a dynamically compiled __dict__"""
759 def __init__(self
, dict):
762 def __getattr__(self
, name
):
763 if name
in self
.dict:
764 return self
.dict[name
]
770 Dynamically manages the original/modified versions of a demo
773 def __init__(self
, name
):
777 # (dict , source , filename , description , error information )
778 # ( 0 , 1 , 2 , 3 , 4 )
779 self
.modules
= [[None, "" , "" , "<original>" , None],
780 [None, "" , "" , "<modified>" , None]]
782 # load original module
783 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
784 self
.SetActive(modOriginal
)
786 # load modified module (if one exists)
787 if DoesModifiedExist(name
):
788 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
791 def LoadFromFile(self
, modID
, filename
):
792 self
.modules
[modID
][2] = filename
793 file = open(filename
, "rt")
794 self
.LoadFromSource(modID
, file.read())
798 def LoadFromSource(self
, modID
, source
):
799 self
.modules
[modID
][1] = source
803 def LoadDict(self
, modID
):
804 if self
.name
!= __name__
:
805 source
= self
.modules
[modID
][1]
806 description
= self
.modules
[modID
][3]
809 self
.modules
[modID
][0] = {}
810 code
= compile(source
, description
, "exec")
811 exec code
in self
.modules
[modID
][0]
813 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
814 self
.modules
[modID
][0] = None
816 self
.modules
[modID
][4] = None
819 def SetActive(self
, modID
):
820 if modID
!= modOriginal
and modID
!= modModified
:
823 self
.modActive
= modID
827 dict = self
.modules
[self
.modActive
][0]
831 return ModuleDictWrapper(dict)
834 def GetActiveID(self
):
835 return self
.modActive
838 def GetSource(self
, modID
= None):
840 modID
= self
.modActive
841 return self
.modules
[modID
][1]
844 def GetFilename(self
, modID
= None):
846 modID
= self
.modActive
847 return self
.modules
[self
.modActive
][2]
850 def GetErrorInfo(self
, modID
= None):
852 modID
= self
.modActive
853 return self
.modules
[self
.modActive
][4]
856 def Exists(self
, modID
):
857 return self
.modules
[modID
][1] != ""
860 def UpdateFile(self
, modID
= None):
861 """Updates the file from which a module was loaded
862 with (possibly updated) source"""
864 modID
= self
.modActive
866 source
= self
.modules
[modID
][1]
867 filename
= self
.modules
[modID
][2]
870 file = open(filename
, "wt")
876 def Delete(self
, modID
):
877 if self
.modActive
== modID
:
880 self
.modules
[modID
][0] = None
881 self
.modules
[modID
][1] = ""
882 self
.modules
[modID
][2] = ""
885 #---------------------------------------------------------------------------
888 """Wraps and stores information about the current exception"""
889 def __init__(self
, exc_info
):
892 excType
, excValue
= exc_info
[:2]
893 # traceback list entries: (filename, line number, function name, text)
894 self
.traceback
= traceback
.extract_tb(exc_info
[2])
896 # --Based on traceback.py::format_exception_only()--
897 if type(excType
) == types
.ClassType
:
898 self
.exception_type
= excType
.__name
__
900 self
.exception_type
= excType
902 # If it's a syntax error, extra information needs
903 # to be added to the traceback
904 if excType
is SyntaxError:
906 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
911 filename
= "<string>"
913 self
.traceback
.append( (filename
, lineno
, "", line
) )
916 self
.exception_details
= str(excValue
)
918 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
925 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
928 #---------------------------------------------------------------------------
930 class DemoErrorPanel(wx
.Panel
):
931 """Panel put into the demo tab when the demo fails to run due to errors"""
933 def __init__(self
, parent
, codePanel
, demoError
, log
):
934 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
935 self
.codePanel
= codePanel
939 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
942 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occurred while trying to run the demo")
943 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
945 # Exception Information
946 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
947 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
948 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
949 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
950 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
951 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
952 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
953 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
954 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
955 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
957 # Set up the traceback list
958 # This one automatically resizes last column to take up remaining space
959 from ListCtrl
import TestListCtrl
960 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
961 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
962 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
963 self
.list.InsertColumn(0, "Filename")
964 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
965 self
.list.InsertColumn(2, "Function")
966 self
.list.InsertColumn(3, "Code")
967 self
.InsertTraceback(self
.list, demoError
.traceback
)
968 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
969 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
970 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
971 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
972 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
973 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
974 + "Double-click on them to go to the offending line")
975 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
978 self
.SetSizer(self
.box
)
981 def InsertTraceback(self
, list, traceback
):
982 #Add the traceback data
983 for x
in range(len(traceback
)):
985 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
986 list.SetStringItem(x
, 1, str(data
[1])) # Line
987 list.SetStringItem(x
, 2, str(data
[2])) # Function
988 list.SetStringItem(x
, 3, str(data
[3])) # Code
990 # Check whether this entry is from the demo module
991 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
992 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
993 # Give it a blue colour
994 item
= self
.list.GetItem(x
)
995 item
.SetTextColour(wx
.BLUE
)
996 self
.list.SetItem(item
)
998 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
1001 def OnItemSelected(self
, event
):
1002 # This occurs before OnDoubleClick and can be used to set the
1003 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1004 self
.currentItem
= event
.m_itemIndex
1008 def OnDoubleClick(self
, event
):
1009 # If double-clicking on a demo's entry, jump to the line number
1010 line
= self
.list.GetItemData(self
.currentItem
)
1012 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1013 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1017 #---------------------------------------------------------------------------
1019 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1020 TBMENU_RESTORE
= wx
.NewId()
1021 TBMENU_CLOSE
= wx
.NewId()
1022 TBMENU_CHANGE
= wx
.NewId()
1023 TBMENU_REMOVE
= wx
.NewId()
1025 def __init__(self
, frame
):
1026 wx
.TaskBarIcon
.__init
__(self
)
1030 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1031 self
.SetIcon(icon
, "wxPython Demo")
1035 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1036 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1037 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1038 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1039 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1042 def CreatePopupMenu(self
):
1044 This method is called by the base class when it needs to popup
1045 the menu for the default EVT_RIGHT_DOWN event. Just create
1046 the menu how you want it and return it from this function,
1047 the base class takes care of the rest.
1050 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1051 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1052 menu
.AppendSeparator()
1053 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1054 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1058 def MakeIcon(self
, img
):
1060 The various platforms have different requirements for the
1063 if "wxMSW" in wx
.PlatformInfo
:
1064 img
= img
.Scale(16, 16)
1065 elif "wxGTK" in wx
.PlatformInfo
:
1066 img
= img
.Scale(22, 22)
1067 # wxMac can be any size upto 128x128, so leave the source img alone....
1068 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1072 def OnTaskBarActivate(self
, evt
):
1073 if self
.frame
.IsIconized():
1074 self
.frame
.Iconize(False)
1075 if not self
.frame
.IsShown():
1076 self
.frame
.Show(True)
1080 def OnTaskBarClose(self
, evt
):
1084 def OnTaskBarChange(self
, evt
):
1085 names
= [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
1086 name
= names
[self
.imgidx
]
1088 getFunc
= getattr(images
, "get%sImage" % name
)
1090 if self
.imgidx
>= len(names
):
1093 icon
= self
.MakeIcon(getFunc())
1094 self
.SetIcon(icon
, "This is a new icon: " + name
)
1097 def OnTaskBarRemove(self
, evt
):
1101 #---------------------------------------------------------------------------
1102 class wxPythonDemo(wx
.Frame
):
1103 overviewText
= "wxPython Overview"
1105 def __init__(self
, parent
, title
):
1106 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1107 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1109 self
.SetMinSize((640,480))
1112 self
.cwd
= os
.getcwd()
1113 self
.curOverview
= ""
1114 self
.demoPage
= None
1115 self
.codePage
= None
1117 self
.firstTime
= True
1120 icon
= images
.getWXPdemoIcon()
1123 self
.tbicon
= DemoTaskBarIcon(self
)
1125 wx
.CallAfter(self
.ShowTip
)
1127 self
.otherWin
= None
1128 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1129 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1130 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1131 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1133 self
.Centre(wx
.BOTH
)
1134 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1136 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1137 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1139 def EmptyHandler(evt
): pass
1140 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1141 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1143 # Prevent TreeCtrl from displaying all items after destruction when True
1147 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1150 self
.mainmenu
= wx
.MenuBar()
1152 item
= menu
.Append(-1, '&Redirect Output',
1153 'Redirect print statements to a window',
1155 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1157 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1158 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1159 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1160 self
.mainmenu
.Append(menu
, '&File')
1164 for item
in _treeList
:
1166 for childItem
in item
[1]:
1167 mi
= submenu
.Append(-1, childItem
)
1168 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1169 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1170 self
.mainmenu
.Append(menu
, '&Demo')
1172 # Make a Demo Code menu
1173 #TODO: Add new menu items
1174 # Like the option-enabled entries to select the
1176 #TODO: should we bother?
1179 #saveID = wx.NewId()
1180 #restoreID = wx.NewId()
1182 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1183 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1184 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1185 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1186 #self.mainmenu.Append(menu, 'Demo &Code')
1191 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1192 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1193 menu
.AppendSeparator()
1195 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1196 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1197 menu
.AppendSeparator()
1198 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1199 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1201 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1202 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1203 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1204 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1205 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1206 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1207 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1208 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1209 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1210 self
.mainmenu
.Append(menu
, '&Help')
1211 self
.SetMenuBar(self
.mainmenu
)
1213 self
.finddata
= wx
.FindReplaceData()
1216 # This is another way to set Accelerators, in addition to
1217 # using the '\t<key>' syntax in the menu items.
1218 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1219 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1220 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1221 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1223 self
.SetAcceleratorTable(aTable
)
1229 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1230 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1233 root
= self
.tree
.AddRoot("wxPython Overview")
1235 for item
in _treeList
:
1236 child
= self
.tree
.AppendItem(root
, item
[0])
1237 if not firstChild
: firstChild
= child
1238 for childItem
in item
[1]:
1239 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1240 self
.treeMap
[childItem
] = theDemo
1242 self
.tree
.Expand(root
)
1243 self
.tree
.Expand(firstChild
)
1244 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1245 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1246 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1247 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1249 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1250 # we put it in a panel first because there seems to be a
1251 # refresh bug of some sort (wxGTK) when it is directly in
1254 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1255 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1257 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1258 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1259 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1260 self
.nb
.AddPage(panel
, self
.overviewText
)
1262 def OnOvrSize(evt
, ovr
=self
.ovr
):
1263 ovr
.SetSize(evt
.GetSize())
1264 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1265 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1267 if "gtk2" in wx
.PlatformInfo
:
1268 self
.ovr
.SetStandardFonts()
1269 self
.SetOverview(self
.overviewText
, mainOverview
)
1272 # Set up a log window
1273 self
.log
= wx
.TextCtrl(splitter2
, -1,
1274 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1276 # Set the wxWindows log target to be this textctrl
1277 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1279 # But instead of the above we want to show how to use our own wx.Log class
1280 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1282 # for serious debugging
1283 #wx.Log_SetActiveTarget(wx.LogStderr())
1284 #wx.Log_SetTraceMask(wx.TraceMessages)
1287 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1288 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1290 # add the windows to the splitter and split it.
1291 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1292 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1294 splitter
.SetMinimumPaneSize(120)
1295 splitter2
.SetMinimumPaneSize(60)
1297 # Make the splitter on the right expand the top window when resized
1298 def SplitterOnSize(evt
):
1299 splitter
= evt
.GetEventObject()
1300 sz
= splitter
.GetSize()
1301 splitter
.SetSashPosition(sz
.height
- 160, False)
1304 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1306 # select initial items
1307 self
.nb
.SetSelection(0)
1308 self
.tree
.SelectItem(root
)
1310 # Load 'Main' module
1311 self
.LoadDemo(self
.overviewText
)
1314 # select some other initial module?
1315 if len(sys
.argv
) > 1:
1317 if arg
.endswith('.py'):
1319 selectedDemo
= self
.treeMap
.get(arg
, None)
1321 self
.tree
.SelectItem(selectedDemo
)
1322 self
.tree
.EnsureVisible(selectedDemo
)
1325 #---------------------------------------------
1326 def WriteText(self
, text
):
1327 if text
[-1:] == '\n':
1331 def write(self
, txt
):
1334 #---------------------------------------------
1335 def OnItemExpanded(self
, event
):
1336 item
= event
.GetItem()
1337 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1340 #---------------------------------------------
1341 def OnItemCollapsed(self
, event
):
1342 item
= event
.GetItem()
1343 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1346 #---------------------------------------------
1347 def OnTreeLeftDown(self
, event
):
1348 # reset the overview text if the tree item is clicked on again
1349 pt
= event
.GetPosition();
1350 item
, flags
= self
.tree
.HitTest(pt
)
1351 if item
== self
.tree
.GetSelection():
1352 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1355 #---------------------------------------------
1356 def OnSelChanged(self
, event
):
1357 if self
.dying
or not self
.loaded
:
1360 item
= event
.GetItem()
1361 itemText
= self
.tree
.GetItemText(item
)
1362 self
.LoadDemo(itemText
)
1364 #---------------------------------------------
1365 def LoadDemo(self
, demoName
):
1367 wx
.BeginBusyCursor()
1370 self
.ShutdownDemoModule()
1372 if demoName
== self
.overviewText
:
1373 # User selected the "wxPython Overview" node
1375 # Changing the main window at runtime not yet supported...
1376 self
.demoModules
= DemoModules(__name__
)
1377 self
.SetOverview(self
.overviewText
, mainOverview
)
1378 self
.LoadDemoSource()
1379 self
.UpdateNotebook(0)
1381 if os
.path
.exists(GetOriginalFilename(demoName
)):
1382 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1383 self
.demoModules
= DemoModules(demoName
)
1384 self
.LoadDemoSource()
1387 self
.SetOverview("wxPython", mainOverview
)
1388 self
.codePage
= None
1389 self
.UpdateNotebook(0)
1393 #---------------------------------------------
1394 def LoadDemoSource(self
):
1395 self
.codePage
= None
1396 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1397 self
.codePage
.LoadDemo(self
.demoModules
)
1399 #---------------------------------------------
1400 def RunModule(self
):
1401 """Runs the active module"""
1403 module
= self
.demoModules
.GetActive()
1404 self
.ShutdownDemoModule()
1407 # o The RunTest() for all samples must now return a window that can
1408 # be palced in a tab in the main notebook.
1409 # o If an error occurs (or has occurred before) an error tab is created.
1411 if module
is not None:
1412 wx
.LogMessage("Running demo module...")
1413 if hasattr(module
, "overview"):
1414 overviewText
= module
.overview
1417 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1419 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1420 DemoError(sys
.exc_info()), self
)
1422 assert self
.demoPage
is not None, "runTest must return a window!"
1425 # There was a previous error in compiling or exec-ing
1426 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1427 self
.demoModules
.GetErrorInfo(), self
)
1429 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1432 # cahnge to the demo page the first time a module is run
1433 self
.UpdateNotebook(2)
1434 self
.firstTime
= False
1436 # otherwise just stay on the same tab in case the user has changed to another one
1437 self
.UpdateNotebook()
1439 #---------------------------------------------
1440 def ShutdownDemoModule(self
):
1442 # inform the window that it's time to quit if it cares
1443 if hasattr(self
.demoPage
, "ShutdownDemo"):
1444 self
.demoPage
.ShutdownDemo()
1445 wx
.YieldIfNeeded() # in case the page has pending events
1446 self
.demoPage
= None
1448 #---------------------------------------------
1449 def UpdateNotebook(self
, select
= -1):
1453 def UpdatePage(page
, pageText
):
1456 for i
in range(nb
.GetPageCount()):
1457 if nb
.GetPageText(i
) == pageText
:
1465 nb
.AddPage(page
, pageText
)
1466 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1468 if nb
.GetPage(pagePos
) != page
:
1469 # Reload an existing page
1471 nb
.DeletePage(pagePos
)
1472 nb
.InsertPage(pagePos
, page
, pageText
)
1474 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1476 # Excellent! No redraw/flicker
1477 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1480 nb
.DeletePage(pagePos
)
1481 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1483 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1486 select
= nb
.GetSelection()
1488 UpdatePage(self
.codePage
, "Demo Code")
1489 UpdatePage(self
.demoPage
, "Demo")
1491 if select
>= 0 and select
< nb
.GetPageCount():
1492 nb
.SetSelection(select
)
1494 #---------------------------------------------
1495 def SetOverview(self
, name
, text
):
1496 self
.curOverview
= text
1498 if lead
!= '<html>' and lead
!= '<HTML>':
1499 text
= '<br>'.join(text
.split('\n'))
1501 text
= text
.decode('iso8859_1')
1502 self
.ovr
.SetPage(text
)
1503 self
.nb
.SetPageText(0, name
)
1505 #---------------------------------------------
1507 def OnFileExit(self
, *event
):
1510 def OnToggleRedirect(self
, event
):
1514 print "Print statements and other standard output will now be directed to this window."
1517 print "Print statements and other standard output will now be sent to the usual location."
1519 def OnHelpAbout(self
, event
):
1520 from About
import MyAboutBox
1521 about
= MyAboutBox(self
)
1525 def OnHelpFind(self
, event
):
1526 if self
.finddlg
!= None:
1529 self
.nb
.SetSelection(1)
1530 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1534 self
.finddlg
.Show(True)
1537 def OnUpdateFindItems(self
, evt
):
1538 evt
.Enable(self
.finddlg
== None)
1541 def OnFind(self
, event
):
1542 editor
= self
.codePage
.editor
1543 self
.nb
.SetSelection(1)
1544 end
= editor
.GetLastPosition()
1545 textstring
= editor
.GetRange(0, end
).lower()
1546 start
= editor
.GetSelection()[1]
1547 findstring
= self
.finddata
.GetFindString().lower()
1548 loc
= textstring
.find(findstring
, start
)
1549 if loc
== -1 and start
!= 0:
1550 # string not found, start at beginning
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 #----------------------------------------------------------------------------