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')
403 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
405 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
407 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
410 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
412 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
413 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
415 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
416 # Strings and characters
417 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
418 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
420 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
422 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
423 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
425 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
427 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
429 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
430 # Identifiers. I leave this as not bold because everything seems
431 # to be an identifier if it doesn't match the above criterae
432 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
435 self
.SetCaretForeground("BLUE")
436 # Selection background
437 self
.SetSelBackground(1, '#66CCFF')
439 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
440 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
442 def RegisterModifiedEvent(self
, eventHandler
):
443 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
447 class DemoCodeEditor(wx
.TextCtrl
):
448 def __init__(self
, parent
):
449 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
450 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
452 def RegisterModifiedEvent(self
, eventHandler
):
453 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
455 def SetReadOnly(self
, flag
):
456 self
.SetEditable(not flag
)
457 # NOTE: STC already has this method
460 return self
.GetValue()
462 def GetPositionFromLine(line
):
463 return self
.XYToPosition(0,line
)
465 def GotoLine(self
, line
):
466 pos
= self
.editor
.GetPositionFromLine(line
)
467 self
.editor
.SetInsertionPoint(pos
)
468 self
.editor
.ShowPosition(pos
)
470 def SelectLine(self
, line
):
471 start
= self
.GetPositionFromLine(line
)
472 end
= start
+ self
.GetLineLength(line
)
473 self
.SetSelection(start
, end
)
476 #---------------------------------------------------------------------------
477 # Constants for module versions
481 modDefault
= modOriginal
483 #---------------------------------------------------------------------------
485 class DemoCodePanel(wx
.Panel
):
486 """Panel for the 'Demo Code' tab"""
487 def __init__(self
, parent
, mainFrame
):
488 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
489 if 'wxMSW' in wx
.PlatformInfo
:
491 self
.mainFrame
= mainFrame
492 self
.editor
= DemoCodeEditor(self
)
493 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
495 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
496 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
497 self
.btnSave
.Enable(False)
498 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
499 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
501 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
502 modModified
: wx
.RadioButton(self
, -1, "Modified") }
504 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
505 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
506 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
507 for modID
, radioButton
in self
.radioButtons
.items():
508 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
509 radioButton
.modID
= modID
# makes it easier for the event handler
510 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
512 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
513 self
.controlBox
.Add(self
.btnRestore
, 0)
515 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
516 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
517 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
518 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
521 self
.SetSizer(self
.box
)
524 # Loads a demo from a DemoModules object
525 def LoadDemo(self
, demoModules
):
526 self
.demoModules
= demoModules
527 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
528 demoModules
.SetActive(modModified
)
530 demoModules
.SetActive(modOriginal
)
531 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
532 self
.ActiveModuleChanged()
535 def ActiveModuleChanged(self
):
536 self
.LoadDemoSource(self
.demoModules
.GetSource())
537 self
.UpdateControlState()
541 def LoadDemoSource(self
, source
):
543 self
.editor
.SetValue(source
)
545 self
.btnSave
.Enable(False)
548 def JumpToLine(self
, line
, highlight
=False):
549 self
.editor
.GotoLine(line
)
550 self
.editor
.SetFocus()
552 self
.editor
.SelectLine(line
)
555 def UpdateControlState(self
):
556 active
= self
.demoModules
.GetActiveID()
557 # Update the radio/restore buttons
558 for moduleID
in self
.radioButtons
:
559 btn
= self
.radioButtons
[moduleID
]
560 if moduleID
== active
:
565 if self
.demoModules
.Exists(moduleID
):
567 if moduleID
== modModified
:
568 self
.btnRestore
.Enable(True)
571 if moduleID
== modModified
:
572 self
.btnRestore
.Enable(False)
575 def OnRadioButton(self
, event
):
576 radioSelected
= event
.GetEventObject()
577 modSelected
= radioSelected
.modID
578 if modSelected
!= self
.demoModules
.GetActiveID():
579 busy
= wx
.BusyInfo("Reloading demo module...")
580 self
.demoModules
.SetActive(modSelected
)
581 self
.ActiveModuleChanged()
584 def ReloadDemo(self
):
585 if self
.demoModules
.name
!= __name__
:
586 self
.mainFrame
.RunModule()
589 def OnCodeModified(self
, event
):
590 self
.btnSave
.Enable(self
.editor
.IsModified())
593 def OnSave(self
, event
):
594 if self
.demoModules
.Exists(modModified
):
595 if self
.demoModules
.GetActiveID() == modOriginal
:
596 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
597 "Do you want to continue?"
598 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
599 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
600 result
= dlg
.ShowModal()
601 if result
== wx
.ID_NO
:
605 self
.demoModules
.SetActive(modModified
)
606 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
608 # Create the demo directory if one doesn't already exist
609 if not os
.path
.exists(GetModifiedDirectory()):
611 os
.makedirs(GetModifiedDirectory())
612 if not os
.path
.exists(GetModifiedDirectory()):
613 wx
.LogMessage("BUG: Created demo directory but it still doesn't exit")
616 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
619 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
622 f
= open(modifiedFilename
, "wt")
623 source
= self
.editor
.GetText()
629 busy
= wx
.BusyInfo("Reloading demo module...")
630 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
631 self
.ActiveModuleChanged()
634 def OnRestore(self
, event
): # Handles the "Delete Modified" button
635 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
636 self
.demoModules
.Delete(modModified
)
637 os
.unlink(modifiedFilename
) # Delete the modified copy
638 busy
= wx
.BusyInfo("Reloading demo module...")
639 self
.ActiveModuleChanged()
642 #---------------------------------------------------------------------------
645 """Convert paths to the platform-specific separator"""
646 str = apply(os
.path
.join
, tuple(path
.split('/')))
647 # HACK: on Linux, a leading / gets lost...
648 if path
.startswith('/'):
653 def GetModifiedDirectory():
655 Returns the directory where modified versions of the demo files
658 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
661 def GetModifiedFilename(name
):
663 Returns the filename of the modified version of the specified demo
665 if not name
.endswith(".py"):
667 return GetModifiedDirectory() + name
670 def GetOriginalFilename(name
):
672 Returns the filename of the original version of the specified demo
674 if not name
.endswith(".py"):
679 def DoesModifiedExist(name
):
680 """Returns whether the specified demo has a modified copy"""
681 if os
.path
.exists(GetModifiedFilename(name
)):
687 #---------------------------------------------------------------------------
689 class ModuleDictWrapper
:
690 """Emulates a module with a dynamically compiled __dict__"""
691 def __init__(self
, dict):
694 def __getattr__(self
, name
):
695 if name
in self
.dict:
696 return self
.dict[name
]
702 Dynamically manages the original/modified versions of a demo
705 def __init__(self
, name
):
709 # (dict , source , filename , description , error information )
710 # ( 0 , 1 , 2 , 3 , 4 )
711 self
.modules
= [[None, "" , "" , "<original>" , None],
712 [None, "" , "" , "<modified>" , None]]
714 # load original module
715 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
716 self
.SetActive(modOriginal
)
718 # load modified module (if one exists)
719 if DoesModifiedExist(name
):
720 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
723 def LoadFromFile(self
, modID
, filename
):
724 self
.modules
[modID
][2] = filename
725 file = open(filename
, "rt")
726 self
.LoadFromSource(modID
, file.read())
730 def LoadFromSource(self
, modID
, source
):
731 self
.modules
[modID
][1] = source
735 def LoadDict(self
, modID
):
736 if self
.name
!= __name__
:
737 source
= self
.modules
[modID
][1]
738 description
= self
.modules
[modID
][3]
741 self
.modules
[modID
][0] = {}
742 code
= compile(source
, description
, "exec")
743 exec code
in self
.modules
[modID
][0]
745 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
746 self
.modules
[modID
][0] = None
748 self
.modules
[modID
][4] = None
751 def SetActive(self
, modID
):
752 if modID
!= modOriginal
and modID
!= modModified
:
755 self
.modActive
= modID
759 dict = self
.modules
[self
.modActive
][0]
763 return ModuleDictWrapper(dict)
766 def GetActiveID(self
):
767 return self
.modActive
770 def GetSource(self
, modID
= None):
772 modID
= self
.modActive
773 return self
.modules
[modID
][1]
776 def GetFilename(self
, modID
= None):
778 modID
= self
.modActive
779 return self
.modules
[self
.modActive
][2]
782 def GetErrorInfo(self
, modID
= None):
784 modID
= self
.modActive
785 return self
.modules
[self
.modActive
][4]
788 def Exists(self
, modID
):
789 return self
.modules
[modID
][1] != ""
792 def UpdateFile(self
, modID
= None):
793 """Updates the file from which a module was loaded
794 with (possibly updated) source"""
796 modID
= self
.modActive
798 source
= self
.modules
[modID
][1]
799 filename
= self
.modules
[modID
][2]
802 file = open(filename
, "wt")
808 def Delete(self
, modID
):
809 if self
.modActive
== modID
:
812 self
.modules
[modID
][0] = None
813 self
.modules
[modID
][1] = ""
814 self
.modules
[modID
][2] = ""
817 #---------------------------------------------------------------------------
820 """Wraps and stores information about the current exception"""
821 def __init__(self
, exc_info
):
824 excType
, excValue
= exc_info
[:2]
825 # traceback list entries: (filename, line number, function name, text)
826 self
.traceback
= traceback
.extract_tb(exc_info
[2])
828 # --Based on traceback.py::format_exception_only()--
829 if type(excType
) == types
.ClassType
:
830 self
.exception_type
= excType
.__name
__
832 self
.exception_type
= excType
834 # If it's a syntax error, extra information needs
835 # to be added to the traceback
836 if excType
is SyntaxError:
838 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
843 filename
= "<string>"
845 self
.traceback
.append( (filename
, lineno
, "", line
) )
848 self
.exception_details
= str(excValue
)
850 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
857 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
860 #---------------------------------------------------------------------------
862 class DemoErrorPanel(wx
.Panel
):
863 """Panel put into the demo tab when the demo fails to run due to errors"""
865 def __init__(self
, parent
, codePanel
, demoError
, log
):
866 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
867 self
.codePanel
= codePanel
871 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
874 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
875 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
877 # Exception Information
878 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
879 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
880 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
881 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
882 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
883 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
884 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
885 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
886 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
887 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
889 # Set up the traceback list
890 # This one automatically resizes last column to take up remaining space
891 from ListCtrl
import TestListCtrl
892 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
893 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
894 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
895 self
.list.InsertColumn(0, "Filename")
896 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
897 self
.list.InsertColumn(2, "Function")
898 self
.list.InsertColumn(3, "Code")
899 self
.InsertTraceback(self
.list, demoError
.traceback
)
900 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
901 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
902 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
903 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
904 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
905 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
906 + "Double-click on them to go to the offending line")
907 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
910 self
.SetSizer(self
.box
)
913 def InsertTraceback(self
, list, traceback
):
914 #Add the traceback data
915 for x
in range(len(traceback
)):
917 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
918 list.SetStringItem(x
, 1, str(data
[1])) # Line
919 list.SetStringItem(x
, 2, str(data
[2])) # Function
920 list.SetStringItem(x
, 3, str(data
[3])) # Code
922 # Check whether this entry is from the demo module
923 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
924 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
925 # Give it a blue colour
926 item
= self
.list.GetItem(x
)
927 item
.SetTextColour(wx
.BLUE
)
928 self
.list.SetItem(item
)
930 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
933 def OnItemSelected(self
, event
):
934 # This occurs before OnDoubleClick and can be used to set the
935 # currentItem. OnDoubleClick doesn't get a wxListEvent....
936 self
.currentItem
= event
.m_itemIndex
940 def OnDoubleClick(self
, event
):
941 # If double-clicking on a demo's entry, jump to the line number
942 line
= self
.list.GetItemData(self
.currentItem
)
944 self
.nb
.SetSelection(1) # Switch to the code viewer tab
945 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
949 #---------------------------------------------------------------------------
951 class DemoTaskBarIcon(wx
.TaskBarIcon
):
952 TBMENU_RESTORE
= wx
.NewId()
953 TBMENU_CLOSE
= wx
.NewId()
954 TBMENU_CHANGE
= wx
.NewId()
955 TBMENU_REMOVE
= wx
.NewId()
957 def __init__(self
, frame
):
958 wx
.TaskBarIcon
.__init
__(self
)
962 icon
= self
.MakeIcon(images
.getMondrianImage())
963 self
.SetIcon(icon
, "wxPython Demo")
966 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
967 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
968 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
969 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
970 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
973 def CreatePopupMenu(self
):
975 This method is called by the base class when it needs to popup
976 the menu for the default EVT_RIGHT_DOWN event. Just create
977 the menu how you want it and return it from this function,
978 the base class takes care of the rest.
981 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
982 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
983 menu
.AppendSeparator()
984 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
985 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
989 def MakeIcon(self
, img
):
991 The various platforms have different requirements for the
994 if "wxMSW" in wx
.PlatformInfo
:
996 elif "wxGTK" in wx
.PlatformInfo
:
998 # wxMac can be any size upto 128.128....
999 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1003 def OnTaskBarActivate(self
, evt
):
1004 if self
.frame
.IsIconized():
1005 self
.frame
.Iconize(False)
1006 if not self
.frame
.IsShown():
1007 self
.frame
.Show(True)
1011 def OnTaskBarClose(self
, evt
):
1015 def OnTaskBarChange(self
, evt
):
1016 icon
= self
.MakeIcon(images
.getBlom10MaskedImage())
1017 self
.SetIcon(icon
, "This is a new icon")
1020 def OnTaskBarRemove(self
, evt
):
1024 #---------------------------------------------------------------------------
1025 class wxPythonDemo(wx
.Frame
):
1026 overviewText
= "wxPython Overview"
1028 def __init__(self
, parent
, title
):
1029 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1030 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1033 self
.cwd
= os
.getcwd()
1034 self
.curOverview
= ""
1035 self
.demoPage
= None
1036 self
.codePage
= None
1038 self
.firstTime
= True
1040 icon
= images
.getMondrianIcon()
1043 self
.tbicon
= DemoTaskBarIcon(self
)
1045 wx
.CallAfter(self
.ShowTip
)
1047 self
.otherWin
= None
1048 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1049 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1050 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1051 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1053 self
.Centre(wx
.BOTH
)
1054 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1056 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1057 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1059 def EmptyHandler(evt
): pass
1060 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1061 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1063 # Prevent TreeCtrl from displaying all items after destruction when True
1067 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1070 self
.mainmenu
= wx
.MenuBar()
1072 item
= menu
.Append(-1, '&Redirect Output',
1073 'Redirect print statements to a window',
1075 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1077 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1078 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1079 wx
.App_SetMacExitMenuItemId(item
.GetId())
1080 self
.mainmenu
.Append(menu
, '&File')
1084 for item
in _treeList
:
1086 for childItem
in item
[1]:
1087 mi
= submenu
.Append(-1, childItem
)
1088 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1089 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1090 self
.mainmenu
.Append(menu
, '&Demo')
1092 # Make a Demo Code menu
1093 #TODO: Add new menu items
1094 # Like the option-enabled entries to select the
1096 #TODO: should we bother?
1099 #saveID = wx.NewId()
1100 #restoreID = wx.NewId()
1102 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1103 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1104 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1105 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1106 #self.mainmenu.Append(menu, 'Demo &Code')
1111 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1112 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1113 menu
.AppendSeparator()
1115 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1116 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1117 menu
.AppendSeparator()
1118 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1119 wx
.App_SetMacAboutMenuItemId(helpItem
.GetId())
1121 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1122 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1123 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1124 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1125 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1126 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1127 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1128 self
.mainmenu
.Append(menu
, '&Help')
1129 self
.SetMenuBar(self
.mainmenu
)
1131 self
.finddata
= wx
.FindReplaceData()
1134 # This is another way to set Accelerators, in addition to
1135 # using the '\t<key>' syntax in the menu items.
1136 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1137 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1138 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1139 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1141 self
.SetAcceleratorTable(aTable
)
1147 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1148 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1151 root
= self
.tree
.AddRoot("wxPython Overview")
1153 for item
in _treeList
:
1154 child
= self
.tree
.AppendItem(root
, item
[0])
1155 if not firstChild
: firstChild
= child
1156 for childItem
in item
[1]:
1157 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1158 self
.treeMap
[childItem
] = theDemo
1160 self
.tree
.Expand(root
)
1161 self
.tree
.Expand(firstChild
)
1162 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1163 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1164 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1165 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1167 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1168 # we put it in a panel first because there seems to be a
1169 # refresh bug of some sort (wxGTK) when it is directly in
1172 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1173 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1175 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1176 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1177 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1178 self
.nb
.AddPage(panel
, self
.overviewText
)
1180 def OnOvrSize(evt
, ovr
=self
.ovr
):
1181 ovr
.SetSize(evt
.GetSize())
1182 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1183 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1185 if "gtk2" in wx
.PlatformInfo
:
1186 self
.ovr
.SetStandardFonts()
1187 self
.SetOverview(self
.overviewText
, mainOverview
)
1190 # Set up a log window
1191 self
.log
= wx
.TextCtrl(splitter2
, -1,
1192 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1194 # Set the wxWindows log target to be this textctrl
1195 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1197 # But instead of the above we want to show how to use our own wx.Log class
1198 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1200 # for serious debugging
1201 #wx.Log_SetActiveTarget(wx.LogStderr())
1202 #wx.Log_SetTraceMask(wx.TraceMessages)
1205 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1206 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1208 # add the windows to the splitter and split it.
1209 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1210 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1212 splitter
.SetMinimumPaneSize(20)
1213 splitter2
.SetMinimumPaneSize(20)
1215 # Make the splitter on the right expand the top window when resized
1216 def SplitterOnSize(evt
):
1217 splitter
= evt
.GetEventObject()
1218 sz
= splitter
.GetSize()
1219 splitter
.SetSashPosition(sz
.height
- 160, False)
1222 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1224 # select initial items
1225 self
.nb
.SetSelection(0)
1226 self
.tree
.SelectItem(root
)
1228 # Load 'Main' module
1229 self
.LoadDemo(self
.overviewText
)
1232 # select some other initial module?
1233 if len(sys
.argv
) > 1:
1235 if arg
.endswith('.py'):
1237 selectedDemo
= self
.treeMap
.get(arg
, None)
1239 self
.tree
.SelectItem(selectedDemo
)
1240 self
.tree
.EnsureVisible(selectedDemo
)
1243 #---------------------------------------------
1244 def WriteText(self
, text
):
1245 if text
[-1:] == '\n':
1249 def write(self
, txt
):
1252 #---------------------------------------------
1253 def OnItemExpanded(self
, event
):
1254 item
= event
.GetItem()
1255 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1258 #---------------------------------------------
1259 def OnItemCollapsed(self
, event
):
1260 item
= event
.GetItem()
1261 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1264 #---------------------------------------------
1265 def OnTreeLeftDown(self
, event
):
1266 # reset the overview text if the tree item is clicked on again
1267 pt
= event
.GetPosition();
1268 item
, flags
= self
.tree
.HitTest(pt
)
1269 if item
== self
.tree
.GetSelection():
1270 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1273 #---------------------------------------------
1274 def OnSelChanged(self
, event
):
1275 if self
.dying
or not self
.loaded
:
1278 item
= event
.GetItem()
1279 itemText
= self
.tree
.GetItemText(item
)
1280 self
.LoadDemo(itemText
)
1282 #---------------------------------------------
1283 def LoadDemo(self
, demoName
):
1285 wx
.BeginBusyCursor()
1288 self
.ShutdownDemoModule()
1290 if demoName
== self
.overviewText
:
1291 # User selected the "wxPython Overview" node
1293 # Changing the main window at runtime not yet supported...
1294 self
.demoModules
= DemoModules(__name__
)
1295 self
.SetOverview(self
.overviewText
, mainOverview
)
1296 self
.LoadDemoSource()
1297 self
.UpdateNotebook(0)
1299 if os
.path
.exists(GetOriginalFilename(demoName
)):
1300 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1301 self
.demoModules
= DemoModules(demoName
)
1302 self
.LoadDemoSource()
1305 self
.SetOverview("wxPython", mainOverview
)
1306 self
.codePage
= None
1307 self
.UpdateNotebook(0)
1311 #---------------------------------------------
1312 def LoadDemoSource(self
):
1313 self
.codePage
= None
1314 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1315 self
.codePage
.LoadDemo(self
.demoModules
)
1317 #---------------------------------------------
1318 def RunModule(self
):
1319 """Runs the active module"""
1321 module
= self
.demoModules
.GetActive()
1322 self
.ShutdownDemoModule()
1325 # o The RunTest() for all samples must now return a window that can
1326 # be palced in a tab in the main notebook.
1327 # o If an error occurs (or has occured before) an error tab is created.
1329 if module
is not None:
1330 wx
.LogMessage("Running demo module...")
1331 if hasattr(module
, "overview"):
1332 overviewText
= module
.overview
1335 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1337 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1338 DemoError(sys
.exc_info()), self
)
1340 assert self
.demoPage
is not None, "runTest must return a window!"
1343 # There was a previous error in compiling or exec-ing
1344 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1345 self
.demoModules
.GetErrorInfo(), self
)
1347 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1350 # cahnge to the demo page the first time a module is run
1351 self
.UpdateNotebook(2)
1352 self
.firstTime
= False
1354 # otherwise just stay on the same tab in case the user has changed to another one
1355 self
.UpdateNotebook()
1357 #---------------------------------------------
1358 def ShutdownDemoModule(self
):
1360 # inform the window that it's time to quit if it cares
1361 if hasattr(self
.demoPage
, "ShutdownDemo"):
1362 self
.demoPage
.ShutdownDemo()
1363 wx
.YieldIfNeeded() # in case the page has pending events
1364 self
.demoPage
= None
1366 #---------------------------------------------
1367 def UpdateNotebook(self
, select
= -1):
1371 def UpdatePage(page
, pageText
):
1374 for i
in range(nb
.GetPageCount()):
1375 if nb
.GetPageText(i
) == pageText
:
1383 nb
.AddPage(page
, pageText
)
1384 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1386 if nb
.GetPage(pagePos
) != page
:
1387 # Reload an existing page
1389 nb
.DeletePage(pagePos
)
1390 nb
.InsertPage(pagePos
, page
, pageText
)
1392 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1394 # Excellent! No redraw/flicker
1395 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1398 nb
.DeletePage(pagePos
)
1399 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1401 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1404 select
= nb
.GetSelection()
1406 UpdatePage(self
.codePage
, "Demo Code")
1407 UpdatePage(self
.demoPage
, "Demo")
1409 if select
>= 0 and select
< nb
.GetPageCount():
1410 nb
.SetSelection(select
)
1412 #---------------------------------------------
1413 def SetOverview(self
, name
, text
):
1414 self
.curOverview
= text
1416 if lead
!= '<html>' and lead
!= '<HTML>':
1417 text
= '<br>'.join(text
.split('\n'))
1419 text
= text
.decode('iso8859_1')
1420 self
.ovr
.SetPage(text
)
1421 self
.nb
.SetPageText(0, name
)
1423 #---------------------------------------------
1425 def OnFileExit(self
, *event
):
1428 def OnToggleRedirect(self
, event
):
1432 print "Print statements and other standard output will now be directed to this window."
1435 print "Print statements and other standard output will now be sent to the usual location."
1437 def OnHelpAbout(self
, event
):
1438 from About
import MyAboutBox
1439 about
= MyAboutBox(self
)
1443 def OnHelpFind(self
, event
):
1444 self
.nb
.SetSelection(1)
1445 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1449 self
.finddlg
.Show(True)
1451 def OnFind(self
, event
):
1452 editor
= self
.codePage
.editor
1453 self
.nb
.SetSelection(1)
1454 end
= editor
.GetLastPosition()
1455 textstring
= editor
.GetRange(0, end
).lower()
1456 start
= editor
.GetSelection()[1]
1457 findstring
= self
.finddata
.GetFindString().lower()
1458 loc
= textstring
.find(findstring
, start
)
1459 if loc
== -1 and start
!= 0:
1460 # string not found, start at beginning
1462 loc
= textstring
.find(findstring
, start
)
1464 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1465 'Find String Not Found in Demo File',
1466 wx
.OK | wx
.ICON_INFORMATION
)
1471 self
.finddlg
.SetFocus()
1474 self
.finddlg
.Destroy()
1475 editor
.ShowPosition(loc
)
1476 editor
.SetSelection(loc
, loc
+ len(findstring
))
1480 def OnFindNext(self
, event
):
1481 if self
.finddata
.GetFindString():
1484 self
.OnHelpFind(event
)
1486 def OnFindClose(self
, event
):
1487 event
.GetDialog().Destroy()
1490 def OnOpenShellWindow(self
, evt
):
1492 # if it already exists then just make sure it's visible
1498 # Make a PyShell window
1500 namespace
= { 'wx' : wx
,
1501 'app' : wx
.GetApp(),
1504 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1505 self
.shell
.SetSize((640,480))
1508 # Hook the close event of the main frame window so that we
1509 # close the shell at the same time if it still exists
1510 def CloseShell(evt
):
1514 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1517 #---------------------------------------------
1518 def OnCloseWindow(self
, event
):
1520 self
.demoPage
= None
1521 self
.codePage
= None
1522 self
.mainmenu
= None
1523 self
.tbicon
.Destroy()
1527 #---------------------------------------------
1528 def OnIdle(self
, event
):
1530 self
.otherWin
.Raise()
1531 self
.demoPage
= self
.otherWin
1532 self
.otherWin
= None
1535 #---------------------------------------------
1538 showTipText
= open(opj("data/showTips")).read()
1539 showTip
, index
= eval(showTipText
)
1541 showTip
, index
= (1, 0)
1543 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1545 showTip
= wx
.ShowTip(self
, tp
)
1546 index
= tp
.GetCurrentTip()
1547 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1550 #---------------------------------------------
1551 def OnDemoMenu(self
, event
):
1553 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1557 self
.tree
.SelectItem(selectedDemo
)
1558 self
.tree
.EnsureVisible(selectedDemo
)
1562 #---------------------------------------------
1563 def OnIconfiy(self
, evt
):
1564 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1567 #---------------------------------------------
1568 def OnMaximize(self
, evt
):
1569 wx
.LogMessage("OnMaximize")
1572 #---------------------------------------------
1573 def OnActivate(self
, evt
):
1574 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1577 #---------------------------------------------
1578 def OnAppActivate(self
, evt
):
1579 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1582 #---------------------------------------------------------------------------
1583 #---------------------------------------------------------------------------
1585 class MySplashScreen(wx
.SplashScreen
):
1587 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1588 wx
.SplashScreen
.__init
__(self
, bmp
,
1589 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1591 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1593 def OnClose(self
, evt
):
1595 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1597 evt
.Skip() # Make sure the default handler runs too...
1600 class MyApp(wx
.App
):
1603 Create and show the splash screen. It will then create and show
1604 the main frame when it is time to do so.
1608 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1610 # Normally when using a SplashScreen you would create it, show
1611 # it and then continue on with the applicaiton's
1612 # initialization, finally creating and showing the main
1613 # application window(s). In this case we have nothing else to
1614 # do so we'll delay showing the main frame until later (see
1615 # OnClose above) so the users can see the SplashScreen effect.
1616 splash
= MySplashScreen()
1623 #---------------------------------------------------------------------------
1627 demoPath
= os
.path
.dirname(__file__
)
1634 #---------------------------------------------------------------------------
1637 mainOverview
= """<html><body>
1640 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1641 language. It allows Python programmers to create programs with a
1642 robust, highly functional graphical user interface, simply and easily.
1643 It is implemented as a Python extension module (native code) that
1644 wraps the popular wxWindows cross platform GUI library, which is
1647 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1648 means that it is free for anyone to use and the source code is
1649 available for anyone to look at and modify. Or anyone can contribute
1650 fixes or enhancements to the project.
1652 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1653 same program will run on multiple platforms without modification.
1654 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1655 or unix-like systems, and Macintosh OS X. Since the language is
1656 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1659 <p> <b>This demo</b> is not only a collection of test cases for
1660 wxPython, but is also designed to help you learn about and how to use
1661 wxPython. Each sample is listed in the tree control on the left.
1662 When a sample is selected in the tree then a module is loaded and run
1663 (usually in a tab of this notebook,) and the source code of the module
1664 is loaded in another tab for you to browse and learn from.
1669 #----------------------------------------------------------------------------
1670 #----------------------------------------------------------------------------
1672 if __name__
== '__main__':
1676 #----------------------------------------------------------------------------