]> git.saurik.com Git - wxWidgets.git/blame - wxPython/demo/Main.py
pop the menu up on mouse down, not up (this is more common behaviour in Windows and...
[wxWidgets.git] / wxPython / demo / Main.py
CommitLineData
cf694132
RD
1#!/bin/env python
2#----------------------------------------------------------------------------
3# Name: Main.py
4# Purpose: Testing lots of stuff, controls, window types, etc.
5#
f6bcfd97 6# Author: Robin Dunn
cf694132 7#
f6bcfd97 8# Created: A long time ago, in a galaxy far, far away...
cf694132
RD
9# RCS-ID: $Id$
10# Copyright: (c) 1999 by Total Control Software
11# Licence: wxWindows license
12#----------------------------------------------------------------------------
13
1e4a197e 14import sys, os, time
cf694132 15
1fded56b
RD
16import wx # This module uses the new wx namespace
17import wx.html
606d919c 18
96bfd053
RD
19import images
20
d14a1e28
RD
21# For debugging
22##wx.Trap();
ef8b9c3e 23##print "wx.VERSION_STRING = ", wx.VERSION_STRING
4276dc52 24##print os.getpid();
ef8b9c3e 25##raw_input("Press Enter...")
6fa68946 26
1e4a197e 27
cf694132
RD
28#---------------------------------------------------------------------------
29
30
31_treeList = [
9c67cbec 32 # new stuff
f847103a 33 ('Recent Additions and Updates', [
f6063c19 34 'OGL',
9c67cbec
RD
35 ]),
36
1e4a197e 37 # managed windows == things with a (optional) caption you can close
9c67cbec 38 ('Base Frames and Dialogs', [
299647ac
RD
39 'Dialog',
40 'Frame',
41 'MDIWindows',
42 'MiniFrame',
43 'Wizard',
9c67cbec
RD
44 ]),
45
46 # the common dialogs
47 ('Common Dialogs', [
299647ac
RD
48 'ColourDialog',
49 'DirDialog',
50 'FileDialog',
51 'FileDialog_Save',
52 'FindReplaceDialog',
53 'FontDialog',
54 'MessageDialog',
55 'PageSetupDialog',
56 'PrintDialog',
57 'ProgressDialog',
58 'SingleChoiceDialog',
59 'TextEntryDialog',
9c67cbec
RD
60 ]),
61
af83019e 62 # dialogs from libraries
9c67cbec 63 ('More Dialogs', [
9c67cbec 64 'ImageBrowser',
299647ac
RD
65 'MultipleChoiceDialog',
66 'ScrolledMessageDialog',
9c67cbec
RD
67 ]),
68
69 # core controls
70 ('Core Windows/Controls', [
8b7fa2d9 71 'BitmapButton',
299647ac
RD
72 'Button',
73 'CheckBox',
74 'CheckListBox',
75 'Choice',
76 'ComboBox',
77 'Gauge',
78 'Grid',
79 'Grid_MegaExample',
80 'ListBox',
81 'ListCtrl',
82 'ListCtrl_virtual',
83 'Listbook',
84 'Menu',
85 'Notebook',
1fded56b 86 'PopupMenu',
299647ac
RD
87 'PopupWindow',
88 'RadioBox',
89 'RadioButton',
90 'SashWindow',
91 'ScrolledWindow',
92 'Slider',
93 'SpinButton',
94 'SpinCtrl',
95 'SplitterWindow',
96 'StaticBitmap',
97 'StaticText',
98 'StatusBar',
99 'TextCtrl',
100 'ToggleButton',
101 'ToolBar',
102 'TreeCtrl',
103 'Validator',
9c67cbec
RD
104 ]),
105
d14a1e28
RD
106 ('Custom Controls', [
107 'AnalogClockWindow',
108 'ColourSelect',
299647ac 109 'Editor',
d14a1e28 110 'GenericButtons',
299647ac
RD
111 'GenericDirCtrl',
112 'LEDNumberCtrl',
113 'MultiSash',
114 'PopupControl',
115 'PyColourChooser',
116 'TreeListCtrl',
d14a1e28
RD
117 ]),
118
8b9a4190 119 # controls coming from other libraries
9c67cbec 120 ('More Windows/Controls', [
b7c75283
RD
121 'ActiveX_FlashWindow',
122 'ActiveX_IEHtmlWindow',
123 'ActiveX_PDFWindow',
299647ac
RD
124 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
125 'Calendar',
126 'CalendarCtrl',
9c67cbec 127 'ContextHelp',
299647ac
RD
128 'DynamicSashWindow',
129 'EditableListBox',
9c67cbec
RD
130 'FancyText',
131 'FileBrowseButton',
299647ac
RD
132 'FloatBar',
133 'FloatCanvas',
134 'HtmlWindow',
299647ac
RD
135 'IntCtrl',
136 'MVCTree',
1fded56b 137 'MaskedEditControls',
299647ac
RD
138 'MaskedNumCtrl',
139 'MimeTypesManager',
9c67cbec 140 'PyCrust',
80b27b4e 141 'PyPlot',
299647ac
RD
142 'PyShell',
143 'ScrolledPanel',
9c67cbec 144 'SplitTree',
299647ac
RD
145 'StyledTextCtrl_1',
146 'StyledTextCtrl_2',
9c67cbec 147 'TablePrint',
1e4a197e 148 'Throbber',
299647ac
RD
149 'TimeCtrl',
150 'VListBox',
9c67cbec
RD
151 ]),
152
153 # How to lay out the controls in a frame/dialog
154 ('Window Layout', [
299647ac 155 'GridBagSizer',
9c67cbec 156 'LayoutAnchors',
299647ac 157 'LayoutConstraints',
9c67cbec
RD
158 'Layoutf',
159 'RowColSizer',
299647ac 160 'ScrolledPanel',
9c67cbec 161 'Sizers',
299647ac
RD
162 'XmlResource',
163 'XmlResourceHandler',
164 'XmlResourceSubclass',
9c67cbec
RD
165 ]),
166
167 # ditto
168 ('Process and Events', [
1e4a197e 169 'EventManager',
299647ac 170 'KeyEvents',
299647ac 171 'Process',
9c67cbec
RD
172 'PythonEvents',
173 'Threads',
299647ac
RD
174 'Timer',
175 'infoframe',
9c67cbec
RD
176 ]),
177
178 # Clipboard and DnD
179 ('Clipboard and DnD', [
180 'CustomDragAndDrop',
181 'DragAndDrop',
182 'URLDragAndDrop',
183 ]),
184
185 # Images
1e4a197e 186 ('Using Images', [
299647ac 187 'ArtProvider',
76343679 188 'Cursor',
299647ac
RD
189 'DragImage',
190 'Image',
8a88769e 191 'ImageAlpha',
299647ac
RD
192 'ImageFromStream',
193 'Mask',
1e4a197e 194 'Throbber',
9c67cbec
RD
195 ]),
196
197 # Other stuff
198 ('Miscellaneous', [
199 'ColourDB',
200 'DialogUnits',
201 'DrawXXXList',
299647ac 202 'FileHistory',
9c67cbec 203 'FontEnumerator',
299647ac 204 'Joystick',
299647ac 205 'OGL',
9c67cbec 206 'PrintFramework',
3628e088 207 'ShapedWindow',
78862f24 208 'Sound',
9c67cbec 209 'Unicode',
9c67cbec
RD
210 ]),
211
212 # need libs not coming with the demo
d7403ad2 213 ('Samples using an external library', [
299647ac 214 'GLCanvas',
9c67cbec
RD
215 ]),
216
70a357c2 217
9c67cbec
RD
218 ('Check out the samples dir too', [
219 ]),
220
9c67cbec
RD
221]
222
223
cf694132
RD
224
225#---------------------------------------------------------------------------
8b9a4190 226# Show how to derive a custom wxLog class
cf694132 227
1fded56b 228class MyLog(wx.PyLog):
76bfdc78 229 def __init__(self, textCtrl, logTime=0):
1fded56b 230 wx.PyLog.__init__(self)
76bfdc78
RD
231 self.tc = textCtrl
232 self.logTime = logTime
233
234 def DoLogString(self, message, timeStamp):
235 if self.logTime:
236 message = time.strftime("%X", time.localtime(timeStamp)) + \
237 ": " + message
1e4a197e
RD
238 if self.tc:
239 self.tc.AppendText(message + '\n')
76bfdc78
RD
240
241
1fded56b 242class MyTP(wx.PyTipProvider):
861a0196
RD
243 def GetTip(self):
244 return "This is my tip"
245
1fded56b
RD
246#---------------------------------------------------------------------------
247# A class to be used to display source code in the demo. Try using the
299647ac 248# wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
1fded56b 249# if there is an error, such as the stc module not being present.
8b9a4190 250#
1fded56b
RD
251
252try:
253 ##raise ImportError
254 from wx import stc
299647ac 255 from StyledTextCtrl_2 import PythonSTC
1fded56b
RD
256 class DemoCodeViewer(PythonSTC):
257 def __init__(self, parent, ID):
a5d9c77b 258 PythonSTC.__init__(self, parent, ID, wx.BORDER_NONE)
80b27b4e 259 self.SetUpEditor()
1fded56b
RD
260
261 # Some methods to make it compatible with how the wxTextCtrl is used
262 def SetValue(self, value):
263 self.SetReadOnly(False)
264 self.SetText(value)
265 self.SetReadOnly(True)
266
267 def Clear(self):
268 self.ClearAll()
269
270 def SetInsertionPoint(self, pos):
271 self.SetCurrentPos(pos)
272
273 def ShowPosition(self, pos):
274 self.GotoPos(pos)
275
276 def GetLastPosition(self):
277 return self.GetLength()
278
279 def GetRange(self, start, end):
280 return self.GetTextRange(start, end)
281
282 def GetSelection(self):
283 return self.GetAnchor(), self.GetCurrentPos()
284
285 def SetSelection(self, start, end):
286 self.SetSelectionStart(start)
287 self.SetSelectionEnd(end)
288
80b27b4e
RD
289 def SetUpEditor(self):
290 """
291 This method carries out the work of setting up the demo editor.
292 It's seperate so as not to clutter up the init code.
293 """
294 import keyword
295
296 self.SetLexer(stc.STC_LEX_PYTHON)
297 self.SetKeyWords(0, " ".join(keyword.kwlist))
298
299 # Enable folding
300 self.SetProperty("fold", "1" )
301
302 # Highlight tab/space mixing (shouldn't be any)
303 self.SetProperty("tab.timmy.whinge.level", "1")
304
305 # Set left and right margins
306 self.SetMargins(2,2)
307
308 # Set up the numbers in the margin for margin #1
309 self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
310 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
311 self.SetMarginWidth(1, 40)
312
313 # Indentation and tab stuff
314 self.SetIndent(4) # Proscribed indent size for wx
315 self.SetIndentationGuides(True) # Show indent guides
316 self.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
317 self.SetTabIndents(True) # Tab key indents
318 self.SetTabWidth(4) # Proscribed tab size for wx
319 self.SetUseTabs(False) # Use spaces rather than tabs, or
320 # TabTimmy will complain!
321 # White space
322 self.SetViewWhiteSpace(False) # Don't view white space
323
324 # EOL
325 #self.SetEOLMode(wx.stc.STC_EOL_CRLF) # Just leave it at the default (autosense)
326 self.SetViewEOL(False)
327 # No right-edge mode indicator
328 self.SetEdgeMode(stc.STC_EDGE_NONE)
329
330 # Setup a margin to hold fold markers
331 self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
332 self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
333 self.SetMarginSensitive(2, True)
334 self.SetMarginWidth(2, 12)
335
336 # and now set up the fold markers
337 self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "black")
338 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "black")
339 self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "black")
340 self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "black")
341 self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "black")
342 self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "black")
343 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "black")
344
345 # Global default style
346 if wx.Platform == '__WXMSW__':
347 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
348 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
349 else:
350 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
351 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
352
353 # Clear styles and revert to default.
354 self.StyleClearAll()
355
356 # Following style specs only indicate differences from default.
357 # The rest remains unchanged.
358
359 # Line numbers in margin
360 self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')
361
362 # Highlighted brace
363 self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
364 # Unmatched brace
365 self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
366 # Indentation guide
367 self.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
368
369 # Python styles
370 self.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
371 # Comments
a253aa20
RD
372 self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0')
373 self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
80b27b4e
RD
374 # Numbers
375 self.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
376 # Strings and characters
377 self.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
378 self.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
379 # Keywords
380 self.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
381 # Triple quotes
382 self.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
383 self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
384 # Class names
385 self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
386 # Function names
387 self.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
388 # Operators
389 self.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
390 # Identifiers. I leave this as not bold because everything seems
391 # to be an identifier if it doesn't match the above criterae
392 self.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
393
394 # Caret color
395 self.SetCaretForeground("BLUE")
396 # Selection background
397 self.SetSelBackground(1, '#66CCFF')
398
399 self.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
400 self.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
401
1fded56b
RD
402
403except ImportError:
404 class DemoCodeViewer(wx.TextCtrl):
405 def __init__(self, parent, ID):
406 wx.TextCtrl.__init__(self, parent, ID, style =
407 wx.TE_MULTILINE | wx.TE_READONLY |
408 wx.HSCROLL | wx.TE_RICH2 | wx.TE_NOHIDESEL)
409
410
6c5ae2d2
RD
411#---------------------------------------------------------------------------
412
413def opj(path):
414 """Convert paths to the platform-specific separator"""
1e4a197e 415 return apply(os.path.join, tuple(path.split('/')))
6c5ae2d2
RD
416
417
76bfdc78
RD
418#---------------------------------------------------------------------------
419
1fded56b 420class wxPythonDemo(wx.Frame):
e9159fe8 421 overviewText = "wxPython Overview"
c368d904 422
cf694132 423 def __init__(self, parent, id, title):
1fded56b 424 wx.Frame.__init__(self, parent, -1, title, size = (800, 600),
a253aa20 425 style=wx.DEFAULT_FRAME_STYLE|wx.NO_FULL_REPAINT_ON_RESIZE)
a5d9c77b 426
2f90df85 427
694759cf 428 self.cwd = os.getcwd()
3ca6a5f0 429 self.curOverview = ""
1e4a197e 430 self.window = None
694759cf 431
afb810d9 432 icon = images.getMondrianIcon()
96bfd053 433 self.SetIcon(icon)
c368d904 434
4a9067b9 435 if wx.Platform != '__WXMAC__':
c368d904 436 # setup a taskbar icon, and catch some events from it
f6063c19
RD
437 if wx.Platform == '__WXGTK__':
438 dimension = 22
439 else:
440 dimension = 16
4a9067b9 441 icon = wx.IconFromBitmap(
f6063c19
RD
442 images.getMondrianImage().Scale(dimension,dimension).ConvertToBitmap() )
443 #icon = wx.Icon('bmp_source/mondrian.ico', wx.BITMAP_TYPE_ICO)
444 #icon = images.getMondrianIcon()
1fded56b 445 self.tbicon = wx.TaskBarIcon()
c368d904 446 self.tbicon.SetIcon(icon, "wxPython Demo")
80b27b4e
RD
447 self.tbicon.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
448 self.tbicon.Bind(wx.EVT_TASKBAR_RIGHT_UP, self.OnTaskBarMenu)
449 self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE)
450 self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE)
c368d904 451
1fded56b 452 wx.CallAfter(self.ShowTip)
cf694132
RD
453
454 self.otherWin = None
80b27b4e
RD
455 self.Bind(wx.EVT_IDLE, self.OnIdle)
456 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
457 self.Bind(wx.EVT_ICONIZE, self.OnIconfiy)
458 self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize)
cf694132 459
1fded56b
RD
460 self.Centre(wx.BOTH)
461 self.CreateStatusBar(1, wx.ST_SIZEGRIP)
5a7823f5 462
0c8f2860
RD
463 splitter = wx.SplitterWindow(self, -1, style=wx.CLIP_CHILDREN | wx.SP_LIVE_UPDATE | wx.SP_3D)
464 splitter2 = wx.SplitterWindow(splitter, -1, style=wx.CLIP_CHILDREN | wx.SP_LIVE_UPDATE | wx.SP_3D)
5a7823f5 465
8edf1c75
RD
466 # Set up a log on the View Log Notebook page
467 self.log = wx.TextCtrl(splitter2, -1,
468 style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
ef8b9c3e 469
8edf1c75
RD
470 # Set the wxWindows log target to be this textctrl
471 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
472
473 # But instead of the above we want to show how to use our own wx.Log class
474 wx.Log_SetActiveTarget(MyLog(self.log))
475
476 # for serious debugging
477 #wx.Log_SetActiveTarget(wx.LogStderr())
478 #wx.Log_SetTraceMask(wx.TraceMessages)
479
480
481
d56cebe7 482 def EmptyHandler(evt): pass
80b27b4e
RD
483 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
484 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
cf694132 485
1e4a197e
RD
486 # Prevent TreeCtrl from displaying all items after destruction when True
487 self.dying = False
cf694132
RD
488
489 # Make a File menu
1fded56b
RD
490 self.mainmenu = wx.MenuBar()
491 menu = wx.Menu()
330af869
RD
492 item = menu.Append(-1, '&Redirect Output',
493 'Redirect print statements to a window',
494 wx.ITEM_CHECK)
495 self.Bind(wx.EVT_MENU, self.OnToggleRedirect, item)
496
c8000995
RD
497 item = menu.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
498 self.Bind(wx.EVT_MENU, self.OnFileExit, item)
499 wx.App_SetMacExitMenuItemId(item.GetId())
330af869 500
cf694132
RD
501 self.mainmenu.Append(menu, '&File')
502
ec3e670f 503 # Make a Demo menu
1fded56b 504 menu = wx.Menu()
ec3e670f 505 for item in _treeList:
1fded56b 506 submenu = wx.Menu()
ec3e670f 507 for childItem in item[1]:
c8000995
RD
508 mi = submenu.Append(-1, childItem)
509 self.Bind(wx.EVT_MENU, self.OnDemoMenu, mi)
1fded56b 510 menu.AppendMenu(wx.NewId(), item[0], submenu)
ec3e670f
RD
511 self.mainmenu.Append(menu, '&Demo')
512
513
cf694132 514 # Make a Help menu
1fded56b
RD
515 helpID = wx.NewId()
516 findID = wx.NewId()
517 findnextID = wx.NewId()
518 menu = wx.Menu()
c8000995
RD
519 findItem = menu.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
520 findnextItem = menu.Append(-1, 'Find &Next\tF3', 'Find Next')
1e4a197e 521 menu.AppendSeparator()
c8000995
RD
522 helpItem = menu.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
523 wx.App_SetMacAboutMenuItemId(helpItem.GetId())
524 self.Bind(wx.EVT_MENU, self.OnHelpAbout, helpItem)
525 self.Bind(wx.EVT_MENU, self.OnHelpFind, findItem)
526 self.Bind(wx.EVT_MENU, self.OnFindNext, findnextItem)
80b27b4e
RD
527 self.Bind(wx.EVT_COMMAND_FIND, self.OnFind)
528 self.Bind(wx.EVT_COMMAND_FIND_NEXT, self.OnFind)
529 self.Bind(wx.EVT_COMMAND_FIND_CLOSE, self.OnFindClose)
cf694132
RD
530 self.mainmenu.Append(menu, '&Help')
531 self.SetMenuBar(self.mainmenu)
532
1fded56b 533 self.finddata = wx.FindReplaceData()
1e4a197e
RD
534
535 if 0:
536 # This is another way to set Accelerators, in addition to
537 # using the '\t<key>' syntax in the menu items.
1fded56b
RD
538 aTable = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), exitID),
539 (wx.ACCEL_CTRL, ord('H'), helpID),
540 (wx.ACCEL_CTRL, ord('F'), findID),
541 (wx.ACCEL_NORMAL, WXK_F3, findnextID)
542 ])
1e4a197e 543 self.SetAcceleratorTable(aTable)
2f90df85 544
bb0054cd 545
cf694132 546 # Create a TreeCtrl
1fded56b 547 tID = wx.NewId()
f6bcfd97 548 self.treeMap = {}
3628e088
RD
549 self.tree = wx.TreeCtrl(splitter, tID, style =
550 wx.TR_DEFAULT_STYLE #| wx.TR_HAS_VARIABLE_ROW_HEIGHT
eb0f373c 551 )
afb810d9 552
e9159fe8 553 root = self.tree.AddRoot("wxPython Overview")
f6bcfd97
BP
554 firstChild = None
555 for item in _treeList:
556 child = self.tree.AppendItem(root, item[0])
557 if not firstChild: firstChild = child
558 for childItem in item[1]:
559 theDemo = self.tree.AppendItem(child, childItem)
560 self.treeMap[childItem] = theDemo
561
562 self.tree.Expand(root)
563 self.tree.Expand(firstChild)
80b27b4e
RD
564 self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, id=tID)
565 self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=tID)
566 self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=tID)
567 self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown)
cf694132 568
cf694132 569 # Create a Notebook
1fded56b 570 self.nb = wx.Notebook(splitter2, -1, style=wx.CLIP_CHILDREN)
cf694132 571
1fded56b 572 # Set up a wx.html.HtmlWindow on the Overview Notebook page
0bdca46d
RD
573 # we put it in a panel first because there seems to be a
574 # refresh bug of some sort (wxGTK) when it is directly in
575 # the notebook...
576 if 0: # the old way
1fded56b 577 self.ovr = wx.html.HtmlWindow(self.nb, -1, size=(400, 400))
0bdca46d
RD
578 self.nb.AddPage(self.ovr, self.overviewText)
579
1fded56b
RD
580 else: # hopefully I can remove this hacky code soon, see SF bug #216861
581 panel = wx.Panel(self.nb, -1, style=wx.CLIP_CHILDREN)
582 self.ovr = wx.html.HtmlWindow(panel, -1, size=(400, 400))
0bdca46d
RD
583 self.nb.AddPage(panel, self.overviewText)
584
585 def OnOvrSize(evt, ovr=self.ovr):
586 ovr.SetSize(evt.GetSize())
587
80b27b4e
RD
588 panel.Bind(wx.EVT_SIZE, OnOvrSize)
589 panel.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
0bdca46d 590
c368d904 591
e9159fe8 592 self.SetOverview(self.overviewText, overview)
cf694132
RD
593
594
1fded56b
RD
595 # Set up a notebook page for viewing the source code of each sample
596 self.txt = DemoCodeViewer(self.nb, -1)
cf694132 597 self.nb.AddPage(self.txt, "Demo Code")
80b27b4e 598 self.LoadDemoSource('Main.py')
cf694132
RD
599
600
f6bcfd97 601 # add the windows to the splitter and split it.
2f0f3b0f 602 splitter2.SplitHorizontally(self.nb, self.log, -120)
1e4a197e 603 splitter.SplitVertically(self.tree, splitter2, 180)
afb810d9 604
f6bcfd97 605 splitter.SetMinimumPaneSize(20)
afb810d9
RD
606 splitter2.SetMinimumPaneSize(20)
607
cf694132 608
11926a78 609 # Make the splitter on the right expand the top window when resized
2f0f3b0f
RD
610 def SplitterOnSize(evt):
611 splitter = evt.GetEventObject()
612 sz = splitter.GetSize()
613 splitter.SetSashPosition(sz.height - 120, False)
614 evt.Skip()
80b27b4e
RD
615
616 splitter2.Bind(wx.EVT_SIZE, SplitterOnSize)
2f0f3b0f 617
cf694132 618
bb0054cd
RD
619 # select initial items
620 self.nb.SetSelection(0)
f6bcfd97 621 self.tree.SelectItem(root)
ec3e670f
RD
622
623 if len(sys.argv) == 2:
624 try:
625 selectedDemo = self.treeMap[sys.argv[1]]
626 except:
627 selectedDemo = None
f6bcfd97 628 if selectedDemo:
ec3e670f
RD
629 self.tree.SelectItem(selectedDemo)
630 self.tree.EnsureVisible(selectedDemo)
631
bb0054cd 632
ef8b9c3e 633## wx.LogMessage('window handle: %s' % self.GetHandle())
2abc0a0f
RD
634
635
cf694132
RD
636 #---------------------------------------------
637 def WriteText(self, text):
f6bcfd97
BP
638 if text[-1:] == '\n':
639 text = text[:-1]
1fded56b 640 wx.LogMessage(text)
f6bcfd97 641
cf694132
RD
642
643 def write(self, txt):
644 self.WriteText(txt)
645
646 #---------------------------------------------
647 def OnItemExpanded(self, event):
648 item = event.GetItem()
1fded56b 649 wx.LogMessage("OnItemExpanded: %s" % self.tree.GetItemText(item))
c368d904 650 event.Skip()
cf694132
RD
651
652 #---------------------------------------------
653 def OnItemCollapsed(self, event):
654 item = event.GetItem()
1fded56b 655 wx.LogMessage("OnItemCollapsed: %s" % self.tree.GetItemText(item))
c368d904 656 event.Skip()
f6bcfd97
BP
657
658 #---------------------------------------------
659 def OnTreeLeftDown(self, event):
660 pt = event.GetPosition();
661 item, flags = self.tree.HitTest(pt)
662 if item == self.tree.GetSelection():
d975da9b 663 self.SetOverview(self.tree.GetItemText(item)+" Overview", self.curOverview)
185d7c3e 664 event.Skip()
cf694132
RD
665
666 #---------------------------------------------
667 def OnSelChanged(self, event):
668 if self.dying:
669 return
670
5a7823f5
RD
671 item = event.GetItem()
672 itemText = self.tree.GetItemText(item)
673 self.RunDemo(itemText)
674
675
676 #---------------------------------------------
677 def RunDemo(self, itemText):
694759cf 678 os.chdir(self.cwd)
cf694132
RD
679 if self.nb.GetPageCount() == 3:
680 if self.nb.GetSelection() == 2:
681 self.nb.SetSelection(0)
1e4a197e
RD
682 # inform the window that it's time to quit if it cares
683 if self.window is not None:
684 if hasattr(self.window, "ShutdownDemo"):
685 self.window.ShutdownDemo()
1fded56b 686 wx.SafeYield() # in case the page has pending events
cf694132
RD
687 self.nb.DeletePage(2)
688
e9159fe8 689 if itemText == self.overviewText:
80b27b4e 690 self.LoadDemoSource('Main.py')
e9159fe8 691 self.SetOverview(self.overviewText, overview)
e91a9dfc 692 self.window = None
cf694132
RD
693
694 else:
695 if os.path.exists(itemText + '.py'):
1fded56b
RD
696 wx.BeginBusyCursor()
697 wx.LogMessage("Running demo %s.py..." % itemText)
f6bcfd97 698 try:
80b27b4e
RD
699 self.LoadDemoSource(itemText + '.py')
700
701 if (sys.modules.has_key(itemText)):
702 reload(sys.modules[itemText])
703
f6bcfd97 704 module = __import__(itemText, globals())
e9159fe8 705 self.SetOverview(itemText + " Overview", module.overview)
f6bcfd97 706 finally:
1fded56b 707 wx.EndBusyCursor()
5a1eefc7 708 self.tree.Refresh()
cf694132 709
f6bcfd97 710 self.window = module.runTest(self, self.nb, self) ###
1e4a197e 711 if self.window is not None:
e91a9dfc 712 self.nb.AddPage(self.window, 'Demo')
cf694132 713 self.nb.SetSelection(2)
cf694132
RD
714
715 else:
f6bcfd97 716 self.ovr.SetPage("")
cf694132 717 self.txt.Clear()
e91a9dfc 718 self.window = None
cf694132 719
2e55c818 720 self.tree.SetFocus()
2f90df85 721
cf694132
RD
722
723 #---------------------------------------------
724 # Get the Demo files
80b27b4e 725 def LoadDemoSource(self, filename):
cf694132 726 self.txt.Clear()
bb0054cd
RD
727 try:
728 self.txt.SetValue(open(filename).read())
8bf5d46e 729 except IOError:
1fded56b 730 self.txt.SetValue("Cannot open %s file." % filename)
cf694132
RD
731
732 self.txt.SetInsertionPoint(0)
733 self.txt.ShowPosition(0)
734
735 #---------------------------------------------
736 def SetOverview(self, name, text):
f6bcfd97
BP
737 self.curOverview = text
738 lead = text[:6]
739 if lead != '<html>' and lead != '<HTML>':
1e4a197e 740 text = '<br>'.join(text.split('\n'))
f6bcfd97 741 self.ovr.SetPage(text)
cf694132 742 self.nb.SetPageText(0, name)
cf694132
RD
743
744 #---------------------------------------------
745 # Menu methods
c368d904 746 def OnFileExit(self, *event):
cf694132
RD
747 self.Close()
748
330af869
RD
749 def OnToggleRedirect(self, event):
750 app = wx.GetApp()
751 if event.Checked():
752 app.RedirectStdio()
753 print "Print statements and other standard output will now be directed to this window."
754 else:
755 app.RestoreStdio()
756 print "Print statements and other standard output will now be sent to the usual location."
757
cf694132 758 def OnHelpAbout(self, event):
e166644c 759 from About import MyAboutBox
ec3e670f 760 about = MyAboutBox(self)
cf694132
RD
761 about.ShowModal()
762 about.Destroy()
763
1e4a197e
RD
764 def OnHelpFind(self, event):
765 self.nb.SetSelection(1)
1fded56b
RD
766 self.finddlg = wx.FindReplaceDialog(self, self.finddata, "Find",
767 wx.FR_NOUPDOWN |
768 wx.FR_NOMATCHCASE |
769 wx.FR_NOWHOLEWORD)
1e4a197e
RD
770 self.finddlg.Show(True)
771
772 def OnFind(self, event):
773 self.nb.SetSelection(1)
774 end = self.txt.GetLastPosition()
775 textstring = self.txt.GetRange(0, end).lower()
776 start = self.txt.GetSelection()[1]
777 findstring = self.finddata.GetFindString().lower()
778 loc = textstring.find(findstring, start)
779 if loc == -1 and start != 0:
780 # string not found, start at beginning
781 start = 0
782 loc = textstring.find(findstring, start)
783 if loc == -1:
1fded56b 784 dlg = wx.MessageDialog(self, 'Find String Not Found',
1e4a197e 785 'Find String Not Found in Demo File',
1fded56b 786 wx.OK | wx.ICON_INFORMATION)
1e4a197e
RD
787 dlg.ShowModal()
788 dlg.Destroy()
789 if self.finddlg:
790 if loc == -1:
791 self.finddlg.SetFocus()
792 return
793 else:
794 self.finddlg.Destroy()
1e4a197e 795 self.txt.ShowPosition(loc)
1fded56b 796 self.txt.SetSelection(loc, loc + len(findstring))
1e4a197e
RD
797
798
799
800 def OnFindNext(self, event):
801 if self.finddata.GetFindString():
802 self.OnFind(event)
803 else:
804 self.OnHelpFind(event)
805
806 def OnFindClose(self, event):
807 event.GetDialog().Destroy()
808
cf694132
RD
809
810 #---------------------------------------------
811 def OnCloseWindow(self, event):
1e4a197e 812 self.dying = True
e91a9dfc 813 self.window = None
26197023 814 self.mainmenu = None
cf694132
RD
815 self.Destroy()
816
c368d904 817
cf694132
RD
818 #---------------------------------------------
819 def OnIdle(self, event):
820 if self.otherWin:
821 self.otherWin.Raise()
e91a9dfc 822 self.window = self.otherWin
cf694132
RD
823 self.otherWin = None
824
ccf691a4
RD
825
826 #---------------------------------------------
827 def ShowTip(self):
828 try:
829 showTipText = open(opj("data/showTips")).read()
830 showTip, index = eval(showTipText)
831 except IOError:
832 showTip, index = (1, 0)
833 if showTip:
1fded56b 834 tp = wx.CreateFileTipProvider(opj("data/tips.txt"), index)
861a0196 835 ##tp = MyTP(0)
1fded56b 836 showTip = wx.ShowTip(self, tp)
ccf691a4
RD
837 index = tp.GetCurrentTip()
838 open(opj("data/showTips"), "w").write(str( (showTip, index) ))
839
840
ec3e670f
RD
841 #---------------------------------------------
842 def OnDemoMenu(self, event):
f6bcfd97
BP
843 try:
844 selectedDemo = self.treeMap[self.mainmenu.GetLabel(event.GetId())]
845 except:
846 selectedDemo = None
847 if selectedDemo:
848 self.tree.SelectItem(selectedDemo)
849 self.tree.EnsureVisible(selectedDemo)
ec3e670f 850
c368d904
RD
851
852 #---------------------------------------------
853 def OnTaskBarActivate(self, evt):
854 if self.IsIconized():
1e4a197e 855 self.Iconize(False)
c368d904 856 if not self.IsShown():
1e4a197e 857 self.Show(True)
c368d904
RD
858 self.Raise()
859
860 #---------------------------------------------
861
862 TBMENU_RESTORE = 1000
863 TBMENU_CLOSE = 1001
864
865 def OnTaskBarMenu(self, evt):
1fded56b 866 menu = wx.Menu()
c368d904
RD
867 menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
868 menu.Append(self.TBMENU_CLOSE, "Close")
869 self.tbicon.PopupMenu(menu)
870 menu.Destroy()
871
872 #---------------------------------------------
873 def OnTaskBarClose(self, evt):
874 self.Close()
875
1fded56b 876 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
c368d904 877 # prod the main idle handler a bit to get the window to actually close
1fded56b 878 wx.GetApp().ProcessIdle()
c368d904
RD
879
880
f3d9dc1d
RD
881 #---------------------------------------------
882 def OnIconfiy(self, evt):
1fded56b 883 wx.LogMessage("OnIconfiy")
f3d9dc1d
RD
884 evt.Skip()
885
886 #---------------------------------------------
887 def OnMaximize(self, evt):
1fded56b 888 wx.LogMessage("OnMaximize")
f3d9dc1d
RD
889 evt.Skip()
890
891
892
893
cf694132
RD
894#---------------------------------------------------------------------------
895#---------------------------------------------------------------------------
896
1fded56b 897class MySplashScreen(wx.SplashScreen):
b5a5d647 898 def __init__(self):
1fded56b
RD
899 bmp = wx.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
900 wx.SplashScreen.__init__(self, bmp,
a253aa20
RD
901 wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
902 3000, None, -1)
80b27b4e 903 self.Bind(wx.EVT_CLOSE, self.OnClose)
b5a5d647
RD
904
905 def OnClose(self, evt):
8eca4fef 906 self.Hide()
9fb56e0c 907 frame = wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
1e4a197e 908 frame.Show()
ccf691a4 909 evt.Skip() # Make sure the default handler runs too...
cf694132 910
b5a5d647 911
1fded56b 912class MyApp(wx.App):
b5a5d647
RD
913 def OnInit(self):
914 """
68320e40 915 Create and show the splash screen. It will then create and show
b5a5d647
RD
916 the main frame when it is time to do so.
917 """
1e4a197e 918
a253aa20
RD
919 # Normally when using a SplashScreen you would create it, show
920 # it and then continue on with the applicaiton's
921 # initialization, finally creating and showing the main
922 # application window(s). In this case we have nothing else to
923 # do so we'll delay showing the main frame until later (see
b7aef858 924 # OnClose above) so the users can see the SplashScreen effect.
b5a5d647
RD
925 splash = MySplashScreen()
926 splash.Show()
a253aa20 927
1e4a197e 928 return True
b5a5d647
RD
929
930
931
cf694132
RD
932#---------------------------------------------------------------------------
933
934def main():
e02c03a4 935 try:
d56cebe7 936 demoPath = os.path.dirname(__file__)
e02c03a4
RD
937 os.chdir(demoPath)
938 except:
939 pass
980f458f 940 app = MyApp(0) ##wx.Platform == "__WXMAC__")
cf694132
RD
941 app.MainLoop()
942
943
944#---------------------------------------------------------------------------
945
946
947
f6bcfd97 948overview = """<html><body>
1fded56b
RD
949<h2>wxPython</h2>
950
f6063c19
RD
951<p> wxPython is a <b>GUI toolkit</b> for the Python programming
952language. It allows Python programmers to create programs with a
953robust, highly functional graphical user interface, simply and easily.
954It is implemented as a Python extension module (native code) that
955wraps the popular wxWindows cross platform GUI library, which is
956written in C++.
1fded56b
RD
957
958<p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
959means that it is free for anyone to use and the source code is
960available for anyone to look at and modify. Or anyone can contribute
8b9a4190 961fixes or enhancements to the project.
1fded56b
RD
962
963<p> wxPython is a <b>cross-platform</b> toolkit. This means that the
964same program will run on multiple platforms without modification.
965Currently supported platforms are 32-bit Microsoft Windows, most Unix
966or unix-like systems, and Macintosh OS X. Since the language is
967Python, wxPython programs are <b>simple, easy</b> to write and easy to
968understand.
969
970<p> <b>This demo</b> is not only a collection of test cases for
971wxPython, but is also designed to help you learn about and how to use
972wxPython. Each sample is listed in the tree control on the left.
973When a sample is selected in the tree then a module is loaded and run
974(usually in a tab of this notebook,) and the source code of the module
975is loaded in another tab for you to browse and learn from.
976
977"""
cf694132
RD
978
979
980#----------------------------------------------------------------------------
981#----------------------------------------------------------------------------
982
983if __name__ == '__main__':
984 main()
985
986#----------------------------------------------------------------------------
987
988
989
990
991
992
993