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', [
56 # managed windows == things with a (optional) caption you can close
57 ('Frames and Dialogs', [
80 # dialogs from libraries
83 'MultipleChoiceDialog',
84 'ScrolledMessageDialog',
88 ('Core Windows/Controls', [
127 ('Custom Controls', [
140 # controls coming from other libraries
141 ('More Windows/Controls', [
142 'ActiveX_FlashWindow',
143 'ActiveX_IEHtmlWindow',
145 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
158 'MaskedEditControls',
175 # How to lay out the controls in a frame/dialog
185 'XmlResourceHandler',
186 'XmlResourceSubclass',
190 ('Process and Events', [
197 ##'infoframe', # needs better explaination and some fixing
201 ('Clipboard and DnD', [
222 ##'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
):
258 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
261 self
.tc
.AppendText(message
+ '\n')
264 class MyTP(wx
.PyTipProvider
):
266 return "This is my tip"
268 #---------------------------------------------------------------------------
269 # A class to be used to simply display a message in the demo pane
270 # rather than running the sample itself.
272 class MessagePanel(wx
.Panel
):
273 def __init__(self
, parent
, message
, caption
='', flags
=0):
274 wx
.Panel
.__init
__(self
, parent
)
279 if flags
& wx
.ICON_EXCLAMATION
:
280 artid
= wx
.ART_WARNING
281 elif flags
& wx
.ICON_ERROR
:
283 elif flags
& wx
.ICON_QUESTION
:
284 artid
= wx
.ART_QUESTION
285 elif flags
& wx
.ICON_INFORMATION
:
286 artid
= wx
.ART_INFORMATION
288 if artid
is not None:
289 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
290 icon
= wx
.StaticBitmap(self
, -1, bmp
)
292 icon
= (32,32) # make a spacer instead
295 caption
= wx
.StaticText(self
, -1, caption
)
296 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
298 message
= wx
.StaticText(self
, -1, message
)
300 # add to sizers for layout
301 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
307 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
314 box
= wx
.BoxSizer(wx
.VERTICAL
)
316 box
.Add(hbox
, 0, wx
.EXPAND
)
323 #---------------------------------------------------------------------------
324 # A class to be used to display source code in the demo. Try using the
325 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
326 # if there is an error, such as the stc module not being present.
330 ##raise ImportError # for testing the alternate implementation
332 from StyledTextCtrl_2
import PythonSTC
334 class DemoCodeEditor(PythonSTC
):
335 def __init__(self
, parent
):
336 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
339 # Some methods to make it compatible with how the wxTextCtrl is used
340 def SetValue(self
, value
):
342 value
= value
.decode('iso8859_1')
344 self
.EmptyUndoBuffer()
347 def IsModified(self
):
348 return self
.GetModify()
353 def SetInsertionPoint(self
, pos
):
354 self
.SetCurrentPos(pos
)
357 def ShowPosition(self
, pos
):
358 line
= self
.LineFromPosition(pos
)
359 #self.EnsureVisible(line)
362 def GetLastPosition(self
):
363 return self
.GetLength()
365 def GetPositionFromLine(self
, line
):
366 return self
.PositionFromLine(line
)
368 def GetRange(self
, start
, end
):
369 return self
.GetTextRange(start
, end
)
371 def GetSelection(self
):
372 return self
.GetAnchor(), self
.GetCurrentPos()
374 def SetSelection(self
, start
, end
):
375 self
.SetSelectionStart(start
)
376 self
.SetSelectionEnd(end
)
378 def SelectLine(self
, line
):
379 start
= self
.PositionFromLine(line
)
380 end
= self
.GetLineEndPosition(line
)
381 self
.SetSelection(start
, end
)
383 def SetUpEditor(self
):
385 This method carries out the work of setting up the demo editor.
386 It's seperate so as not to clutter up the init code.
390 self
.SetLexer(stc
.STC_LEX_PYTHON
)
391 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
394 self
.SetProperty("fold", "1" )
396 # Highlight tab/space mixing (shouldn't be any)
397 self
.SetProperty("tab.timmy.whinge.level", "1")
399 # Set left and right margins
402 # Set up the numbers in the margin for margin #1
403 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
404 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
405 self
.SetMarginWidth(1, 40)
407 # Indentation and tab stuff
408 self
.SetIndent(4) # Proscribed indent size for wx
409 self
.SetIndentationGuides(True) # Show indent guides
410 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
411 self
.SetTabIndents(True) # Tab key indents
412 self
.SetTabWidth(4) # Proscribed tab size for wx
413 self
.SetUseTabs(False) # Use spaces rather than tabs, or
414 # TabTimmy will complain!
416 self
.SetViewWhiteSpace(False) # Don't view white space
418 # EOL: Since we are loading/saving ourselves, and the
419 # strings will always have \n's in them, set the STC to
420 # edit them that way.
421 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
422 self
.SetViewEOL(False)
424 # No right-edge mode indicator
425 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
427 # Setup a margin to hold fold markers
428 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
429 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
430 self
.SetMarginSensitive(2, True)
431 self
.SetMarginWidth(2, 12)
433 # and now set up the fold markers
434 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
435 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
436 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
437 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
438 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
439 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
440 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
442 # Global default style
443 if wx
.Platform
== '__WXMSW__':
444 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
445 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
447 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
448 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
450 # Clear styles and revert to default.
453 # Following style specs only indicate differences from default.
454 # The rest remains unchanged.
456 # Line numbers in margin
457 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
459 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
461 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
463 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
466 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
468 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
469 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
471 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
472 # Strings and characters
473 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
474 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
476 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
478 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
479 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
481 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
483 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
485 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
486 # Identifiers. I leave this as not bold because everything seems
487 # to be an identifier if it doesn't match the above criterae
488 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
491 self
.SetCaretForeground("BLUE")
492 # Selection background
493 self
.SetSelBackground(1, '#66CCFF')
495 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
496 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
498 def RegisterModifiedEvent(self
, eventHandler
):
499 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
503 class DemoCodeEditor(wx
.TextCtrl
):
504 def __init__(self
, parent
):
505 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
506 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
508 def RegisterModifiedEvent(self
, eventHandler
):
509 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
511 def SetReadOnly(self
, flag
):
512 self
.SetEditable(not flag
)
513 # NOTE: STC already has this method
516 return self
.GetValue()
518 def GetPositionFromLine(line
):
519 return self
.XYToPosition(0,line
)
521 def GotoLine(self
, line
):
522 pos
= self
.editor
.GetPositionFromLine(line
)
523 self
.editor
.SetInsertionPoint(pos
)
524 self
.editor
.ShowPosition(pos
)
526 def SelectLine(self
, line
):
527 start
= self
.GetPositionFromLine(line
)
528 end
= start
+ self
.GetLineLength(line
)
529 self
.SetSelection(start
, end
)
532 #---------------------------------------------------------------------------
533 # Constants for module versions
537 modDefault
= modOriginal
539 #---------------------------------------------------------------------------
541 class DemoCodePanel(wx
.Panel
):
542 """Panel for the 'Demo Code' tab"""
543 def __init__(self
, parent
, mainFrame
):
544 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
545 if 'wxMSW' in wx
.PlatformInfo
:
547 self
.mainFrame
= mainFrame
548 self
.editor
= DemoCodeEditor(self
)
549 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
551 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
552 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
553 self
.btnSave
.Enable(False)
554 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
555 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
557 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
558 modModified
: wx
.RadioButton(self
, -1, "Modified") }
560 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
561 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
562 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
563 for modID
, radioButton
in self
.radioButtons
.items():
564 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
565 radioButton
.modID
= modID
# makes it easier for the event handler
566 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
568 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
569 self
.controlBox
.Add(self
.btnRestore
, 0)
571 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
572 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
573 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
574 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
577 self
.SetSizer(self
.box
)
580 # Loads a demo from a DemoModules object
581 def LoadDemo(self
, demoModules
):
582 self
.demoModules
= demoModules
583 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
584 demoModules
.SetActive(modModified
)
586 demoModules
.SetActive(modOriginal
)
587 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
588 self
.ActiveModuleChanged()
591 def ActiveModuleChanged(self
):
592 self
.LoadDemoSource(self
.demoModules
.GetSource())
593 self
.UpdateControlState()
597 def LoadDemoSource(self
, source
):
599 self
.editor
.SetValue(source
)
601 self
.btnSave
.Enable(False)
604 def JumpToLine(self
, line
, highlight
=False):
605 self
.editor
.GotoLine(line
)
606 self
.editor
.SetFocus()
608 self
.editor
.SelectLine(line
)
611 def UpdateControlState(self
):
612 active
= self
.demoModules
.GetActiveID()
613 # Update the radio/restore buttons
614 for moduleID
in self
.radioButtons
:
615 btn
= self
.radioButtons
[moduleID
]
616 if moduleID
== active
:
621 if self
.demoModules
.Exists(moduleID
):
623 if moduleID
== modModified
:
624 self
.btnRestore
.Enable(True)
627 if moduleID
== modModified
:
628 self
.btnRestore
.Enable(False)
631 def OnRadioButton(self
, event
):
632 radioSelected
= event
.GetEventObject()
633 modSelected
= radioSelected
.modID
634 if modSelected
!= self
.demoModules
.GetActiveID():
635 busy
= wx
.BusyInfo("Reloading demo module...")
636 self
.demoModules
.SetActive(modSelected
)
637 self
.ActiveModuleChanged()
640 def ReloadDemo(self
):
641 if self
.demoModules
.name
!= __name__
:
642 self
.mainFrame
.RunModule()
645 def OnCodeModified(self
, event
):
646 self
.btnSave
.Enable(self
.editor
.IsModified())
649 def OnSave(self
, event
):
650 if self
.demoModules
.Exists(modModified
):
651 if self
.demoModules
.GetActiveID() == modOriginal
:
652 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
653 "Do you want to continue?"
654 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
655 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
656 result
= dlg
.ShowModal()
657 if result
== wx
.ID_NO
:
661 self
.demoModules
.SetActive(modModified
)
662 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
664 # Create the demo directory if one doesn't already exist
665 if not os
.path
.exists(GetModifiedDirectory()):
667 os
.makedirs(GetModifiedDirectory())
668 if not os
.path
.exists(GetModifiedDirectory()):
669 wx
.LogMessage("BUG: Created demo directory but it still doesn't exit")
672 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
675 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
678 f
= open(modifiedFilename
, "wt")
679 source
= self
.editor
.GetText()
685 busy
= wx
.BusyInfo("Reloading demo module...")
686 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
687 self
.ActiveModuleChanged()
690 def OnRestore(self
, event
): # Handles the "Delete Modified" button
691 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
692 self
.demoModules
.Delete(modModified
)
693 os
.unlink(modifiedFilename
) # Delete the modified copy
694 busy
= wx
.BusyInfo("Reloading demo module...")
695 self
.ActiveModuleChanged()
698 #---------------------------------------------------------------------------
701 """Convert paths to the platform-specific separator"""
702 str = apply(os
.path
.join
, tuple(path
.split('/')))
703 # HACK: on Linux, a leading / gets lost...
704 if path
.startswith('/'):
709 def GetModifiedDirectory():
711 Returns the directory where modified versions of the demo files
714 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
717 def GetModifiedFilename(name
):
719 Returns the filename of the modified version of the specified demo
721 if not name
.endswith(".py"):
723 return GetModifiedDirectory() + name
726 def GetOriginalFilename(name
):
728 Returns the filename of the original version of the specified demo
730 if not name
.endswith(".py"):
735 def DoesModifiedExist(name
):
736 """Returns whether the specified demo has a modified copy"""
737 if os
.path
.exists(GetModifiedFilename(name
)):
743 #---------------------------------------------------------------------------
745 class ModuleDictWrapper
:
746 """Emulates a module with a dynamically compiled __dict__"""
747 def __init__(self
, dict):
750 def __getattr__(self
, name
):
751 if name
in self
.dict:
752 return self
.dict[name
]
758 Dynamically manages the original/modified versions of a demo
761 def __init__(self
, name
):
765 # (dict , source , filename , description , error information )
766 # ( 0 , 1 , 2 , 3 , 4 )
767 self
.modules
= [[None, "" , "" , "<original>" , None],
768 [None, "" , "" , "<modified>" , None]]
770 # load original module
771 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
772 self
.SetActive(modOriginal
)
774 # load modified module (if one exists)
775 if DoesModifiedExist(name
):
776 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
779 def LoadFromFile(self
, modID
, filename
):
780 self
.modules
[modID
][2] = filename
781 file = open(filename
, "rt")
782 self
.LoadFromSource(modID
, file.read())
786 def LoadFromSource(self
, modID
, source
):
787 self
.modules
[modID
][1] = source
791 def LoadDict(self
, modID
):
792 if self
.name
!= __name__
:
793 source
= self
.modules
[modID
][1]
794 description
= self
.modules
[modID
][3]
797 self
.modules
[modID
][0] = {}
798 code
= compile(source
, description
, "exec")
799 exec code
in self
.modules
[modID
][0]
801 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
802 self
.modules
[modID
][0] = None
804 self
.modules
[modID
][4] = None
807 def SetActive(self
, modID
):
808 if modID
!= modOriginal
and modID
!= modModified
:
811 self
.modActive
= modID
815 dict = self
.modules
[self
.modActive
][0]
819 return ModuleDictWrapper(dict)
822 def GetActiveID(self
):
823 return self
.modActive
826 def GetSource(self
, modID
= None):
828 modID
= self
.modActive
829 return self
.modules
[modID
][1]
832 def GetFilename(self
, modID
= None):
834 modID
= self
.modActive
835 return self
.modules
[self
.modActive
][2]
838 def GetErrorInfo(self
, modID
= None):
840 modID
= self
.modActive
841 return self
.modules
[self
.modActive
][4]
844 def Exists(self
, modID
):
845 return self
.modules
[modID
][1] != ""
848 def UpdateFile(self
, modID
= None):
849 """Updates the file from which a module was loaded
850 with (possibly updated) source"""
852 modID
= self
.modActive
854 source
= self
.modules
[modID
][1]
855 filename
= self
.modules
[modID
][2]
858 file = open(filename
, "wt")
864 def Delete(self
, modID
):
865 if self
.modActive
== modID
:
868 self
.modules
[modID
][0] = None
869 self
.modules
[modID
][1] = ""
870 self
.modules
[modID
][2] = ""
873 #---------------------------------------------------------------------------
876 """Wraps and stores information about the current exception"""
877 def __init__(self
, exc_info
):
880 excType
, excValue
= exc_info
[:2]
881 # traceback list entries: (filename, line number, function name, text)
882 self
.traceback
= traceback
.extract_tb(exc_info
[2])
884 # --Based on traceback.py::format_exception_only()--
885 if type(excType
) == types
.ClassType
:
886 self
.exception_type
= excType
.__name
__
888 self
.exception_type
= excType
890 # If it's a syntax error, extra information needs
891 # to be added to the traceback
892 if excType
is SyntaxError:
894 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
899 filename
= "<string>"
901 self
.traceback
.append( (filename
, lineno
, "", line
) )
904 self
.exception_details
= str(excValue
)
906 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
913 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
916 #---------------------------------------------------------------------------
918 class DemoErrorPanel(wx
.Panel
):
919 """Panel put into the demo tab when the demo fails to run due to errors"""
921 def __init__(self
, parent
, codePanel
, demoError
, log
):
922 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
923 self
.codePanel
= codePanel
927 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
930 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
931 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
933 # Exception Information
934 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
935 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
936 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
937 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
938 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
939 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
940 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
941 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
942 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
943 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
945 # Set up the traceback list
946 # This one automatically resizes last column to take up remaining space
947 from ListCtrl
import TestListCtrl
948 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
949 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
950 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
951 self
.list.InsertColumn(0, "Filename")
952 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
953 self
.list.InsertColumn(2, "Function")
954 self
.list.InsertColumn(3, "Code")
955 self
.InsertTraceback(self
.list, demoError
.traceback
)
956 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
957 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
958 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
959 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
960 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
961 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
962 + "Double-click on them to go to the offending line")
963 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
966 self
.SetSizer(self
.box
)
969 def InsertTraceback(self
, list, traceback
):
970 #Add the traceback data
971 for x
in range(len(traceback
)):
973 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
974 list.SetStringItem(x
, 1, str(data
[1])) # Line
975 list.SetStringItem(x
, 2, str(data
[2])) # Function
976 list.SetStringItem(x
, 3, str(data
[3])) # Code
978 # Check whether this entry is from the demo module
979 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
980 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
981 # Give it a blue colour
982 item
= self
.list.GetItem(x
)
983 item
.SetTextColour(wx
.BLUE
)
984 self
.list.SetItem(item
)
986 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
989 def OnItemSelected(self
, event
):
990 # This occurs before OnDoubleClick and can be used to set the
991 # currentItem. OnDoubleClick doesn't get a wxListEvent....
992 self
.currentItem
= event
.m_itemIndex
996 def OnDoubleClick(self
, event
):
997 # If double-clicking on a demo's entry, jump to the line number
998 line
= self
.list.GetItemData(self
.currentItem
)
1000 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1001 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1005 #---------------------------------------------------------------------------
1007 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1008 TBMENU_RESTORE
= wx
.NewId()
1009 TBMENU_CLOSE
= wx
.NewId()
1010 TBMENU_CHANGE
= wx
.NewId()
1011 TBMENU_REMOVE
= wx
.NewId()
1013 def __init__(self
, frame
):
1014 wx
.TaskBarIcon
.__init
__(self
)
1018 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1019 self
.SetIcon(icon
, "wxPython Demo")
1023 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1024 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1025 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1026 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1027 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1030 def CreatePopupMenu(self
):
1032 This method is called by the base class when it needs to popup
1033 the menu for the default EVT_RIGHT_DOWN event. Just create
1034 the menu how you want it and return it from this function,
1035 the base class takes care of the rest.
1038 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1039 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1040 menu
.AppendSeparator()
1041 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1042 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1046 def MakeIcon(self
, img
):
1048 The various platforms have different requirements for the
1051 if "wxMSW" in wx
.PlatformInfo
:
1052 img
= img
.Scale(16, 16)
1053 elif "wxGTK" in wx
.PlatformInfo
:
1054 img
= img
.Scale(22, 22)
1055 # wxMac can be any size upto 128x128, so leave the source img alone....
1056 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1060 def OnTaskBarActivate(self
, evt
):
1061 if self
.frame
.IsIconized():
1062 self
.frame
.Iconize(False)
1063 if not self
.frame
.IsShown():
1064 self
.frame
.Show(True)
1068 def OnTaskBarClose(self
, evt
):
1072 def OnTaskBarChange(self
, evt
):
1073 names
= [ "WXPdemo", "WXP", "Mondrian", "Test2m",
1074 "Blom08m", "Blom10m", "Blom15m" ]
1075 name
= names
[self
.imgidx
]
1077 getFunc
= getattr(images
, "get%sImage" % name
)
1079 if self
.imgidx
>= len(names
):
1082 icon
= self
.MakeIcon(getFunc())
1083 self
.SetIcon(icon
, "This is a new icon: " + name
)
1086 def OnTaskBarRemove(self
, evt
):
1090 #---------------------------------------------------------------------------
1091 class wxPythonDemo(wx
.Frame
):
1092 overviewText
= "wxPython Overview"
1094 def __init__(self
, parent
, title
):
1095 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1096 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1098 self
.SetMinSize((640,480))
1101 self
.cwd
= os
.getcwd()
1102 self
.curOverview
= ""
1103 self
.demoPage
= None
1104 self
.codePage
= None
1106 self
.firstTime
= True
1108 icon
= images
.getWXPdemoIcon()
1111 self
.tbicon
= DemoTaskBarIcon(self
)
1113 wx
.CallAfter(self
.ShowTip
)
1115 self
.otherWin
= None
1116 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1117 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1118 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1119 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1121 self
.Centre(wx
.BOTH
)
1122 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1124 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1125 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1127 def EmptyHandler(evt
): pass
1128 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1129 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1131 # Prevent TreeCtrl from displaying all items after destruction when True
1135 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1138 self
.mainmenu
= wx
.MenuBar()
1140 item
= menu
.Append(-1, '&Redirect Output',
1141 'Redirect print statements to a window',
1143 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1145 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1146 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1147 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1148 self
.mainmenu
.Append(menu
, '&File')
1152 for item
in _treeList
:
1154 for childItem
in item
[1]:
1155 mi
= submenu
.Append(-1, childItem
)
1156 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1157 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1158 self
.mainmenu
.Append(menu
, '&Demo')
1160 # Make a Demo Code menu
1161 #TODO: Add new menu items
1162 # Like the option-enabled entries to select the
1164 #TODO: should we bother?
1167 #saveID = wx.NewId()
1168 #restoreID = wx.NewId()
1170 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1171 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1172 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1173 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1174 #self.mainmenu.Append(menu, 'Demo &Code')
1179 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1180 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1181 menu
.AppendSeparator()
1183 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1184 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1185 menu
.AppendSeparator()
1186 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1187 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1189 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1190 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1191 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1192 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1193 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1194 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1195 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1196 self
.mainmenu
.Append(menu
, '&Help')
1197 self
.SetMenuBar(self
.mainmenu
)
1199 self
.finddata
= wx
.FindReplaceData()
1202 # This is another way to set Accelerators, in addition to
1203 # using the '\t<key>' syntax in the menu items.
1204 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1205 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1206 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1207 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1209 self
.SetAcceleratorTable(aTable
)
1215 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1216 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1219 root
= self
.tree
.AddRoot("wxPython Overview")
1221 for item
in _treeList
:
1222 child
= self
.tree
.AppendItem(root
, item
[0])
1223 if not firstChild
: firstChild
= child
1224 for childItem
in item
[1]:
1225 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1226 self
.treeMap
[childItem
] = theDemo
1228 self
.tree
.Expand(root
)
1229 self
.tree
.Expand(firstChild
)
1230 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1231 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1232 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1233 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1235 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1236 # we put it in a panel first because there seems to be a
1237 # refresh bug of some sort (wxGTK) when it is directly in
1240 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1241 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1243 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1244 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1245 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1246 self
.nb
.AddPage(panel
, self
.overviewText
)
1248 def OnOvrSize(evt
, ovr
=self
.ovr
):
1249 ovr
.SetSize(evt
.GetSize())
1250 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1251 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1253 if "gtk2" in wx
.PlatformInfo
:
1254 self
.ovr
.SetStandardFonts()
1255 self
.SetOverview(self
.overviewText
, mainOverview
)
1258 # Set up a log window
1259 self
.log
= wx
.TextCtrl(splitter2
, -1,
1260 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1262 # Set the wxWindows log target to be this textctrl
1263 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1265 # But instead of the above we want to show how to use our own wx.Log class
1266 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1268 # for serious debugging
1269 #wx.Log_SetActiveTarget(wx.LogStderr())
1270 #wx.Log_SetTraceMask(wx.TraceMessages)
1273 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1274 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1276 # add the windows to the splitter and split it.
1277 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1278 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1280 splitter
.SetMinimumPaneSize(120)
1281 splitter2
.SetMinimumPaneSize(60)
1283 # Make the splitter on the right expand the top window when resized
1284 def SplitterOnSize(evt
):
1285 splitter
= evt
.GetEventObject()
1286 sz
= splitter
.GetSize()
1287 splitter
.SetSashPosition(sz
.height
- 160, False)
1290 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1292 # select initial items
1293 self
.nb
.SetSelection(0)
1294 self
.tree
.SelectItem(root
)
1296 # Load 'Main' module
1297 self
.LoadDemo(self
.overviewText
)
1300 # select some other initial module?
1301 if len(sys
.argv
) > 1:
1303 if arg
.endswith('.py'):
1305 selectedDemo
= self
.treeMap
.get(arg
, None)
1307 self
.tree
.SelectItem(selectedDemo
)
1308 self
.tree
.EnsureVisible(selectedDemo
)
1311 #---------------------------------------------
1312 def WriteText(self
, text
):
1313 if text
[-1:] == '\n':
1317 def write(self
, txt
):
1320 #---------------------------------------------
1321 def OnItemExpanded(self
, event
):
1322 item
= event
.GetItem()
1323 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1326 #---------------------------------------------
1327 def OnItemCollapsed(self
, event
):
1328 item
= event
.GetItem()
1329 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1332 #---------------------------------------------
1333 def OnTreeLeftDown(self
, event
):
1334 # reset the overview text if the tree item is clicked on again
1335 pt
= event
.GetPosition();
1336 item
, flags
= self
.tree
.HitTest(pt
)
1337 if item
== self
.tree
.GetSelection():
1338 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1341 #---------------------------------------------
1342 def OnSelChanged(self
, event
):
1343 if self
.dying
or not self
.loaded
:
1346 item
= event
.GetItem()
1347 itemText
= self
.tree
.GetItemText(item
)
1348 self
.LoadDemo(itemText
)
1350 #---------------------------------------------
1351 def LoadDemo(self
, demoName
):
1353 wx
.BeginBusyCursor()
1356 self
.ShutdownDemoModule()
1358 if demoName
== self
.overviewText
:
1359 # User selected the "wxPython Overview" node
1361 # Changing the main window at runtime not yet supported...
1362 self
.demoModules
= DemoModules(__name__
)
1363 self
.SetOverview(self
.overviewText
, mainOverview
)
1364 self
.LoadDemoSource()
1365 self
.UpdateNotebook(0)
1367 if os
.path
.exists(GetOriginalFilename(demoName
)):
1368 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1369 self
.demoModules
= DemoModules(demoName
)
1370 self
.LoadDemoSource()
1373 self
.SetOverview("wxPython", mainOverview
)
1374 self
.codePage
= None
1375 self
.UpdateNotebook(0)
1379 #---------------------------------------------
1380 def LoadDemoSource(self
):
1381 self
.codePage
= None
1382 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1383 self
.codePage
.LoadDemo(self
.demoModules
)
1385 #---------------------------------------------
1386 def RunModule(self
):
1387 """Runs the active module"""
1389 module
= self
.demoModules
.GetActive()
1390 self
.ShutdownDemoModule()
1393 # o The RunTest() for all samples must now return a window that can
1394 # be palced in a tab in the main notebook.
1395 # o If an error occurs (or has occured before) an error tab is created.
1397 if module
is not None:
1398 wx
.LogMessage("Running demo module...")
1399 if hasattr(module
, "overview"):
1400 overviewText
= module
.overview
1403 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1405 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1406 DemoError(sys
.exc_info()), self
)
1408 assert self
.demoPage
is not None, "runTest must return a window!"
1411 # There was a previous error in compiling or exec-ing
1412 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1413 self
.demoModules
.GetErrorInfo(), self
)
1415 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1418 # cahnge to the demo page the first time a module is run
1419 self
.UpdateNotebook(2)
1420 self
.firstTime
= False
1422 # otherwise just stay on the same tab in case the user has changed to another one
1423 self
.UpdateNotebook()
1425 #---------------------------------------------
1426 def ShutdownDemoModule(self
):
1428 # inform the window that it's time to quit if it cares
1429 if hasattr(self
.demoPage
, "ShutdownDemo"):
1430 self
.demoPage
.ShutdownDemo()
1431 wx
.YieldIfNeeded() # in case the page has pending events
1432 self
.demoPage
= None
1434 #---------------------------------------------
1435 def UpdateNotebook(self
, select
= -1):
1439 def UpdatePage(page
, pageText
):
1442 for i
in range(nb
.GetPageCount()):
1443 if nb
.GetPageText(i
) == pageText
:
1451 nb
.AddPage(page
, pageText
)
1452 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1454 if nb
.GetPage(pagePos
) != page
:
1455 # Reload an existing page
1457 nb
.DeletePage(pagePos
)
1458 nb
.InsertPage(pagePos
, page
, pageText
)
1460 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1462 # Excellent! No redraw/flicker
1463 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1466 nb
.DeletePage(pagePos
)
1467 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1469 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1472 select
= nb
.GetSelection()
1474 UpdatePage(self
.codePage
, "Demo Code")
1475 UpdatePage(self
.demoPage
, "Demo")
1477 if select
>= 0 and select
< nb
.GetPageCount():
1478 nb
.SetSelection(select
)
1480 #---------------------------------------------
1481 def SetOverview(self
, name
, text
):
1482 self
.curOverview
= text
1484 if lead
!= '<html>' and lead
!= '<HTML>':
1485 text
= '<br>'.join(text
.split('\n'))
1487 text
= text
.decode('iso8859_1')
1488 self
.ovr
.SetPage(text
)
1489 self
.nb
.SetPageText(0, name
)
1491 #---------------------------------------------
1493 def OnFileExit(self
, *event
):
1496 def OnToggleRedirect(self
, event
):
1500 print "Print statements and other standard output will now be directed to this window."
1503 print "Print statements and other standard output will now be sent to the usual location."
1505 def OnHelpAbout(self
, event
):
1506 from About
import MyAboutBox
1507 about
= MyAboutBox(self
)
1511 def OnHelpFind(self
, event
):
1512 self
.nb
.SetSelection(1)
1513 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1517 self
.finddlg
.Show(True)
1519 def OnFind(self
, event
):
1520 editor
= self
.codePage
.editor
1521 self
.nb
.SetSelection(1)
1522 end
= editor
.GetLastPosition()
1523 textstring
= editor
.GetRange(0, end
).lower()
1524 start
= editor
.GetSelection()[1]
1525 findstring
= self
.finddata
.GetFindString().lower()
1526 loc
= textstring
.find(findstring
, start
)
1527 if loc
== -1 and start
!= 0:
1528 # string not found, start at beginning
1530 loc
= textstring
.find(findstring
, start
)
1532 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1533 'Find String Not Found in Demo File',
1534 wx
.OK | wx
.ICON_INFORMATION
)
1539 self
.finddlg
.SetFocus()
1542 self
.finddlg
.Destroy()
1543 editor
.ShowPosition(loc
)
1544 editor
.SetSelection(loc
, loc
+ len(findstring
))
1548 def OnFindNext(self
, event
):
1549 if self
.finddata
.GetFindString():
1552 self
.OnHelpFind(event
)
1554 def OnFindClose(self
, event
):
1555 event
.GetDialog().Destroy()
1558 def OnOpenShellWindow(self
, evt
):
1560 # if it already exists then just make sure it's visible
1566 # Make a PyShell window
1568 namespace
= { 'wx' : wx
,
1569 'app' : wx
.GetApp(),
1572 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1573 self
.shell
.SetSize((640,480))
1576 # Hook the close event of the main frame window so that we
1577 # close the shell at the same time if it still exists
1578 def CloseShell(evt
):
1582 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1585 #---------------------------------------------
1586 def OnCloseWindow(self
, event
):
1588 self
.demoPage
= None
1589 self
.codePage
= None
1590 self
.mainmenu
= None
1591 self
.tbicon
.Destroy()
1595 #---------------------------------------------
1596 def OnIdle(self
, event
):
1598 self
.otherWin
.Raise()
1599 self
.demoPage
= self
.otherWin
1600 self
.otherWin
= None
1603 #---------------------------------------------
1606 showTipText
= open(opj("data/showTips")).read()
1607 showTip
, index
= eval(showTipText
)
1609 showTip
, index
= (1, 0)
1611 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1613 showTip
= wx
.ShowTip(self
, tp
)
1614 index
= tp
.GetCurrentTip()
1615 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1618 #---------------------------------------------
1619 def OnDemoMenu(self
, event
):
1621 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1625 self
.tree
.SelectItem(selectedDemo
)
1626 self
.tree
.EnsureVisible(selectedDemo
)
1630 #---------------------------------------------
1631 def OnIconfiy(self
, evt
):
1632 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1635 #---------------------------------------------
1636 def OnMaximize(self
, evt
):
1637 wx
.LogMessage("OnMaximize")
1640 #---------------------------------------------
1641 def OnActivate(self
, evt
):
1642 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1645 #---------------------------------------------
1646 def OnAppActivate(self
, evt
):
1647 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1650 #---------------------------------------------------------------------------
1651 #---------------------------------------------------------------------------
1653 class MySplashScreen(wx
.SplashScreen
):
1655 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1656 wx
.SplashScreen
.__init
__(self
, bmp
,
1657 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1659 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1661 def OnClose(self
, evt
):
1663 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1665 evt
.Skip() # Make sure the default handler runs too...
1668 class MyApp(wx
.App
):
1671 Create and show the splash screen. It will then create and show
1672 the main frame when it is time to do so.
1676 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1678 # Normally when using a SplashScreen you would create it, show
1679 # it and then continue on with the applicaiton's
1680 # initialization, finally creating and showing the main
1681 # application window(s). In this case we have nothing else to
1682 # do so we'll delay showing the main frame until later (see
1683 # OnClose above) so the users can see the SplashScreen effect.
1684 splash
= MySplashScreen()
1691 #---------------------------------------------------------------------------
1695 demoPath
= os
.path
.dirname(__file__
)
1702 #---------------------------------------------------------------------------
1705 mainOverview
= """<html><body>
1708 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1709 language. It allows Python programmers to create programs with a
1710 robust, highly functional graphical user interface, simply and easily.
1711 It is implemented as a Python extension module (native code) that
1712 wraps the popular wxWindows cross platform GUI library, which is
1715 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1716 means that it is free for anyone to use and the source code is
1717 available for anyone to look at and modify. Or anyone can contribute
1718 fixes or enhancements to the project.
1720 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1721 same program will run on multiple platforms without modification.
1722 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1723 or unix-like systems, and Macintosh OS X. Since the language is
1724 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1727 <p> <b>This demo</b> is not only a collection of test cases for
1728 wxPython, but is also designed to help you learn about and how to use
1729 wxPython. Each sample is listed in the tree control on the left.
1730 When a sample is selected in the tree then a module is loaded and run
1731 (usually in a tab of this notebook,) and the source code of the module
1732 is loaded in another tab for you to browse and learn from.
1737 #----------------------------------------------------------------------------
1738 #----------------------------------------------------------------------------
1740 if __name__
== '__main__':
1744 #----------------------------------------------------------------------------