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', [
77 # dialogs from libraries
80 'MultipleChoiceDialog',
81 'ScrolledMessageDialog',
85 ('Core Windows/Controls', [
124 ('Custom Controls', [
137 # controls coming from other libraries
138 ('More Windows/Controls', [
139 'ActiveX_FlashWindow',
140 'ActiveX_IEHtmlWindow',
142 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
155 'MaskedEditControls',
172 # How to lay out the controls in a frame/dialog
182 'XmlResourceHandler',
183 'XmlResourceSubclass',
187 ('Process and Events', [
194 ##'infoframe', # needs better explaination and some fixing
198 ('Clipboard and DnD', [
219 ##'DialogUnits', # needs more explainations
232 # need libs not coming with the demo
233 ('Samples using an external library', [
238 ('Check out the samples dir too', [
245 #---------------------------------------------------------------------------
246 # Show how to derive a custom wxLog class
248 class MyLog(wx
.PyLog
):
249 def __init__(self
, textCtrl
, logTime
=0):
250 wx
.PyLog
.__init
__(self
)
252 self
.logTime
= logTime
254 def DoLogString(self
, message
, timeStamp
):
255 #print message, timeStamp
257 # message = time.strftime("%X", time.localtime(timeStamp)) + \
260 self
.tc
.AppendText(message
+ '\n')
263 class MyTP(wx
.PyTipProvider
):
265 return "This is my tip"
267 #---------------------------------------------------------------------------
268 # A class to be used to simply display a message in the demo pane
269 # rather than running the sample itself.
271 class MessagePanel(wx
.Panel
):
272 def __init__(self
, parent
, message
, caption
='', flags
=0):
273 wx
.Panel
.__init
__(self
, parent
)
278 if flags
& wx
.ICON_EXCLAMATION
:
279 artid
= wx
.ART_WARNING
280 elif flags
& wx
.ICON_ERROR
:
282 elif flags
& wx
.ICON_QUESTION
:
283 artid
= wx
.ART_QUESTION
284 elif flags
& wx
.ICON_INFORMATION
:
285 artid
= wx
.ART_INFORMATION
287 if artid
is not None:
288 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
289 icon
= wx
.StaticBitmap(self
, -1, bmp
)
291 icon
= (32,32) # make a spacer instead
294 caption
= wx
.StaticText(self
, -1, caption
)
295 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
297 message
= wx
.StaticText(self
, -1, message
)
299 # add to sizers for layout
300 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
306 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
313 box
= wx
.BoxSizer(wx
.VERTICAL
)
315 box
.Add(hbox
, 0, wx
.EXPAND
)
322 #---------------------------------------------------------------------------
323 # A class to be used to display source code in the demo. Try using the
324 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
325 # if there is an error, such as the stc module not being present.
329 ##raise ImportError # for testing the alternate implementation
331 from StyledTextCtrl_2
import PythonSTC
333 class DemoCodeEditor(PythonSTC
):
334 def __init__(self
, parent
):
335 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
338 # Some methods to make it compatible with how the wxTextCtrl is used
339 def SetValue(self
, value
):
341 value
= value
.decode('iso8859_1')
343 self
.EmptyUndoBuffer()
346 def IsModified(self
):
347 return self
.GetModify()
352 def SetInsertionPoint(self
, pos
):
353 self
.SetCurrentPos(pos
)
356 def ShowPosition(self
, pos
):
357 line
= self
.LineFromPosition(pos
)
358 #self.EnsureVisible(line)
361 def GetLastPosition(self
):
362 return self
.GetLength()
364 def GetPositionFromLine(self
, line
):
365 return self
.PositionFromLine(line
)
367 def GetRange(self
, start
, end
):
368 return self
.GetTextRange(start
, end
)
370 def GetSelection(self
):
371 return self
.GetAnchor(), self
.GetCurrentPos()
373 def SetSelection(self
, start
, end
):
374 self
.SetSelectionStart(start
)
375 self
.SetSelectionEnd(end
)
377 def SelectLine(self
, line
):
378 start
= self
.PositionFromLine(line
)
379 end
= self
.GetLineEndPosition(line
)
380 self
.SetSelection(start
, end
)
382 def SetUpEditor(self
):
384 This method carries out the work of setting up the demo editor.
385 It's seperate so as not to clutter up the init code.
389 self
.SetLexer(stc
.STC_LEX_PYTHON
)
390 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
393 self
.SetProperty("fold", "1" )
395 # Highlight tab/space mixing (shouldn't be any)
396 self
.SetProperty("tab.timmy.whinge.level", "1")
398 # Set left and right margins
401 # Set up the numbers in the margin for margin #1
402 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
403 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
404 self
.SetMarginWidth(1, 40)
406 # Indentation and tab stuff
407 self
.SetIndent(4) # Proscribed indent size for wx
408 self
.SetIndentationGuides(True) # Show indent guides
409 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
410 self
.SetTabIndents(True) # Tab key indents
411 self
.SetTabWidth(4) # Proscribed tab size for wx
412 self
.SetUseTabs(False) # Use spaces rather than tabs, or
413 # TabTimmy will complain!
415 self
.SetViewWhiteSpace(False) # Don't view white space
417 # EOL: Since we are loading/saving ourselves, and the
418 # strings will always have \n's in them, set the STC to
419 # edit them that way.
420 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
421 self
.SetViewEOL(False)
423 # No right-edge mode indicator
424 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
426 # Setup a margin to hold fold markers
427 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
428 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
429 self
.SetMarginSensitive(2, True)
430 self
.SetMarginWidth(2, 12)
432 # and now set up the fold markers
433 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
434 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
435 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
436 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
437 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
438 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
439 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
441 # Global default style
442 if wx
.Platform
== '__WXMSW__':
443 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
444 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
446 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
447 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
449 # Clear styles and revert to default.
452 # Following style specs only indicate differences from default.
453 # The rest remains unchanged.
455 # Line numbers in margin
456 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
458 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
460 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
462 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
465 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
467 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
468 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
470 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
471 # Strings and characters
472 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
473 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
475 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
477 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
478 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
480 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
482 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
484 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
485 # Identifiers. I leave this as not bold because everything seems
486 # to be an identifier if it doesn't match the above criterae
487 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
490 self
.SetCaretForeground("BLUE")
491 # Selection background
492 self
.SetSelBackground(1, '#66CCFF')
494 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
495 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
497 def RegisterModifiedEvent(self
, eventHandler
):
498 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
502 class DemoCodeEditor(wx
.TextCtrl
):
503 def __init__(self
, parent
):
504 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
505 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
507 def RegisterModifiedEvent(self
, eventHandler
):
508 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
510 def SetReadOnly(self
, flag
):
511 self
.SetEditable(not flag
)
512 # NOTE: STC already has this method
515 return self
.GetValue()
517 def GetPositionFromLine(self
, line
):
518 return self
.XYToPosition(0,line
)
520 def GotoLine(self
, line
):
521 pos
= self
.GetPositionFromLine(line
)
522 self
.SetInsertionPoint(pos
)
523 self
.ShowPosition(pos
)
525 def SelectLine(self
, line
):
526 start
= self
.GetPositionFromLine(line
)
527 end
= start
+ self
.GetLineLength(line
)
528 self
.SetSelection(start
, end
)
531 #---------------------------------------------------------------------------
532 # Constants for module versions
536 modDefault
= modOriginal
538 #---------------------------------------------------------------------------
540 class DemoCodePanel(wx
.Panel
):
541 """Panel for the 'Demo Code' tab"""
542 def __init__(self
, parent
, mainFrame
):
543 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
544 if 'wxMSW' in wx
.PlatformInfo
:
546 self
.mainFrame
= mainFrame
547 self
.editor
= DemoCodeEditor(self
)
548 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
550 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
551 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
552 self
.btnSave
.Enable(False)
553 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
554 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
556 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
557 modModified
: wx
.RadioButton(self
, -1, "Modified") }
559 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
560 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
561 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
562 for modID
, radioButton
in self
.radioButtons
.items():
563 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
564 radioButton
.modID
= modID
# makes it easier for the event handler
565 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
567 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
568 self
.controlBox
.Add(self
.btnRestore
, 0)
570 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
571 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
572 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
573 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
576 self
.SetSizer(self
.box
)
579 # Loads a demo from a DemoModules object
580 def LoadDemo(self
, demoModules
):
581 self
.demoModules
= demoModules
582 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
583 demoModules
.SetActive(modModified
)
585 demoModules
.SetActive(modOriginal
)
586 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
587 self
.ActiveModuleChanged()
590 def ActiveModuleChanged(self
):
591 self
.LoadDemoSource(self
.demoModules
.GetSource())
592 self
.UpdateControlState()
596 def LoadDemoSource(self
, source
):
598 self
.editor
.SetValue(source
)
600 self
.btnSave
.Enable(False)
603 def JumpToLine(self
, line
, highlight
=False):
604 self
.editor
.GotoLine(line
)
605 self
.editor
.SetFocus()
607 self
.editor
.SelectLine(line
)
610 def UpdateControlState(self
):
611 active
= self
.demoModules
.GetActiveID()
612 # Update the radio/restore buttons
613 for moduleID
in self
.radioButtons
:
614 btn
= self
.radioButtons
[moduleID
]
615 if moduleID
== active
:
620 if self
.demoModules
.Exists(moduleID
):
622 if moduleID
== modModified
:
623 self
.btnRestore
.Enable(True)
626 if moduleID
== modModified
:
627 self
.btnRestore
.Enable(False)
630 def OnRadioButton(self
, event
):
631 radioSelected
= event
.GetEventObject()
632 modSelected
= radioSelected
.modID
633 if modSelected
!= self
.demoModules
.GetActiveID():
634 busy
= wx
.BusyInfo("Reloading demo module...")
635 self
.demoModules
.SetActive(modSelected
)
636 self
.ActiveModuleChanged()
639 def ReloadDemo(self
):
640 if self
.demoModules
.name
!= __name__
:
641 self
.mainFrame
.RunModule()
644 def OnCodeModified(self
, event
):
645 self
.btnSave
.Enable(self
.editor
.IsModified())
648 def OnSave(self
, event
):
649 if self
.demoModules
.Exists(modModified
):
650 if self
.demoModules
.GetActiveID() == modOriginal
:
651 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
652 "Do you want to continue?"
653 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
654 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
655 result
= dlg
.ShowModal()
656 if result
== wx
.ID_NO
:
660 self
.demoModules
.SetActive(modModified
)
661 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
663 # Create the demo directory if one doesn't already exist
664 if not os
.path
.exists(GetModifiedDirectory()):
666 os
.makedirs(GetModifiedDirectory())
667 if not os
.path
.exists(GetModifiedDirectory()):
668 wx
.LogMessage("BUG: Created demo directory but it still doesn't exit")
671 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
674 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
677 f
= open(modifiedFilename
, "wt")
678 source
= self
.editor
.GetText()
684 busy
= wx
.BusyInfo("Reloading demo module...")
685 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
686 self
.ActiveModuleChanged()
689 def OnRestore(self
, event
): # Handles the "Delete Modified" button
690 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
691 self
.demoModules
.Delete(modModified
)
692 os
.unlink(modifiedFilename
) # Delete the modified copy
693 busy
= wx
.BusyInfo("Reloading demo module...")
694 self
.ActiveModuleChanged()
697 #---------------------------------------------------------------------------
700 """Convert paths to the platform-specific separator"""
701 str = apply(os
.path
.join
, tuple(path
.split('/')))
702 # HACK: on Linux, a leading / gets lost...
703 if path
.startswith('/'):
708 def GetModifiedDirectory():
710 Returns the directory where modified versions of the demo files
713 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
716 def GetModifiedFilename(name
):
718 Returns the filename of the modified version of the specified demo
720 if not name
.endswith(".py"):
722 return GetModifiedDirectory() + name
725 def GetOriginalFilename(name
):
727 Returns the filename of the original version of the specified demo
729 if not name
.endswith(".py"):
734 def DoesModifiedExist(name
):
735 """Returns whether the specified demo has a modified copy"""
736 if os
.path
.exists(GetModifiedFilename(name
)):
742 #---------------------------------------------------------------------------
744 class ModuleDictWrapper
:
745 """Emulates a module with a dynamically compiled __dict__"""
746 def __init__(self
, dict):
749 def __getattr__(self
, name
):
750 if name
in self
.dict:
751 return self
.dict[name
]
757 Dynamically manages the original/modified versions of a demo
760 def __init__(self
, name
):
764 # (dict , source , filename , description , error information )
765 # ( 0 , 1 , 2 , 3 , 4 )
766 self
.modules
= [[None, "" , "" , "<original>" , None],
767 [None, "" , "" , "<modified>" , None]]
769 # load original module
770 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
771 self
.SetActive(modOriginal
)
773 # load modified module (if one exists)
774 if DoesModifiedExist(name
):
775 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
778 def LoadFromFile(self
, modID
, filename
):
779 self
.modules
[modID
][2] = filename
780 file = open(filename
, "rt")
781 self
.LoadFromSource(modID
, file.read())
785 def LoadFromSource(self
, modID
, source
):
786 self
.modules
[modID
][1] = source
790 def LoadDict(self
, modID
):
791 if self
.name
!= __name__
:
792 source
= self
.modules
[modID
][1]
793 description
= self
.modules
[modID
][3]
796 self
.modules
[modID
][0] = {}
797 code
= compile(source
, description
, "exec")
798 exec code
in self
.modules
[modID
][0]
800 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
801 self
.modules
[modID
][0] = None
803 self
.modules
[modID
][4] = None
806 def SetActive(self
, modID
):
807 if modID
!= modOriginal
and modID
!= modModified
:
810 self
.modActive
= modID
814 dict = self
.modules
[self
.modActive
][0]
818 return ModuleDictWrapper(dict)
821 def GetActiveID(self
):
822 return self
.modActive
825 def GetSource(self
, modID
= None):
827 modID
= self
.modActive
828 return self
.modules
[modID
][1]
831 def GetFilename(self
, modID
= None):
833 modID
= self
.modActive
834 return self
.modules
[self
.modActive
][2]
837 def GetErrorInfo(self
, modID
= None):
839 modID
= self
.modActive
840 return self
.modules
[self
.modActive
][4]
843 def Exists(self
, modID
):
844 return self
.modules
[modID
][1] != ""
847 def UpdateFile(self
, modID
= None):
848 """Updates the file from which a module was loaded
849 with (possibly updated) source"""
851 modID
= self
.modActive
853 source
= self
.modules
[modID
][1]
854 filename
= self
.modules
[modID
][2]
857 file = open(filename
, "wt")
863 def Delete(self
, modID
):
864 if self
.modActive
== modID
:
867 self
.modules
[modID
][0] = None
868 self
.modules
[modID
][1] = ""
869 self
.modules
[modID
][2] = ""
872 #---------------------------------------------------------------------------
875 """Wraps and stores information about the current exception"""
876 def __init__(self
, exc_info
):
879 excType
, excValue
= exc_info
[:2]
880 # traceback list entries: (filename, line number, function name, text)
881 self
.traceback
= traceback
.extract_tb(exc_info
[2])
883 # --Based on traceback.py::format_exception_only()--
884 if type(excType
) == types
.ClassType
:
885 self
.exception_type
= excType
.__name
__
887 self
.exception_type
= excType
889 # If it's a syntax error, extra information needs
890 # to be added to the traceback
891 if excType
is SyntaxError:
893 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
898 filename
= "<string>"
900 self
.traceback
.append( (filename
, lineno
, "", line
) )
903 self
.exception_details
= str(excValue
)
905 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
912 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
915 #---------------------------------------------------------------------------
917 class DemoErrorPanel(wx
.Panel
):
918 """Panel put into the demo tab when the demo fails to run due to errors"""
920 def __init__(self
, parent
, codePanel
, demoError
, log
):
921 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
922 self
.codePanel
= codePanel
926 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
929 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
930 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
932 # Exception Information
933 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
934 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
935 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
936 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
937 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
938 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
939 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
940 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
941 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
942 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
944 # Set up the traceback list
945 # This one automatically resizes last column to take up remaining space
946 from ListCtrl
import TestListCtrl
947 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
948 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
949 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
950 self
.list.InsertColumn(0, "Filename")
951 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
952 self
.list.InsertColumn(2, "Function")
953 self
.list.InsertColumn(3, "Code")
954 self
.InsertTraceback(self
.list, demoError
.traceback
)
955 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
956 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
957 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
958 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
959 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
960 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
961 + "Double-click on them to go to the offending line")
962 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
965 self
.SetSizer(self
.box
)
968 def InsertTraceback(self
, list, traceback
):
969 #Add the traceback data
970 for x
in range(len(traceback
)):
972 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
973 list.SetStringItem(x
, 1, str(data
[1])) # Line
974 list.SetStringItem(x
, 2, str(data
[2])) # Function
975 list.SetStringItem(x
, 3, str(data
[3])) # Code
977 # Check whether this entry is from the demo module
978 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
979 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
980 # Give it a blue colour
981 item
= self
.list.GetItem(x
)
982 item
.SetTextColour(wx
.BLUE
)
983 self
.list.SetItem(item
)
985 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
988 def OnItemSelected(self
, event
):
989 # This occurs before OnDoubleClick and can be used to set the
990 # currentItem. OnDoubleClick doesn't get a wxListEvent....
991 self
.currentItem
= event
.m_itemIndex
995 def OnDoubleClick(self
, event
):
996 # If double-clicking on a demo's entry, jump to the line number
997 line
= self
.list.GetItemData(self
.currentItem
)
999 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1000 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1004 #---------------------------------------------------------------------------
1006 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1007 TBMENU_RESTORE
= wx
.NewId()
1008 TBMENU_CLOSE
= wx
.NewId()
1009 TBMENU_CHANGE
= wx
.NewId()
1010 TBMENU_REMOVE
= wx
.NewId()
1012 def __init__(self
, frame
):
1013 wx
.TaskBarIcon
.__init
__(self
)
1017 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1018 self
.SetIcon(icon
, "wxPython Demo")
1022 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1023 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1024 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1025 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1026 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1029 def CreatePopupMenu(self
):
1031 This method is called by the base class when it needs to popup
1032 the menu for the default EVT_RIGHT_DOWN event. Just create
1033 the menu how you want it and return it from this function,
1034 the base class takes care of the rest.
1037 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1038 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1039 menu
.AppendSeparator()
1040 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1041 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1045 def MakeIcon(self
, img
):
1047 The various platforms have different requirements for the
1050 if "wxMSW" in wx
.PlatformInfo
:
1051 img
= img
.Scale(16, 16)
1052 elif "wxGTK" in wx
.PlatformInfo
:
1053 img
= img
.Scale(22, 22)
1054 # wxMac can be any size upto 128x128, so leave the source img alone....
1055 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1059 def OnTaskBarActivate(self
, evt
):
1060 if self
.frame
.IsIconized():
1061 self
.frame
.Iconize(False)
1062 if not self
.frame
.IsShown():
1063 self
.frame
.Show(True)
1067 def OnTaskBarClose(self
, evt
):
1071 def OnTaskBarChange(self
, evt
):
1072 names
= [ "WXPdemo", "WXP", "Mondrian", "Test2m",
1073 "Blom08m", "Blom10m", "Blom15m" ]
1074 name
= names
[self
.imgidx
]
1076 getFunc
= getattr(images
, "get%sImage" % name
)
1078 if self
.imgidx
>= len(names
):
1081 icon
= self
.MakeIcon(getFunc())
1082 self
.SetIcon(icon
, "This is a new icon: " + name
)
1085 def OnTaskBarRemove(self
, evt
):
1089 #---------------------------------------------------------------------------
1090 class wxPythonDemo(wx
.Frame
):
1091 overviewText
= "wxPython Overview"
1093 def __init__(self
, parent
, title
):
1094 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1095 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1097 self
.SetMinSize((640,480))
1100 self
.cwd
= os
.getcwd()
1101 self
.curOverview
= ""
1102 self
.demoPage
= None
1103 self
.codePage
= None
1105 self
.firstTime
= True
1107 icon
= images
.getWXPdemoIcon()
1110 self
.tbicon
= DemoTaskBarIcon(self
)
1112 wx
.CallAfter(self
.ShowTip
)
1114 self
.otherWin
= None
1115 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1116 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1117 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1118 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1120 self
.Centre(wx
.BOTH
)
1121 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1123 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1124 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1126 def EmptyHandler(evt
): pass
1127 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1128 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1130 # Prevent TreeCtrl from displaying all items after destruction when True
1134 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1137 self
.mainmenu
= wx
.MenuBar()
1139 item
= menu
.Append(-1, '&Redirect Output',
1140 'Redirect print statements to a window',
1142 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1144 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1145 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1146 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1147 self
.mainmenu
.Append(menu
, '&File')
1151 for item
in _treeList
:
1153 for childItem
in item
[1]:
1154 mi
= submenu
.Append(-1, childItem
)
1155 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1156 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1157 self
.mainmenu
.Append(menu
, '&Demo')
1159 # Make a Demo Code menu
1160 #TODO: Add new menu items
1161 # Like the option-enabled entries to select the
1163 #TODO: should we bother?
1166 #saveID = wx.NewId()
1167 #restoreID = wx.NewId()
1169 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1170 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1171 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1172 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1173 #self.mainmenu.Append(menu, 'Demo &Code')
1178 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1179 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1180 menu
.AppendSeparator()
1182 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1183 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1184 menu
.AppendSeparator()
1185 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1186 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1188 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1189 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1190 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1191 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1192 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1193 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1194 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1195 self
.mainmenu
.Append(menu
, '&Help')
1196 self
.SetMenuBar(self
.mainmenu
)
1198 self
.finddata
= wx
.FindReplaceData()
1201 # This is another way to set Accelerators, in addition to
1202 # using the '\t<key>' syntax in the menu items.
1203 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1204 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1205 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1206 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1208 self
.SetAcceleratorTable(aTable
)
1214 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1215 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1218 root
= self
.tree
.AddRoot("wxPython Overview")
1220 for item
in _treeList
:
1221 child
= self
.tree
.AppendItem(root
, item
[0])
1222 if not firstChild
: firstChild
= child
1223 for childItem
in item
[1]:
1224 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1225 self
.treeMap
[childItem
] = theDemo
1227 self
.tree
.Expand(root
)
1228 self
.tree
.Expand(firstChild
)
1229 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1230 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1231 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1232 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1234 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1235 # we put it in a panel first because there seems to be a
1236 # refresh bug of some sort (wxGTK) when it is directly in
1239 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1240 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1242 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1243 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1244 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1245 self
.nb
.AddPage(panel
, self
.overviewText
)
1247 def OnOvrSize(evt
, ovr
=self
.ovr
):
1248 ovr
.SetSize(evt
.GetSize())
1249 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1250 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1252 if "gtk2" in wx
.PlatformInfo
:
1253 self
.ovr
.SetStandardFonts()
1254 self
.SetOverview(self
.overviewText
, mainOverview
)
1257 # Set up a log window
1258 self
.log
= wx
.TextCtrl(splitter2
, -1,
1259 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1261 # Set the wxWindows log target to be this textctrl
1262 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1264 # But instead of the above we want to show how to use our own wx.Log class
1265 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1267 # for serious debugging
1268 #wx.Log_SetActiveTarget(wx.LogStderr())
1269 #wx.Log_SetTraceMask(wx.TraceMessages)
1272 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1273 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1275 # add the windows to the splitter and split it.
1276 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1277 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1279 splitter
.SetMinimumPaneSize(120)
1280 splitter2
.SetMinimumPaneSize(60)
1282 # Make the splitter on the right expand the top window when resized
1283 def SplitterOnSize(evt
):
1284 splitter
= evt
.GetEventObject()
1285 sz
= splitter
.GetSize()
1286 splitter
.SetSashPosition(sz
.height
- 160, False)
1289 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1291 # select initial items
1292 self
.nb
.SetSelection(0)
1293 self
.tree
.SelectItem(root
)
1295 # Load 'Main' module
1296 self
.LoadDemo(self
.overviewText
)
1299 # select some other initial module?
1300 if len(sys
.argv
) > 1:
1302 if arg
.endswith('.py'):
1304 selectedDemo
= self
.treeMap
.get(arg
, None)
1306 self
.tree
.SelectItem(selectedDemo
)
1307 self
.tree
.EnsureVisible(selectedDemo
)
1310 #---------------------------------------------
1311 def WriteText(self
, text
):
1312 if text
[-1:] == '\n':
1316 def write(self
, txt
):
1319 #---------------------------------------------
1320 def OnItemExpanded(self
, event
):
1321 item
= event
.GetItem()
1322 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1325 #---------------------------------------------
1326 def OnItemCollapsed(self
, event
):
1327 item
= event
.GetItem()
1328 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1331 #---------------------------------------------
1332 def OnTreeLeftDown(self
, event
):
1333 # reset the overview text if the tree item is clicked on again
1334 pt
= event
.GetPosition();
1335 item
, flags
= self
.tree
.HitTest(pt
)
1336 if item
== self
.tree
.GetSelection():
1337 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1340 #---------------------------------------------
1341 def OnSelChanged(self
, event
):
1342 if self
.dying
or not self
.loaded
:
1345 item
= event
.GetItem()
1346 itemText
= self
.tree
.GetItemText(item
)
1347 self
.LoadDemo(itemText
)
1349 #---------------------------------------------
1350 def LoadDemo(self
, demoName
):
1352 wx
.BeginBusyCursor()
1355 self
.ShutdownDemoModule()
1357 if demoName
== self
.overviewText
:
1358 # User selected the "wxPython Overview" node
1360 # Changing the main window at runtime not yet supported...
1361 self
.demoModules
= DemoModules(__name__
)
1362 self
.SetOverview(self
.overviewText
, mainOverview
)
1363 self
.LoadDemoSource()
1364 self
.UpdateNotebook(0)
1366 if os
.path
.exists(GetOriginalFilename(demoName
)):
1367 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1368 self
.demoModules
= DemoModules(demoName
)
1369 self
.LoadDemoSource()
1372 self
.SetOverview("wxPython", mainOverview
)
1373 self
.codePage
= None
1374 self
.UpdateNotebook(0)
1378 #---------------------------------------------
1379 def LoadDemoSource(self
):
1380 self
.codePage
= None
1381 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1382 self
.codePage
.LoadDemo(self
.demoModules
)
1384 #---------------------------------------------
1385 def RunModule(self
):
1386 """Runs the active module"""
1388 module
= self
.demoModules
.GetActive()
1389 self
.ShutdownDemoModule()
1392 # o The RunTest() for all samples must now return a window that can
1393 # be palced in a tab in the main notebook.
1394 # o If an error occurs (or has occured before) an error tab is created.
1396 if module
is not None:
1397 wx
.LogMessage("Running demo module...")
1398 if hasattr(module
, "overview"):
1399 overviewText
= module
.overview
1402 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1404 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1405 DemoError(sys
.exc_info()), self
)
1407 assert self
.demoPage
is not None, "runTest must return a window!"
1410 # There was a previous error in compiling or exec-ing
1411 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1412 self
.demoModules
.GetErrorInfo(), self
)
1414 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1417 # cahnge to the demo page the first time a module is run
1418 self
.UpdateNotebook(2)
1419 self
.firstTime
= False
1421 # otherwise just stay on the same tab in case the user has changed to another one
1422 self
.UpdateNotebook()
1424 #---------------------------------------------
1425 def ShutdownDemoModule(self
):
1427 # inform the window that it's time to quit if it cares
1428 if hasattr(self
.demoPage
, "ShutdownDemo"):
1429 self
.demoPage
.ShutdownDemo()
1430 wx
.YieldIfNeeded() # in case the page has pending events
1431 self
.demoPage
= None
1433 #---------------------------------------------
1434 def UpdateNotebook(self
, select
= -1):
1438 def UpdatePage(page
, pageText
):
1441 for i
in range(nb
.GetPageCount()):
1442 if nb
.GetPageText(i
) == pageText
:
1450 nb
.AddPage(page
, pageText
)
1451 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1453 if nb
.GetPage(pagePos
) != page
:
1454 # Reload an existing page
1456 nb
.DeletePage(pagePos
)
1457 nb
.InsertPage(pagePos
, page
, pageText
)
1459 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1461 # Excellent! No redraw/flicker
1462 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1465 nb
.DeletePage(pagePos
)
1466 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1468 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1471 select
= nb
.GetSelection()
1473 UpdatePage(self
.codePage
, "Demo Code")
1474 UpdatePage(self
.demoPage
, "Demo")
1476 if select
>= 0 and select
< nb
.GetPageCount():
1477 nb
.SetSelection(select
)
1479 #---------------------------------------------
1480 def SetOverview(self
, name
, text
):
1481 self
.curOverview
= text
1483 if lead
!= '<html>' and lead
!= '<HTML>':
1484 text
= '<br>'.join(text
.split('\n'))
1486 text
= text
.decode('iso8859_1')
1487 self
.ovr
.SetPage(text
)
1488 self
.nb
.SetPageText(0, name
)
1490 #---------------------------------------------
1492 def OnFileExit(self
, *event
):
1495 def OnToggleRedirect(self
, event
):
1499 print "Print statements and other standard output will now be directed to this window."
1502 print "Print statements and other standard output will now be sent to the usual location."
1504 def OnHelpAbout(self
, event
):
1505 from About
import MyAboutBox
1506 about
= MyAboutBox(self
)
1510 def OnHelpFind(self
, event
):
1511 self
.nb
.SetSelection(1)
1512 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1516 self
.finddlg
.Show(True)
1518 def OnFind(self
, event
):
1519 editor
= self
.codePage
.editor
1520 self
.nb
.SetSelection(1)
1521 end
= editor
.GetLastPosition()
1522 textstring
= editor
.GetRange(0, end
).lower()
1523 start
= editor
.GetSelection()[1]
1524 findstring
= self
.finddata
.GetFindString().lower()
1525 loc
= textstring
.find(findstring
, start
)
1526 if loc
== -1 and start
!= 0:
1527 # string not found, start at beginning
1529 loc
= textstring
.find(findstring
, start
)
1531 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1532 'Find String Not Found in Demo File',
1533 wx
.OK | wx
.ICON_INFORMATION
)
1538 self
.finddlg
.SetFocus()
1541 self
.finddlg
.Destroy()
1542 editor
.ShowPosition(loc
)
1543 editor
.SetSelection(loc
, loc
+ len(findstring
))
1547 def OnFindNext(self
, event
):
1548 if self
.finddata
.GetFindString():
1551 self
.OnHelpFind(event
)
1553 def OnFindClose(self
, event
):
1554 event
.GetDialog().Destroy()
1557 def OnOpenShellWindow(self
, evt
):
1559 # if it already exists then just make sure it's visible
1565 # Make a PyShell window
1567 namespace
= { 'wx' : wx
,
1568 'app' : wx
.GetApp(),
1571 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1572 self
.shell
.SetSize((640,480))
1575 # Hook the close event of the main frame window so that we
1576 # close the shell at the same time if it still exists
1577 def CloseShell(evt
):
1581 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1584 #---------------------------------------------
1585 def OnCloseWindow(self
, event
):
1587 self
.demoPage
= None
1588 self
.codePage
= None
1589 self
.mainmenu
= None
1590 self
.tbicon
.Destroy()
1594 #---------------------------------------------
1595 def OnIdle(self
, event
):
1597 self
.otherWin
.Raise()
1598 self
.demoPage
= self
.otherWin
1599 self
.otherWin
= None
1602 #---------------------------------------------
1605 showTipText
= open(opj("data/showTips")).read()
1606 showTip
, index
= eval(showTipText
)
1608 showTip
, index
= (1, 0)
1610 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1612 showTip
= wx
.ShowTip(self
, tp
)
1613 index
= tp
.GetCurrentTip()
1614 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1617 #---------------------------------------------
1618 def OnDemoMenu(self
, event
):
1620 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1624 self
.tree
.SelectItem(selectedDemo
)
1625 self
.tree
.EnsureVisible(selectedDemo
)
1629 #---------------------------------------------
1630 def OnIconfiy(self
, evt
):
1631 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1634 #---------------------------------------------
1635 def OnMaximize(self
, evt
):
1636 wx
.LogMessage("OnMaximize")
1639 #---------------------------------------------
1640 def OnActivate(self
, evt
):
1641 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1644 #---------------------------------------------
1645 def OnAppActivate(self
, evt
):
1646 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1649 #---------------------------------------------------------------------------
1650 #---------------------------------------------------------------------------
1652 class MySplashScreen(wx
.SplashScreen
):
1654 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1655 wx
.SplashScreen
.__init
__(self
, bmp
,
1656 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1658 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1660 def OnClose(self
, evt
):
1662 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1664 evt
.Skip() # Make sure the default handler runs too...
1667 class MyApp(wx
.App
):
1670 Create and show the splash screen. It will then create and show
1671 the main frame when it is time to do so.
1675 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1677 # Normally when using a SplashScreen you would create it, show
1678 # it and then continue on with the applicaiton's
1679 # initialization, finally creating and showing the main
1680 # application window(s). In this case we have nothing else to
1681 # do so we'll delay showing the main frame until later (see
1682 # OnClose above) so the users can see the SplashScreen effect.
1683 splash
= MySplashScreen()
1690 #---------------------------------------------------------------------------
1694 demoPath
= os
.path
.dirname(__file__
)
1701 #---------------------------------------------------------------------------
1704 mainOverview
= """<html><body>
1707 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1708 language. It allows Python programmers to create programs with a
1709 robust, highly functional graphical user interface, simply and easily.
1710 It is implemented as a Python extension module (native code) that
1711 wraps the popular wxWindows cross platform GUI library, which is
1714 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1715 means that it is free for anyone to use and the source code is
1716 available for anyone to look at and modify. Or anyone can contribute
1717 fixes or enhancements to the project.
1719 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1720 same program will run on multiple platforms without modification.
1721 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1722 or unix-like systems, and Macintosh OS X. Since the language is
1723 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1726 <p> <b>This demo</b> is not only a collection of test cases for
1727 wxPython, but is also designed to help you learn about and how to use
1728 wxPython. Each sample is listed in the tree control on the left.
1729 When a sample is selected in the tree then a module is loaded and run
1730 (usually in a tab of this notebook,) and the source code of the module
1731 is loaded in another tab for you to browse and learn from.
1736 #----------------------------------------------------------------------------
1737 #----------------------------------------------------------------------------
1739 if __name__
== '__main__':
1743 #----------------------------------------------------------------------------