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', [
54 # managed windows == things with a (optional) caption you can close
55 ('Frames and Dialogs', [
78 # dialogs from libraries
81 'MultipleChoiceDialog',
82 'ScrolledMessageDialog',
86 ('Core Windows/Controls', [
125 ('Custom Controls', [
138 # controls coming from other libraries
139 ('More Windows/Controls', [
140 'ActiveX_FlashWindow',
141 'ActiveX_IEHtmlWindow',
143 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
157 'MaskedEditControls',
174 # How to lay out the controls in a frame/dialog
184 'XmlResourceHandler',
185 'XmlResourceSubclass',
189 ('Process and Events', [
196 ##'infoframe', # needs better explaination and some fixing
200 ('Clipboard and DnD', [
221 ##'DialogUnits', # needs more explainations
234 # need libs not coming with the demo
235 ('Samples using an external library', [
240 ('Check out the samples dir too', [
247 #---------------------------------------------------------------------------
248 # Show how to derive a custom wxLog class
250 class MyLog(wx
.PyLog
):
251 def __init__(self
, textCtrl
, logTime
=0):
252 wx
.PyLog
.__init
__(self
)
254 self
.logTime
= logTime
256 def DoLogString(self
, message
, timeStamp
):
257 #print message, timeStamp
259 # message = time.strftime("%X", time.localtime(timeStamp)) + \
262 self
.tc
.AppendText(message
+ '\n')
265 class MyTP(wx
.PyTipProvider
):
267 return "This is my tip"
269 #---------------------------------------------------------------------------
270 # A class to be used to simply display a message in the demo pane
271 # rather than running the sample itself.
273 class MessagePanel(wx
.Panel
):
274 def __init__(self
, parent
, message
, caption
='', flags
=0):
275 wx
.Panel
.__init
__(self
, parent
)
280 if flags
& wx
.ICON_EXCLAMATION
:
281 artid
= wx
.ART_WARNING
282 elif flags
& wx
.ICON_ERROR
:
284 elif flags
& wx
.ICON_QUESTION
:
285 artid
= wx
.ART_QUESTION
286 elif flags
& wx
.ICON_INFORMATION
:
287 artid
= wx
.ART_INFORMATION
289 if artid
is not None:
290 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
291 icon
= wx
.StaticBitmap(self
, -1, bmp
)
293 icon
= (32,32) # make a spacer instead
296 caption
= wx
.StaticText(self
, -1, caption
)
297 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
299 message
= wx
.StaticText(self
, -1, message
)
301 # add to sizers for layout
302 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
308 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
315 box
= wx
.BoxSizer(wx
.VERTICAL
)
317 box
.Add(hbox
, 0, wx
.EXPAND
)
324 #---------------------------------------------------------------------------
325 # A class to be used to display source code in the demo. Try using the
326 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
327 # if there is an error, such as the stc module not being present.
331 ##raise ImportError # for testing the alternate implementation
333 from StyledTextCtrl_2
import PythonSTC
335 class DemoCodeEditor(PythonSTC
):
336 def __init__(self
, parent
):
337 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
340 # Some methods to make it compatible with how the wxTextCtrl is used
341 def SetValue(self
, value
):
343 value
= value
.decode('iso8859_1')
345 self
.EmptyUndoBuffer()
348 def IsModified(self
):
349 return self
.GetModify()
354 def SetInsertionPoint(self
, pos
):
355 self
.SetCurrentPos(pos
)
358 def ShowPosition(self
, pos
):
359 line
= self
.LineFromPosition(pos
)
360 #self.EnsureVisible(line)
363 def GetLastPosition(self
):
364 return self
.GetLength()
366 def GetPositionFromLine(self
, line
):
367 return self
.PositionFromLine(line
)
369 def GetRange(self
, start
, end
):
370 return self
.GetTextRange(start
, end
)
372 def GetSelection(self
):
373 return self
.GetAnchor(), self
.GetCurrentPos()
375 def SetSelection(self
, start
, end
):
376 self
.SetSelectionStart(start
)
377 self
.SetSelectionEnd(end
)
379 def SelectLine(self
, line
):
380 start
= self
.PositionFromLine(line
)
381 end
= self
.GetLineEndPosition(line
)
382 self
.SetSelection(start
, end
)
384 def SetUpEditor(self
):
386 This method carries out the work of setting up the demo editor.
387 It's seperate so as not to clutter up the init code.
391 self
.SetLexer(stc
.STC_LEX_PYTHON
)
392 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
395 self
.SetProperty("fold", "1" )
397 # Highlight tab/space mixing (shouldn't be any)
398 self
.SetProperty("tab.timmy.whinge.level", "1")
400 # Set left and right margins
403 # Set up the numbers in the margin for margin #1
404 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
405 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
406 self
.SetMarginWidth(1, 40)
408 # Indentation and tab stuff
409 self
.SetIndent(4) # Proscribed indent size for wx
410 self
.SetIndentationGuides(True) # Show indent guides
411 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
412 self
.SetTabIndents(True) # Tab key indents
413 self
.SetTabWidth(4) # Proscribed tab size for wx
414 self
.SetUseTabs(False) # Use spaces rather than tabs, or
415 # TabTimmy will complain!
417 self
.SetViewWhiteSpace(False) # Don't view white space
419 # EOL: Since we are loading/saving ourselves, and the
420 # strings will always have \n's in them, set the STC to
421 # edit them that way.
422 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
423 self
.SetViewEOL(False)
425 # No right-edge mode indicator
426 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
428 # Setup a margin to hold fold markers
429 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
430 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
431 self
.SetMarginSensitive(2, True)
432 self
.SetMarginWidth(2, 12)
434 # and now set up the fold markers
435 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
436 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
437 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
438 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
439 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
440 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
441 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
443 # Global default style
444 if wx
.Platform
== '__WXMSW__':
445 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
446 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
448 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
449 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
451 # Clear styles and revert to default.
454 # Following style specs only indicate differences from default.
455 # The rest remains unchanged.
457 # Line numbers in margin
458 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
460 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
462 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
464 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
467 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
469 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
470 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
472 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
473 # Strings and characters
474 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
475 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
477 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
479 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
480 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
482 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
484 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
486 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
487 # Identifiers. I leave this as not bold because everything seems
488 # to be an identifier if it doesn't match the above criterae
489 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
492 self
.SetCaretForeground("BLUE")
493 # Selection background
494 self
.SetSelBackground(1, '#66CCFF')
496 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
497 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
499 def RegisterModifiedEvent(self
, eventHandler
):
500 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
504 class DemoCodeEditor(wx
.TextCtrl
):
505 def __init__(self
, parent
):
506 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
507 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
509 def RegisterModifiedEvent(self
, eventHandler
):
510 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
512 def SetReadOnly(self
, flag
):
513 self
.SetEditable(not flag
)
514 # NOTE: STC already has this method
517 return self
.GetValue()
519 def GetPositionFromLine(self
, line
):
520 return self
.XYToPosition(0,line
)
522 def GotoLine(self
, line
):
523 pos
= self
.GetPositionFromLine(line
)
524 self
.SetInsertionPoint(pos
)
525 self
.ShowPosition(pos
)
527 def SelectLine(self
, line
):
528 start
= self
.GetPositionFromLine(line
)
529 end
= start
+ self
.GetLineLength(line
)
530 self
.SetSelection(start
, end
)
533 #---------------------------------------------------------------------------
534 # Constants for module versions
538 modDefault
= modOriginal
540 #---------------------------------------------------------------------------
542 class DemoCodePanel(wx
.Panel
):
543 """Panel for the 'Demo Code' tab"""
544 def __init__(self
, parent
, mainFrame
):
545 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
546 if 'wxMSW' in wx
.PlatformInfo
:
548 self
.mainFrame
= mainFrame
549 self
.editor
= DemoCodeEditor(self
)
550 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
552 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
553 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
554 self
.btnSave
.Enable(False)
555 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
556 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
558 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
559 modModified
: wx
.RadioButton(self
, -1, "Modified") }
561 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
562 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
563 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
564 for modID
, radioButton
in self
.radioButtons
.items():
565 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
566 radioButton
.modID
= modID
# makes it easier for the event handler
567 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
569 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
570 self
.controlBox
.Add(self
.btnRestore
, 0)
572 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
573 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
574 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
575 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
578 self
.SetSizer(self
.box
)
581 # Loads a demo from a DemoModules object
582 def LoadDemo(self
, demoModules
):
583 self
.demoModules
= demoModules
584 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
585 demoModules
.SetActive(modModified
)
587 demoModules
.SetActive(modOriginal
)
588 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
589 self
.ActiveModuleChanged()
592 def ActiveModuleChanged(self
):
593 self
.LoadDemoSource(self
.demoModules
.GetSource())
594 self
.UpdateControlState()
598 def LoadDemoSource(self
, source
):
600 self
.editor
.SetValue(source
)
602 self
.btnSave
.Enable(False)
605 def JumpToLine(self
, line
, highlight
=False):
606 self
.editor
.GotoLine(line
)
607 self
.editor
.SetFocus()
609 self
.editor
.SelectLine(line
)
612 def UpdateControlState(self
):
613 active
= self
.demoModules
.GetActiveID()
614 # Update the radio/restore buttons
615 for moduleID
in self
.radioButtons
:
616 btn
= self
.radioButtons
[moduleID
]
617 if moduleID
== active
:
622 if self
.demoModules
.Exists(moduleID
):
624 if moduleID
== modModified
:
625 self
.btnRestore
.Enable(True)
628 if moduleID
== modModified
:
629 self
.btnRestore
.Enable(False)
632 def OnRadioButton(self
, event
):
633 radioSelected
= event
.GetEventObject()
634 modSelected
= radioSelected
.modID
635 if modSelected
!= self
.demoModules
.GetActiveID():
636 busy
= wx
.BusyInfo("Reloading demo module...")
637 self
.demoModules
.SetActive(modSelected
)
638 self
.ActiveModuleChanged()
641 def ReloadDemo(self
):
642 if self
.demoModules
.name
!= __name__
:
643 self
.mainFrame
.RunModule()
646 def OnCodeModified(self
, event
):
647 self
.btnSave
.Enable(self
.editor
.IsModified())
650 def OnSave(self
, event
):
651 if self
.demoModules
.Exists(modModified
):
652 if self
.demoModules
.GetActiveID() == modOriginal
:
653 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
654 "Do you want to continue?"
655 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
656 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
657 result
= dlg
.ShowModal()
658 if result
== wx
.ID_NO
:
662 self
.demoModules
.SetActive(modModified
)
663 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
665 # Create the demo directory if one doesn't already exist
666 if not os
.path
.exists(GetModifiedDirectory()):
668 os
.makedirs(GetModifiedDirectory())
669 if not os
.path
.exists(GetModifiedDirectory()):
670 wx
.LogMessage("BUG: Created demo directory but it still doesn't exit")
673 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
676 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
679 f
= open(modifiedFilename
, "wt")
680 source
= self
.editor
.GetText()
686 busy
= wx
.BusyInfo("Reloading demo module...")
687 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
688 self
.ActiveModuleChanged()
691 def OnRestore(self
, event
): # Handles the "Delete Modified" button
692 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
693 self
.demoModules
.Delete(modModified
)
694 os
.unlink(modifiedFilename
) # Delete the modified copy
695 busy
= wx
.BusyInfo("Reloading demo module...")
696 self
.ActiveModuleChanged()
699 #---------------------------------------------------------------------------
702 """Convert paths to the platform-specific separator"""
703 str = apply(os
.path
.join
, tuple(path
.split('/')))
704 # HACK: on Linux, a leading / gets lost...
705 if path
.startswith('/'):
710 def GetModifiedDirectory():
712 Returns the directory where modified versions of the demo files
715 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
718 def GetModifiedFilename(name
):
720 Returns the filename of the modified version of the specified demo
722 if not name
.endswith(".py"):
724 return GetModifiedDirectory() + name
727 def GetOriginalFilename(name
):
729 Returns the filename of the original version of the specified demo
731 if not name
.endswith(".py"):
736 def DoesModifiedExist(name
):
737 """Returns whether the specified demo has a modified copy"""
738 if os
.path
.exists(GetModifiedFilename(name
)):
744 #---------------------------------------------------------------------------
746 class ModuleDictWrapper
:
747 """Emulates a module with a dynamically compiled __dict__"""
748 def __init__(self
, dict):
751 def __getattr__(self
, name
):
752 if name
in self
.dict:
753 return self
.dict[name
]
759 Dynamically manages the original/modified versions of a demo
762 def __init__(self
, name
):
766 # (dict , source , filename , description , error information )
767 # ( 0 , 1 , 2 , 3 , 4 )
768 self
.modules
= [[None, "" , "" , "<original>" , None],
769 [None, "" , "" , "<modified>" , None]]
771 # load original module
772 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
773 self
.SetActive(modOriginal
)
775 # load modified module (if one exists)
776 if DoesModifiedExist(name
):
777 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
780 def LoadFromFile(self
, modID
, filename
):
781 self
.modules
[modID
][2] = filename
782 file = open(filename
, "rt")
783 self
.LoadFromSource(modID
, file.read())
787 def LoadFromSource(self
, modID
, source
):
788 self
.modules
[modID
][1] = source
792 def LoadDict(self
, modID
):
793 if self
.name
!= __name__
:
794 source
= self
.modules
[modID
][1]
795 description
= self
.modules
[modID
][3]
798 self
.modules
[modID
][0] = {}
799 code
= compile(source
, description
, "exec")
800 exec code
in self
.modules
[modID
][0]
802 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
803 self
.modules
[modID
][0] = None
805 self
.modules
[modID
][4] = None
808 def SetActive(self
, modID
):
809 if modID
!= modOriginal
and modID
!= modModified
:
812 self
.modActive
= modID
816 dict = self
.modules
[self
.modActive
][0]
820 return ModuleDictWrapper(dict)
823 def GetActiveID(self
):
824 return self
.modActive
827 def GetSource(self
, modID
= None):
829 modID
= self
.modActive
830 return self
.modules
[modID
][1]
833 def GetFilename(self
, modID
= None):
835 modID
= self
.modActive
836 return self
.modules
[self
.modActive
][2]
839 def GetErrorInfo(self
, modID
= None):
841 modID
= self
.modActive
842 return self
.modules
[self
.modActive
][4]
845 def Exists(self
, modID
):
846 return self
.modules
[modID
][1] != ""
849 def UpdateFile(self
, modID
= None):
850 """Updates the file from which a module was loaded
851 with (possibly updated) source"""
853 modID
= self
.modActive
855 source
= self
.modules
[modID
][1]
856 filename
= self
.modules
[modID
][2]
859 file = open(filename
, "wt")
865 def Delete(self
, modID
):
866 if self
.modActive
== modID
:
869 self
.modules
[modID
][0] = None
870 self
.modules
[modID
][1] = ""
871 self
.modules
[modID
][2] = ""
874 #---------------------------------------------------------------------------
877 """Wraps and stores information about the current exception"""
878 def __init__(self
, exc_info
):
881 excType
, excValue
= exc_info
[:2]
882 # traceback list entries: (filename, line number, function name, text)
883 self
.traceback
= traceback
.extract_tb(exc_info
[2])
885 # --Based on traceback.py::format_exception_only()--
886 if type(excType
) == types
.ClassType
:
887 self
.exception_type
= excType
.__name
__
889 self
.exception_type
= excType
891 # If it's a syntax error, extra information needs
892 # to be added to the traceback
893 if excType
is SyntaxError:
895 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
900 filename
= "<string>"
902 self
.traceback
.append( (filename
, lineno
, "", line
) )
905 self
.exception_details
= str(excValue
)
907 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
914 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
917 #---------------------------------------------------------------------------
919 class DemoErrorPanel(wx
.Panel
):
920 """Panel put into the demo tab when the demo fails to run due to errors"""
922 def __init__(self
, parent
, codePanel
, demoError
, log
):
923 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
924 self
.codePanel
= codePanel
928 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
931 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
932 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
934 # Exception Information
935 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
936 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
937 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
938 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
939 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
940 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
941 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
942 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
943 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
944 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
946 # Set up the traceback list
947 # This one automatically resizes last column to take up remaining space
948 from ListCtrl
import TestListCtrl
949 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
950 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
951 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
952 self
.list.InsertColumn(0, "Filename")
953 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
954 self
.list.InsertColumn(2, "Function")
955 self
.list.InsertColumn(3, "Code")
956 self
.InsertTraceback(self
.list, demoError
.traceback
)
957 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
958 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
959 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
960 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
961 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
962 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
963 + "Double-click on them to go to the offending line")
964 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
967 self
.SetSizer(self
.box
)
970 def InsertTraceback(self
, list, traceback
):
971 #Add the traceback data
972 for x
in range(len(traceback
)):
974 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
975 list.SetStringItem(x
, 1, str(data
[1])) # Line
976 list.SetStringItem(x
, 2, str(data
[2])) # Function
977 list.SetStringItem(x
, 3, str(data
[3])) # Code
979 # Check whether this entry is from the demo module
980 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
981 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
982 # Give it a blue colour
983 item
= self
.list.GetItem(x
)
984 item
.SetTextColour(wx
.BLUE
)
985 self
.list.SetItem(item
)
987 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
990 def OnItemSelected(self
, event
):
991 # This occurs before OnDoubleClick and can be used to set the
992 # currentItem. OnDoubleClick doesn't get a wxListEvent....
993 self
.currentItem
= event
.m_itemIndex
997 def OnDoubleClick(self
, event
):
998 # If double-clicking on a demo's entry, jump to the line number
999 line
= self
.list.GetItemData(self
.currentItem
)
1001 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1002 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1006 #---------------------------------------------------------------------------
1008 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1009 TBMENU_RESTORE
= wx
.NewId()
1010 TBMENU_CLOSE
= wx
.NewId()
1011 TBMENU_CHANGE
= wx
.NewId()
1012 TBMENU_REMOVE
= wx
.NewId()
1014 def __init__(self
, frame
):
1015 wx
.TaskBarIcon
.__init
__(self
)
1019 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1020 self
.SetIcon(icon
, "wxPython Demo")
1024 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1025 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1026 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1027 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1028 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1031 def CreatePopupMenu(self
):
1033 This method is called by the base class when it needs to popup
1034 the menu for the default EVT_RIGHT_DOWN event. Just create
1035 the menu how you want it and return it from this function,
1036 the base class takes care of the rest.
1039 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1040 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1041 menu
.AppendSeparator()
1042 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1043 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1047 def MakeIcon(self
, img
):
1049 The various platforms have different requirements for the
1052 if "wxMSW" in wx
.PlatformInfo
:
1053 img
= img
.Scale(16, 16)
1054 elif "wxGTK" in wx
.PlatformInfo
:
1055 img
= img
.Scale(22, 22)
1056 # wxMac can be any size upto 128x128, so leave the source img alone....
1057 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1061 def OnTaskBarActivate(self
, evt
):
1062 if self
.frame
.IsIconized():
1063 self
.frame
.Iconize(False)
1064 if not self
.frame
.IsShown():
1065 self
.frame
.Show(True)
1069 def OnTaskBarClose(self
, evt
):
1073 def OnTaskBarChange(self
, evt
):
1074 names
= [ "WXPdemo", "WXP", "Mondrian", "Test2m",
1075 "Blom08m", "Blom10m", "Blom15m" ]
1076 name
= names
[self
.imgidx
]
1078 getFunc
= getattr(images
, "get%sImage" % name
)
1080 if self
.imgidx
>= len(names
):
1083 icon
= self
.MakeIcon(getFunc())
1084 self
.SetIcon(icon
, "This is a new icon: " + name
)
1087 def OnTaskBarRemove(self
, evt
):
1091 #---------------------------------------------------------------------------
1092 class wxPythonDemo(wx
.Frame
):
1093 overviewText
= "wxPython Overview"
1095 def __init__(self
, parent
, title
):
1096 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1097 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1099 self
.SetMinSize((640,480))
1102 self
.cwd
= os
.getcwd()
1103 self
.curOverview
= ""
1104 self
.demoPage
= None
1105 self
.codePage
= None
1107 self
.firstTime
= True
1109 icon
= images
.getWXPdemoIcon()
1112 self
.tbicon
= DemoTaskBarIcon(self
)
1114 wx
.CallAfter(self
.ShowTip
)
1116 self
.otherWin
= None
1117 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1118 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1119 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1120 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1122 self
.Centre(wx
.BOTH
)
1123 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1125 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1126 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1128 def EmptyHandler(evt
): pass
1129 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1130 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1132 # Prevent TreeCtrl from displaying all items after destruction when True
1136 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1139 self
.mainmenu
= wx
.MenuBar()
1141 item
= menu
.Append(-1, '&Redirect Output',
1142 'Redirect print statements to a window',
1144 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1146 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1147 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1148 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1149 self
.mainmenu
.Append(menu
, '&File')
1153 for item
in _treeList
:
1155 for childItem
in item
[1]:
1156 mi
= submenu
.Append(-1, childItem
)
1157 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1158 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1159 self
.mainmenu
.Append(menu
, '&Demo')
1161 # Make a Demo Code menu
1162 #TODO: Add new menu items
1163 # Like the option-enabled entries to select the
1165 #TODO: should we bother?
1168 #saveID = wx.NewId()
1169 #restoreID = wx.NewId()
1171 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1172 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1173 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1174 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1175 #self.mainmenu.Append(menu, 'Demo &Code')
1180 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1181 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1182 menu
.AppendSeparator()
1184 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1185 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1186 menu
.AppendSeparator()
1187 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1188 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1190 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1191 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1192 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1193 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1194 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1195 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1196 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1197 self
.mainmenu
.Append(menu
, '&Help')
1198 self
.SetMenuBar(self
.mainmenu
)
1200 self
.finddata
= wx
.FindReplaceData()
1203 # This is another way to set Accelerators, in addition to
1204 # using the '\t<key>' syntax in the menu items.
1205 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1206 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1207 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1208 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1210 self
.SetAcceleratorTable(aTable
)
1216 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1217 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1220 root
= self
.tree
.AddRoot("wxPython Overview")
1222 for item
in _treeList
:
1223 child
= self
.tree
.AppendItem(root
, item
[0])
1224 if not firstChild
: firstChild
= child
1225 for childItem
in item
[1]:
1226 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1227 self
.treeMap
[childItem
] = theDemo
1229 self
.tree
.Expand(root
)
1230 self
.tree
.Expand(firstChild
)
1231 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1232 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1233 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1234 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1236 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1237 # we put it in a panel first because there seems to be a
1238 # refresh bug of some sort (wxGTK) when it is directly in
1241 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1242 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1244 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1245 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1246 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1247 self
.nb
.AddPage(panel
, self
.overviewText
)
1249 def OnOvrSize(evt
, ovr
=self
.ovr
):
1250 ovr
.SetSize(evt
.GetSize())
1251 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1252 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1254 if "gtk2" in wx
.PlatformInfo
:
1255 self
.ovr
.SetStandardFonts()
1256 self
.SetOverview(self
.overviewText
, mainOverview
)
1259 # Set up a log window
1260 self
.log
= wx
.TextCtrl(splitter2
, -1,
1261 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1263 # Set the wxWindows log target to be this textctrl
1264 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1266 # But instead of the above we want to show how to use our own wx.Log class
1267 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1269 # for serious debugging
1270 #wx.Log_SetActiveTarget(wx.LogStderr())
1271 #wx.Log_SetTraceMask(wx.TraceMessages)
1274 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1275 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1277 # add the windows to the splitter and split it.
1278 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1279 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1281 splitter
.SetMinimumPaneSize(120)
1282 splitter2
.SetMinimumPaneSize(60)
1284 # Make the splitter on the right expand the top window when resized
1285 def SplitterOnSize(evt
):
1286 splitter
= evt
.GetEventObject()
1287 sz
= splitter
.GetSize()
1288 splitter
.SetSashPosition(sz
.height
- 160, False)
1291 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1293 # select initial items
1294 self
.nb
.SetSelection(0)
1295 self
.tree
.SelectItem(root
)
1297 # Load 'Main' module
1298 self
.LoadDemo(self
.overviewText
)
1301 # select some other initial module?
1302 if len(sys
.argv
) > 1:
1304 if arg
.endswith('.py'):
1306 selectedDemo
= self
.treeMap
.get(arg
, None)
1308 self
.tree
.SelectItem(selectedDemo
)
1309 self
.tree
.EnsureVisible(selectedDemo
)
1312 #---------------------------------------------
1313 def WriteText(self
, text
):
1314 if text
[-1:] == '\n':
1318 def write(self
, txt
):
1321 #---------------------------------------------
1322 def OnItemExpanded(self
, event
):
1323 item
= event
.GetItem()
1324 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1327 #---------------------------------------------
1328 def OnItemCollapsed(self
, event
):
1329 item
= event
.GetItem()
1330 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1333 #---------------------------------------------
1334 def OnTreeLeftDown(self
, event
):
1335 # reset the overview text if the tree item is clicked on again
1336 pt
= event
.GetPosition();
1337 item
, flags
= self
.tree
.HitTest(pt
)
1338 if item
== self
.tree
.GetSelection():
1339 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1342 #---------------------------------------------
1343 def OnSelChanged(self
, event
):
1344 if self
.dying
or not self
.loaded
:
1347 item
= event
.GetItem()
1348 itemText
= self
.tree
.GetItemText(item
)
1349 self
.LoadDemo(itemText
)
1351 #---------------------------------------------
1352 def LoadDemo(self
, demoName
):
1354 wx
.BeginBusyCursor()
1357 self
.ShutdownDemoModule()
1359 if demoName
== self
.overviewText
:
1360 # User selected the "wxPython Overview" node
1362 # Changing the main window at runtime not yet supported...
1363 self
.demoModules
= DemoModules(__name__
)
1364 self
.SetOverview(self
.overviewText
, mainOverview
)
1365 self
.LoadDemoSource()
1366 self
.UpdateNotebook(0)
1368 if os
.path
.exists(GetOriginalFilename(demoName
)):
1369 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1370 self
.demoModules
= DemoModules(demoName
)
1371 self
.LoadDemoSource()
1374 self
.SetOverview("wxPython", mainOverview
)
1375 self
.codePage
= None
1376 self
.UpdateNotebook(0)
1380 #---------------------------------------------
1381 def LoadDemoSource(self
):
1382 self
.codePage
= None
1383 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1384 self
.codePage
.LoadDemo(self
.demoModules
)
1386 #---------------------------------------------
1387 def RunModule(self
):
1388 """Runs the active module"""
1390 module
= self
.demoModules
.GetActive()
1391 self
.ShutdownDemoModule()
1394 # o The RunTest() for all samples must now return a window that can
1395 # be palced in a tab in the main notebook.
1396 # o If an error occurs (or has occured before) an error tab is created.
1398 if module
is not None:
1399 wx
.LogMessage("Running demo module...")
1400 if hasattr(module
, "overview"):
1401 overviewText
= module
.overview
1404 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1406 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1407 DemoError(sys
.exc_info()), self
)
1409 assert self
.demoPage
is not None, "runTest must return a window!"
1412 # There was a previous error in compiling or exec-ing
1413 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1414 self
.demoModules
.GetErrorInfo(), self
)
1416 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1419 # cahnge to the demo page the first time a module is run
1420 self
.UpdateNotebook(2)
1421 self
.firstTime
= False
1423 # otherwise just stay on the same tab in case the user has changed to another one
1424 self
.UpdateNotebook()
1426 #---------------------------------------------
1427 def ShutdownDemoModule(self
):
1429 # inform the window that it's time to quit if it cares
1430 if hasattr(self
.demoPage
, "ShutdownDemo"):
1431 self
.demoPage
.ShutdownDemo()
1432 wx
.YieldIfNeeded() # in case the page has pending events
1433 self
.demoPage
= None
1435 #---------------------------------------------
1436 def UpdateNotebook(self
, select
= -1):
1440 def UpdatePage(page
, pageText
):
1443 for i
in range(nb
.GetPageCount()):
1444 if nb
.GetPageText(i
) == pageText
:
1452 nb
.AddPage(page
, pageText
)
1453 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1455 if nb
.GetPage(pagePos
) != page
:
1456 # Reload an existing page
1458 nb
.DeletePage(pagePos
)
1459 nb
.InsertPage(pagePos
, page
, pageText
)
1461 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1463 # Excellent! No redraw/flicker
1464 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1467 nb
.DeletePage(pagePos
)
1468 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1470 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1473 select
= nb
.GetSelection()
1475 UpdatePage(self
.codePage
, "Demo Code")
1476 UpdatePage(self
.demoPage
, "Demo")
1478 if select
>= 0 and select
< nb
.GetPageCount():
1479 nb
.SetSelection(select
)
1481 #---------------------------------------------
1482 def SetOverview(self
, name
, text
):
1483 self
.curOverview
= text
1485 if lead
!= '<html>' and lead
!= '<HTML>':
1486 text
= '<br>'.join(text
.split('\n'))
1488 text
= text
.decode('iso8859_1')
1489 self
.ovr
.SetPage(text
)
1490 self
.nb
.SetPageText(0, name
)
1492 #---------------------------------------------
1494 def OnFileExit(self
, *event
):
1497 def OnToggleRedirect(self
, event
):
1501 print "Print statements and other standard output will now be directed to this window."
1504 print "Print statements and other standard output will now be sent to the usual location."
1506 def OnHelpAbout(self
, event
):
1507 from About
import MyAboutBox
1508 about
= MyAboutBox(self
)
1512 def OnHelpFind(self
, event
):
1513 self
.nb
.SetSelection(1)
1514 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1518 self
.finddlg
.Show(True)
1520 def OnFind(self
, event
):
1521 editor
= self
.codePage
.editor
1522 self
.nb
.SetSelection(1)
1523 end
= editor
.GetLastPosition()
1524 textstring
= editor
.GetRange(0, end
).lower()
1525 start
= editor
.GetSelection()[1]
1526 findstring
= self
.finddata
.GetFindString().lower()
1527 loc
= textstring
.find(findstring
, start
)
1528 if loc
== -1 and start
!= 0:
1529 # string not found, start at beginning
1531 loc
= textstring
.find(findstring
, start
)
1533 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1534 'Find String Not Found in Demo File',
1535 wx
.OK | wx
.ICON_INFORMATION
)
1540 self
.finddlg
.SetFocus()
1543 self
.finddlg
.Destroy()
1544 editor
.ShowPosition(loc
)
1545 editor
.SetSelection(loc
, loc
+ len(findstring
))
1549 def OnFindNext(self
, event
):
1550 if self
.finddata
.GetFindString():
1553 self
.OnHelpFind(event
)
1555 def OnFindClose(self
, event
):
1556 event
.GetDialog().Destroy()
1559 def OnOpenShellWindow(self
, evt
):
1561 # if it already exists then just make sure it's visible
1567 # Make a PyShell window
1569 namespace
= { 'wx' : wx
,
1570 'app' : wx
.GetApp(),
1573 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1574 self
.shell
.SetSize((640,480))
1577 # Hook the close event of the main frame window so that we
1578 # close the shell at the same time if it still exists
1579 def CloseShell(evt
):
1583 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1586 #---------------------------------------------
1587 def OnCloseWindow(self
, event
):
1589 self
.demoPage
= None
1590 self
.codePage
= None
1591 self
.mainmenu
= None
1592 self
.tbicon
.Destroy()
1596 #---------------------------------------------
1597 def OnIdle(self
, event
):
1599 self
.otherWin
.Raise()
1600 self
.demoPage
= self
.otherWin
1601 self
.otherWin
= None
1604 #---------------------------------------------
1607 showTipText
= open(opj("data/showTips")).read()
1608 showTip
, index
= eval(showTipText
)
1610 showTip
, index
= (1, 0)
1612 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1614 showTip
= wx
.ShowTip(self
, tp
)
1615 index
= tp
.GetCurrentTip()
1616 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1619 #---------------------------------------------
1620 def OnDemoMenu(self
, event
):
1622 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1626 self
.tree
.SelectItem(selectedDemo
)
1627 self
.tree
.EnsureVisible(selectedDemo
)
1631 #---------------------------------------------
1632 def OnIconfiy(self
, evt
):
1633 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1636 #---------------------------------------------
1637 def OnMaximize(self
, evt
):
1638 wx
.LogMessage("OnMaximize")
1641 #---------------------------------------------
1642 def OnActivate(self
, evt
):
1643 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1646 #---------------------------------------------
1647 def OnAppActivate(self
, evt
):
1648 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1651 #---------------------------------------------------------------------------
1652 #---------------------------------------------------------------------------
1654 class MySplashScreen(wx
.SplashScreen
):
1656 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1657 wx
.SplashScreen
.__init
__(self
, bmp
,
1658 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1660 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1662 def OnClose(self
, evt
):
1664 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1666 evt
.Skip() # Make sure the default handler runs too...
1669 class MyApp(wx
.App
):
1672 Create and show the splash screen. It will then create and show
1673 the main frame when it is time to do so.
1677 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1679 # Normally when using a SplashScreen you would create it, show
1680 # it and then continue on with the applicaiton's
1681 # initialization, finally creating and showing the main
1682 # application window(s). In this case we have nothing else to
1683 # do so we'll delay showing the main frame until later (see
1684 # OnClose above) so the users can see the SplashScreen effect.
1685 splash
= MySplashScreen()
1692 #---------------------------------------------------------------------------
1696 demoPath
= os
.path
.dirname(__file__
)
1703 #---------------------------------------------------------------------------
1706 mainOverview
= """<html><body>
1709 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1710 language. It allows Python programmers to create programs with a
1711 robust, highly functional graphical user interface, simply and easily.
1712 It is implemented as a Python extension module (native code) that
1713 wraps the popular wxWindows cross platform GUI library, which is
1716 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1717 means that it is free for anyone to use and the source code is
1718 available for anyone to look at and modify. Or anyone can contribute
1719 fixes or enhancements to the project.
1721 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1722 same program will run on multiple platforms without modification.
1723 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1724 or unix-like systems, and Macintosh OS X. Since the language is
1725 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1728 <p> <b>This demo</b> is not only a collection of test cases for
1729 wxPython, but is also designed to help you learn about and how to use
1730 wxPython. Each sample is listed in the tree control on the left.
1731 When a sample is selected in the tree then a module is loaded and run
1732 (usually in a tab of this notebook,) and the source code of the module
1733 is loaded in another tab for you to browse and learn from.
1738 #----------------------------------------------------------------------------
1739 #----------------------------------------------------------------------------
1741 if __name__
== '__main__':
1745 #----------------------------------------------------------------------------