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', [
128 ('Custom Controls', [
141 # controls coming from other libraries
142 ('More Windows/Controls', [
143 'ActiveX_FlashWindow',
144 'ActiveX_IEHtmlWindow',
146 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
161 'MaskedEditControls',
178 # How to lay out the controls in a frame/dialog
188 'XmlResourceHandler',
189 'XmlResourceSubclass',
193 ('Process and Events', [
200 ##'infoframe', # needs better explanation and some fixing
204 ('Clipboard and DnD', [
225 ##'DialogUnits', # needs more explanations
239 # need libs not coming with the demo
240 ('Samples using an external library', [
245 ('Check out the samples dir too', [
252 #---------------------------------------------------------------------------
253 # Show how to derive a custom wxLog class
255 class MyLog(wx
.PyLog
):
256 def __init__(self
, textCtrl
, logTime
=0):
257 wx
.PyLog
.__init
__(self
)
259 self
.logTime
= logTime
261 def DoLogString(self
, message
, timeStamp
):
262 #print message, timeStamp
264 # message = time.strftime("%X", time.localtime(timeStamp)) + \
267 self
.tc
.AppendText(message
+ '\n')
270 class MyTP(wx
.PyTipProvider
):
272 return "This is my tip"
274 #---------------------------------------------------------------------------
275 # A class to be used to simply display a message in the demo pane
276 # rather than running the sample itself.
278 class MessagePanel(wx
.Panel
):
279 def __init__(self
, parent
, message
, caption
='', flags
=0):
280 wx
.Panel
.__init
__(self
, parent
)
285 if flags
& wx
.ICON_EXCLAMATION
:
286 artid
= wx
.ART_WARNING
287 elif flags
& wx
.ICON_ERROR
:
289 elif flags
& wx
.ICON_QUESTION
:
290 artid
= wx
.ART_QUESTION
291 elif flags
& wx
.ICON_INFORMATION
:
292 artid
= wx
.ART_INFORMATION
294 if artid
is not None:
295 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
296 icon
= wx
.StaticBitmap(self
, -1, bmp
)
298 icon
= (32,32) # make a spacer instead
301 caption
= wx
.StaticText(self
, -1, caption
)
302 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
304 message
= wx
.StaticText(self
, -1, message
)
306 # add to sizers for layout
307 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
313 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
320 box
= wx
.BoxSizer(wx
.VERTICAL
)
322 box
.Add(hbox
, 0, wx
.EXPAND
)
329 #---------------------------------------------------------------------------
330 # A class to be used to display source code in the demo. Try using the
331 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
332 # if there is an error, such as the stc module not being present.
336 ##raise ImportError # for testing the alternate implementation
338 from StyledTextCtrl_2
import PythonSTC
340 class DemoCodeEditor(PythonSTC
):
341 def __init__(self
, parent
):
342 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
345 # Some methods to make it compatible with how the wxTextCtrl is used
346 def SetValue(self
, value
):
348 value
= value
.decode('iso8859_1')
350 self
.EmptyUndoBuffer()
353 def IsModified(self
):
354 return self
.GetModify()
359 def SetInsertionPoint(self
, pos
):
360 self
.SetCurrentPos(pos
)
363 def ShowPosition(self
, pos
):
364 line
= self
.LineFromPosition(pos
)
365 #self.EnsureVisible(line)
368 def GetLastPosition(self
):
369 return self
.GetLength()
371 def GetPositionFromLine(self
, line
):
372 return self
.PositionFromLine(line
)
374 def GetRange(self
, start
, end
):
375 return self
.GetTextRange(start
, end
)
377 def GetSelection(self
):
378 return self
.GetAnchor(), self
.GetCurrentPos()
380 def SetSelection(self
, start
, end
):
381 self
.SetSelectionStart(start
)
382 self
.SetSelectionEnd(end
)
384 def SelectLine(self
, line
):
385 start
= self
.PositionFromLine(line
)
386 end
= self
.GetLineEndPosition(line
)
387 self
.SetSelection(start
, end
)
389 def SetUpEditor(self
):
391 This method carries out the work of setting up the demo editor.
392 It's seperate so as not to clutter up the init code.
396 self
.SetLexer(stc
.STC_LEX_PYTHON
)
397 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
400 self
.SetProperty("fold", "1" )
402 # Highlight tab/space mixing (shouldn't be any)
403 self
.SetProperty("tab.timmy.whinge.level", "1")
405 # Set left and right margins
408 # Set up the numbers in the margin for margin #1
409 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
410 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
411 self
.SetMarginWidth(1, 40)
413 # Indentation and tab stuff
414 self
.SetIndent(4) # Proscribed indent size for wx
415 self
.SetIndentationGuides(True) # Show indent guides
416 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
417 self
.SetTabIndents(True) # Tab key indents
418 self
.SetTabWidth(4) # Proscribed tab size for wx
419 self
.SetUseTabs(False) # Use spaces rather than tabs, or
420 # TabTimmy will complain!
422 self
.SetViewWhiteSpace(False) # Don't view white space
424 # EOL: Since we are loading/saving ourselves, and the
425 # strings will always have \n's in them, set the STC to
426 # edit them that way.
427 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
428 self
.SetViewEOL(False)
430 # No right-edge mode indicator
431 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
433 # Setup a margin to hold fold markers
434 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
435 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
436 self
.SetMarginSensitive(2, True)
437 self
.SetMarginWidth(2, 12)
439 # and now set up the fold markers
440 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
441 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
442 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
443 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
444 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
445 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
446 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
448 # Global default style
449 if wx
.Platform
== '__WXMSW__':
450 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
451 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
453 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
454 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
456 # Clear styles and revert to default.
459 # Following style specs only indicate differences from default.
460 # The rest remains unchanged.
462 # Line numbers in margin
463 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
465 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
467 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
469 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
472 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
474 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
475 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
477 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
478 # Strings and characters
479 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
480 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
482 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
484 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
485 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
487 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
489 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
491 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
492 # Identifiers. I leave this as not bold because everything seems
493 # to be an identifier if it doesn't match the above criterae
494 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
497 self
.SetCaretForeground("BLUE")
498 # Selection background
499 self
.SetSelBackground(1, '#66CCFF')
501 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
502 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
504 def RegisterModifiedEvent(self
, eventHandler
):
505 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
509 class DemoCodeEditor(wx
.TextCtrl
):
510 def __init__(self
, parent
):
511 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
512 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
514 def RegisterModifiedEvent(self
, eventHandler
):
515 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
517 def SetReadOnly(self
, flag
):
518 self
.SetEditable(not flag
)
519 # NOTE: STC already has this method
522 return self
.GetValue()
524 def GetPositionFromLine(self
, line
):
525 return self
.XYToPosition(0,line
)
527 def GotoLine(self
, line
):
528 pos
= self
.GetPositionFromLine(line
)
529 self
.SetInsertionPoint(pos
)
530 self
.ShowPosition(pos
)
532 def SelectLine(self
, line
):
533 start
= self
.GetPositionFromLine(line
)
534 end
= start
+ self
.GetLineLength(line
)
535 self
.SetSelection(start
, end
)
538 #---------------------------------------------------------------------------
539 # Constants for module versions
543 modDefault
= modOriginal
545 #---------------------------------------------------------------------------
547 class DemoCodePanel(wx
.Panel
):
548 """Panel for the 'Demo Code' tab"""
549 def __init__(self
, parent
, mainFrame
):
550 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
551 if 'wxMSW' in wx
.PlatformInfo
:
553 self
.mainFrame
= mainFrame
554 self
.editor
= DemoCodeEditor(self
)
555 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
557 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
558 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
559 self
.btnSave
.Enable(False)
560 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
561 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
563 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
564 modModified
: wx
.RadioButton(self
, -1, "Modified") }
566 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
567 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
568 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
569 for modID
, radioButton
in self
.radioButtons
.items():
570 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
571 radioButton
.modID
= modID
# makes it easier for the event handler
572 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
574 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
575 self
.controlBox
.Add(self
.btnRestore
, 0)
577 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
578 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
579 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
580 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
583 self
.SetSizer(self
.box
)
586 # Loads a demo from a DemoModules object
587 def LoadDemo(self
, demoModules
):
588 self
.demoModules
= demoModules
589 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
590 demoModules
.SetActive(modModified
)
592 demoModules
.SetActive(modOriginal
)
593 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
594 self
.ActiveModuleChanged()
597 def ActiveModuleChanged(self
):
598 self
.LoadDemoSource(self
.demoModules
.GetSource())
599 self
.UpdateControlState()
603 def LoadDemoSource(self
, source
):
605 self
.editor
.SetValue(source
)
607 self
.btnSave
.Enable(False)
610 def JumpToLine(self
, line
, highlight
=False):
611 self
.editor
.GotoLine(line
)
612 self
.editor
.SetFocus()
614 self
.editor
.SelectLine(line
)
617 def UpdateControlState(self
):
618 active
= self
.demoModules
.GetActiveID()
619 # Update the radio/restore buttons
620 for moduleID
in self
.radioButtons
:
621 btn
= self
.radioButtons
[moduleID
]
622 if moduleID
== active
:
627 if self
.demoModules
.Exists(moduleID
):
629 if moduleID
== modModified
:
630 self
.btnRestore
.Enable(True)
633 if moduleID
== modModified
:
634 self
.btnRestore
.Enable(False)
637 def OnRadioButton(self
, event
):
638 radioSelected
= event
.GetEventObject()
639 modSelected
= radioSelected
.modID
640 if modSelected
!= self
.demoModules
.GetActiveID():
641 busy
= wx
.BusyInfo("Reloading demo module...")
642 self
.demoModules
.SetActive(modSelected
)
643 self
.ActiveModuleChanged()
646 def ReloadDemo(self
):
647 if self
.demoModules
.name
!= __name__
:
648 self
.mainFrame
.RunModule()
651 def OnCodeModified(self
, event
):
652 self
.btnSave
.Enable(self
.editor
.IsModified())
655 def OnSave(self
, event
):
656 if self
.demoModules
.Exists(modModified
):
657 if self
.demoModules
.GetActiveID() == modOriginal
:
658 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
659 "Do you want to continue?"
660 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
661 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
662 result
= dlg
.ShowModal()
663 if result
== wx
.ID_NO
:
667 self
.demoModules
.SetActive(modModified
)
668 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
670 # Create the demo directory if one doesn't already exist
671 if not os
.path
.exists(GetModifiedDirectory()):
673 os
.makedirs(GetModifiedDirectory())
674 if not os
.path
.exists(GetModifiedDirectory()):
675 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
678 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
681 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
684 f
= open(modifiedFilename
, "wt")
685 source
= self
.editor
.GetText()
691 busy
= wx
.BusyInfo("Reloading demo module...")
692 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
693 self
.ActiveModuleChanged()
696 def OnRestore(self
, event
): # Handles the "Delete Modified" button
697 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
698 self
.demoModules
.Delete(modModified
)
699 os
.unlink(modifiedFilename
) # Delete the modified copy
700 busy
= wx
.BusyInfo("Reloading demo module...")
701 self
.ActiveModuleChanged()
704 #---------------------------------------------------------------------------
707 """Convert paths to the platform-specific separator"""
708 str = apply(os
.path
.join
, tuple(path
.split('/')))
709 # HACK: on Linux, a leading / gets lost...
710 if path
.startswith('/'):
715 def GetModifiedDirectory():
717 Returns the directory where modified versions of the demo files
720 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
723 def GetModifiedFilename(name
):
725 Returns the filename of the modified version of the specified demo
727 if not name
.endswith(".py"):
729 return GetModifiedDirectory() + name
732 def GetOriginalFilename(name
):
734 Returns the filename of the original version of the specified demo
736 if not name
.endswith(".py"):
741 def DoesModifiedExist(name
):
742 """Returns whether the specified demo has a modified copy"""
743 if os
.path
.exists(GetModifiedFilename(name
)):
749 #---------------------------------------------------------------------------
751 class ModuleDictWrapper
:
752 """Emulates a module with a dynamically compiled __dict__"""
753 def __init__(self
, dict):
756 def __getattr__(self
, name
):
757 if name
in self
.dict:
758 return self
.dict[name
]
764 Dynamically manages the original/modified versions of a demo
767 def __init__(self
, name
):
771 # (dict , source , filename , description , error information )
772 # ( 0 , 1 , 2 , 3 , 4 )
773 self
.modules
= [[None, "" , "" , "<original>" , None],
774 [None, "" , "" , "<modified>" , None]]
776 # load original module
777 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
778 self
.SetActive(modOriginal
)
780 # load modified module (if one exists)
781 if DoesModifiedExist(name
):
782 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
785 def LoadFromFile(self
, modID
, filename
):
786 self
.modules
[modID
][2] = filename
787 file = open(filename
, "rt")
788 self
.LoadFromSource(modID
, file.read())
792 def LoadFromSource(self
, modID
, source
):
793 self
.modules
[modID
][1] = source
797 def LoadDict(self
, modID
):
798 if self
.name
!= __name__
:
799 source
= self
.modules
[modID
][1]
800 description
= self
.modules
[modID
][3]
803 self
.modules
[modID
][0] = {}
804 code
= compile(source
, description
, "exec")
805 exec code
in self
.modules
[modID
][0]
807 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
808 self
.modules
[modID
][0] = None
810 self
.modules
[modID
][4] = None
813 def SetActive(self
, modID
):
814 if modID
!= modOriginal
and modID
!= modModified
:
817 self
.modActive
= modID
821 dict = self
.modules
[self
.modActive
][0]
825 return ModuleDictWrapper(dict)
828 def GetActiveID(self
):
829 return self
.modActive
832 def GetSource(self
, modID
= None):
834 modID
= self
.modActive
835 return self
.modules
[modID
][1]
838 def GetFilename(self
, modID
= None):
840 modID
= self
.modActive
841 return self
.modules
[self
.modActive
][2]
844 def GetErrorInfo(self
, modID
= None):
846 modID
= self
.modActive
847 return self
.modules
[self
.modActive
][4]
850 def Exists(self
, modID
):
851 return self
.modules
[modID
][1] != ""
854 def UpdateFile(self
, modID
= None):
855 """Updates the file from which a module was loaded
856 with (possibly updated) source"""
858 modID
= self
.modActive
860 source
= self
.modules
[modID
][1]
861 filename
= self
.modules
[modID
][2]
864 file = open(filename
, "wt")
870 def Delete(self
, modID
):
871 if self
.modActive
== modID
:
874 self
.modules
[modID
][0] = None
875 self
.modules
[modID
][1] = ""
876 self
.modules
[modID
][2] = ""
879 #---------------------------------------------------------------------------
882 """Wraps and stores information about the current exception"""
883 def __init__(self
, exc_info
):
886 excType
, excValue
= exc_info
[:2]
887 # traceback list entries: (filename, line number, function name, text)
888 self
.traceback
= traceback
.extract_tb(exc_info
[2])
890 # --Based on traceback.py::format_exception_only()--
891 if type(excType
) == types
.ClassType
:
892 self
.exception_type
= excType
.__name
__
894 self
.exception_type
= excType
896 # If it's a syntax error, extra information needs
897 # to be added to the traceback
898 if excType
is SyntaxError:
900 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
905 filename
= "<string>"
907 self
.traceback
.append( (filename
, lineno
, "", line
) )
910 self
.exception_details
= str(excValue
)
912 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
919 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
922 #---------------------------------------------------------------------------
924 class DemoErrorPanel(wx
.Panel
):
925 """Panel put into the demo tab when the demo fails to run due to errors"""
927 def __init__(self
, parent
, codePanel
, demoError
, log
):
928 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
929 self
.codePanel
= codePanel
933 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
936 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
937 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
939 # Exception Information
940 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
941 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
942 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
943 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
944 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
945 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
946 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
947 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
948 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
949 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
951 # Set up the traceback list
952 # This one automatically resizes last column to take up remaining space
953 from ListCtrl
import TestListCtrl
954 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
955 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
956 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
957 self
.list.InsertColumn(0, "Filename")
958 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
959 self
.list.InsertColumn(2, "Function")
960 self
.list.InsertColumn(3, "Code")
961 self
.InsertTraceback(self
.list, demoError
.traceback
)
962 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
963 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
964 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
965 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
966 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
967 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
968 + "Double-click on them to go to the offending line")
969 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
972 self
.SetSizer(self
.box
)
975 def InsertTraceback(self
, list, traceback
):
976 #Add the traceback data
977 for x
in range(len(traceback
)):
979 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
980 list.SetStringItem(x
, 1, str(data
[1])) # Line
981 list.SetStringItem(x
, 2, str(data
[2])) # Function
982 list.SetStringItem(x
, 3, str(data
[3])) # Code
984 # Check whether this entry is from the demo module
985 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
986 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
987 # Give it a blue colour
988 item
= self
.list.GetItem(x
)
989 item
.SetTextColour(wx
.BLUE
)
990 self
.list.SetItem(item
)
992 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
995 def OnItemSelected(self
, event
):
996 # This occurs before OnDoubleClick and can be used to set the
997 # currentItem. OnDoubleClick doesn't get a wxListEvent....
998 self
.currentItem
= event
.m_itemIndex
1002 def OnDoubleClick(self
, event
):
1003 # If double-clicking on a demo's entry, jump to the line number
1004 line
= self
.list.GetItemData(self
.currentItem
)
1006 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1007 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1011 #---------------------------------------------------------------------------
1013 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1014 TBMENU_RESTORE
= wx
.NewId()
1015 TBMENU_CLOSE
= wx
.NewId()
1016 TBMENU_CHANGE
= wx
.NewId()
1017 TBMENU_REMOVE
= wx
.NewId()
1019 def __init__(self
, frame
):
1020 wx
.TaskBarIcon
.__init
__(self
)
1024 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1025 self
.SetIcon(icon
, "wxPython Demo")
1029 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1030 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1031 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1032 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1033 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1036 def CreatePopupMenu(self
):
1038 This method is called by the base class when it needs to popup
1039 the menu for the default EVT_RIGHT_DOWN event. Just create
1040 the menu how you want it and return it from this function,
1041 the base class takes care of the rest.
1044 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1045 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1046 menu
.AppendSeparator()
1047 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1048 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1052 def MakeIcon(self
, img
):
1054 The various platforms have different requirements for the
1057 if "wxMSW" in wx
.PlatformInfo
:
1058 img
= img
.Scale(16, 16)
1059 elif "wxGTK" in wx
.PlatformInfo
:
1060 img
= img
.Scale(22, 22)
1061 # wxMac can be any size upto 128x128, so leave the source img alone....
1062 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1066 def OnTaskBarActivate(self
, evt
):
1067 if self
.frame
.IsIconized():
1068 self
.frame
.Iconize(False)
1069 if not self
.frame
.IsShown():
1070 self
.frame
.Show(True)
1074 def OnTaskBarClose(self
, evt
):
1078 def OnTaskBarChange(self
, evt
):
1079 names
= [ "WXPdemo", "WXP", "Mondrian", "Test2m",
1080 "Blom08m", "Blom10m", "Blom15m" ]
1081 name
= names
[self
.imgidx
]
1083 getFunc
= getattr(images
, "get%sImage" % name
)
1085 if self
.imgidx
>= len(names
):
1088 icon
= self
.MakeIcon(getFunc())
1089 self
.SetIcon(icon
, "This is a new icon: " + name
)
1092 def OnTaskBarRemove(self
, evt
):
1096 #---------------------------------------------------------------------------
1097 class wxPythonDemo(wx
.Frame
):
1098 overviewText
= "wxPython Overview"
1100 def __init__(self
, parent
, title
):
1101 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1102 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1104 self
.SetMinSize((640,480))
1107 self
.cwd
= os
.getcwd()
1108 self
.curOverview
= ""
1109 self
.demoPage
= None
1110 self
.codePage
= None
1112 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_COMMAND_FIND
, self
.OnFind
)
1200 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1201 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1202 self
.mainmenu
.Append(menu
, '&Help')
1203 self
.SetMenuBar(self
.mainmenu
)
1205 self
.finddata
= wx
.FindReplaceData()
1208 # This is another way to set Accelerators, in addition to
1209 # using the '\t<key>' syntax in the menu items.
1210 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1211 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1212 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1213 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1215 self
.SetAcceleratorTable(aTable
)
1221 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1222 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1225 root
= self
.tree
.AddRoot("wxPython Overview")
1227 for item
in _treeList
:
1228 child
= self
.tree
.AppendItem(root
, item
[0])
1229 if not firstChild
: firstChild
= child
1230 for childItem
in item
[1]:
1231 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1232 self
.treeMap
[childItem
] = theDemo
1234 self
.tree
.Expand(root
)
1235 self
.tree
.Expand(firstChild
)
1236 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1237 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1238 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1239 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1241 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1242 # we put it in a panel first because there seems to be a
1243 # refresh bug of some sort (wxGTK) when it is directly in
1246 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1247 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1249 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1250 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1251 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1252 self
.nb
.AddPage(panel
, self
.overviewText
)
1254 def OnOvrSize(evt
, ovr
=self
.ovr
):
1255 ovr
.SetSize(evt
.GetSize())
1256 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1257 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1259 if "gtk2" in wx
.PlatformInfo
:
1260 self
.ovr
.SetStandardFonts()
1261 self
.SetOverview(self
.overviewText
, mainOverview
)
1264 # Set up a log window
1265 self
.log
= wx
.TextCtrl(splitter2
, -1,
1266 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1268 # Set the wxWindows log target to be this textctrl
1269 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1271 # But instead of the above we want to show how to use our own wx.Log class
1272 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1274 # for serious debugging
1275 #wx.Log_SetActiveTarget(wx.LogStderr())
1276 #wx.Log_SetTraceMask(wx.TraceMessages)
1279 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1280 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1282 # add the windows to the splitter and split it.
1283 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1284 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1286 splitter
.SetMinimumPaneSize(120)
1287 splitter2
.SetMinimumPaneSize(60)
1289 # Make the splitter on the right expand the top window when resized
1290 def SplitterOnSize(evt
):
1291 splitter
= evt
.GetEventObject()
1292 sz
= splitter
.GetSize()
1293 splitter
.SetSashPosition(sz
.height
- 160, False)
1296 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1298 # select initial items
1299 self
.nb
.SetSelection(0)
1300 self
.tree
.SelectItem(root
)
1302 # Load 'Main' module
1303 self
.LoadDemo(self
.overviewText
)
1306 # select some other initial module?
1307 if len(sys
.argv
) > 1:
1309 if arg
.endswith('.py'):
1311 selectedDemo
= self
.treeMap
.get(arg
, None)
1313 self
.tree
.SelectItem(selectedDemo
)
1314 self
.tree
.EnsureVisible(selectedDemo
)
1317 #---------------------------------------------
1318 def WriteText(self
, text
):
1319 if text
[-1:] == '\n':
1323 def write(self
, txt
):
1326 #---------------------------------------------
1327 def OnItemExpanded(self
, event
):
1328 item
= event
.GetItem()
1329 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1332 #---------------------------------------------
1333 def OnItemCollapsed(self
, event
):
1334 item
= event
.GetItem()
1335 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1338 #---------------------------------------------
1339 def OnTreeLeftDown(self
, event
):
1340 # reset the overview text if the tree item is clicked on again
1341 pt
= event
.GetPosition();
1342 item
, flags
= self
.tree
.HitTest(pt
)
1343 if item
== self
.tree
.GetSelection():
1344 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1347 #---------------------------------------------
1348 def OnSelChanged(self
, event
):
1349 if self
.dying
or not self
.loaded
:
1352 item
= event
.GetItem()
1353 itemText
= self
.tree
.GetItemText(item
)
1354 self
.LoadDemo(itemText
)
1356 #---------------------------------------------
1357 def LoadDemo(self
, demoName
):
1359 wx
.BeginBusyCursor()
1362 self
.ShutdownDemoModule()
1364 if demoName
== self
.overviewText
:
1365 # User selected the "wxPython Overview" node
1367 # Changing the main window at runtime not yet supported...
1368 self
.demoModules
= DemoModules(__name__
)
1369 self
.SetOverview(self
.overviewText
, mainOverview
)
1370 self
.LoadDemoSource()
1371 self
.UpdateNotebook(0)
1373 if os
.path
.exists(GetOriginalFilename(demoName
)):
1374 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1375 self
.demoModules
= DemoModules(demoName
)
1376 self
.LoadDemoSource()
1379 self
.SetOverview("wxPython", mainOverview
)
1380 self
.codePage
= None
1381 self
.UpdateNotebook(0)
1385 #---------------------------------------------
1386 def LoadDemoSource(self
):
1387 self
.codePage
= None
1388 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1389 self
.codePage
.LoadDemo(self
.demoModules
)
1391 #---------------------------------------------
1392 def RunModule(self
):
1393 """Runs the active module"""
1395 module
= self
.demoModules
.GetActive()
1396 self
.ShutdownDemoModule()
1399 # o The RunTest() for all samples must now return a window that can
1400 # be palced in a tab in the main notebook.
1401 # o If an error occurs (or has occured before) an error tab is created.
1403 if module
is not None:
1404 wx
.LogMessage("Running demo module...")
1405 if hasattr(module
, "overview"):
1406 overviewText
= module
.overview
1409 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1411 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1412 DemoError(sys
.exc_info()), self
)
1414 assert self
.demoPage
is not None, "runTest must return a window!"
1417 # There was a previous error in compiling or exec-ing
1418 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1419 self
.demoModules
.GetErrorInfo(), self
)
1421 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1424 # cahnge to the demo page the first time a module is run
1425 self
.UpdateNotebook(2)
1426 self
.firstTime
= False
1428 # otherwise just stay on the same tab in case the user has changed to another one
1429 self
.UpdateNotebook()
1431 #---------------------------------------------
1432 def ShutdownDemoModule(self
):
1434 # inform the window that it's time to quit if it cares
1435 if hasattr(self
.demoPage
, "ShutdownDemo"):
1436 self
.demoPage
.ShutdownDemo()
1437 wx
.YieldIfNeeded() # in case the page has pending events
1438 self
.demoPage
= None
1440 #---------------------------------------------
1441 def UpdateNotebook(self
, select
= -1):
1445 def UpdatePage(page
, pageText
):
1448 for i
in range(nb
.GetPageCount()):
1449 if nb
.GetPageText(i
) == pageText
:
1457 nb
.AddPage(page
, pageText
)
1458 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1460 if nb
.GetPage(pagePos
) != page
:
1461 # Reload an existing page
1463 nb
.DeletePage(pagePos
)
1464 nb
.InsertPage(pagePos
, page
, pageText
)
1466 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1468 # Excellent! No redraw/flicker
1469 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1472 nb
.DeletePage(pagePos
)
1473 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1475 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1478 select
= nb
.GetSelection()
1480 UpdatePage(self
.codePage
, "Demo Code")
1481 UpdatePage(self
.demoPage
, "Demo")
1483 if select
>= 0 and select
< nb
.GetPageCount():
1484 nb
.SetSelection(select
)
1486 #---------------------------------------------
1487 def SetOverview(self
, name
, text
):
1488 self
.curOverview
= text
1490 if lead
!= '<html>' and lead
!= '<HTML>':
1491 text
= '<br>'.join(text
.split('\n'))
1493 text
= text
.decode('iso8859_1')
1494 self
.ovr
.SetPage(text
)
1495 self
.nb
.SetPageText(0, name
)
1497 #---------------------------------------------
1499 def OnFileExit(self
, *event
):
1502 def OnToggleRedirect(self
, event
):
1506 print "Print statements and other standard output will now be directed to this window."
1509 print "Print statements and other standard output will now be sent to the usual location."
1511 def OnHelpAbout(self
, event
):
1512 from About
import MyAboutBox
1513 about
= MyAboutBox(self
)
1517 def OnHelpFind(self
, event
):
1518 self
.nb
.SetSelection(1)
1519 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1523 self
.finddlg
.Show(True)
1525 def OnFind(self
, event
):
1526 editor
= self
.codePage
.editor
1527 self
.nb
.SetSelection(1)
1528 end
= editor
.GetLastPosition()
1529 textstring
= editor
.GetRange(0, end
).lower()
1530 start
= editor
.GetSelection()[1]
1531 findstring
= self
.finddata
.GetFindString().lower()
1532 loc
= textstring
.find(findstring
, start
)
1533 if loc
== -1 and start
!= 0:
1534 # string not found, start at beginning
1536 loc
= textstring
.find(findstring
, start
)
1538 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1539 'Find String Not Found in Demo File',
1540 wx
.OK | wx
.ICON_INFORMATION
)
1545 self
.finddlg
.SetFocus()
1548 self
.finddlg
.Destroy()
1549 editor
.ShowPosition(loc
)
1550 editor
.SetSelection(loc
, loc
+ len(findstring
))
1554 def OnFindNext(self
, event
):
1555 if self
.finddata
.GetFindString():
1558 self
.OnHelpFind(event
)
1560 def OnFindClose(self
, event
):
1561 event
.GetDialog().Destroy()
1564 def OnOpenShellWindow(self
, evt
):
1566 # if it already exists then just make sure it's visible
1572 # Make a PyShell window
1574 namespace
= { 'wx' : wx
,
1575 'app' : wx
.GetApp(),
1578 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1579 self
.shell
.SetSize((640,480))
1582 # Hook the close event of the main frame window so that we
1583 # close the shell at the same time if it still exists
1584 def CloseShell(evt
):
1588 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1591 #---------------------------------------------
1592 def OnCloseWindow(self
, event
):
1594 self
.demoPage
= None
1595 self
.codePage
= None
1596 self
.mainmenu
= None
1597 self
.tbicon
.Destroy()
1601 #---------------------------------------------
1602 def OnIdle(self
, event
):
1604 self
.otherWin
.Raise()
1605 self
.demoPage
= self
.otherWin
1606 self
.otherWin
= None
1609 #---------------------------------------------
1612 showTipText
= open(opj("data/showTips")).read()
1613 showTip
, index
= eval(showTipText
)
1615 showTip
, index
= (1, 0)
1617 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1619 showTip
= wx
.ShowTip(self
, tp
)
1620 index
= tp
.GetCurrentTip()
1621 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1624 #---------------------------------------------
1625 def OnDemoMenu(self
, event
):
1627 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1631 self
.tree
.SelectItem(selectedDemo
)
1632 self
.tree
.EnsureVisible(selectedDemo
)
1636 #---------------------------------------------
1637 def OnIconfiy(self
, evt
):
1638 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1641 #---------------------------------------------
1642 def OnMaximize(self
, evt
):
1643 wx
.LogMessage("OnMaximize")
1646 #---------------------------------------------
1647 def OnActivate(self
, evt
):
1648 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1651 #---------------------------------------------
1652 def OnAppActivate(self
, evt
):
1653 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1656 #---------------------------------------------------------------------------
1657 #---------------------------------------------------------------------------
1659 class MySplashScreen(wx
.SplashScreen
):
1661 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1662 wx
.SplashScreen
.__init
__(self
, bmp
,
1663 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1665 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1667 def OnClose(self
, evt
):
1669 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1671 evt
.Skip() # Make sure the default handler runs too...
1674 class MyApp(wx
.App
):
1677 Create and show the splash screen. It will then create and show
1678 the main frame when it is time to do so.
1682 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1684 # Normally when using a SplashScreen you would create it, show
1685 # it and then continue on with the applicaiton's
1686 # initialization, finally creating and showing the main
1687 # application window(s). In this case we have nothing else to
1688 # do so we'll delay showing the main frame until later (see
1689 # OnClose above) so the users can see the SplashScreen effect.
1690 splash
= MySplashScreen()
1697 #---------------------------------------------------------------------------
1701 demoPath
= os
.path
.dirname(__file__
)
1708 #---------------------------------------------------------------------------
1711 mainOverview
= """<html><body>
1714 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1715 language. It allows Python programmers to create programs with a
1716 robust, highly functional graphical user interface, simply and easily.
1717 It is implemented as a Python extension module (native code) that
1718 wraps the popular wxWindows cross platform GUI library, which is
1721 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1722 means that it is free for anyone to use and the source code is
1723 available for anyone to look at and modify. Or anyone can contribute
1724 fixes or enhancements to the project.
1726 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1727 same program will run on multiple platforms without modification.
1728 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1729 or unix-like systems, and Macintosh OS X. Since the language is
1730 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1733 <p> <b>This demo</b> is not only a collection of test cases for
1734 wxPython, but is also designed to help you learn about and how to use
1735 wxPython. Each sample is listed in the tree control on the left.
1736 When a sample is selected in the tree then a module is loaded and run
1737 (usually in a tab of this notebook,) and the source code of the module
1738 is loaded in another tab for you to browse and learn from.
1743 #----------------------------------------------------------------------------
1744 #----------------------------------------------------------------------------
1746 if __name__
== '__main__':
1750 #----------------------------------------------------------------------------