2 #----------------------------------------------------------------------------
4 # Purpose: Testing lots of stuff, controls, window types, etc.
8 # Created: A long time ago, in a galaxy far, far away...
10 # Copyright: (c) 1999 by Total Control Software
11 # Licence: wxWindows license
12 #----------------------------------------------------------------------------
15 # * Problems with flickering related to ERASE_BACKGROUND
16 # and the splitters. Might be a problem with this 2.5 beta...?
17 # UPDATE: can't see on 2.5.2 GTK - maybe just a faster machine :)
19 # * Annoying switching between tabs and resulting flicker
20 # how to replace a page in the notebook without deleting/adding?
21 # Where is SetPage!? tried freeze...tried reparent of dummy panel....
24 # * UI design more prefessional
25 # * save file positions (new field in demoModules) (@ LoadDemoSource)
26 # * Update main overview
28 # * Why don't we move _treeList into a separate module
30 import sys
, os
, time
, traceback
, types
32 import wx
# This module uses the new wx namespace
39 ##print "wx.VERSION_STRING = ", wx.VERSION_STRING
41 ##raw_input("Press Enter...")
44 #---------------------------------------------------------------------------
49 ('Recent Additions/Updates', [
56 # managed windows == things with a (optional) caption you can close
57 ('Frames and Dialogs', [
80 # dialogs from libraries
83 'MultipleChoiceDialog',
84 'ScrolledMessageDialog',
88 ('Core Windows/Controls', [
127 ('Custom Controls', [
140 # controls coming from other libraries
141 ('More Windows/Controls', [
142 'ActiveX_FlashWindow',
143 'ActiveX_IEHtmlWindow',
145 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
158 'MaskedEditControls',
175 # How to lay out the controls in a frame/dialog
185 'XmlResourceHandler',
186 'XmlResourceSubclass',
190 ('Process and Events', [
197 ##'infoframe', # needs better explaination and some fixing
201 ('Clipboard and DnD', [
222 ##'DialogUnits', # needs more explainations
234 # need libs not coming with the demo
235 ('Samples using an external library', [
240 ('Check out the samples dir too', [
247 #---------------------------------------------------------------------------
248 # Show how to derive a custom wxLog class
250 class MyLog(wx
.PyLog
):
251 def __init__(self
, textCtrl
, logTime
=0):
252 wx
.PyLog
.__init
__(self
)
254 self
.logTime
= logTime
256 def DoLogString(self
, message
, timeStamp
):
258 message
= time
.strftime("%X", time
.localtime(timeStamp
)) + \
261 self
.tc
.AppendText(message
+ '\n')
264 class MyTP(wx
.PyTipProvider
):
266 return "This is my tip"
269 #---------------------------------------------------------------------------
270 # A class to be used to display source code in the demo. Try using the
271 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
272 # if there is an error, such as the stc module not being present.
276 ##raise ImportError # for testing the alternate implementation
278 from StyledTextCtrl_2
import PythonSTC
280 class DemoCodeEditor(PythonSTC
):
281 def __init__(self
, parent
):
282 PythonSTC
.__init
__(self
, parent
, -1, style
=wx
.BORDER_NONE
)
285 # Some methods to make it compatible with how the wxTextCtrl is used
286 def SetValue(self
, value
):
288 value
= value
.decode('iso8859_1')
290 self
.EmptyUndoBuffer()
293 def IsModified(self
):
294 return self
.GetModify()
299 def SetInsertionPoint(self
, pos
):
300 self
.SetCurrentPos(pos
)
303 def ShowPosition(self
, pos
):
304 line
= self
.LineFromPosition(pos
)
305 #self.EnsureVisible(line)
308 def GetLastPosition(self
):
309 return self
.GetLength()
311 def GetPositionFromLine(self
, line
):
312 return self
.PositionFromLine(line
)
314 def GetRange(self
, start
, end
):
315 return self
.GetTextRange(start
, end
)
317 def GetSelection(self
):
318 return self
.GetAnchor(), self
.GetCurrentPos()
320 def SetSelection(self
, start
, end
):
321 self
.SetSelectionStart(start
)
322 self
.SetSelectionEnd(end
)
324 def SelectLine(self
, line
):
325 start
= self
.PositionFromLine(line
)
326 end
= self
.GetLineEndPosition(line
)
327 self
.SetSelection(start
, end
)
329 def SetUpEditor(self
):
331 This method carries out the work of setting up the demo editor.
332 It's seperate so as not to clutter up the init code.
336 self
.SetLexer(stc
.STC_LEX_PYTHON
)
337 self
.SetKeyWords(0, " ".join(keyword
.kwlist
))
340 self
.SetProperty("fold", "1" )
342 # Highlight tab/space mixing (shouldn't be any)
343 self
.SetProperty("tab.timmy.whinge.level", "1")
345 # Set left and right margins
348 # Set up the numbers in the margin for margin #1
349 self
.SetMarginType(1, wx
.stc
.STC_MARGIN_NUMBER
)
350 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
351 self
.SetMarginWidth(1, 40)
353 # Indentation and tab stuff
354 self
.SetIndent(4) # Proscribed indent size for wx
355 self
.SetIndentationGuides(True) # Show indent guides
356 self
.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
357 self
.SetTabIndents(True) # Tab key indents
358 self
.SetTabWidth(4) # Proscribed tab size for wx
359 self
.SetUseTabs(False) # Use spaces rather than tabs, or
360 # TabTimmy will complain!
362 self
.SetViewWhiteSpace(False) # Don't view white space
364 # EOL: Since we are loading/saving ourselves, and the
365 # strings will always have \n's in them, set the STC to
366 # edit them that way.
367 self
.SetEOLMode(wx
.stc
.STC_EOL_LF
)
368 self
.SetViewEOL(False)
370 # No right-edge mode indicator
371 self
.SetEdgeMode(stc
.STC_EDGE_NONE
)
373 # Setup a margin to hold fold markers
374 self
.SetMarginType(2, stc
.STC_MARGIN_SYMBOL
)
375 self
.SetMarginMask(2, stc
.STC_MASK_FOLDERS
)
376 self
.SetMarginSensitive(2, True)
377 self
.SetMarginWidth(2, 12)
379 # and now set up the fold markers
380 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEREND
, stc
.STC_MARK_BOXPLUSCONNECTED
, "white", "black")
381 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPENMID
, stc
.STC_MARK_BOXMINUSCONNECTED
, "white", "black")
382 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERMIDTAIL
, stc
.STC_MARK_TCORNER
, "white", "black")
383 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERTAIL
, stc
.STC_MARK_LCORNER
, "white", "black")
384 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDERSUB
, stc
.STC_MARK_VLINE
, "white", "black")
385 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDER
, stc
.STC_MARK_BOXPLUS
, "white", "black")
386 self
.MarkerDefine(stc
.STC_MARKNUM_FOLDEROPEN
, stc
.STC_MARK_BOXMINUS
, "white", "black")
388 # Global default style
389 if wx
.Platform
== '__WXMSW__':
390 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
391 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
393 self
.StyleSetSpec(stc
.STC_STYLE_DEFAULT
,
394 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
396 # Clear styles and revert to default.
399 # Following style specs only indicate differences from default.
400 # The rest remains unchanged.
402 # Line numbers in margin
403 self
.StyleSetSpec(wx
.stc
.STC_STYLE_LINENUMBER
,'fore:#000000,back:#99A9C2')
405 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACELIGHT
,'fore:#00009D,back:#FFFF00')
407 self
.StyleSetSpec(wx
.stc
.STC_STYLE_BRACEBAD
,'fore:#00009D,back:#FF0000')
409 self
.StyleSetSpec(wx
.stc
.STC_STYLE_INDENTGUIDE
, "fore:#CDCDCD")
412 self
.StyleSetSpec(wx
.stc
.STC_P_DEFAULT
, 'fore:#000000')
414 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTLINE
, 'fore:#008000,back:#F0FFF0')
415 self
.StyleSetSpec(wx
.stc
.STC_P_COMMENTBLOCK
, 'fore:#008000,back:#F0FFF0')
417 self
.StyleSetSpec(wx
.stc
.STC_P_NUMBER
, 'fore:#008080')
418 # Strings and characters
419 self
.StyleSetSpec(wx
.stc
.STC_P_STRING
, 'fore:#800080')
420 self
.StyleSetSpec(wx
.stc
.STC_P_CHARACTER
, 'fore:#800080')
422 self
.StyleSetSpec(wx
.stc
.STC_P_WORD
, 'fore:#000080,bold')
424 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLE
, 'fore:#800080,back:#FFFFEA')
425 self
.StyleSetSpec(wx
.stc
.STC_P_TRIPLEDOUBLE
, 'fore:#800080,back:#FFFFEA')
427 self
.StyleSetSpec(wx
.stc
.STC_P_CLASSNAME
, 'fore:#0000FF,bold')
429 self
.StyleSetSpec(wx
.stc
.STC_P_DEFNAME
, 'fore:#008080,bold')
431 self
.StyleSetSpec(wx
.stc
.STC_P_OPERATOR
, 'fore:#800000,bold')
432 # Identifiers. I leave this as not bold because everything seems
433 # to be an identifier if it doesn't match the above criterae
434 self
.StyleSetSpec(wx
.stc
.STC_P_IDENTIFIER
, 'fore:#000000')
437 self
.SetCaretForeground("BLUE")
438 # Selection background
439 self
.SetSelBackground(1, '#66CCFF')
441 self
.SetSelBackground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHT
))
442 self
.SetSelForeground(True, wx
.SystemSettings_GetColour(wx
.SYS_COLOUR_HIGHLIGHTTEXT
))
444 def RegisterModifiedEvent(self
, eventHandler
):
445 self
.Bind(wx
.stc
.EVT_STC_CHANGE
, eventHandler
)
449 class DemoCodeEditor(wx
.TextCtrl
):
450 def __init__(self
, parent
):
451 wx
.TextCtrl
.__init
__(self
, parent
, -1, style
=
452 wx
.TE_MULTILINE | wx
.HSCROLL | wx
.TE_RICH2 | wx
.TE_NOHIDESEL
)
454 def RegisterModifiedEvent(self
, eventHandler
):
455 self
.Bind(wx
.EVT_TEXT
, eventHandler
)
457 def SetReadOnly(self
, flag
):
458 self
.SetEditable(not flag
)
459 # NOTE: STC already has this method
462 return self
.GetValue()
464 def GetPositionFromLine(line
):
465 return self
.XYToPosition(0,line
)
467 def GotoLine(self
, line
):
468 pos
= self
.editor
.GetPositionFromLine(line
)
469 self
.editor
.SetInsertionPoint(pos
)
470 self
.editor
.ShowPosition(pos
)
472 def SelectLine(self
, line
):
473 start
= self
.GetPositionFromLine(line
)
474 end
= start
+ self
.GetLineLength(line
)
475 self
.SetSelection(start
, end
)
478 #---------------------------------------------------------------------------
479 # Constants for module versions
483 modDefault
= modOriginal
485 #---------------------------------------------------------------------------
487 class DemoCodePanel(wx
.Panel
):
488 """Panel for the 'Demo Code' tab"""
489 def __init__(self
, parent
, mainFrame
):
490 wx
.Panel
.__init
__(self
, parent
, size
=(1,1))
491 if 'wxMSW' in wx
.PlatformInfo
:
493 self
.mainFrame
= mainFrame
494 self
.editor
= DemoCodeEditor(self
)
495 self
.editor
.RegisterModifiedEvent(self
.OnCodeModified
)
497 self
.btnSave
= wx
.Button(self
, -1, "Save Changes")
498 self
.btnRestore
= wx
.Button(self
, -1, "Delete Modified")
499 self
.btnSave
.Enable(False)
500 self
.btnSave
.Bind(wx
.EVT_BUTTON
, self
.OnSave
)
501 self
.btnRestore
.Bind(wx
.EVT_BUTTON
, self
.OnRestore
)
503 self
.radioButtons
= { modOriginal
: wx
.RadioButton(self
, -1, "Original", style
= wx
.RB_GROUP
),
504 modModified
: wx
.RadioButton(self
, -1, "Modified") }
506 self
.controlBox
= wx
.BoxSizer(wx
.HORIZONTAL
)
507 self
.controlBox
.Add(wx
.StaticText(self
, -1, "Active Version:"), 0,
508 wx
.RIGHT | wx
.LEFT | wx
.ALIGN_CENTER_VERTICAL
, 5)
509 for modID
, radioButton
in self
.radioButtons
.items():
510 self
.controlBox
.Add(radioButton
, 0, wx
.EXPAND | wx
.RIGHT
, 5)
511 radioButton
.modID
= modID
# makes it easier for the event handler
512 radioButton
.Bind(wx
.EVT_RADIOBUTTON
, self
.OnRadioButton
)
514 self
.controlBox
.Add(self
.btnSave
, 0, wx
.RIGHT
, 5)
515 self
.controlBox
.Add(self
.btnRestore
, 0)
517 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
518 self
.box
.Add(self
.controlBox
, 0, wx
.EXPAND
)
519 self
.box
.Add(wx
.StaticLine(self
), 0, wx
.EXPAND
)
520 self
.box
.Add(self
.editor
, 1, wx
.EXPAND
)
523 self
.SetSizer(self
.box
)
526 # Loads a demo from a DemoModules object
527 def LoadDemo(self
, demoModules
):
528 self
.demoModules
= demoModules
529 if (modDefault
== modModified
) and demoModules
.Exists(modModified
):
530 demoModules
.SetActive(modModified
)
532 demoModules
.SetActive(modOriginal
)
533 self
.radioButtons
[demoModules
.GetActiveID()].Enable(True)
534 self
.ActiveModuleChanged()
537 def ActiveModuleChanged(self
):
538 self
.LoadDemoSource(self
.demoModules
.GetSource())
539 self
.UpdateControlState()
543 def LoadDemoSource(self
, source
):
545 self
.editor
.SetValue(source
)
547 self
.btnSave
.Enable(False)
550 def JumpToLine(self
, line
, highlight
=False):
551 self
.editor
.GotoLine(line
)
552 self
.editor
.SetFocus()
554 self
.editor
.SelectLine(line
)
557 def UpdateControlState(self
):
558 active
= self
.demoModules
.GetActiveID()
559 # Update the radio/restore buttons
560 for moduleID
in self
.radioButtons
:
561 btn
= self
.radioButtons
[moduleID
]
562 if moduleID
== active
:
567 if self
.demoModules
.Exists(moduleID
):
569 if moduleID
== modModified
:
570 self
.btnRestore
.Enable(True)
573 if moduleID
== modModified
:
574 self
.btnRestore
.Enable(False)
577 def OnRadioButton(self
, event
):
578 radioSelected
= event
.GetEventObject()
579 modSelected
= radioSelected
.modID
580 if modSelected
!= self
.demoModules
.GetActiveID():
581 busy
= wx
.BusyInfo("Reloading demo module...")
582 self
.demoModules
.SetActive(modSelected
)
583 self
.ActiveModuleChanged()
586 def ReloadDemo(self
):
587 if self
.demoModules
.name
!= __name__
:
588 self
.mainFrame
.RunModule()
591 def OnCodeModified(self
, event
):
592 self
.btnSave
.Enable(self
.editor
.IsModified())
595 def OnSave(self
, event
):
596 if self
.demoModules
.Exists(modModified
):
597 if self
.demoModules
.GetActiveID() == modOriginal
:
598 overwriteMsg
= "You are about to overwrite an already existing modified copy\n" + \
599 "Do you want to continue?"
600 dlg
= wx
.MessageDialog(self
, overwriteMsg
, "wxPython Demo",
601 wx
.YES_NO | wx
.NO_DEFAULT| wx
.ICON_EXCLAMATION
)
602 result
= dlg
.ShowModal()
603 if result
== wx
.ID_NO
:
607 self
.demoModules
.SetActive(modModified
)
608 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
610 # Create the demo directory if one doesn't already exist
611 if not os
.path
.exists(GetModifiedDirectory()):
613 os
.makedirs(GetModifiedDirectory())
614 if not os
.path
.exists(GetModifiedDirectory()):
615 wx
.LogMessage("BUG: Created demo directory but it still doesn't exit")
618 wx
.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
621 wx
.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
624 f
= open(modifiedFilename
, "wt")
625 source
= self
.editor
.GetText()
631 busy
= wx
.BusyInfo("Reloading demo module...")
632 self
.demoModules
.LoadFromFile(modModified
, modifiedFilename
)
633 self
.ActiveModuleChanged()
636 def OnRestore(self
, event
): # Handles the "Delete Modified" button
637 modifiedFilename
= GetModifiedFilename(self
.demoModules
.name
)
638 self
.demoModules
.Delete(modModified
)
639 os
.unlink(modifiedFilename
) # Delete the modified copy
640 busy
= wx
.BusyInfo("Reloading demo module...")
641 self
.ActiveModuleChanged()
644 #---------------------------------------------------------------------------
647 """Convert paths to the platform-specific separator"""
648 str = apply(os
.path
.join
, tuple(path
.split('/')))
649 # HACK: on Linux, a leading / gets lost...
650 if path
.startswith('/'):
655 def GetModifiedDirectory():
657 Returns the directory where modified versions of the demo files
660 return opj(wx
.GetHomeDir() + "/.wxPyDemo/modified/")
663 def GetModifiedFilename(name
):
665 Returns the filename of the modified version of the specified demo
667 if not name
.endswith(".py"):
669 return GetModifiedDirectory() + name
672 def GetOriginalFilename(name
):
674 Returns the filename of the original version of the specified demo
676 if not name
.endswith(".py"):
681 def DoesModifiedExist(name
):
682 """Returns whether the specified demo has a modified copy"""
683 if os
.path
.exists(GetModifiedFilename(name
)):
689 #---------------------------------------------------------------------------
691 class ModuleDictWrapper
:
692 """Emulates a module with a dynamically compiled __dict__"""
693 def __init__(self
, dict):
696 def __getattr__(self
, name
):
697 if name
in self
.dict:
698 return self
.dict[name
]
704 Dynamically manages the original/modified versions of a demo
707 def __init__(self
, name
):
711 # (dict , source , filename , description , error information )
712 # ( 0 , 1 , 2 , 3 , 4 )
713 self
.modules
= [[None, "" , "" , "<original>" , None],
714 [None, "" , "" , "<modified>" , None]]
716 # load original module
717 self
.LoadFromFile(modOriginal
, GetOriginalFilename(name
))
718 self
.SetActive(modOriginal
)
720 # load modified module (if one exists)
721 if DoesModifiedExist(name
):
722 self
.LoadFromFile(modModified
, GetModifiedFilename(name
))
725 def LoadFromFile(self
, modID
, filename
):
726 self
.modules
[modID
][2] = filename
727 file = open(filename
, "rt")
728 self
.LoadFromSource(modID
, file.read())
732 def LoadFromSource(self
, modID
, source
):
733 self
.modules
[modID
][1] = source
737 def LoadDict(self
, modID
):
738 if self
.name
!= __name__
:
739 source
= self
.modules
[modID
][1]
740 description
= self
.modules
[modID
][3]
743 self
.modules
[modID
][0] = {}
744 code
= compile(source
, description
, "exec")
745 exec code
in self
.modules
[modID
][0]
747 self
.modules
[modID
][4] = DemoError(sys
.exc_info())
748 self
.modules
[modID
][0] = None
750 self
.modules
[modID
][4] = None
753 def SetActive(self
, modID
):
754 if modID
!= modOriginal
and modID
!= modModified
:
757 self
.modActive
= modID
761 dict = self
.modules
[self
.modActive
][0]
765 return ModuleDictWrapper(dict)
768 def GetActiveID(self
):
769 return self
.modActive
772 def GetSource(self
, modID
= None):
774 modID
= self
.modActive
775 return self
.modules
[modID
][1]
778 def GetFilename(self
, modID
= None):
780 modID
= self
.modActive
781 return self
.modules
[self
.modActive
][2]
784 def GetErrorInfo(self
, modID
= None):
786 modID
= self
.modActive
787 return self
.modules
[self
.modActive
][4]
790 def Exists(self
, modID
):
791 return self
.modules
[modID
][1] != ""
794 def UpdateFile(self
, modID
= None):
795 """Updates the file from which a module was loaded
796 with (possibly updated) source"""
798 modID
= self
.modActive
800 source
= self
.modules
[modID
][1]
801 filename
= self
.modules
[modID
][2]
804 file = open(filename
, "wt")
810 def Delete(self
, modID
):
811 if self
.modActive
== modID
:
814 self
.modules
[modID
][0] = None
815 self
.modules
[modID
][1] = ""
816 self
.modules
[modID
][2] = ""
819 #---------------------------------------------------------------------------
822 """Wraps and stores information about the current exception"""
823 def __init__(self
, exc_info
):
826 excType
, excValue
= exc_info
[:2]
827 # traceback list entries: (filename, line number, function name, text)
828 self
.traceback
= traceback
.extract_tb(exc_info
[2])
830 # --Based on traceback.py::format_exception_only()--
831 if type(excType
) == types
.ClassType
:
832 self
.exception_type
= excType
.__name
__
834 self
.exception_type
= excType
836 # If it's a syntax error, extra information needs
837 # to be added to the traceback
838 if excType
is SyntaxError:
840 msg
, (filename
, lineno
, self
.offset
, line
) = excValue
845 filename
= "<string>"
847 self
.traceback
.append( (filename
, lineno
, "", line
) )
850 self
.exception_details
= str(excValue
)
852 self
.exception_details
= "<unprintable %s object>" & type(excValue
).__name
__
859 Details : %s" % ( str(self
.exception_type
), str(self
.traceback
), self
.exception_details
)
862 #---------------------------------------------------------------------------
864 class DemoErrorPanel(wx
.Panel
):
865 """Panel put into the demo tab when the demo fails to run due to errors"""
867 def __init__(self
, parent
, codePanel
, demoError
, log
):
868 wx
.Panel
.__init
__(self
, parent
, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
869 self
.codePanel
= codePanel
873 self
.box
= wx
.BoxSizer(wx
.VERTICAL
)
876 self
.box
.Add(wx
.StaticText(self
, -1, "An error has occured while trying to run the demo")
877 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 10)
879 # Exception Information
880 boxInfo
= wx
.StaticBox(self
, -1, "Exception Info" )
881 boxInfoSizer
= wx
.StaticBoxSizer(boxInfo
, wx
.VERTICAL
) # Used to center the grid within the box
882 boxInfoGrid
= wx
.FlexGridSizer(0, 2, 0, 0)
883 textFlags
= wx
.ALIGN_RIGHT | wx
.LEFT | wx
.RIGHT | wx
.TOP
884 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Type: "), 0, textFlags
, 5 )
885 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_type
) , 0, textFlags
, 5 )
886 boxInfoGrid
.Add(wx
.StaticText(self
, -1, "Details: ") , 0, textFlags
, 5 )
887 boxInfoGrid
.Add(wx
.StaticText(self
, -1, demoError
.exception_details
) , 0, textFlags
, 5 )
888 boxInfoSizer
.Add(boxInfoGrid
, 0, wx
.ALIGN_CENTRE | wx
.ALL
, 5 )
889 self
.box
.Add(boxInfoSizer
, 0, wx
.ALIGN_CENTER | wx
.ALL
, 5)
891 # Set up the traceback list
892 # This one automatically resizes last column to take up remaining space
893 from ListCtrl
import TestListCtrl
894 self
.list = TestListCtrl(self
, -1, style
=wx
.LC_REPORT | wx
.SUNKEN_BORDER
)
895 self
.list.Bind(wx
.EVT_LEFT_DCLICK
, self
.OnDoubleClick
)
896 self
.list.Bind(wx
.EVT_LIST_ITEM_SELECTED
, self
.OnItemSelected
)
897 self
.list.InsertColumn(0, "Filename")
898 self
.list.InsertColumn(1, "Line", wx
.LIST_FORMAT_RIGHT
)
899 self
.list.InsertColumn(2, "Function")
900 self
.list.InsertColumn(3, "Code")
901 self
.InsertTraceback(self
.list, demoError
.traceback
)
902 self
.list.SetColumnWidth(0, wx
.LIST_AUTOSIZE
)
903 self
.list.SetColumnWidth(2, wx
.LIST_AUTOSIZE
)
904 self
.box
.Add(wx
.StaticText(self
, -1, "Traceback:")
905 , 0, wx
.ALIGN_CENTER | wx
.TOP
, 5)
906 self
.box
.Add(self
.list, 1, wx
.GROW | wx
.ALIGN_CENTER | wx
.ALL
, 5)
907 self
.box
.Add(wx
.StaticText(self
, -1, "Entries from the demo module are shown in blue\n"
908 + "Double-click on them to go to the offending line")
909 , 0, wx
.ALIGN_CENTER | wx
.BOTTOM
, 5)
912 self
.SetSizer(self
.box
)
915 def InsertTraceback(self
, list, traceback
):
916 #Add the traceback data
917 for x
in range(len(traceback
)):
919 list.InsertStringItem(x
, os
.path
.basename(data
[0])) # Filename
920 list.SetStringItem(x
, 1, str(data
[1])) # Line
921 list.SetStringItem(x
, 2, str(data
[2])) # Function
922 list.SetStringItem(x
, 3, str(data
[3])) # Code
924 # Check whether this entry is from the demo module
925 if data
[0] == "<original>" or data
[0] == "<modified>": # FIXME: make more generalised
926 self
.list.SetItemData(x
, int(data
[1])) # Store line number for easy access
927 # Give it a blue colour
928 item
= self
.list.GetItem(x
)
929 item
.SetTextColour(wx
.BLUE
)
930 self
.list.SetItem(item
)
932 self
.list.SetItemData(x
, -1) # Editor can't jump into this one's code
935 def OnItemSelected(self
, event
):
936 # This occurs before OnDoubleClick and can be used to set the
937 # currentItem. OnDoubleClick doesn't get a wxListEvent....
938 self
.currentItem
= event
.m_itemIndex
942 def OnDoubleClick(self
, event
):
943 # If double-clicking on a demo's entry, jump to the line number
944 line
= self
.list.GetItemData(self
.currentItem
)
946 self
.nb
.SetSelection(1) # Switch to the code viewer tab
947 wx
.CallAfter(self
.codePanel
.JumpToLine
, line
-1, True)
951 #---------------------------------------------------------------------------
953 class DemoTaskBarIcon(wx
.TaskBarIcon
):
954 TBMENU_RESTORE
= wx
.NewId()
955 TBMENU_CLOSE
= wx
.NewId()
956 TBMENU_CHANGE
= wx
.NewId()
957 TBMENU_REMOVE
= wx
.NewId()
959 def __init__(self
, frame
):
960 wx
.TaskBarIcon
.__init
__(self
)
964 icon
= self
.MakeIcon(images
.getMondrianImage())
965 self
.SetIcon(icon
, "wxPython Demo")
968 self
.Bind(wx
.EVT_TASKBAR_LEFT_DCLICK
, self
.OnTaskBarActivate
)
969 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarActivate
, id=self
.TBMENU_RESTORE
)
970 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarClose
, id=self
.TBMENU_CLOSE
)
971 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarChange
, id=self
.TBMENU_CHANGE
)
972 self
.Bind(wx
.EVT_MENU
, self
.OnTaskBarRemove
, id=self
.TBMENU_REMOVE
)
975 def CreatePopupMenu(self
):
977 This method is called by the base class when it needs to popup
978 the menu for the default EVT_RIGHT_DOWN event. Just create
979 the menu how you want it and return it from this function,
980 the base class takes care of the rest.
983 menu
.Append(self
.TBMENU_RESTORE
, "Restore wxPython Demo")
984 menu
.Append(self
.TBMENU_CLOSE
, "Close wxPython Demo")
985 menu
.AppendSeparator()
986 menu
.Append(self
.TBMENU_CHANGE
, "Change the TB Icon")
987 menu
.Append(self
.TBMENU_REMOVE
, "Remove the TB Icon")
991 def MakeIcon(self
, img
):
993 The various platforms have different requirements for the
996 if "wxMSW" in wx
.PlatformInfo
:
998 elif "wxGTK" in wx
.PlatformInfo
:
1000 # wxMac can be any size upto 128.128....
1001 icon
= wx
.IconFromBitmap(img
.ConvertToBitmap() )
1005 def OnTaskBarActivate(self
, evt
):
1006 if self
.frame
.IsIconized():
1007 self
.frame
.Iconize(False)
1008 if not self
.frame
.IsShown():
1009 self
.frame
.Show(True)
1013 def OnTaskBarClose(self
, evt
):
1017 def OnTaskBarChange(self
, evt
):
1018 icon
= self
.MakeIcon(images
.getBlom10MaskedImage())
1019 self
.SetIcon(icon
, "This is a new icon")
1022 def OnTaskBarRemove(self
, evt
):
1026 #---------------------------------------------------------------------------
1027 class wxPythonDemo(wx
.Frame
):
1028 overviewText
= "wxPython Overview"
1030 def __init__(self
, parent
, title
):
1031 wx
.Frame
.__init
__(self
, parent
, -1, title
, size
= (950, 720),
1032 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
1035 self
.cwd
= os
.getcwd()
1036 self
.curOverview
= ""
1037 self
.demoPage
= None
1038 self
.codePage
= None
1040 self
.firstTime
= True
1042 icon
= images
.getMondrianIcon()
1045 self
.tbicon
= DemoTaskBarIcon(self
)
1047 wx
.CallAfter(self
.ShowTip
)
1049 self
.otherWin
= None
1050 self
.Bind(wx
.EVT_IDLE
, self
.OnIdle
)
1051 self
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
)
1052 self
.Bind(wx
.EVT_ICONIZE
, self
.OnIconfiy
)
1053 self
.Bind(wx
.EVT_MAXIMIZE
, self
.OnMaximize
)
1055 self
.Centre(wx
.BOTH
)
1056 self
.CreateStatusBar(1, wx
.ST_SIZEGRIP
)
1058 splitter
= wx
.SplitterWindow(self
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1059 splitter2
= wx
.SplitterWindow(splitter
, -1, style
=wx
.CLIP_CHILDREN | wx
.SP_LIVE_UPDATE | wx
.SP_3D
)
1061 def EmptyHandler(evt
): pass
1062 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1063 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1065 # Prevent TreeCtrl from displaying all items after destruction when True
1069 self
.nb
= wx
.Notebook(splitter2
, -1, style
=wx
.CLIP_CHILDREN
)
1072 self
.mainmenu
= wx
.MenuBar()
1074 item
= menu
.Append(-1, '&Redirect Output',
1075 'Redirect print statements to a window',
1077 self
.Bind(wx
.EVT_MENU
, self
.OnToggleRedirect
, item
)
1079 item
= menu
.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1080 self
.Bind(wx
.EVT_MENU
, self
.OnFileExit
, item
)
1081 wx
.App_SetMacExitMenuItemId(item
.GetId())
1082 self
.mainmenu
.Append(menu
, '&File')
1086 for item
in _treeList
:
1088 for childItem
in item
[1]:
1089 mi
= submenu
.Append(-1, childItem
)
1090 self
.Bind(wx
.EVT_MENU
, self
.OnDemoMenu
, mi
)
1091 menu
.AppendMenu(wx
.NewId(), item
[0], submenu
)
1092 self
.mainmenu
.Append(menu
, '&Demo')
1094 # Make a Demo Code menu
1095 #TODO: Add new menu items
1096 # Like the option-enabled entries to select the
1098 #TODO: should we bother?
1101 #saveID = wx.NewId()
1102 #restoreID = wx.NewId()
1104 #menu.Append(saveID, '&Save\tCtrl-S', 'Save edited demo')
1105 #menu.Append(restoreID, '&Delete Modified\tCtrl-R', 'Delete modified copy')
1106 #self.Bind(wx.EVT_MENU, self.codePage.OnSave, id=saveID)
1107 #self.Bind(wx.EVT_MENU, self.codePage.OnRestore, id=restoreID)
1108 #self.mainmenu.Append(menu, 'Demo &Code')
1113 findItem
= menu
.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1114 findnextItem
= menu
.Append(-1, 'Find &Next\tF3', 'Find Next')
1115 menu
.AppendSeparator()
1117 shellItem
= menu
.Append(-1, 'Open Py&Shell Window\tF5',
1118 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1119 menu
.AppendSeparator()
1120 helpItem
= menu
.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
1121 wx
.App_SetMacAboutMenuItemId(helpItem
.GetId())
1123 self
.Bind(wx
.EVT_MENU
, self
.OnOpenShellWindow
, shellItem
)
1124 self
.Bind(wx
.EVT_MENU
, self
.OnHelpAbout
, helpItem
)
1125 self
.Bind(wx
.EVT_MENU
, self
.OnHelpFind
, findItem
)
1126 self
.Bind(wx
.EVT_MENU
, self
.OnFindNext
, findnextItem
)
1127 self
.Bind(wx
.EVT_COMMAND_FIND
, self
.OnFind
)
1128 self
.Bind(wx
.EVT_COMMAND_FIND_NEXT
, self
.OnFind
)
1129 self
.Bind(wx
.EVT_COMMAND_FIND_CLOSE
, self
.OnFindClose
)
1130 self
.mainmenu
.Append(menu
, '&Help')
1131 self
.SetMenuBar(self
.mainmenu
)
1133 self
.finddata
= wx
.FindReplaceData()
1136 # This is another way to set Accelerators, in addition to
1137 # using the '\t<key>' syntax in the menu items.
1138 aTable
= wx
.AcceleratorTable([(wx
.ACCEL_ALT
, ord('X'), exitID
),
1139 (wx
.ACCEL_CTRL
, ord('H'), helpID
),
1140 (wx
.ACCEL_CTRL
, ord('F'), findID
),
1141 (wx
.ACCEL_NORMAL
, WXK_F3
, findnextID
)
1143 self
.SetAcceleratorTable(aTable
)
1149 self
.tree
= wx
.TreeCtrl(splitter
, tID
, style
=
1150 wx
.TR_DEFAULT_STYLE
#| wx.TR_HAS_VARIABLE_ROW_HEIGHT
1153 root
= self
.tree
.AddRoot("wxPython Overview")
1155 for item
in _treeList
:
1156 child
= self
.tree
.AppendItem(root
, item
[0])
1157 if not firstChild
: firstChild
= child
1158 for childItem
in item
[1]:
1159 theDemo
= self
.tree
.AppendItem(child
, childItem
)
1160 self
.treeMap
[childItem
] = theDemo
1162 self
.tree
.Expand(root
)
1163 self
.tree
.Expand(firstChild
)
1164 self
.tree
.Bind(wx
.EVT_TREE_ITEM_EXPANDED
, self
.OnItemExpanded
, id=tID
)
1165 self
.tree
.Bind(wx
.EVT_TREE_ITEM_COLLAPSED
, self
.OnItemCollapsed
, id=tID
)
1166 self
.tree
.Bind(wx
.EVT_TREE_SEL_CHANGED
, self
.OnSelChanged
, id=tID
)
1167 self
.tree
.Bind(wx
.EVT_LEFT_DOWN
, self
.OnTreeLeftDown
)
1169 # Set up a wx.html.HtmlWindow on the Overview Notebook page
1170 # we put it in a panel first because there seems to be a
1171 # refresh bug of some sort (wxGTK) when it is directly in
1174 self
.ovr
= wx
.html
.HtmlWindow(self
.nb
, -1, size
=(400, 400))
1175 self
.nb
.AddPage(self
.ovr
, self
.overviewText
)
1177 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1178 panel
= wx
.Panel(self
.nb
, -1, style
=wx
.CLIP_CHILDREN
)
1179 self
.ovr
= wx
.html
.HtmlWindow(panel
, -1, size
=(400, 400))
1180 self
.nb
.AddPage(panel
, self
.overviewText
)
1182 def OnOvrSize(evt
, ovr
=self
.ovr
):
1183 ovr
.SetSize(evt
.GetSize())
1184 panel
.Bind(wx
.EVT_SIZE
, OnOvrSize
)
1185 panel
.Bind(wx
.EVT_ERASE_BACKGROUND
, EmptyHandler
)
1187 if "gtk2" in wx
.PlatformInfo
:
1188 self
.ovr
.SetStandardFonts()
1189 self
.SetOverview(self
.overviewText
, mainOverview
)
1192 # Set up a log window
1193 self
.log
= wx
.TextCtrl(splitter2
, -1,
1194 style
= wx
.TE_MULTILINE|wx
.TE_READONLY|wx
.HSCROLL
)
1196 # Set the wxWindows log target to be this textctrl
1197 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
1199 # But instead of the above we want to show how to use our own wx.Log class
1200 wx
.Log_SetActiveTarget(MyLog(self
.log
))
1202 # for serious debugging
1203 #wx.Log_SetActiveTarget(wx.LogStderr())
1204 #wx.Log_SetTraceMask(wx.TraceMessages)
1207 self
.Bind(wx
.EVT_ACTIVATE
, self
.OnActivate
)
1208 wx
.GetApp().Bind(wx
.EVT_ACTIVATE_APP
, self
.OnAppActivate
)
1210 # add the windows to the splitter and split it.
1211 splitter2
.SplitHorizontally(self
.nb
, self
.log
, -160)
1212 splitter
.SplitVertically(self
.tree
, splitter2
, 200)
1214 splitter
.SetMinimumPaneSize(20)
1215 splitter2
.SetMinimumPaneSize(20)
1217 # Make the splitter on the right expand the top window when resized
1218 def SplitterOnSize(evt
):
1219 splitter
= evt
.GetEventObject()
1220 sz
= splitter
.GetSize()
1221 splitter
.SetSashPosition(sz
.height
- 160, False)
1224 splitter2
.Bind(wx
.EVT_SIZE
, SplitterOnSize
)
1226 # select initial items
1227 self
.nb
.SetSelection(0)
1228 self
.tree
.SelectItem(root
)
1230 # Load 'Main' module
1231 self
.LoadDemo(self
.overviewText
)
1234 # select some other initial module?
1235 if len(sys
.argv
) > 1:
1237 if arg
.endswith('.py'):
1239 selectedDemo
= self
.treeMap
.get(arg
, None)
1241 self
.tree
.SelectItem(selectedDemo
)
1242 self
.tree
.EnsureVisible(selectedDemo
)
1245 #---------------------------------------------
1246 def WriteText(self
, text
):
1247 if text
[-1:] == '\n':
1251 def write(self
, txt
):
1254 #---------------------------------------------
1255 def OnItemExpanded(self
, event
):
1256 item
= event
.GetItem()
1257 wx
.LogMessage("OnItemExpanded: %s" % self
.tree
.GetItemText(item
))
1260 #---------------------------------------------
1261 def OnItemCollapsed(self
, event
):
1262 item
= event
.GetItem()
1263 wx
.LogMessage("OnItemCollapsed: %s" % self
.tree
.GetItemText(item
))
1266 #---------------------------------------------
1267 def OnTreeLeftDown(self
, event
):
1268 # reset the overview text if the tree item is clicked on again
1269 pt
= event
.GetPosition();
1270 item
, flags
= self
.tree
.HitTest(pt
)
1271 if item
== self
.tree
.GetSelection():
1272 self
.SetOverview(self
.tree
.GetItemText(item
)+" Overview", self
.curOverview
)
1275 #---------------------------------------------
1276 def OnSelChanged(self
, event
):
1277 if self
.dying
or not self
.loaded
:
1280 item
= event
.GetItem()
1281 itemText
= self
.tree
.GetItemText(item
)
1282 self
.LoadDemo(itemText
)
1284 #---------------------------------------------
1285 def LoadDemo(self
, demoName
):
1287 wx
.BeginBusyCursor()
1290 self
.ShutdownDemoModule()
1292 if demoName
== self
.overviewText
:
1293 # User selected the "wxPython Overview" node
1295 # Changing the main window at runtime not yet supported...
1296 self
.demoModules
= DemoModules(__name__
)
1297 self
.SetOverview(self
.overviewText
, mainOverview
)
1298 self
.LoadDemoSource()
1299 self
.UpdateNotebook(0)
1301 if os
.path
.exists(GetOriginalFilename(demoName
)):
1302 wx
.LogMessage("Loading demo %s.py..." % demoName
)
1303 self
.demoModules
= DemoModules(demoName
)
1304 self
.LoadDemoSource()
1307 self
.SetOverview("wxPython", mainOverview
)
1308 self
.codePage
= None
1309 self
.UpdateNotebook(0)
1313 #---------------------------------------------
1314 def LoadDemoSource(self
):
1315 self
.codePage
= None
1316 self
.codePage
= DemoCodePanel(self
.nb
, self
)
1317 self
.codePage
.LoadDemo(self
.demoModules
)
1319 #---------------------------------------------
1320 def RunModule(self
):
1321 """Runs the active module"""
1323 module
= self
.demoModules
.GetActive()
1324 self
.ShutdownDemoModule()
1327 # o The RunTest() for all samples must now return a window that can
1328 # be palced in a tab in the main notebook.
1329 # o If an error occurs (or has occured before) an error tab is created.
1331 if module
is not None:
1332 wx
.LogMessage("Running demo module...")
1333 if hasattr(module
, "overview"):
1334 overviewText
= module
.overview
1337 self
.demoPage
= module
.runTest(self
, self
.nb
, self
)
1339 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1340 DemoError(sys
.exc_info()), self
)
1342 assert self
.demoPage
is not None, "runTest must return a window!"
1345 # There was a previous error in compiling or exec-ing
1346 self
.demoPage
= DemoErrorPanel(self
.nb
, self
.codePage
,
1347 self
.demoModules
.GetErrorInfo(), self
)
1349 self
.SetOverview(self
.demoModules
.name
+ " Overview", overviewText
)
1352 # cahnge to the demo page the first time a module is run
1353 self
.UpdateNotebook(2)
1354 self
.firstTime
= False
1356 # otherwise just stay on the same tab in case the user has changed to another one
1357 self
.UpdateNotebook()
1359 #---------------------------------------------
1360 def ShutdownDemoModule(self
):
1362 # inform the window that it's time to quit if it cares
1363 if hasattr(self
.demoPage
, "ShutdownDemo"):
1364 self
.demoPage
.ShutdownDemo()
1365 wx
.YieldIfNeeded() # in case the page has pending events
1366 self
.demoPage
= None
1368 #---------------------------------------------
1369 def UpdateNotebook(self
, select
= -1):
1373 def UpdatePage(page
, pageText
):
1376 for i
in range(nb
.GetPageCount()):
1377 if nb
.GetPageText(i
) == pageText
:
1385 nb
.AddPage(page
, pageText
)
1386 if debug
: wx
.LogMessage("DBG: ADDED %s" % pageText
)
1388 if nb
.GetPage(pagePos
) != page
:
1389 # Reload an existing page
1391 nb
.DeletePage(pagePos
)
1392 nb
.InsertPage(pagePos
, page
, pageText
)
1394 if debug
: wx
.LogMessage("DBG: RELOADED %s" % pageText
)
1396 # Excellent! No redraw/flicker
1397 if debug
: wx
.LogMessage("DBG: SAVED from reloading %s" % pageText
)
1400 nb
.DeletePage(pagePos
)
1401 if debug
: wx
.LogMessage("DBG: DELETED %s" % pageText
)
1403 if debug
: wx
.LogMessage("DBG: STILL GONE - %s" % pageText
)
1406 select
= nb
.GetSelection()
1408 UpdatePage(self
.codePage
, "Demo Code")
1409 UpdatePage(self
.demoPage
, "Demo")
1411 if select
>= 0 and select
< nb
.GetPageCount():
1412 nb
.SetSelection(select
)
1414 #---------------------------------------------
1415 def SetOverview(self
, name
, text
):
1416 self
.curOverview
= text
1418 if lead
!= '<html>' and lead
!= '<HTML>':
1419 text
= '<br>'.join(text
.split('\n'))
1421 text
= text
.decode('iso8859_1')
1422 self
.ovr
.SetPage(text
)
1423 self
.nb
.SetPageText(0, name
)
1425 #---------------------------------------------
1427 def OnFileExit(self
, *event
):
1430 def OnToggleRedirect(self
, event
):
1434 print "Print statements and other standard output will now be directed to this window."
1437 print "Print statements and other standard output will now be sent to the usual location."
1439 def OnHelpAbout(self
, event
):
1440 from About
import MyAboutBox
1441 about
= MyAboutBox(self
)
1445 def OnHelpFind(self
, event
):
1446 self
.nb
.SetSelection(1)
1447 self
.finddlg
= wx
.FindReplaceDialog(self
, self
.finddata
, "Find",
1451 self
.finddlg
.Show(True)
1453 def OnFind(self
, event
):
1454 editor
= self
.codePage
.editor
1455 self
.nb
.SetSelection(1)
1456 end
= editor
.GetLastPosition()
1457 textstring
= editor
.GetRange(0, end
).lower()
1458 start
= editor
.GetSelection()[1]
1459 findstring
= self
.finddata
.GetFindString().lower()
1460 loc
= textstring
.find(findstring
, start
)
1461 if loc
== -1 and start
!= 0:
1462 # string not found, start at beginning
1464 loc
= textstring
.find(findstring
, start
)
1466 dlg
= wx
.MessageDialog(self
, 'Find String Not Found',
1467 'Find String Not Found in Demo File',
1468 wx
.OK | wx
.ICON_INFORMATION
)
1473 self
.finddlg
.SetFocus()
1476 self
.finddlg
.Destroy()
1477 editor
.ShowPosition(loc
)
1478 editor
.SetSelection(loc
, loc
+ len(findstring
))
1482 def OnFindNext(self
, event
):
1483 if self
.finddata
.GetFindString():
1486 self
.OnHelpFind(event
)
1488 def OnFindClose(self
, event
):
1489 event
.GetDialog().Destroy()
1492 def OnOpenShellWindow(self
, evt
):
1494 # if it already exists then just make sure it's visible
1500 # Make a PyShell window
1502 namespace
= { 'wx' : wx
,
1503 'app' : wx
.GetApp(),
1506 self
.shell
= py
.shell
.ShellFrame(None, locals=namespace
)
1507 self
.shell
.SetSize((640,480))
1510 # Hook the close event of the main frame window so that we
1511 # close the shell at the same time if it still exists
1512 def CloseShell(evt
):
1516 self
.Bind(wx
.EVT_CLOSE
, CloseShell
)
1519 #---------------------------------------------
1520 def OnCloseWindow(self
, event
):
1522 self
.demoPage
= None
1523 self
.codePage
= None
1524 self
.mainmenu
= None
1525 self
.tbicon
.Destroy()
1529 #---------------------------------------------
1530 def OnIdle(self
, event
):
1532 self
.otherWin
.Raise()
1533 self
.demoPage
= self
.otherWin
1534 self
.otherWin
= None
1537 #---------------------------------------------
1540 showTipText
= open(opj("data/showTips")).read()
1541 showTip
, index
= eval(showTipText
)
1543 showTip
, index
= (1, 0)
1545 tp
= wx
.CreateFileTipProvider(opj("data/tips.txt"), index
)
1547 showTip
= wx
.ShowTip(self
, tp
)
1548 index
= tp
.GetCurrentTip()
1549 open(opj("data/showTips"), "w").write(str( (showTip
, index
) ))
1552 #---------------------------------------------
1553 def OnDemoMenu(self
, event
):
1555 selectedDemo
= self
.treeMap
[self
.mainmenu
.GetLabel(event
.GetId())]
1559 self
.tree
.SelectItem(selectedDemo
)
1560 self
.tree
.EnsureVisible(selectedDemo
)
1564 #---------------------------------------------
1565 def OnIconfiy(self
, evt
):
1566 wx
.LogMessage("OnIconfiy: %s" % evt
.Iconized())
1569 #---------------------------------------------
1570 def OnMaximize(self
, evt
):
1571 wx
.LogMessage("OnMaximize")
1574 #---------------------------------------------
1575 def OnActivate(self
, evt
):
1576 wx
.LogMessage("OnActivate: %s" % evt
.GetActive())
1579 #---------------------------------------------
1580 def OnAppActivate(self
, evt
):
1581 wx
.LogMessage("OnAppActivate: %s" % evt
.GetActive())
1584 #---------------------------------------------------------------------------
1585 #---------------------------------------------------------------------------
1587 class MySplashScreen(wx
.SplashScreen
):
1589 bmp
= wx
.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
1590 wx
.SplashScreen
.__init
__(self
, bmp
,
1591 wx
.SPLASH_CENTRE_ON_SCREEN | wx
.SPLASH_TIMEOUT
,
1593 self
.Bind(wx
.EVT_CLOSE
, self
.OnClose
)
1595 def OnClose(self
, evt
):
1597 frame
= wxPythonDemo(None, "wxPython: (A Demonstration)")
1599 evt
.Skip() # Make sure the default handler runs too...
1602 class MyApp(wx
.App
):
1605 Create and show the splash screen. It will then create and show
1606 the main frame when it is time to do so.
1610 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1612 # Normally when using a SplashScreen you would create it, show
1613 # it and then continue on with the applicaiton's
1614 # initialization, finally creating and showing the main
1615 # application window(s). In this case we have nothing else to
1616 # do so we'll delay showing the main frame until later (see
1617 # OnClose above) so the users can see the SplashScreen effect.
1618 splash
= MySplashScreen()
1625 #---------------------------------------------------------------------------
1629 demoPath
= os
.path
.dirname(__file__
)
1636 #---------------------------------------------------------------------------
1639 mainOverview
= """<html><body>
1642 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
1643 language. It allows Python programmers to create programs with a
1644 robust, highly functional graphical user interface, simply and easily.
1645 It is implemented as a Python extension module (native code) that
1646 wraps the popular wxWindows cross platform GUI library, which is
1649 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1650 means that it is free for anyone to use and the source code is
1651 available for anyone to look at and modify. Or anyone can contribute
1652 fixes or enhancements to the project.
1654 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1655 same program will run on multiple platforms without modification.
1656 Currently supported platforms are 32-bit Microsoft Windows, most Unix
1657 or unix-like systems, and Macintosh OS X. Since the language is
1658 Python, wxPython programs are <b>simple, easy</b> to write and easy to
1661 <p> <b>This demo</b> is not only a collection of test cases for
1662 wxPython, but is also designed to help you learn about and how to use
1663 wxPython. Each sample is listed in the tree control on the left.
1664 When a sample is selected in the tree then a module is loaded and run
1665 (usually in a tab of this notebook,) and the source code of the module
1666 is loaded in another tab for you to browse and learn from.
1671 #----------------------------------------------------------------------------
1672 #----------------------------------------------------------------------------
1674 if __name__
== '__main__':
1678 #----------------------------------------------------------------------------