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 # managed windows == things with a (optional) caption you can close
54 ('Frames and Dialogs', [
78 # dialogs from libraries
81 'MultipleChoiceDialog',
82 'ScrolledMessageDialog',
86 ('Core Windows/Controls', [
126 ('Custom Controls', [
139 # controls coming from other libraries
140 ('More Windows/Controls', [
141 'ActiveX_FlashWindow',
142 'ActiveX_IEHtmlWindow',
144 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
160 'MaskedEditControls',
177 # How to lay out the controls in a frame/dialog
187 'XmlResourceHandler',
188 'XmlResourceSubclass',
192 ('Process and Events', [
199 ##'infoframe', # needs better explanation and some fixing
203 ('Clipboard and DnD', [
224 ##'DialogUnits', # needs more explanations
238 # need libs not coming with the demo
239 ('Samples using an external library', [
244 ('Check out the samples dir too', [
251 #---------------------------------------------------------------------------
252 # Show how to derive a custom wxLog class
254 class MyLog(wx
.PyLog
):
255 def __init__(self
, textCtrl
, logTime
=0):
256 wx
.PyLog
.__init
__(self
)
258 self
.logTime
= logTime
260 def DoLogString(self
, message
, timeStamp
):
261 #print message, timeStamp
263 # message = time.strftime("%X", time.localtime(timeStamp)) + \
266 self
.tc
.AppendText(message
+ '\n')
269 class MyTP(wx
.PyTipProvider
):
271 return "This is my tip"
273 #---------------------------------------------------------------------------
274 # A class to be used to simply display a message in the demo pane
275 # rather than running the sample itself.
277 class MessagePanel(wx
.Panel
):
278 def __init__(self
, parent
, message
, caption
='', flags
=0):
279 wx
.Panel
.__init
__(self
, parent
)
284 if flags
& wx
.ICON_EXCLAMATION
:
285 artid
= wx
.ART_WARNING
286 elif flags
& wx
.ICON_ERROR
:
288 elif flags
& wx
.ICON_QUESTION
:
289 artid
= wx
.ART_QUESTION
290 elif flags
& wx
.ICON_INFORMATION
:
291 artid
= wx
.ART_INFORMATION
293 if artid
is not None:
294 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
295 icon
= wx
.StaticBitmap(self
, -1, bmp
)
297 icon
= (32,32) # make a spacer instead
300 caption
= wx
.StaticText(self
, -1, caption
)
301 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
303 message
= wx
.StaticText(self
, -1, message
)
305 # add to sizers for layout
306 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
312 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
319 box
= wx
.BoxSizer(wx
.VERTICAL
)
321 box
.Add(hbox
, 0, wx
.EXPAND
)
328 #---------------------------------------------------------------------------
329 # A class to be used to display source code in the demo. Try using the
330 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
331 # if there is an error, such as the stc module not being present.
335 ##raise ImportError # for testing the alternate implementation
337 from StyledTextCtrl_2
import PythonSTC
339 class DemoCodeEditor(PythonSTC
):
340 def __init__(self
, parent
):
341 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
344 # Some methods to make it compatible with how the wxTextCtrl is used
345 def SetValue(self
, value
):
347 value
= value
.decode('iso8859_1')
349 self
.EmptyUndoBuffer()
352 def IsModified(self
):
353 return self
.GetModify()
358 def SetInsertionPoint(self
, pos
):
359 self
.SetCurrentPos(pos
)
362 def ShowPosition(self
, pos
):
363 line
= self
.LineFromPosition(pos
)
364 #self.EnsureVisible(line)
367 def GetLastPosition(self
):
368 return self
.GetLength()
370 def GetPositionFromLine(self
, line
):
371 return self
.PositionFromLine(line
)
373 def GetRange(self
, start
, end
):
374 return self
.GetTextRange(start
, end
)
376 def GetSelection(self
):
377 return self
.GetAnchor(), self
.GetCurrentPos()
379 def SetSelection(self
, start
, end
):
380 self
.SetSelectionStart(start
)
381 self
.SetSelectionEnd(end
)
383 def SelectLine(self
, line
):
384 start
= self
.PositionFromLine(line
)
385 end
= self
.GetLineEndPosition(line
)
386 self
.SetSelection(start
, end
)
388 def SetUpEditor(self
):
390 This method carries out the work of setting up the demo editor.
391 It's seperate so as not to clutter up the init code.
395 self
.SetLexer(stc
.STC_LEX_PYTHON
)
396 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
399 self
.SetProperty("fold", "1" )
401 # Highlight tab/space mixing (shouldn't be any)
402 self
.SetProperty("tab.timmy.whinge.level", "1")
404 # Set left and right margins
407 # Set up the numbers in the margin for margin #1
408 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
409 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
410 self
.SetMarginWidth(1, 40)
412 # Indentation and tab stuff
413 self
.SetIndent(4) # Proscribed indent size for wx
414 self
.SetIndentationGuides(True) # Show indent guides
415 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
416 self
.SetTabIndents(True) # Tab key indents
417 self
.SetTabWidth(4) # Proscribed tab size for wx
418 self
.SetUseTabs(False) # Use spaces rather than tabs, or
419 # TabTimmy will complain!
421 self
.SetViewWhiteSpace(False) # Don't view white space
423 # EOL: Since we are loading/saving ourselves, and the
424 # strings will always have \n's in them, set the STC to
425 # edit them that way.
426 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
427 self
.SetViewEOL(False)
429 # No right-edge mode indicator
430 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
432 # Setup a margin to hold fold markers
433 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
434 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
435 self
.SetMarginSensitive(2, True)
436 self
.SetMarginWidth(2, 12)
438 # and now set up the fold markers
439 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
440 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
441 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
442 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
443 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
444 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
445 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
447 # Global default style
448 if wx
.Platform
== '__WXMSW__':
449 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
450 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
452 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
453 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
455 # Clear styles and revert to default.
458 # Following style specs only indicate differences from default.
459 # The rest remains unchanged.
461 # Line numbers in margin
462 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
464 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
466 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
468 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
471 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
473 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
474 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
476 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
477 # Strings and characters
478 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
479 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
481 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
483 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
484 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
486 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
488 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
490 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
491 # Identifiers. I leave this as not bold because everything seems
492 # to be an identifier if it doesn't match the above criterae
493 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
496 self
.SetCaretForeground("BLUE")
497 # Selection background
498 self
.SetSelBackground(1, '#66CCFF')
500 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
501 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
503 def RegisterModifiedEvent(self
, eventHandler
):
504 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
508 class DemoCodeEditor(wx
.TextCtrl
):
509 def __init__(self
, parent
):
510 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
511 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
513 def RegisterModifiedEvent(self
, eventHandler
):
514 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
516 def SetReadOnly(self
, flag
):
517 self
.SetEditable(not flag
)
518 # NOTE: STC already has this method
521 return self
.GetValue()
523 def GetPositionFromLine(self
, line
):
524 return self
.XYToPosition(0,line
)
526 def GotoLine(self
, line
):
527 pos
= self
.GetPositionFromLine(line
)
528 self
.SetInsertionPoint(pos
)
529 self
.ShowPosition(pos
)
531 def SelectLine(self
, line
):
532 start
= self
.GetPositionFromLine(line
)
533 end
= start
+ self
.GetLineLength(line
)
534 self
.SetSelection(start
, end
)
537 #---------------------------------------------------------------------------
538 # Constants for module versions
542 modDefault
= modOriginal
544 #---------------------------------------------------------------------------
546 class DemoCodePanel(wx
.Panel
):
547 """Panel for the 'Demo Code' tab"""
548 def __init__(self
, parent
, mainFrame
):
549 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
550 if 'wxMSW' in wx
.PlatformInfo
:
552 self
.mainFrame
= mainFrame
553 self
.editor
= DemoCodeEditor(self
)
554 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
556 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
557 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
558 self
.btnSave
.Enable(False)
559 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
560 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
562 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
563 modModified
: wx
.RadioButton(self
, -1, "Modified") }
565 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
566 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
567 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
568 for modID
, radioButton
in self
.radioButtons
.items():
569 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
570 radioButton
.modID
= modID
# makes it easier for the event handler
571 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
573 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
574 self
.controlBox
.Add(self
.btnRestore
, 0)
576 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
577 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
578 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
579 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
582 self
.SetSizer(self
.box
)
585 # Loads a demo from a DemoModules object
586 def LoadDemo(self
, demoModules
):
587 self
.demoModules
= demoModules
588 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
589 demoModules
.SetActive(modModified
)
591 demoModules
.SetActive(modOriginal
)
592 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
593 self
.ActiveModuleChanged()
596 def ActiveModuleChanged(self
):
597 self
.LoadDemoSource(self
.demoModules
.GetSource())
598 self
.UpdateControlState()
602 def LoadDemoSource(self
, source
):
604 self
.editor
.SetValue(source
)
606 self
.btnSave
.Enable(False)
609 def JumpToLine(self
, line
, highlight
=False):
610 self
.editor
.GotoLine(line
)
611 self
.editor
.SetFocus()
613 self
.editor
.SelectLine(line
)
616 def UpdateControlState(self
):
617 active
= self
.demoModules
.GetActiveID()
618 # Update the radio/restore buttons
619 for moduleID
in self
.radioButtons
:
620 btn
= self
.radioButtons
[moduleID
]
621 if moduleID
== active
:
626 if self
.demoModules
.Exists(moduleID
):
628 if moduleID
== modModified
:
629 self
.btnRestore
.Enable(True)
632 if moduleID
== modModified
:
633 self
.btnRestore
.Enable(False)
636 def OnRadioButton(self
, event
):
637 radioSelected
= event
.GetEventObject()
638 modSelected
= radioSelected
.modID
639 if modSelected
!= self
.demoModules
.GetActiveID():
640 busy
= wx
.BusyInfo("Reloading demo module...")
641 self
.demoModules
.SetActive(modSelected
)
642 self
.ActiveModuleChanged()
645 def ReloadDemo(self
):
646 if self
.demoModules
.name
!= __name__
:
647 self
.mainFrame
.RunModule()
650 def OnCodeModified(self
, event
):
651 self
.btnSave
.Enable(self
.editor
.IsModified())
654 def OnSave(self
, event
):
655 if self
.demoModules
.Exists(modModified
):
656 if self
.demoModules
.GetActiveID() == modOriginal
:
657 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
658 "Do you want to continue?"
659 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
660 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
661 result
= dlg
.ShowModal()
662 if result
== wx
.ID_NO
:
666 self
.demoModules
.SetActive(modModified
)
667 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
669 # Create the demo directory if one doesn't already exist
670 if not os
.path
.exists(GetModifiedDirectory()):
672 os
.makedirs(GetModifiedDirectory())
673 if not os
.path
.exists(GetModifiedDirectory()):
674 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
677 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
680 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
683 f
= open(modifiedFilename
, "wt")
684 source
= self
.editor
.GetText()
690 busy
= wx
.BusyInfo("Reloading demo module...")
691 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
692 self
.ActiveModuleChanged()
695 def OnRestore(self
, event
): # Handles the "Delete Modified" button
696 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
697 self
.demoModules
.Delete(modModified
)
698 os
.unlink(modifiedFilename
) # Delete the modified copy
699 busy
= wx
.BusyInfo("Reloading demo module...")
700 self
.ActiveModuleChanged()
703 #---------------------------------------------------------------------------
706 """Convert paths to the platform-specific separator"""
707 str = apply(os
.path
.join
, tuple(path
.split('/')))
708 # HACK: on Linux, a leading / gets lost...
709 if path
.startswith('/'):
714 def GetModifiedDirectory():
716 Returns the directory where modified versions of the demo files
719 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
722 def GetModifiedFilename(name
):
724 Returns the filename of the modified version of the specified demo
726 if not name
.endswith(".py"):
728 return GetModifiedDirectory() + name
731 def GetOriginalFilename(name
):
733 Returns the filename of the original version of the specified demo
735 if not name
.endswith(".py"):
740 def DoesModifiedExist(name
):
741 """Returns whether the specified demo has a modified copy"""
742 if os
.path
.exists(GetModifiedFilename(name
)):
748 #---------------------------------------------------------------------------
750 class ModuleDictWrapper
:
751 """Emulates a module with a dynamically compiled __dict__"""
752 def __init__(self
, dict):
755 def __getattr__(self
, name
):
756 if name
in self
.dict:
757 return self
.dict[name
]
763 Dynamically manages the original/modified versions of a demo
766 def __init__(self
, name
):
770 # (dict , source , filename , description , error information )
771 # ( 0 , 1 , 2 , 3 , 4 )
772 self
.modules
= [[None, "" , "" , "<original>" , None],
773 [None, "" , "" , "<modified>" , None]]
775 # load original module
776 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
777 self
.SetActive(modOriginal
)
779 # load modified module (if one exists)
780 if DoesModifiedExist(name
):
781 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
784 def LoadFromFile(self
, modID
, filename
):
785 self
.modules
[modID
][2] = filename
786 file = open(filename
, "rt")
787 self
.LoadFromSource(modID
, file.read())
791 def LoadFromSource(self
, modID
, source
):
792 self
.modules
[modID
][1] = source
796 def LoadDict(self
, modID
):
797 if self
.name
!= __name__
:
798 source
= self
.modules
[modID
][1]
799 description
= self
.modules
[modID
][3]
802 self
.modules
[modID
][0] = {}
803 code
= compile(source
, description
, "exec")
804 exec code
in self
.modules
[modID
][0]
806 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
807 self
.modules
[modID
][0] = None
809 self
.modules
[modID
][4] = None
812 def SetActive(self
, modID
):
813 if modID
!= modOriginal
and modID
!= modModified
:
816 self
.modActive
= modID
820 dict = self
.modules
[self
.modActive
][0]
824 return ModuleDictWrapper(dict)
827 def GetActiveID(self
):
828 return self
.modActive
831 def GetSource(self
, modID
= None):
833 modID
= self
.modActive
834 return self
.modules
[modID
][1]
837 def GetFilename(self
, modID
= None):
839 modID
= self
.modActive
840 return self
.modules
[self
.modActive
][2]
843 def GetErrorInfo(self
, modID
= None):
845 modID
= self
.modActive
846 return self
.modules
[self
.modActive
][4]
849 def Exists(self
, modID
):
850 return self
.modules
[modID
][1] != ""
853 def UpdateFile(self
, modID
= None):
854 """Updates the file from which a module was loaded
855 with (possibly updated) source"""
857 modID
= self
.modActive
859 source
= self
.modules
[modID
][1]
860 filename
= self
.modules
[modID
][2]
863 file = open(filename
, "wt")
869 def Delete(self
, modID
):
870 if self
.modActive
== modID
:
873 self
.modules
[modID
][0] = None
874 self
.modules
[modID
][1] = ""
875 self
.modules
[modID
][2] = ""
878 #---------------------------------------------------------------------------
881 """Wraps and stores information about the current exception"""
882 def __init__(self
, exc_info
):
885 excType
, excValue
= exc_info
[:2]
886 # traceback list entries: (filename, line number, function name, text)
887 self
.traceback
= traceback
.extract_tb(exc_info
[2])
889 # --Based on traceback.py::format_exception_only()--
890 if type(excType
) == types
.ClassType
:
891 self
.exception_type
= excType
.__name
__
893 self
.exception_type
= excType
895 # If it's a syntax error, extra information needs
896 # to be added to the traceback
897 if excType
is SyntaxError:
899 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
904 filename
= "<string>"
906 self
.traceback
.append( (filename
, lineno
, "", line
) )
909 self
.exception_details
= str(excValue
)
911 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
918 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
921 #---------------------------------------------------------------------------
923 class DemoErrorPanel(wx
.Panel
):
924 """Panel put into the demo tab when the demo fails to run due to errors"""
926 def __init__(self
, parent
, codePanel
, demoError
, log
):
927 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
928 self
.codePanel
= codePanel
932 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
935 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
936 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
938 # Exception Information
939 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
940 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
941 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
942 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
943 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
944 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
945 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
946 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
947 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
948 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
950 # Set up the traceback list
951 # This one automatically resizes last column to take up remaining space
952 from ListCtrl
import TestListCtrl
953 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
954 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
955 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
956 self
.list.InsertColumn(0, "Filename")
957 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
958 self
.list.InsertColumn(2, "Function")
959 self
.list.InsertColumn(3, "Code")
960 self
.InsertTraceback(self
.list, demoError
.traceback
)
961 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
962 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
963 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
964 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
965 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
966 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
967 + "Double-click on them to go to the offending line")
968 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
971 self
.SetSizer(self
.box
)
974 def InsertTraceback(self
, list, traceback
):
975 #Add the traceback data
976 for x
in range(len(traceback
)):
978 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
979 list.SetStringItem(x
, 1, str(data
[1])) # Line
980 list.SetStringItem(x
, 2, str(data
[2])) # Function
981 list.SetStringItem(x
, 3, str(data
[3])) # Code
983 # Check whether this entry is from the demo module
984 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
985 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
986 # Give it a blue colour
987 item
= self
.list.GetItem(x
)
988 item
.SetTextColour(wx
.BLUE
)
989 self
.list.SetItem(item
)
991 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
994 def OnItemSelected(self
, event
):
995 # This occurs before OnDoubleClick and can be used to set the
996 # currentItem. OnDoubleClick doesn't get a wxListEvent....
997 self
.currentItem
= event
.m_itemIndex
1001 def OnDoubleClick(self
, event
):
1002 # If double-clicking on a demo's entry, jump to the line number
1003 line
= self
.list.GetItemData(self
.currentItem
)
1005 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1006 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1010 #---------------------------------------------------------------------------
1012 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1013 TBMENU_RESTORE
= wx
.NewId()
1014 TBMENU_CLOSE
= wx
.NewId()
1015 TBMENU_CHANGE
= wx
.NewId()
1016 TBMENU_REMOVE
= wx
.NewId()
1018 def __init__(self
, frame
):
1019 wx
.TaskBarIcon
.__init
__(self
)
1023 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1024 self
.SetIcon(icon
, "wxPython Demo")
1028 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1029 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1030 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1031 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1032 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1035 def CreatePopupMenu(self
):
1037 This method is called by the base class when it needs to popup
1038 the menu for the default EVT_RIGHT_DOWN event. Just create
1039 the menu how you want it and return it from this function,
1040 the base class takes care of the rest.
1043 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1044 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1045 menu
.AppendSeparator()
1046 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1047 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1051 def MakeIcon(self
, img
):
1053 The various platforms have different requirements for the
1056 if "wxMSW" in wx
.PlatformInfo
:
1057 img
= img
.Scale(16, 16)
1058 elif "wxGTK" in wx
.PlatformInfo
:
1059 img
= img
.Scale(22, 22)
1060 # wxMac can be any size upto 128x128, so leave the source img alone....
1061 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1065 def OnTaskBarActivate(self
, evt
):
1066 if self
.frame
.IsIconized():
1067 self
.frame
.Iconize(False)
1068 if not self
.frame
.IsShown():
1069 self
.frame
.Show(True)
1073 def OnTaskBarClose(self
, evt
):
1077 def OnTaskBarChange(self
, evt
):
1078 names
= [ "WXPdemo", "WXP", "Mondrian", "Test2m",
1079 "Blom08m", "Blom10m", "Blom15m" ]
1080 name
= names
[self
.imgidx
]
1082 getFunc
= getattr(images
, "get%sImage" % name
)
1084 if self
.imgidx
>= len(names
):
1087 icon
= self
.MakeIcon(getFunc())
1088 self
.SetIcon(icon
, "This is a new icon: " + name
)
1091 def OnTaskBarRemove(self
, evt
):
1095 #---------------------------------------------------------------------------
1096 class wxPythonDemo(wx
.Frame
):
1097 overviewText
= "wxPython Overview"
1099 def __init__(self
, parent
, title
):
1100 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1101 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1103 self
.SetMinSize((640,480))
1106 self
.cwd
= os
.getcwd()
1107 self
.curOverview
= ""
1108 self
.demoPage
= None
1109 self
.codePage
= None
1111 self
.firstTime
= True
1114 icon
= images
.getWXPdemoIcon()
1117 self
.tbicon
= DemoTaskBarIcon(self
)
1119 wx
.CallAfter(self
.ShowTip
)
1121 self
.otherWin
= None
1122 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1123 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1124 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1125 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1127 self
.Centre(wx
.BOTH
)
1128 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1130 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1131 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1133 def EmptyHandler(evt
): pass
1134 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1135 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1137 # Prevent TreeCtrl from displaying all items after destruction when True
1141 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1144 self
.mainmenu
= wx
.MenuBar()
1146 item
= menu
.Append(-1, '&Redirect Output',
1147 'Redirect print statements to a window',
1149 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1151 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1152 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1153 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1154 self
.mainmenu
.Append(menu
, '&File')
1158 for item
in _treeList
:
1160 for childItem
in item
[1]:
1161 mi
= submenu
.Append(-1, childItem
)
1162 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1163 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1164 self
.mainmenu
.Append(menu
, '&Demo')
1166 # Make a Demo Code menu
1167 #TODO: Add new menu items
1168 # Like the option-enabled entries to select the
1170 #TODO: should we bother?
1173 #saveID = wx.NewId()
1174 #restoreID = wx.NewId()
1176 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1177 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1178 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1179 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1180 #self.mainmenu.Append(menu, 'Demo &Code')
1185 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1186 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1187 menu
.AppendSeparator()
1189 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1190 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1191 menu
.AppendSeparator()
1192 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1193 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1195 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1196 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1197 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1198 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1199 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1200 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1201 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1202 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1203 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1204 self
.mainmenu
.Append(menu
, '&Help')
1205 self
.SetMenuBar(self
.mainmenu
)
1207 self
.finddata
= wx
.FindReplaceData()
1210 # This is another way to set Accelerators, in addition to
1211 # using the '\t<key>' syntax in the menu items.
1212 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1213 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1214 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1215 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1217 self
.SetAcceleratorTable(aTable
)
1223 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1224 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1227 root
= self
.tree
.AddRoot("wxPython Overview")
1229 for item
in _treeList
:
1230 child
= self
.tree
.AppendItem(root
, item
[0])
1231 if not firstChild
: firstChild
= child
1232 for childItem
in item
[1]:
1233 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1234 self
.treeMap
[childItem
] = theDemo
1236 self
.tree
.Expand(root
)
1237 self
.tree
.Expand(firstChild
)
1238 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1239 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1240 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1241 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1243 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1244 # we put it in a panel first because there seems to be a
1245 # refresh bug of some sort (wxGTK) when it is directly in
1248 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1249 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1251 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1252 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1253 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1254 self
.nb
.AddPage(panel
, self
.overviewText
)
1256 def OnOvrSize(evt
, ovr
=self
.ovr
):
1257 ovr
.SetSize(evt
.GetSize())
1258 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1259 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1261 if "gtk2" in wx
.PlatformInfo
:
1262 self
.ovr
.SetStandardFonts()
1263 self
.SetOverview(self
.overviewText
, mainOverview
)
1266 # Set up a log window
1267 self
.log
= wx
.TextCtrl(splitter2
, -1,
1268 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1270 # Set the wxWindows log target to be this textctrl
1271 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1273 # But instead of the above we want to show how to use our own wx.Log class
1274 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1276 # for serious debugging
1277 #wx.Log_SetActiveTarget(wx.LogStderr())
1278 #wx.Log_SetTraceMask(wx.TraceMessages)
1281 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1282 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1284 # add the windows to the splitter and split it.
1285 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1286 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1288 splitter
.SetMinimumPaneSize(120)
1289 splitter2
.SetMinimumPaneSize(60)
1291 # Make the splitter on the right expand the top window when resized
1292 def SplitterOnSize(evt
):
1293 splitter
= evt
.GetEventObject()
1294 sz
= splitter
.GetSize()
1295 splitter
.SetSashPosition(sz
.height
- 160, False)
1298 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1300 # select initial items
1301 self
.nb
.SetSelection(0)
1302 self
.tree
.SelectItem(root
)
1304 # Load 'Main' module
1305 self
.LoadDemo(self
.overviewText
)
1308 # select some other initial module?
1309 if len(sys
.argv
) > 1:
1311 if arg
.endswith('.py'):
1313 selectedDemo
= self
.treeMap
.get(arg
, None)
1315 self
.tree
.SelectItem(selectedDemo
)
1316 self
.tree
.EnsureVisible(selectedDemo
)
1319 #---------------------------------------------
1320 def WriteText(self
, text
):
1321 if text
[-1:] == '\n':
1325 def write(self
, txt
):
1328 #---------------------------------------------
1329 def OnItemExpanded(self
, event
):
1330 item
= event
.GetItem()
1331 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1334 #---------------------------------------------
1335 def OnItemCollapsed(self
, event
):
1336 item
= event
.GetItem()
1337 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1340 #---------------------------------------------
1341 def OnTreeLeftDown(self
, event
):
1342 # reset the overview text if the tree item is clicked on again
1343 pt
= event
.GetPosition();
1344 item
, flags
= self
.tree
.HitTest(pt
)
1345 if item
== self
.tree
.GetSelection():
1346 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1349 #---------------------------------------------
1350 def OnSelChanged(self
, event
):
1351 if self
.dying
or not self
.loaded
:
1354 item
= event
.GetItem()
1355 itemText
= self
.tree
.GetItemText(item
)
1356 self
.LoadDemo(itemText
)
1358 #---------------------------------------------
1359 def LoadDemo(self
, demoName
):
1361 wx
.BeginBusyCursor()
1364 self
.ShutdownDemoModule()
1366 if demoName
== self
.overviewText
:
1367 # User selected the "wxPython Overview" node
1369 # Changing the main window at runtime not yet supported...
1370 self
.demoModules
= DemoModules(__name__
)
1371 self
.SetOverview(self
.overviewText
, mainOverview
)
1372 self
.LoadDemoSource()
1373 self
.UpdateNotebook(0)
1375 if os
.path
.exists(GetOriginalFilename(demoName
)):
1376 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1377 self
.demoModules
= DemoModules(demoName
)
1378 self
.LoadDemoSource()
1381 self
.SetOverview("wxPython", mainOverview
)
1382 self
.codePage
= None
1383 self
.UpdateNotebook(0)
1387 #---------------------------------------------
1388 def LoadDemoSource(self
):
1389 self
.codePage
= None
1390 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1391 self
.codePage
.LoadDemo(self
.demoModules
)
1393 #---------------------------------------------
1394 def RunModule(self
):
1395 """Runs the active module"""
1397 module
= self
.demoModules
.GetActive()
1398 self
.ShutdownDemoModule()
1401 # o The RunTest() for all samples must now return a window that can
1402 # be palced in a tab in the main notebook.
1403 # o If an error occurs (or has occured before) an error tab is created.
1405 if module
is not None:
1406 wx
.LogMessage("Running demo module...")
1407 if hasattr(module
, "overview"):
1408 overviewText
= module
.overview
1411 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1413 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1414 DemoError(sys
.exc_info()), self
)
1416 assert self
.demoPage
is not None, "runTest must return a window!"
1419 # There was a previous error in compiling or exec-ing
1420 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1421 self
.demoModules
.GetErrorInfo(), self
)
1423 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1426 # cahnge to the demo page the first time a module is run
1427 self
.UpdateNotebook(2)
1428 self
.firstTime
= False
1430 # otherwise just stay on the same tab in case the user has changed to another one
1431 self
.UpdateNotebook()
1433 #---------------------------------------------
1434 def ShutdownDemoModule(self
):
1436 # inform the window that it's time to quit if it cares
1437 if hasattr(self
.demoPage
, "ShutdownDemo"):
1438 self
.demoPage
.ShutdownDemo()
1439 wx
.YieldIfNeeded() # in case the page has pending events
1440 self
.demoPage
= None
1442 #---------------------------------------------
1443 def UpdateNotebook(self
, select
= -1):
1447 def UpdatePage(page
, pageText
):
1450 for i
in range(nb
.GetPageCount()):
1451 if nb
.GetPageText(i
) == pageText
:
1459 nb
.AddPage(page
, pageText
)
1460 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1462 if nb
.GetPage(pagePos
) != page
:
1463 # Reload an existing page
1465 nb
.DeletePage(pagePos
)
1466 nb
.InsertPage(pagePos
, page
, pageText
)
1468 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1470 # Excellent! No redraw/flicker
1471 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1474 nb
.DeletePage(pagePos
)
1475 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1477 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1480 select
= nb
.GetSelection()
1482 UpdatePage(self
.codePage
, "Demo Code")
1483 UpdatePage(self
.demoPage
, "Demo")
1485 if select
>= 0 and select
< nb
.GetPageCount():
1486 nb
.SetSelection(select
)
1488 #---------------------------------------------
1489 def SetOverview(self
, name
, text
):
1490 self
.curOverview
= text
1492 if lead
!= '<html>' and lead
!= '<HTML>':
1493 text
= '<br>'.join(text
.split('\n'))
1495 text
= text
.decode('iso8859_1')
1496 self
.ovr
.SetPage(text
)
1497 self
.nb
.SetPageText(0, name
)
1499 #---------------------------------------------
1501 def OnFileExit(self
, *event
):
1504 def OnToggleRedirect(self
, event
):
1508 print "Print statements and other standard output will now be directed to this window."
1511 print "Print statements and other standard output will now be sent to the usual location."
1513 def OnHelpAbout(self
, event
):
1514 from About
import MyAboutBox
1515 about
= MyAboutBox(self
)
1519 def OnHelpFind(self
, event
):
1520 if self
.finddlg
!= None:
1523 self
.nb
.SetSelection(1)
1524 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1528 self
.finddlg
.Show(True)
1531 def OnUpdateFindItems(self
, evt
):
1532 evt
.Enable(self
.finddlg
== None)
1535 def OnFind(self
, event
):
1536 editor
= self
.codePage
.editor
1537 self
.nb
.SetSelection(1)
1538 end
= editor
.GetLastPosition()
1539 textstring
= editor
.GetRange(0, end
).lower()
1540 start
= editor
.GetSelection()[1]
1541 findstring
= self
.finddata
.GetFindString().lower()
1542 loc
= textstring
.find(findstring
, start
)
1543 if loc
== -1 and start
!= 0:
1544 # string not found, start at beginning
1546 loc
= textstring
.find(findstring
, start
)
1548 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1549 'Find String Not Found in Demo File',
1550 wx
.OK | wx
.ICON_INFORMATION
)
1555 self
.finddlg
.SetFocus()
1558 self
.finddlg
.Destroy()
1560 editor
.ShowPosition(loc
)
1561 editor
.SetSelection(loc
, loc
+ len(findstring
))
1565 def OnFindNext(self
, event
):
1566 if self
.finddata
.GetFindString():
1569 self
.OnHelpFind(event
)
1571 def OnFindClose(self
, event
):
1572 event
.GetDialog().Destroy()
1576 def OnOpenShellWindow(self
, evt
):
1578 # if it already exists then just make sure it's visible
1584 # Make a PyShell window
1586 namespace
= { 'wx' : wx
,
1587 'app' : wx
.GetApp(),
1590 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1591 self
.shell
.SetSize((640,480))
1594 # Hook the close event of the main frame window so that we
1595 # close the shell at the same time if it still exists
1596 def CloseShell(evt
):
1600 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1603 #---------------------------------------------
1604 def OnCloseWindow(self
, event
):
1606 self
.demoPage
= None
1607 self
.codePage
= None
1608 self
.mainmenu
= None
1609 self
.tbicon
.Destroy()
1613 #---------------------------------------------
1614 def OnIdle(self
, event
):
1616 self
.otherWin
.Raise()
1617 self
.demoPage
= self
.otherWin
1618 self
.otherWin
= None
1621 #---------------------------------------------
1624 showTipText
= open(opj("data/showTips")).read()
1625 showTip
, index
= eval(showTipText
)
1627 showTip
, index
= (1, 0)
1629 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1631 showTip
= wx
.ShowTip(self
, tp
)
1632 index
= tp
.GetCurrentTip()
1633 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1636 #---------------------------------------------
1637 def OnDemoMenu(self
, event
):
1639 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1643 self
.tree
.SelectItem(selectedDemo
)
1644 self
.tree
.EnsureVisible(selectedDemo
)
1648 #---------------------------------------------
1649 def OnIconfiy(self
, evt
):
1650 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1653 #---------------------------------------------
1654 def OnMaximize(self
, evt
):
1655 wx
.LogMessage("OnMaximize")
1658 #---------------------------------------------
1659 def OnActivate(self
, evt
):
1660 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1663 #---------------------------------------------
1664 def OnAppActivate(self
, evt
):
1665 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1668 #---------------------------------------------------------------------------
1669 #---------------------------------------------------------------------------
1671 class MySplashScreen(wx
.SplashScreen
):
1673 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1674 wx
.SplashScreen
.__init
__(self
, bmp
,
1675 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1677 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1679 def OnClose(self
, evt
):
1681 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1683 evt
.Skip() # Make sure the default handler runs too...
1686 class MyApp(wx
.App
):
1689 Create and show the splash screen. It will then create and show
1690 the main frame when it is time to do so.
1693 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1696 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1698 # Normally when using a SplashScreen you would create it, show
1699 # it and then continue on with the applicaiton's
1700 # initialization, finally creating and showing the main
1701 # application window(s). In this case we have nothing else to
1702 # do so we'll delay showing the main frame until later (see
1703 # OnClose above) so the users can see the SplashScreen effect.
1704 splash
= MySplashScreen()
1711 #---------------------------------------------------------------------------
1715 demoPath
= os
.path
.dirname(__file__
)
1722 #---------------------------------------------------------------------------
1725 mainOverview
= """<html><body>
1728 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1729 language. It allows Python programmers to create programs with a
1730 robust, highly functional graphical user interface, simply and easily.
1731 It is implemented as a Python extension module (native code) that
1732 wraps the popular wxWindows cross platform GUI library, which is
1735 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1736 means that it is free for anyone to use and the source code is
1737 available for anyone to look at and modify. Or anyone can contribute
1738 fixes or enhancements to the project.
1740 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1741 same program will run on multiple platforms without modification.
1742 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1743 or unix-like systems, and Macintosh OS X. Since the language is
1744 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1747 <p> <b>This demo</b> is not only a collection of test cases for
1748 wxPython, but is also designed to help you learn about and how to use
1749 wxPython. Each sample is listed in the tree control on the left.
1750 When a sample is selected in the tree then a module is loaded and run
1751 (usually in a tab of this notebook,) and the source code of the module
1752 is loaded in another tab for you to browse and learn from.
1757 #----------------------------------------------------------------------------
1758 #----------------------------------------------------------------------------
1760 if __name__
== '__main__':
1764 #----------------------------------------------------------------------------