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', [
55 # managed windows == things with a (optional) caption you can close
56 ('Frames and Dialogs', [
79 # dialogs from libraries
82 'MultipleChoiceDialog',
83 'ScrolledMessageDialog',
87 ('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.
156 'MaskedEditControls',
173 # How to lay out the controls in a frame/dialog
183 'XmlResourceHandler',
184 'XmlResourceSubclass',
188 ('Process and Events', [
195 ##'infoframe', # needs better explaination and some fixing
199 ('Clipboard and DnD', [
220 ##'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
):
256 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
259 self
.tc
.AppendText(message
+ '\n')
262 class MyTP(wx
.PyTipProvider
):
264 return "This is my tip"
267 #---------------------------------------------------------------------------
268 # A class to be used to display source code in the demo. Try using the
269 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
270 # if there is an error, such as the stc module not being present.
274 ##raise ImportError # for testing the alternate implementation
276 from StyledTextCtrl_2
import PythonSTC
278 class DemoCodeEditor(PythonSTC
):
279 def __init__(self
, parent
):
280 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
283 # Some methods to make it compatible with how the wxTextCtrl is used
284 def SetValue(self
, value
):
286 value
= value
.decode('iso8859_1')
288 self
.EmptyUndoBuffer()
291 def IsModified(self
):
292 return self
.GetModify()
297 def SetInsertionPoint(self
, pos
):
298 self
.SetCurrentPos(pos
)
301 def ShowPosition(self
, pos
):
302 line
= self
.LineFromPosition(pos
)
303 #self.EnsureVisible(line)
306 def GetLastPosition(self
):
307 return self
.GetLength()
309 def GetPositionFromLine(self
, line
):
310 return self
.PositionFromLine(line
)
312 def GetRange(self
, start
, end
):
313 return self
.GetTextRange(start
, end
)
315 def GetSelection(self
):
316 return self
.GetAnchor(), self
.GetCurrentPos()
318 def SetSelection(self
, start
, end
):
319 self
.SetSelectionStart(start
)
320 self
.SetSelectionEnd(end
)
322 def SelectLine(self
, line
):
323 start
= self
.PositionFromLine(line
)
324 end
= self
.GetLineEndPosition(line
)
325 self
.SetSelection(start
, end
)
327 def SetUpEditor(self
):
329 This method carries out the work of setting up the demo editor.
330 It's seperate so as not to clutter up the init code.
334 self
.SetLexer(stc
.STC_LEX_PYTHON
)
335 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
338 self
.SetProperty("fold", "1" )
340 # Highlight tab/space mixing (shouldn't be any)
341 self
.SetProperty("tab.timmy.whinge.level", "1")
343 # Set left and right margins
346 # Set up the numbers in the margin for margin #1
347 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
348 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
349 self
.SetMarginWidth(1, 40)
351 # Indentation and tab stuff
352 self
.SetIndent(4) # Proscribed indent size for wx
353 self
.SetIndentationGuides(True) # Show indent guides
354 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
355 self
.SetTabIndents(True) # Tab key indents
356 self
.SetTabWidth(4) # Proscribed tab size for wx
357 self
.SetUseTabs(False) # Use spaces rather than tabs, or
358 # TabTimmy will complain!
360 self
.SetViewWhiteSpace(False) # Don't view white space
362 # EOL: Since we are loading/saving ourselves, and the
363 # strings will always have \n's in them, set the STC to
364 # edit them that way.
365 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
366 self
.SetViewEOL(False)
368 # No right-edge mode indicator
369 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
371 # Setup a margin to hold fold markers
372 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
373 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
374 self
.SetMarginSensitive(2, True)
375 self
.SetMarginWidth(2, 12)
377 # and now set up the fold markers
378 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
379 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
380 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
381 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
382 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
383 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
384 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
386 # Global default style
387 if wx
.Platform
== '__WXMSW__':
388 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
389 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
391 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
392 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
394 # Clear styles and revert to default.
397 # Following style specs only indicate differences from default.
398 # The rest remains unchanged.
400 # Line numbers in margin
401 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
404 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
406 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
408 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
411 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
413 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
414 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
416 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
417 # Strings and characters
418 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
419 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
421 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
423 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
424 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
426 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
428 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
430 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
431 # Identifiers. I leave this as not bold because everything seems
432 # to be an identifier if it doesn't match the above criterae
433 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
436 self
.SetCaretForeground("BLUE")
437 # Selection background
438 self
.SetSelBackground(1, '#66CCFF')
440 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
441 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
443 def RegisterModifiedEvent(self
, eventHandler
):
444 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
448 class DemoCodeEditor(wx
.TextCtrl
):
449 def __init__(self
, parent
):
450 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
451 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
453 def RegisterModifiedEvent(self
, eventHandler
):
454 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
456 def SetReadOnly(self
, flag
):
457 self
.SetEditable(not flag
)
458 # NOTE: STC already has this method
461 return self
.GetValue()
463 def GetPositionFromLine(line
):
464 return self
.XYToPosition(0,line
)
466 def GotoLine(self
, line
):
467 pos
= self
.editor
.GetPositionFromLine(line
)
468 self
.editor
.SetInsertionPoint(pos
)
469 self
.editor
.ShowPosition(pos
)
471 def SelectLine(self
, line
):
472 start
= self
.GetPositionFromLine(line
)
473 end
= start
+ self
.GetLineLength(line
)
474 self
.SetSelection(start
, end
)
477 #---------------------------------------------------------------------------
478 # Constants for module versions
482 modDefault
= modOriginal
484 #---------------------------------------------------------------------------
486 class DemoCodePanel(wx
.Panel
):
487 """Panel for the 'Demo Code' tab"""
488 def __init__(self
, parent
, mainFrame
):
489 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
490 if 'wxMSW' in wx
.PlatformInfo
:
492 self
.mainFrame
= mainFrame
493 self
.editor
= DemoCodeEditor(self
)
494 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
496 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
497 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
498 self
.btnSave
.Enable(False)
499 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
500 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
502 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
503 modModified
: wx
.RadioButton(self
, -1, "Modified") }
505 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
506 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
507 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
508 for modID
, radioButton
in self
.radioButtons
.items():
509 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
510 radioButton
.modID
= modID
# makes it easier for the event handler
511 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
513 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
514 self
.controlBox
.Add(self
.btnRestore
, 0)
516 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
517 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
518 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
519 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
522 self
.SetSizer(self
.box
)
525 # Loads a demo from a DemoModules object
526 def LoadDemo(self
, demoModules
):
527 self
.demoModules
= demoModules
528 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
529 demoModules
.SetActive(modModified
)
531 demoModules
.SetActive(modOriginal
)
532 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
533 self
.ActiveModuleChanged()
536 def ActiveModuleChanged(self
):
537 self
.LoadDemoSource(self
.demoModules
.GetSource())
538 self
.UpdateControlState()
542 def LoadDemoSource(self
, source
):
544 self
.editor
.SetValue(source
)
546 self
.btnSave
.Enable(False)
549 def JumpToLine(self
, line
, highlight
=False):
550 self
.editor
.GotoLine(line
)
551 self
.editor
.SetFocus()
553 self
.editor
.SelectLine(line
)
556 def UpdateControlState(self
):
557 active
= self
.demoModules
.GetActiveID()
558 # Update the radio/restore buttons
559 for moduleID
in self
.radioButtons
:
560 btn
= self
.radioButtons
[moduleID
]
561 if moduleID
== active
:
566 if self
.demoModules
.Exists(moduleID
):
568 if moduleID
== modModified
:
569 self
.btnRestore
.Enable(True)
572 if moduleID
== modModified
:
573 self
.btnRestore
.Enable(False)
576 def OnRadioButton(self
, event
):
577 radioSelected
= event
.GetEventObject()
578 modSelected
= radioSelected
.modID
579 if modSelected
!= self
.demoModules
.GetActiveID():
580 busy
= wx
.BusyInfo("Reloading demo module...")
581 self
.demoModules
.SetActive(modSelected
)
582 self
.ActiveModuleChanged()
585 def ReloadDemo(self
):
586 if self
.demoModules
.name
!= __name__
:
587 self
.mainFrame
.RunModule()
590 def OnCodeModified(self
, event
):
591 self
.btnSave
.Enable(self
.editor
.IsModified())
594 def OnSave(self
, event
):
595 if self
.demoModules
.Exists(modModified
):
596 if self
.demoModules
.GetActiveID() == modOriginal
:
597 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
598 "Do you want to continue?"
599 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
600 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
601 result
= dlg
.ShowModal()
602 if result
== wx
.ID_NO
:
606 self
.demoModules
.SetActive(modModified
)
607 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
609 # Create the demo directory if one doesn't already exist
610 if not os
.path
.exists(GetModifiedDirectory()):
612 os
.makedirs(GetModifiedDirectory())
613 if not os
.path
.exists(GetModifiedDirectory()):
614 wx
.LogMessage("BUG: Created demo directory but it still doesn't exit")
617 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
620 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
623 f
= open(modifiedFilename
, "wt")
624 source
= self
.editor
.GetText()
630 busy
= wx
.BusyInfo("Reloading demo module...")
631 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
632 self
.ActiveModuleChanged()
635 def OnRestore(self
, event
): # Handles the "Delete Modified" button
636 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
637 self
.demoModules
.Delete(modModified
)
638 os
.unlink(modifiedFilename
) # Delete the modified copy
639 busy
= wx
.BusyInfo("Reloading demo module...")
640 self
.ActiveModuleChanged()
643 #---------------------------------------------------------------------------
646 """Convert paths to the platform-specific separator"""
647 str = apply(os
.path
.join
, tuple(path
.split('/')))
648 # HACK: on Linux, a leading / gets lost...
649 if path
.startswith('/'):
654 def GetModifiedDirectory():
656 Returns the directory where modified versions of the demo files
659 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
662 def GetModifiedFilename(name
):
664 Returns the filename of the modified version of the specified demo
666 if not name
.endswith(".py"):
668 return GetModifiedDirectory() + name
671 def GetOriginalFilename(name
):
673 Returns the filename of the original version of the specified demo
675 if not name
.endswith(".py"):
680 def DoesModifiedExist(name
):
681 """Returns whether the specified demo has a modified copy"""
682 if os
.path
.exists(GetModifiedFilename(name
)):
688 #---------------------------------------------------------------------------
690 class ModuleDictWrapper
:
691 """Emulates a module with a dynamically compiled __dict__"""
692 def __init__(self
, dict):
695 def __getattr__(self
, name
):
696 if name
in self
.dict:
697 return self
.dict[name
]
703 Dynamically manages the original/modified versions of a demo
706 def __init__(self
, name
):
710 # (dict , source , filename , description , error information )
711 # ( 0 , 1 , 2 , 3 , 4 )
712 self
.modules
= [[None, "" , "" , "<original>" , None],
713 [None, "" , "" , "<modified>" , None]]
715 # load original module
716 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
717 self
.SetActive(modOriginal
)
719 # load modified module (if one exists)
720 if DoesModifiedExist(name
):
721 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
724 def LoadFromFile(self
, modID
, filename
):
725 self
.modules
[modID
][2] = filename
726 file = open(filename
, "rt")
727 self
.LoadFromSource(modID
, file.read())
731 def LoadFromSource(self
, modID
, source
):
732 self
.modules
[modID
][1] = source
736 def LoadDict(self
, modID
):
737 if self
.name
!= __name__
:
738 source
= self
.modules
[modID
][1]
739 description
= self
.modules
[modID
][3]
742 self
.modules
[modID
][0] = {}
743 code
= compile(source
, description
, "exec")
744 exec code
in self
.modules
[modID
][0]
746 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
747 self
.modules
[modID
][0] = None
749 self
.modules
[modID
][4] = None
752 def SetActive(self
, modID
):
753 if modID
!= modOriginal
and modID
!= modModified
:
756 self
.modActive
= modID
760 dict = self
.modules
[self
.modActive
][0]
764 return ModuleDictWrapper(dict)
767 def GetActiveID(self
):
768 return self
.modActive
771 def GetSource(self
, modID
= None):
773 modID
= self
.modActive
774 return self
.modules
[modID
][1]
777 def GetFilename(self
, modID
= None):
779 modID
= self
.modActive
780 return self
.modules
[self
.modActive
][2]
783 def GetErrorInfo(self
, modID
= None):
785 modID
= self
.modActive
786 return self
.modules
[self
.modActive
][4]
789 def Exists(self
, modID
):
790 return self
.modules
[modID
][1] != ""
793 def UpdateFile(self
, modID
= None):
794 """Updates the file from which a module was loaded
795 with (possibly updated) source"""
797 modID
= self
.modActive
799 source
= self
.modules
[modID
][1]
800 filename
= self
.modules
[modID
][2]
803 file = open(filename
, "wt")
809 def Delete(self
, modID
):
810 if self
.modActive
== modID
:
813 self
.modules
[modID
][0] = None
814 self
.modules
[modID
][1] = ""
815 self
.modules
[modID
][2] = ""
818 #---------------------------------------------------------------------------
821 """Wraps and stores information about the current exception"""
822 def __init__(self
, exc_info
):
825 excType
, excValue
= exc_info
[:2]
826 # traceback list entries: (filename, line number, function name, text)
827 self
.traceback
= traceback
.extract_tb(exc_info
[2])
829 # --Based on traceback.py::format_exception_only()--
830 if type(excType
) == types
.ClassType
:
831 self
.exception_type
= excType
.__name
__
833 self
.exception_type
= excType
835 # If it's a syntax error, extra information needs
836 # to be added to the traceback
837 if excType
is SyntaxError:
839 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
844 filename
= "<string>"
846 self
.traceback
.append( (filename
, lineno
, "", line
) )
849 self
.exception_details
= str(excValue
)
851 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
858 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
861 #---------------------------------------------------------------------------
863 class DemoErrorPanel(wx
.Panel
):
864 """Panel put into the demo tab when the demo fails to run due to errors"""
866 def __init__(self
, parent
, codePanel
, demoError
, log
):
867 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
868 self
.codePanel
= codePanel
872 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
875 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
876 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
878 # Exception Information
879 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
880 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
881 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
882 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
883 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
884 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
885 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
886 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
887 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
888 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
890 # Set up the traceback list
891 # This one automatically resizes last column to take up remaining space
892 from ListCtrl
import TestListCtrl
893 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
894 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
895 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
896 self
.list.InsertColumn(0, "Filename")
897 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
898 self
.list.InsertColumn(2, "Function")
899 self
.list.InsertColumn(3, "Code")
900 self
.InsertTraceback(self
.list, demoError
.traceback
)
901 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
902 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
903 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
904 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
905 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
906 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
907 + "Double-click on them to go to the offending line")
908 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
911 self
.SetSizer(self
.box
)
914 def InsertTraceback(self
, list, traceback
):
915 #Add the traceback data
916 for x
in range(len(traceback
)):
918 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
919 list.SetStringItem(x
, 1, str(data
[1])) # Line
920 list.SetStringItem(x
, 2, str(data
[2])) # Function
921 list.SetStringItem(x
, 3, str(data
[3])) # Code
923 # Check whether this entry is from the demo module
924 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
925 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
926 # Give it a blue colour
927 item
= self
.list.GetItem(x
)
928 item
.SetTextColour(wx
.BLUE
)
929 self
.list.SetItem(item
)
931 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
934 def OnItemSelected(self
, event
):
935 # This occurs before OnDoubleClick and can be used to set the
936 # currentItem. OnDoubleClick doesn't get a wxListEvent....
937 self
.currentItem
= event
.m_itemIndex
941 def OnDoubleClick(self
, event
):
942 # If double-clicking on a demo's entry, jump to the line number
943 line
= self
.list.GetItemData(self
.currentItem
)
945 self
.nb
.SetSelection(1) # Switch to the code viewer tab
946 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
950 #---------------------------------------------------------------------------
952 class DemoTaskBarIcon(wx
.TaskBarIcon
):
953 TBMENU_RESTORE
= wx
.NewId()
954 TBMENU_CLOSE
= wx
.NewId()
955 TBMENU_CHANGE
= wx
.NewId()
956 TBMENU_REMOVE
= wx
.NewId()
958 def __init__(self
, frame
):
959 wx
.TaskBarIcon
.__init
__(self
)
963 icon
= self
.MakeIcon(images
.getMondrianImage())
964 self
.SetIcon(icon
, "wxPython Demo")
967 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
968 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
969 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
970 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
971 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
974 def CreatePopupMenu(self
):
976 This method is called by the base class when it needs to popup
977 the menu for the default EVT_RIGHT_DOWN event. Just create
978 the menu how you want it and return it from this function,
979 the base class takes care of the rest.
982 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
983 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
984 menu
.AppendSeparator()
985 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
986 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
990 def MakeIcon(self
, img
):
992 The various platforms have different requirements for the
995 if "wxMSW" in wx
.PlatformInfo
:
997 elif "wxGTK" in wx
.PlatformInfo
:
999 # wxMac can be any size upto 128.128....
1000 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1004 def OnTaskBarActivate(self
, evt
):
1005 if self
.frame
.IsIconized():
1006 self
.frame
.Iconize(False)
1007 if not self
.frame
.IsShown():
1008 self
.frame
.Show(True)
1012 def OnTaskBarClose(self
, evt
):
1016 def OnTaskBarChange(self
, evt
):
1017 icon
= self
.MakeIcon(images
.getBlom10MaskedImage())
1018 self
.SetIcon(icon
, "This is a new icon")
1021 def OnTaskBarRemove(self
, evt
):
1025 #---------------------------------------------------------------------------
1026 class wxPythonDemo(wx
.Frame
):
1027 overviewText
= "wxPython Overview"
1029 def __init__(self
, parent
, title
):
1030 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1031 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1034 self
.cwd
= os
.getcwd()
1035 self
.curOverview
= ""
1036 self
.demoPage
= None
1037 self
.codePage
= None
1039 self
.firstTime
= True
1041 icon
= images
.getMondrianIcon()
1044 self
.tbicon
= DemoTaskBarIcon(self
)
1046 wx
.CallAfter(self
.ShowTip
)
1048 self
.otherWin
= None
1049 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1050 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1051 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1052 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1054 self
.Centre(wx
.BOTH
)
1055 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1057 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1058 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1060 def EmptyHandler(evt
): pass
1061 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1062 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1064 # Prevent TreeCtrl from displaying all items after destruction when True
1068 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1071 self
.mainmenu
= wx
.MenuBar()
1073 item
= menu
.Append(-1, '&Redirect Output',
1074 'Redirect print statements to a window',
1076 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1078 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1079 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1080 wx
.App_SetMacExitMenuItemId(item
.GetId())
1081 self
.mainmenu
.Append(menu
, '&File')
1085 for item
in _treeList
:
1087 for childItem
in item
[1]:
1088 mi
= submenu
.Append(-1, childItem
)
1089 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1090 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1091 self
.mainmenu
.Append(menu
, '&Demo')
1093 # Make a Demo Code menu
1094 #TODO: Add new menu items
1095 # Like the option-enabled entries to select the
1097 #TODO: should we bother?
1100 #saveID = wx.NewId()
1101 #restoreID = wx.NewId()
1103 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1104 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1105 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1106 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1107 #self.mainmenu.Append(menu, 'Demo &Code')
1112 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1113 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1114 menu
.AppendSeparator()
1116 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1117 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1118 menu
.AppendSeparator()
1119 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1120 wx
.App_SetMacAboutMenuItemId(helpItem
.GetId())
1122 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1123 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1124 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1125 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1126 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1127 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1128 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1129 self
.mainmenu
.Append(menu
, '&Help')
1130 self
.SetMenuBar(self
.mainmenu
)
1132 self
.finddata
= wx
.FindReplaceData()
1135 # This is another way to set Accelerators, in addition to
1136 # using the '\t<key>' syntax in the menu items.
1137 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1138 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1139 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1140 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1142 self
.SetAcceleratorTable(aTable
)
1148 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1149 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1152 root
= self
.tree
.AddRoot("wxPython Overview")
1154 for item
in _treeList
:
1155 child
= self
.tree
.AppendItem(root
, item
[0])
1156 if not firstChild
: firstChild
= child
1157 for childItem
in item
[1]:
1158 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1159 self
.treeMap
[childItem
] = theDemo
1161 self
.tree
.Expand(root
)
1162 self
.tree
.Expand(firstChild
)
1163 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1164 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1165 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1166 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1168 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1169 # we put it in a panel first because there seems to be a
1170 # refresh bug of some sort (wxGTK) when it is directly in
1173 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1174 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1176 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1177 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1178 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1179 self
.nb
.AddPage(panel
, self
.overviewText
)
1181 def OnOvrSize(evt
, ovr
=self
.ovr
):
1182 ovr
.SetSize(evt
.GetSize())
1183 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1184 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1186 if "gtk2" in wx
.PlatformInfo
:
1187 self
.ovr
.SetStandardFonts()
1188 self
.SetOverview(self
.overviewText
, mainOverview
)
1191 # Set up a log window
1192 self
.log
= wx
.TextCtrl(splitter2
, -1,
1193 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1195 # Set the wxWindows log target to be this textctrl
1196 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1198 # But instead of the above we want to show how to use our own wx.Log class
1199 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1201 # for serious debugging
1202 #wx.Log_SetActiveTarget(wx.LogStderr())
1203 #wx.Log_SetTraceMask(wx.TraceMessages)
1206 # add the windows to the splitter and split it.
1207 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1208 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1210 splitter
.SetMinimumPaneSize(20)
1211 splitter2
.SetMinimumPaneSize(20)
1213 # Make the splitter on the right expand the top window when resized
1214 def SplitterOnSize(evt
):
1215 splitter
= evt
.GetEventObject()
1216 sz
= splitter
.GetSize()
1217 splitter
.SetSashPosition(sz
.height
- 160, False)
1220 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1222 # select initial items
1223 self
.nb
.SetSelection(0)
1224 self
.tree
.SelectItem(root
)
1226 # Load 'Main' module
1227 self
.LoadDemo(self
.overviewText
)
1230 # select some other initial module?
1231 if len(sys
.argv
) > 1:
1233 if arg
.endswith('.py'):
1235 selectedDemo
= self
.treeMap
.get(arg
, None)
1237 self
.tree
.SelectItem(selectedDemo
)
1238 self
.tree
.EnsureVisible(selectedDemo
)
1241 #---------------------------------------------
1242 def WriteText(self
, text
):
1243 if text
[-1:] == '\n':
1247 def write(self
, txt
):
1250 #---------------------------------------------
1251 def OnItemExpanded(self
, event
):
1252 item
= event
.GetItem()
1253 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1256 #---------------------------------------------
1257 def OnItemCollapsed(self
, event
):
1258 item
= event
.GetItem()
1259 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1262 #---------------------------------------------
1263 def OnTreeLeftDown(self
, event
):
1264 # reset the overview text if the tree item is clicked on again
1265 pt
= event
.GetPosition();
1266 item
, flags
= self
.tree
.HitTest(pt
)
1267 if item
== self
.tree
.GetSelection():
1268 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1271 #---------------------------------------------
1272 def OnSelChanged(self
, event
):
1273 if self
.dying
or not self
.loaded
:
1276 item
= event
.GetItem()
1277 itemText
= self
.tree
.GetItemText(item
)
1278 self
.LoadDemo(itemText
)
1280 #---------------------------------------------
1281 def LoadDemo(self
, demoName
):
1283 wx
.BeginBusyCursor()
1286 self
.ShutdownDemoModule()
1288 if demoName
== self
.overviewText
:
1289 # User selected the "wxPython Overview" node
1291 # Changing the main window at runtime not yet supported...
1292 self
.demoModules
= DemoModules(__name__
)
1293 self
.SetOverview(self
.overviewText
, mainOverview
)
1294 self
.LoadDemoSource()
1295 self
.UpdateNotebook(0)
1297 if os
.path
.exists(GetOriginalFilename(demoName
)):
1298 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1299 self
.demoModules
= DemoModules(demoName
)
1300 self
.LoadDemoSource()
1303 self
.SetOverview("wxPython", mainOverview
)
1304 self
.codePage
= None
1305 self
.UpdateNotebook(0)
1309 #---------------------------------------------
1310 def LoadDemoSource(self
):
1311 self
.codePage
= None
1312 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1313 self
.codePage
.LoadDemo(self
.demoModules
)
1315 #---------------------------------------------
1316 def RunModule(self
):
1317 """Runs the active module"""
1319 module
= self
.demoModules
.GetActive()
1320 self
.ShutdownDemoModule()
1323 # o If the demo returns a window it is placed in a tab.
1324 # o Otherwise, a placeholder tab is created, informing the user that the
1325 # demo runs outside the main window, and allowing it to be reloaded.
1326 # o If an error occurs (or has occured before) an error tab is created.
1328 if module
is not None:
1329 wx
.LogMessage("Running demo module...")
1330 if hasattr(module
, "overview"):
1331 overviewText
= module
.overview
1334 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1336 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1337 DemoError(sys
.exc_info()), self
)
1339 assert self
.demoPage
is not None, "runTest must return a window!"
1342 # There was a previous error in compiling or exec-ing
1343 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1344 self
.demoModules
.GetErrorInfo(), self
)
1346 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1349 # cahnge to the demo page the first time a module is run
1350 self
.UpdateNotebook(2)
1351 self
.firstTime
= False
1353 # otherwise just stay on the same tab in case the user has changed to another one
1354 self
.UpdateNotebook()
1356 #---------------------------------------------
1357 def ShutdownDemoModule(self
):
1359 # inform the window that it's time to quit if it cares
1360 if hasattr(self
.demoPage
, "ShutdownDemo"):
1361 self
.demoPage
.ShutdownDemo()
1362 wx
.YieldIfNeeded() # in case the page has pending events
1363 self
.demoPage
= None
1365 #---------------------------------------------
1366 def UpdateNotebook(self
, select
= -1):
1370 def UpdatePage(page
, pageText
):
1373 for i
in range(nb
.GetPageCount()):
1374 if nb
.GetPageText(i
) == pageText
:
1382 nb
.AddPage(page
, pageText
)
1383 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1385 if nb
.GetPage(pagePos
) != page
:
1386 # Reload an existing page
1388 nb
.DeletePage(pagePos
)
1389 nb
.InsertPage(pagePos
, page
, pageText
)
1391 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1393 # Excellent! No redraw/flicker
1394 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1397 nb
.DeletePage(pagePos
)
1398 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1400 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1403 select
= nb
.GetSelection()
1405 UpdatePage(self
.codePage
, "Demo Code")
1406 UpdatePage(self
.demoPage
, "Demo")
1408 if select
>= 0 and select
< nb
.GetPageCount():
1409 nb
.SetSelection(select
)
1411 #---------------------------------------------
1412 def SetOverview(self
, name
, text
):
1413 self
.curOverview
= text
1415 if lead
!= '<html>' and lead
!= '<HTML>':
1416 text
= '<br>'.join(text
.split('\n'))
1418 text
= text
.decode('iso8859_1')
1419 self
.ovr
.SetPage(text
)
1420 self
.nb
.SetPageText(0, name
)
1422 #---------------------------------------------
1424 def OnFileExit(self
, *event
):
1427 def OnToggleRedirect(self
, event
):
1431 print "Print statements and other standard output will now be directed to this window."
1434 print "Print statements and other standard output will now be sent to the usual location."
1436 def OnHelpAbout(self
, event
):
1437 from About
import MyAboutBox
1438 about
= MyAboutBox(self
)
1442 def OnHelpFind(self
, event
):
1443 self
.nb
.SetSelection(1)
1444 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1448 self
.finddlg
.Show(True)
1450 def OnFind(self
, event
):
1451 editor
= self
.codePage
.editor
1452 self
.nb
.SetSelection(1)
1453 end
= editor
.GetLastPosition()
1454 textstring
= editor
.GetRange(0, end
).lower()
1455 start
= editor
.GetSelection()[1]
1456 findstring
= self
.finddata
.GetFindString().lower()
1457 loc
= textstring
.find(findstring
, start
)
1458 if loc
== -1 and start
!= 0:
1459 # string not found, start at beginning
1461 loc
= textstring
.find(findstring
, start
)
1463 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1464 'Find String Not Found in Demo File',
1465 wx
.OK | wx
.ICON_INFORMATION
)
1470 self
.finddlg
.SetFocus()
1473 self
.finddlg
.Destroy()
1474 editor
.ShowPosition(loc
)
1475 editor
.SetSelection(loc
, loc
+ len(findstring
))
1479 def OnFindNext(self
, event
):
1480 if self
.finddata
.GetFindString():
1483 self
.OnHelpFind(event
)
1485 def OnFindClose(self
, event
):
1486 event
.GetDialog().Destroy()
1489 def OnOpenShellWindow(self
, evt
):
1491 # if it already exists then just make sure it's visible
1497 # Make a PyShell window
1499 namespace
= { 'wx' : wx
,
1500 'app' : wx
.GetApp(),
1503 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1504 self
.shell
.SetSize((640,480))
1507 # Hook the close event of the main frame window so that we
1508 # close the shell at the same time if it still exists
1509 def CloseShell(evt
):
1513 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1516 #---------------------------------------------
1517 def OnCloseWindow(self
, event
):
1519 self
.demoPage
= None
1520 self
.codePage
= None
1521 self
.mainmenu
= None
1522 self
.tbicon
.Destroy()
1526 #---------------------------------------------
1527 def OnIdle(self
, event
):
1529 self
.otherWin
.Raise()
1530 self
.demoPage
= self
.otherWin
1531 self
.otherWin
= None
1534 #---------------------------------------------
1537 showTipText
= open(opj("data/showTips")).read()
1538 showTip
, index
= eval(showTipText
)
1540 showTip
, index
= (1, 0)
1542 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1544 showTip
= wx
.ShowTip(self
, tp
)
1545 index
= tp
.GetCurrentTip()
1546 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1549 #---------------------------------------------
1550 def OnDemoMenu(self
, event
):
1552 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1556 self
.tree
.SelectItem(selectedDemo
)
1557 self
.tree
.EnsureVisible(selectedDemo
)
1561 #---------------------------------------------
1562 def OnIconfiy(self
, evt
):
1563 wx
.LogMessage("OnIconfiy: %d" % evt
.Iconized())
1566 #---------------------------------------------
1567 def OnMaximize(self
, evt
):
1568 wx
.LogMessage("OnMaximize")
1574 #---------------------------------------------------------------------------
1575 #---------------------------------------------------------------------------
1577 class MySplashScreen(wx
.SplashScreen
):
1579 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1580 wx
.SplashScreen
.__init
__(self
, bmp
,
1581 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1583 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1585 def OnClose(self
, evt
):
1587 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1589 evt
.Skip() # Make sure the default handler runs too...
1592 class MyApp(wx
.App
):
1595 Create and show the splash screen. It will then create and show
1596 the main frame when it is time to do so.
1600 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1602 # Normally when using a SplashScreen you would create it, show
1603 # it and then continue on with the applicaiton's
1604 # initialization, finally creating and showing the main
1605 # application window(s). In this case we have nothing else to
1606 # do so we'll delay showing the main frame until later (see
1607 # OnClose above) so the users can see the SplashScreen effect.
1608 splash
= MySplashScreen()
1615 #---------------------------------------------------------------------------
1619 demoPath
= os
.path
.dirname(__file__
)
1626 #---------------------------------------------------------------------------
1629 mainOverview
= """<html><body>
1632 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1633 language. It allows Python programmers to create programs with a
1634 robust, highly functional graphical user interface, simply and easily.
1635 It is implemented as a Python extension module (native code) that
1636 wraps the popular wxWindows cross platform GUI library, which is
1639 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1640 means that it is free for anyone to use and the source code is
1641 available for anyone to look at and modify. Or anyone can contribute
1642 fixes or enhancements to the project.
1644 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1645 same program will run on multiple platforms without modification.
1646 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1647 or unix-like systems, and Macintosh OS X. Since the language is
1648 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1651 <p> <b>This demo</b> is not only a collection of test cases for
1652 wxPython, but is also designed to help you learn about and how to use
1653 wxPython. Each sample is listed in the tree control on the left.
1654 When a sample is selected in the tree then a module is loaded and run
1655 (usually in a tab of this notebook,) and the source code of the module
1656 is loaded in another tab for you to browse and learn from.
1661 #----------------------------------------------------------------------------
1662 #----------------------------------------------------------------------------
1664 if __name__
== '__main__':
1668 #----------------------------------------------------------------------------