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', [
125 ('Custom Controls', [
138 # controls coming from other libraries
139 ('More Windows/Controls', [
140 'ActiveX_FlashWindow',
141 'ActiveX_IEHtmlWindow',
143 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
159 'MaskedEditControls',
176 # How to lay out the controls in a frame/dialog
186 'XmlResourceHandler',
187 'XmlResourceSubclass',
191 ('Process and Events', [
198 ##'infoframe', # needs better explanation and some fixing
202 ('Clipboard and DnD', [
223 ##'DialogUnits', # needs more explanations
237 # need libs not coming with the demo
238 ('Samples using an external library', [
243 ('Check out the samples dir too', [
250 #---------------------------------------------------------------------------
251 # Show how to derive a custom wxLog class
253 class MyLog(wx
.PyLog
):
254 def __init__(self
, textCtrl
, logTime
=0):
255 wx
.PyLog
.__init
__(self
)
257 self
.logTime
= logTime
259 def DoLogString(self
, message
, timeStamp
):
260 #print message, timeStamp
262 # message = time.strftime("%X", time.localtime(timeStamp)) + \
265 self
.tc
.AppendText(message
+ '\n')
268 class MyTP(wx
.PyTipProvider
):
270 return "This is my tip"
272 #---------------------------------------------------------------------------
273 # A class to be used to simply display a message in the demo pane
274 # rather than running the sample itself.
276 class MessagePanel(wx
.Panel
):
277 def __init__(self
, parent
, message
, caption
='', flags
=0):
278 wx
.Panel
.__init
__(self
, parent
)
283 if flags
& wx
.ICON_EXCLAMATION
:
284 artid
= wx
.ART_WARNING
285 elif flags
& wx
.ICON_ERROR
:
287 elif flags
& wx
.ICON_QUESTION
:
288 artid
= wx
.ART_QUESTION
289 elif flags
& wx
.ICON_INFORMATION
:
290 artid
= wx
.ART_INFORMATION
292 if artid
is not None:
293 bmp
= wx
.ArtProvider
.GetBitmap(artid
, wx
.ART_MESSAGE_BOX
, (32,32))
294 icon
= wx
.StaticBitmap(self
, -1, bmp
)
296 icon
= (32,32) # make a spacer instead
299 caption
= wx
.StaticText(self
, -1, caption
)
300 caption
.SetFont(wx
.Font(28, wx
.SWISS
, wx
.NORMAL
, wx
.BOLD
))
302 message
= wx
.StaticText(self
, -1, message
)
304 # add to sizers for layout
305 tbox
= wx
.BoxSizer(wx
.VERTICAL
)
311 hbox
= wx
.BoxSizer(wx
.HORIZONTAL
)
318 box
= wx
.BoxSizer(wx
.VERTICAL
)
320 box
.Add(hbox
, 0, wx
.EXPAND
)
327 #---------------------------------------------------------------------------
328 # A class to be used to display source code in the demo. Try using the
329 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
330 # if there is an error, such as the stc module not being present.
334 ##raise ImportError # for testing the alternate implementation
336 from StyledTextCtrl_2
import PythonSTC
338 class DemoCodeEditor(PythonSTC
):
339 def __init__(self
, parent
):
340 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
343 # Some methods to make it compatible with how the wxTextCtrl is used
344 def SetValue(self
, value
):
346 value
= value
.decode('iso8859_1')
348 self
.EmptyUndoBuffer()
351 def IsModified(self
):
352 return self
.GetModify()
357 def SetInsertionPoint(self
, pos
):
358 self
.SetCurrentPos(pos
)
361 def ShowPosition(self
, pos
):
362 line
= self
.LineFromPosition(pos
)
363 #self.EnsureVisible(line)
366 def GetLastPosition(self
):
367 return self
.GetLength()
369 def GetPositionFromLine(self
, line
):
370 return self
.PositionFromLine(line
)
372 def GetRange(self
, start
, end
):
373 return self
.GetTextRange(start
, end
)
375 def GetSelection(self
):
376 return self
.GetAnchor(), self
.GetCurrentPos()
378 def SetSelection(self
, start
, end
):
379 self
.SetSelectionStart(start
)
380 self
.SetSelectionEnd(end
)
382 def SelectLine(self
, line
):
383 start
= self
.PositionFromLine(line
)
384 end
= self
.GetLineEndPosition(line
)
385 self
.SetSelection(start
, end
)
387 def SetUpEditor(self
):
389 This method carries out the work of setting up the demo editor.
390 It's seperate so as not to clutter up the init code.
394 self
.SetLexer(stc
.STC_LEX_PYTHON
)
395 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
398 self
.SetProperty("fold", "1" )
400 # Highlight tab/space mixing (shouldn't be any)
401 self
.SetProperty("tab.timmy.whinge.level", "1")
403 # Set left and right margins
406 # Set up the numbers in the margin for margin #1
407 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
408 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
409 self
.SetMarginWidth(1, 40)
411 # Indentation and tab stuff
412 self
.SetIndent(4) # Proscribed indent size for wx
413 self
.SetIndentationGuides(True) # Show indent guides
414 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
415 self
.SetTabIndents(True) # Tab key indents
416 self
.SetTabWidth(4) # Proscribed tab size for wx
417 self
.SetUseTabs(False) # Use spaces rather than tabs, or
418 # TabTimmy will complain!
420 self
.SetViewWhiteSpace(False) # Don't view white space
422 # EOL: Since we are loading/saving ourselves, and the
423 # strings will always have \n's in them, set the STC to
424 # edit them that way.
425 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
426 self
.SetViewEOL(False)
428 # No right-edge mode indicator
429 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
431 # Setup a margin to hold fold markers
432 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
433 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
434 self
.SetMarginSensitive(2, True)
435 self
.SetMarginWidth(2, 12)
437 # and now set up the fold markers
438 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
439 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
440 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
441 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
442 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
443 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
444 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
446 # Global default style
447 if wx
.Platform
== '__WXMSW__':
448 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
449 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
451 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
452 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
454 # Clear styles and revert to default.
457 # Following style specs only indicate differences from default.
458 # The rest remains unchanged.
460 # Line numbers in margin
461 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
463 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
465 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
467 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
470 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
472 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
473 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
475 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
476 # Strings and characters
477 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
478 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
480 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
482 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
483 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
485 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
487 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
489 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
490 # Identifiers. I leave this as not bold because everything seems
491 # to be an identifier if it doesn't match the above criterae
492 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
495 self
.SetCaretForeground("BLUE")
496 # Selection background
497 self
.SetSelBackground(1, '#66CCFF')
499 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
500 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
502 def RegisterModifiedEvent(self
, eventHandler
):
503 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
507 class DemoCodeEditor(wx
.TextCtrl
):
508 def __init__(self
, parent
):
509 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
510 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
512 def RegisterModifiedEvent(self
, eventHandler
):
513 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
515 def SetReadOnly(self
, flag
):
516 self
.SetEditable(not flag
)
517 # NOTE: STC already has this method
520 return self
.GetValue()
522 def GetPositionFromLine(self
, line
):
523 return self
.XYToPosition(0,line
)
525 def GotoLine(self
, line
):
526 pos
= self
.GetPositionFromLine(line
)
527 self
.SetInsertionPoint(pos
)
528 self
.ShowPosition(pos
)
530 def SelectLine(self
, line
):
531 start
= self
.GetPositionFromLine(line
)
532 end
= start
+ self
.GetLineLength(line
)
533 self
.SetSelection(start
, end
)
536 #---------------------------------------------------------------------------
537 # Constants for module versions
541 modDefault
= modOriginal
543 #---------------------------------------------------------------------------
545 class DemoCodePanel(wx
.Panel
):
546 """Panel for the 'Demo Code' tab"""
547 def __init__(self
, parent
, mainFrame
):
548 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
549 if 'wxMSW' in wx
.PlatformInfo
:
551 self
.mainFrame
= mainFrame
552 self
.editor
= DemoCodeEditor(self
)
553 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
555 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
556 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
557 self
.btnSave
.Enable(False)
558 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
559 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
561 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
562 modModified
: wx
.RadioButton(self
, -1, "Modified") }
564 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
565 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
566 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
567 for modID
, radioButton
in self
.radioButtons
.items():
568 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
569 radioButton
.modID
= modID
# makes it easier for the event handler
570 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
572 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
573 self
.controlBox
.Add(self
.btnRestore
, 0)
575 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
576 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
577 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
578 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
581 self
.SetSizer(self
.box
)
584 # Loads a demo from a DemoModules object
585 def LoadDemo(self
, demoModules
):
586 self
.demoModules
= demoModules
587 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
588 demoModules
.SetActive(modModified
)
590 demoModules
.SetActive(modOriginal
)
591 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
592 self
.ActiveModuleChanged()
595 def ActiveModuleChanged(self
):
596 self
.LoadDemoSource(self
.demoModules
.GetSource())
597 self
.UpdateControlState()
601 def LoadDemoSource(self
, source
):
603 self
.editor
.SetValue(source
)
605 self
.btnSave
.Enable(False)
608 def JumpToLine(self
, line
, highlight
=False):
609 self
.editor
.GotoLine(line
)
610 self
.editor
.SetFocus()
612 self
.editor
.SelectLine(line
)
615 def UpdateControlState(self
):
616 active
= self
.demoModules
.GetActiveID()
617 # Update the radio/restore buttons
618 for moduleID
in self
.radioButtons
:
619 btn
= self
.radioButtons
[moduleID
]
620 if moduleID
== active
:
625 if self
.demoModules
.Exists(moduleID
):
627 if moduleID
== modModified
:
628 self
.btnRestore
.Enable(True)
631 if moduleID
== modModified
:
632 self
.btnRestore
.Enable(False)
635 def OnRadioButton(self
, event
):
636 radioSelected
= event
.GetEventObject()
637 modSelected
= radioSelected
.modID
638 if modSelected
!= self
.demoModules
.GetActiveID():
639 busy
= wx
.BusyInfo("Reloading demo module...")
640 self
.demoModules
.SetActive(modSelected
)
641 self
.ActiveModuleChanged()
644 def ReloadDemo(self
):
645 if self
.demoModules
.name
!= __name__
:
646 self
.mainFrame
.RunModule()
649 def OnCodeModified(self
, event
):
650 self
.btnSave
.Enable(self
.editor
.IsModified())
653 def OnSave(self
, event
):
654 if self
.demoModules
.Exists(modModified
):
655 if self
.demoModules
.GetActiveID() == modOriginal
:
656 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
657 "Do you want to continue?"
658 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
659 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
660 result
= dlg
.ShowModal()
661 if result
== wx
.ID_NO
:
665 self
.demoModules
.SetActive(modModified
)
666 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
668 # Create the demo directory if one doesn't already exist
669 if not os
.path
.exists(GetModifiedDirectory()):
671 os
.makedirs(GetModifiedDirectory())
672 if not os
.path
.exists(GetModifiedDirectory()):
673 wx
.LogMessage("BUG: Created demo directory but it still doesn't exist")
676 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
679 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
682 f
= open(modifiedFilename
, "wt")
683 source
= self
.editor
.GetText()
689 busy
= wx
.BusyInfo("Reloading demo module...")
690 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
691 self
.ActiveModuleChanged()
694 def OnRestore(self
, event
): # Handles the "Delete Modified" button
695 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
696 self
.demoModules
.Delete(modModified
)
697 os
.unlink(modifiedFilename
) # Delete the modified copy
698 busy
= wx
.BusyInfo("Reloading demo module...")
699 self
.ActiveModuleChanged()
702 #---------------------------------------------------------------------------
705 """Convert paths to the platform-specific separator"""
706 str = apply(os
.path
.join
, tuple(path
.split('/')))
707 # HACK: on Linux, a leading / gets lost...
708 if path
.startswith('/'):
713 def GetModifiedDirectory():
715 Returns the directory where modified versions of the demo files
718 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
721 def GetModifiedFilename(name
):
723 Returns the filename of the modified version of the specified demo
725 if not name
.endswith(".py"):
727 return GetModifiedDirectory() + name
730 def GetOriginalFilename(name
):
732 Returns the filename of the original version of the specified demo
734 if not name
.endswith(".py"):
739 def DoesModifiedExist(name
):
740 """Returns whether the specified demo has a modified copy"""
741 if os
.path
.exists(GetModifiedFilename(name
)):
747 #---------------------------------------------------------------------------
749 class ModuleDictWrapper
:
750 """Emulates a module with a dynamically compiled __dict__"""
751 def __init__(self
, dict):
754 def __getattr__(self
, name
):
755 if name
in self
.dict:
756 return self
.dict[name
]
762 Dynamically manages the original/modified versions of a demo
765 def __init__(self
, name
):
769 # (dict , source , filename , description , error information )
770 # ( 0 , 1 , 2 , 3 , 4 )
771 self
.modules
= [[None, "" , "" , "<original>" , None],
772 [None, "" , "" , "<modified>" , None]]
774 # load original module
775 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
776 self
.SetActive(modOriginal
)
778 # load modified module (if one exists)
779 if DoesModifiedExist(name
):
780 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
783 def LoadFromFile(self
, modID
, filename
):
784 self
.modules
[modID
][2] = filename
785 file = open(filename
, "rt")
786 self
.LoadFromSource(modID
, file.read())
790 def LoadFromSource(self
, modID
, source
):
791 self
.modules
[modID
][1] = source
795 def LoadDict(self
, modID
):
796 if self
.name
!= __name__
:
797 source
= self
.modules
[modID
][1]
798 description
= self
.modules
[modID
][3]
801 self
.modules
[modID
][0] = {}
802 code
= compile(source
, description
, "exec")
803 exec code
in self
.modules
[modID
][0]
805 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
806 self
.modules
[modID
][0] = None
808 self
.modules
[modID
][4] = None
811 def SetActive(self
, modID
):
812 if modID
!= modOriginal
and modID
!= modModified
:
815 self
.modActive
= modID
819 dict = self
.modules
[self
.modActive
][0]
823 return ModuleDictWrapper(dict)
826 def GetActiveID(self
):
827 return self
.modActive
830 def GetSource(self
, modID
= None):
832 modID
= self
.modActive
833 return self
.modules
[modID
][1]
836 def GetFilename(self
, modID
= None):
838 modID
= self
.modActive
839 return self
.modules
[self
.modActive
][2]
842 def GetErrorInfo(self
, modID
= None):
844 modID
= self
.modActive
845 return self
.modules
[self
.modActive
][4]
848 def Exists(self
, modID
):
849 return self
.modules
[modID
][1] != ""
852 def UpdateFile(self
, modID
= None):
853 """Updates the file from which a module was loaded
854 with (possibly updated) source"""
856 modID
= self
.modActive
858 source
= self
.modules
[modID
][1]
859 filename
= self
.modules
[modID
][2]
862 file = open(filename
, "wt")
868 def Delete(self
, modID
):
869 if self
.modActive
== modID
:
872 self
.modules
[modID
][0] = None
873 self
.modules
[modID
][1] = ""
874 self
.modules
[modID
][2] = ""
877 #---------------------------------------------------------------------------
880 """Wraps and stores information about the current exception"""
881 def __init__(self
, exc_info
):
884 excType
, excValue
= exc_info
[:2]
885 # traceback list entries: (filename, line number, function name, text)
886 self
.traceback
= traceback
.extract_tb(exc_info
[2])
888 # --Based on traceback.py::format_exception_only()--
889 if type(excType
) == types
.ClassType
:
890 self
.exception_type
= excType
.__name
__
892 self
.exception_type
= excType
894 # If it's a syntax error, extra information needs
895 # to be added to the traceback
896 if excType
is SyntaxError:
898 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
903 filename
= "<string>"
905 self
.traceback
.append( (filename
, lineno
, "", line
) )
908 self
.exception_details
= str(excValue
)
910 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
917 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
920 #---------------------------------------------------------------------------
922 class DemoErrorPanel(wx
.Panel
):
923 """Panel put into the demo tab when the demo fails to run due to errors"""
925 def __init__(self
, parent
, codePanel
, demoError
, log
):
926 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
927 self
.codePanel
= codePanel
931 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
934 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
935 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
937 # Exception Information
938 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
939 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
940 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
941 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
942 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
943 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
944 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
945 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
946 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
947 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
949 # Set up the traceback list
950 # This one automatically resizes last column to take up remaining space
951 from ListCtrl
import TestListCtrl
952 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
953 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
954 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
955 self
.list.InsertColumn(0, "Filename")
956 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
957 self
.list.InsertColumn(2, "Function")
958 self
.list.InsertColumn(3, "Code")
959 self
.InsertTraceback(self
.list, demoError
.traceback
)
960 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
961 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
962 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
963 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
964 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
965 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
966 + "Double-click on them to go to the offending line")
967 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
970 self
.SetSizer(self
.box
)
973 def InsertTraceback(self
, list, traceback
):
974 #Add the traceback data
975 for x
in range(len(traceback
)):
977 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
978 list.SetStringItem(x
, 1, str(data
[1])) # Line
979 list.SetStringItem(x
, 2, str(data
[2])) # Function
980 list.SetStringItem(x
, 3, str(data
[3])) # Code
982 # Check whether this entry is from the demo module
983 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
984 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
985 # Give it a blue colour
986 item
= self
.list.GetItem(x
)
987 item
.SetTextColour(wx
.BLUE
)
988 self
.list.SetItem(item
)
990 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
993 def OnItemSelected(self
, event
):
994 # This occurs before OnDoubleClick and can be used to set the
995 # currentItem. OnDoubleClick doesn't get a wxListEvent....
996 self
.currentItem
= event
.m_itemIndex
1000 def OnDoubleClick(self
, event
):
1001 # If double-clicking on a demo's entry, jump to the line number
1002 line
= self
.list.GetItemData(self
.currentItem
)
1004 self
.nb
.SetSelection(1) # Switch to the code viewer tab
1005 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
1009 #---------------------------------------------------------------------------
1011 class DemoTaskBarIcon(wx
.TaskBarIcon
):
1012 TBMENU_RESTORE
= wx
.NewId()
1013 TBMENU_CLOSE
= wx
.NewId()
1014 TBMENU_CHANGE
= wx
.NewId()
1015 TBMENU_REMOVE
= wx
.NewId()
1017 def __init__(self
, frame
):
1018 wx
.TaskBarIcon
.__init
__(self
)
1022 icon
= self
.MakeIcon(images
.getWXPdemoImage())
1023 self
.SetIcon(icon
, "wxPython Demo")
1027 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
1028 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
1029 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
1030 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
1031 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
1034 def CreatePopupMenu(self
):
1036 This method is called by the base class when it needs to popup
1037 the menu for the default EVT_RIGHT_DOWN event. Just create
1038 the menu how you want it and return it from this function,
1039 the base class takes care of the rest.
1042 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
1043 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
1044 menu
.AppendSeparator()
1045 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
1046 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
1050 def MakeIcon(self
, img
):
1052 The various platforms have different requirements for the
1055 if "wxMSW" in wx
.PlatformInfo
:
1056 img
= img
.Scale(16, 16)
1057 elif "wxGTK" in wx
.PlatformInfo
:
1058 img
= img
.Scale(22, 22)
1059 # wxMac can be any size upto 128x128, so leave the source img alone....
1060 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1064 def OnTaskBarActivate(self
, evt
):
1065 if self
.frame
.IsIconized():
1066 self
.frame
.Iconize(False)
1067 if not self
.frame
.IsShown():
1068 self
.frame
.Show(True)
1072 def OnTaskBarClose(self
, evt
):
1076 def OnTaskBarChange(self
, evt
):
1077 names
= [ "WXPdemo", "WXP", "Mondrian", "Test2m",
1078 "Blom08m", "Blom10m", "Blom15m" ]
1079 name
= names
[self
.imgidx
]
1081 getFunc
= getattr(images
, "get%sImage" % name
)
1083 if self
.imgidx
>= len(names
):
1086 icon
= self
.MakeIcon(getFunc())
1087 self
.SetIcon(icon
, "This is a new icon: " + name
)
1090 def OnTaskBarRemove(self
, evt
):
1094 #---------------------------------------------------------------------------
1095 class wxPythonDemo(wx
.Frame
):
1096 overviewText
= "wxPython Overview"
1098 def __init__(self
, parent
, title
):
1099 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1100 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1102 self
.SetMinSize((640,480))
1105 self
.cwd
= os
.getcwd()
1106 self
.curOverview
= ""
1107 self
.demoPage
= None
1108 self
.codePage
= None
1110 self
.firstTime
= True
1113 icon
= images
.getWXPdemoIcon()
1116 self
.tbicon
= DemoTaskBarIcon(self
)
1118 wx
.CallAfter(self
.ShowTip
)
1120 self
.otherWin
= None
1121 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1122 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1123 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1124 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1126 self
.Centre(wx
.BOTH
)
1127 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1129 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1130 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1132 def EmptyHandler(evt
): pass
1133 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1134 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1136 # Prevent TreeCtrl from displaying all items after destruction when True
1140 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1143 self
.mainmenu
= wx
.MenuBar()
1145 item
= menu
.Append(-1, '&Redirect Output',
1146 'Redirect print statements to a window',
1148 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1150 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1151 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1152 wx
.App
.SetMacExitMenuItemId(item
.GetId())
1153 self
.mainmenu
.Append(menu
, '&File')
1157 for item
in _treeList
:
1159 for childItem
in item
[1]:
1160 mi
= submenu
.Append(-1, childItem
)
1161 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1162 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1163 self
.mainmenu
.Append(menu
, '&Demo')
1165 # Make a Demo Code menu
1166 #TODO: Add new menu items
1167 # Like the option-enabled entries to select the
1169 #TODO: should we bother?
1172 #saveID = wx.NewId()
1173 #restoreID = wx.NewId()
1175 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1176 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1177 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1178 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1179 #self.mainmenu.Append(menu, 'Demo &Code')
1184 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1185 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1186 menu
.AppendSeparator()
1188 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1189 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1190 menu
.AppendSeparator()
1191 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1192 wx
.App
.SetMacAboutMenuItemId(helpItem
.GetId())
1194 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1195 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1196 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1197 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1198 self
.Bind(wx
.EVT_FIND
, self
.OnFind
)
1199 self
.Bind(wx
.EVT_FIND_NEXT
, self
.OnFind
)
1200 self
.Bind(wx
.EVT_FIND_CLOSE
, self
.OnFindClose
)
1201 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findItem
)
1202 self
.Bind(wx
.EVT_UPDATE_UI
, self
.OnUpdateFindItems
, findnextItem
)
1203 self
.mainmenu
.Append(menu
, '&Help')
1204 self
.SetMenuBar(self
.mainmenu
)
1206 self
.finddata
= wx
.FindReplaceData()
1209 # This is another way to set Accelerators, in addition to
1210 # using the '\t<key>' syntax in the menu items.
1211 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1212 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1213 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1214 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1216 self
.SetAcceleratorTable(aTable
)
1222 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1223 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1226 root
= self
.tree
.AddRoot("wxPython Overview")
1228 for item
in _treeList
:
1229 child
= self
.tree
.AppendItem(root
, item
[0])
1230 if not firstChild
: firstChild
= child
1231 for childItem
in item
[1]:
1232 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1233 self
.treeMap
[childItem
] = theDemo
1235 self
.tree
.Expand(root
)
1236 self
.tree
.Expand(firstChild
)
1237 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1238 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1239 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1240 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1242 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1243 # we put it in a panel first because there seems to be a
1244 # refresh bug of some sort (wxGTK) when it is directly in
1247 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1248 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1250 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1251 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1252 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1253 self
.nb
.AddPage(panel
, self
.overviewText
)
1255 def OnOvrSize(evt
, ovr
=self
.ovr
):
1256 ovr
.SetSize(evt
.GetSize())
1257 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1258 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1260 if "gtk2" in wx
.PlatformInfo
:
1261 self
.ovr
.SetStandardFonts()
1262 self
.SetOverview(self
.overviewText
, mainOverview
)
1265 # Set up a log window
1266 self
.log
= wx
.TextCtrl(splitter2
, -1,
1267 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1269 # Set the wxWindows log target to be this textctrl
1270 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1272 # But instead of the above we want to show how to use our own wx.Log class
1273 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1275 # for serious debugging
1276 #wx.Log_SetActiveTarget(wx.LogStderr())
1277 #wx.Log_SetTraceMask(wx.TraceMessages)
1280 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1281 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1283 # add the windows to the splitter and split it.
1284 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1285 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1287 splitter
.SetMinimumPaneSize(120)
1288 splitter2
.SetMinimumPaneSize(60)
1290 # Make the splitter on the right expand the top window when resized
1291 def SplitterOnSize(evt
):
1292 splitter
= evt
.GetEventObject()
1293 sz
= splitter
.GetSize()
1294 splitter
.SetSashPosition(sz
.height
- 160, False)
1297 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1299 # select initial items
1300 self
.nb
.SetSelection(0)
1301 self
.tree
.SelectItem(root
)
1303 # Load 'Main' module
1304 self
.LoadDemo(self
.overviewText
)
1307 # select some other initial module?
1308 if len(sys
.argv
) > 1:
1310 if arg
.endswith('.py'):
1312 selectedDemo
= self
.treeMap
.get(arg
, None)
1314 self
.tree
.SelectItem(selectedDemo
)
1315 self
.tree
.EnsureVisible(selectedDemo
)
1318 #---------------------------------------------
1319 def WriteText(self
, text
):
1320 if text
[-1:] == '\n':
1324 def write(self
, txt
):
1327 #---------------------------------------------
1328 def OnItemExpanded(self
, event
):
1329 item
= event
.GetItem()
1330 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1333 #---------------------------------------------
1334 def OnItemCollapsed(self
, event
):
1335 item
= event
.GetItem()
1336 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1339 #---------------------------------------------
1340 def OnTreeLeftDown(self
, event
):
1341 # reset the overview text if the tree item is clicked on again
1342 pt
= event
.GetPosition();
1343 item
, flags
= self
.tree
.HitTest(pt
)
1344 if item
== self
.tree
.GetSelection():
1345 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1348 #---------------------------------------------
1349 def OnSelChanged(self
, event
):
1350 if self
.dying
or not self
.loaded
:
1353 item
= event
.GetItem()
1354 itemText
= self
.tree
.GetItemText(item
)
1355 self
.LoadDemo(itemText
)
1357 #---------------------------------------------
1358 def LoadDemo(self
, demoName
):
1360 wx
.BeginBusyCursor()
1363 self
.ShutdownDemoModule()
1365 if demoName
== self
.overviewText
:
1366 # User selected the "wxPython Overview" node
1368 # Changing the main window at runtime not yet supported...
1369 self
.demoModules
= DemoModules(__name__
)
1370 self
.SetOverview(self
.overviewText
, mainOverview
)
1371 self
.LoadDemoSource()
1372 self
.UpdateNotebook(0)
1374 if os
.path
.exists(GetOriginalFilename(demoName
)):
1375 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1376 self
.demoModules
= DemoModules(demoName
)
1377 self
.LoadDemoSource()
1380 self
.SetOverview("wxPython", mainOverview
)
1381 self
.codePage
= None
1382 self
.UpdateNotebook(0)
1386 #---------------------------------------------
1387 def LoadDemoSource(self
):
1388 self
.codePage
= None
1389 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1390 self
.codePage
.LoadDemo(self
.demoModules
)
1392 #---------------------------------------------
1393 def RunModule(self
):
1394 """Runs the active module"""
1396 module
= self
.demoModules
.GetActive()
1397 self
.ShutdownDemoModule()
1400 # o The RunTest() for all samples must now return a window that can
1401 # be palced in a tab in the main notebook.
1402 # o If an error occurs (or has occured before) an error tab is created.
1404 if module
is not None:
1405 wx
.LogMessage("Running demo module...")
1406 if hasattr(module
, "overview"):
1407 overviewText
= module
.overview
1410 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1412 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1413 DemoError(sys
.exc_info()), self
)
1415 assert self
.demoPage
is not None, "runTest must return a window!"
1418 # There was a previous error in compiling or exec-ing
1419 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1420 self
.demoModules
.GetErrorInfo(), self
)
1422 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1425 # cahnge to the demo page the first time a module is run
1426 self
.UpdateNotebook(2)
1427 self
.firstTime
= False
1429 # otherwise just stay on the same tab in case the user has changed to another one
1430 self
.UpdateNotebook()
1432 #---------------------------------------------
1433 def ShutdownDemoModule(self
):
1435 # inform the window that it's time to quit if it cares
1436 if hasattr(self
.demoPage
, "ShutdownDemo"):
1437 self
.demoPage
.ShutdownDemo()
1438 wx
.YieldIfNeeded() # in case the page has pending events
1439 self
.demoPage
= None
1441 #---------------------------------------------
1442 def UpdateNotebook(self
, select
= -1):
1446 def UpdatePage(page
, pageText
):
1449 for i
in range(nb
.GetPageCount()):
1450 if nb
.GetPageText(i
) == pageText
:
1458 nb
.AddPage(page
, pageText
)
1459 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1461 if nb
.GetPage(pagePos
) != page
:
1462 # Reload an existing page
1464 nb
.DeletePage(pagePos
)
1465 nb
.InsertPage(pagePos
, page
, pageText
)
1467 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1469 # Excellent! No redraw/flicker
1470 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1473 nb
.DeletePage(pagePos
)
1474 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1476 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1479 select
= nb
.GetSelection()
1481 UpdatePage(self
.codePage
, "Demo Code")
1482 UpdatePage(self
.demoPage
, "Demo")
1484 if select
>= 0 and select
< nb
.GetPageCount():
1485 nb
.SetSelection(select
)
1487 #---------------------------------------------
1488 def SetOverview(self
, name
, text
):
1489 self
.curOverview
= text
1491 if lead
!= '<html>' and lead
!= '<HTML>':
1492 text
= '<br>'.join(text
.split('\n'))
1494 text
= text
.decode('iso8859_1')
1495 self
.ovr
.SetPage(text
)
1496 self
.nb
.SetPageText(0, name
)
1498 #---------------------------------------------
1500 def OnFileExit(self
, *event
):
1503 def OnToggleRedirect(self
, event
):
1507 print "Print statements and other standard output will now be directed to this window."
1510 print "Print statements and other standard output will now be sent to the usual location."
1512 def OnHelpAbout(self
, event
):
1513 from About
import MyAboutBox
1514 about
= MyAboutBox(self
)
1518 def OnHelpFind(self
, event
):
1519 if self
.finddlg
!= None:
1522 self
.nb
.SetSelection(1)
1523 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1527 self
.finddlg
.Show(True)
1530 def OnUpdateFindItems(self
, evt
):
1531 evt
.Enable(self
.finddlg
== None)
1534 def OnFind(self
, event
):
1535 editor
= self
.codePage
.editor
1536 self
.nb
.SetSelection(1)
1537 end
= editor
.GetLastPosition()
1538 textstring
= editor
.GetRange(0, end
).lower()
1539 start
= editor
.GetSelection()[1]
1540 findstring
= self
.finddata
.GetFindString().lower()
1541 loc
= textstring
.find(findstring
, start
)
1542 if loc
== -1 and start
!= 0:
1543 # string not found, start at beginning
1545 loc
= textstring
.find(findstring
, start
)
1547 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1548 'Find String Not Found in Demo File',
1549 wx
.OK | wx
.ICON_INFORMATION
)
1554 self
.finddlg
.SetFocus()
1557 self
.finddlg
.Destroy()
1559 editor
.ShowPosition(loc
)
1560 editor
.SetSelection(loc
, loc
+ len(findstring
))
1564 def OnFindNext(self
, event
):
1565 if self
.finddata
.GetFindString():
1568 self
.OnHelpFind(event
)
1570 def OnFindClose(self
, event
):
1571 event
.GetDialog().Destroy()
1575 def OnOpenShellWindow(self
, evt
):
1577 # if it already exists then just make sure it's visible
1583 # Make a PyShell window
1585 namespace
= { 'wx' : wx
,
1586 'app' : wx
.GetApp(),
1589 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1590 self
.shell
.SetSize((640,480))
1593 # Hook the close event of the main frame window so that we
1594 # close the shell at the same time if it still exists
1595 def CloseShell(evt
):
1599 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1602 #---------------------------------------------
1603 def OnCloseWindow(self
, event
):
1605 self
.demoPage
= None
1606 self
.codePage
= None
1607 self
.mainmenu
= None
1608 self
.tbicon
.Destroy()
1612 #---------------------------------------------
1613 def OnIdle(self
, event
):
1615 self
.otherWin
.Raise()
1616 self
.demoPage
= self
.otherWin
1617 self
.otherWin
= None
1620 #---------------------------------------------
1623 showTipText
= open(opj("data/showTips")).read()
1624 showTip
, index
= eval(showTipText
)
1626 showTip
, index
= (1, 0)
1628 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1630 showTip
= wx
.ShowTip(self
, tp
)
1631 index
= tp
.GetCurrentTip()
1632 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1635 #---------------------------------------------
1636 def OnDemoMenu(self
, event
):
1638 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1642 self
.tree
.SelectItem(selectedDemo
)
1643 self
.tree
.EnsureVisible(selectedDemo
)
1647 #---------------------------------------------
1648 def OnIconfiy(self
, evt
):
1649 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1652 #---------------------------------------------
1653 def OnMaximize(self
, evt
):
1654 wx
.LogMessage("OnMaximize")
1657 #---------------------------------------------
1658 def OnActivate(self
, evt
):
1659 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1662 #---------------------------------------------
1663 def OnAppActivate(self
, evt
):
1664 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1667 #---------------------------------------------------------------------------
1668 #---------------------------------------------------------------------------
1670 class MySplashScreen(wx
.SplashScreen
):
1672 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1673 wx
.SplashScreen
.__init
__(self
, bmp
,
1674 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1676 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1678 def OnClose(self
, evt
):
1680 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1682 evt
.Skip() # Make sure the default handler runs too...
1685 class MyApp(wx
.App
):
1688 Create and show the splash screen. It will then create and show
1689 the main frame when it is time to do so.
1692 wx
.SystemOptions
.SetOptionInt("mac.window-plain-transition", 1)
1695 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1697 # Normally when using a SplashScreen you would create it, show
1698 # it and then continue on with the applicaiton's
1699 # initialization, finally creating and showing the main
1700 # application window(s). In this case we have nothing else to
1701 # do so we'll delay showing the main frame until later (see
1702 # OnClose above) so the users can see the SplashScreen effect.
1703 splash
= MySplashScreen()
1710 #---------------------------------------------------------------------------
1714 demoPath
= os
.path
.dirname(__file__
)
1721 #---------------------------------------------------------------------------
1724 mainOverview
= """<html><body>
1727 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1728 language. It allows Python programmers to create programs with a
1729 robust, highly functional graphical user interface, simply and easily.
1730 It is implemented as a Python extension module (native code) that
1731 wraps the popular wxWindows cross platform GUI library, which is
1734 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1735 means that it is free for anyone to use and the source code is
1736 available for anyone to look at and modify. Or anyone can contribute
1737 fixes or enhancements to the project.
1739 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1740 same program will run on multiple platforms without modification.
1741 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1742 or unix-like systems, and Macintosh OS X. Since the language is
1743 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1746 <p> <b>This demo</b> is not only a collection of test cases for
1747 wxPython, but is also designed to help you learn about and how to use
1748 wxPython. Each sample is listed in the tree control on the left.
1749 When a sample is selected in the tree then a module is loaded and run
1750 (usually in a tab of this notebook,) and the source code of the module
1751 is loaded in another tab for you to browse and learn from.
1756 #----------------------------------------------------------------------------
1757 #----------------------------------------------------------------------------
1759 if __name__
== '__main__':
1763 #----------------------------------------------------------------------------