Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | #!/usr/bin/env python |
2 | ||
3 | # ------------------------------------------------------------------ | |
4 | # Display a splash screen as quickly as possible (before importing | |
5 | # modules and initialising Pmw). | |
6 | ||
7 | import Tkinter | |
8 | root = Tkinter.Tk(className = 'Demo') | |
9 | root.withdraw() | |
10 | ||
11 | splash = Tkinter.Toplevel() | |
12 | splash.withdraw() | |
13 | splash.title('Welcome to the Pmw demos') | |
14 | text = Tkinter.Label(splash, | |
15 | font=('Helvetica', 16, 'bold'), | |
16 | relief = 'raised', | |
17 | borderwidth = 2, | |
18 | padx=50, pady=50, | |
19 | text = | |
20 | 'Welcome to the Pmw megawidgets demo.\n' | |
21 | '\n' | |
22 | 'In a moment the main window will appear.\n' | |
23 | 'Please enjoy yourself while you wait.\n' | |
24 | 'You may be interested to know that splash screens\n' | |
25 | '(as this window is called) were first devised to draw\n' | |
26 | 'attention away from the fact the certain applications\n' | |
27 | 'are slow to start. They are normally flashier and more\n' | |
28 | 'entertaining than this one. This is a budget model.' | |
29 | ) | |
30 | text.pack(fill = 'both', expand = 1) | |
31 | splash.update_idletasks() | |
32 | ||
33 | width = splash.winfo_reqwidth() | |
34 | height = splash.winfo_reqheight() | |
35 | x = (root.winfo_screenwidth() - width) / 2 - root.winfo_vrootx() | |
36 | y = (root.winfo_screenheight() - height) / 3 - root.winfo_vrooty() | |
37 | if x < 0: | |
38 | x = 0 | |
39 | if y < 0: | |
40 | y = 0 | |
41 | geometry = '%dx%d+%d+%d' % (width, height, x, y) | |
42 | ||
43 | splash.geometry(geometry) | |
44 | splash.update_idletasks() | |
45 | splash.deiconify() | |
46 | root.update() | |
47 | ||
48 | # ------------------------------------------------------------------ | |
49 | ||
50 | # Now crank up the application windows. | |
51 | ||
52 | import imp | |
53 | import os | |
54 | import re | |
55 | import string | |
56 | import sys | |
57 | import types | |
58 | import Tkinter | |
59 | import DemoVersion | |
60 | import Args | |
61 | ||
62 | # Find where the other scripts are, so they can be listed. | |
63 | if __name__ == '__main__': | |
64 | script_name = sys.argv[0] | |
65 | else: | |
66 | script_name = imp.find_module('DemoVersion')[1] | |
67 | ||
68 | script_name = os.path.normpath(script_name) | |
69 | script_name = DemoVersion.expandLinks(script_name) | |
70 | script_dir = os.path.dirname(script_name) | |
71 | script_dir = DemoVersion.expandLinks(script_dir) | |
72 | ||
73 | # Add the '../../..' directory to the path. | |
74 | package_dir = os.path.dirname(script_dir) | |
75 | package_dir = DemoVersion.expandLinks(package_dir) | |
76 | package_dir = os.path.dirname(package_dir) | |
77 | package_dir = DemoVersion.expandLinks(package_dir) | |
78 | package_dir = os.path.dirname(package_dir) | |
79 | package_dir = DemoVersion.expandLinks(package_dir) | |
80 | sys.path[:0] = [package_dir] | |
81 | ||
82 | # Import Pmw after modifying sys.path (it may not be in the default path). | |
83 | import Pmw | |
84 | DemoVersion.setPmwVersion() | |
85 | ||
86 | class Demo(Pmw.MegaWidget): | |
87 | ||
88 | def __init__(self, parent=None, **kw): | |
89 | ||
90 | # Define the megawidget options. | |
91 | optiondefs = () | |
92 | self.defineoptions(kw, optiondefs) | |
93 | ||
94 | # Initialise the base class (after defining the options). | |
95 | Pmw.MegaWidget.__init__(self, parent) | |
96 | ||
97 | # Create the contents. | |
98 | top = self.interior() | |
99 | ||
100 | panes = Pmw.PanedWidget(top, orient = 'horizontal') | |
101 | panes.pack(fill = 'both', expand = 1) | |
102 | ||
103 | panes.add('widgetlist') | |
104 | self._widgetlist = Pmw.ScrolledListBox(panes.pane('widgetlist'), | |
105 | selectioncommand = Pmw.busycallback(self.startDemo), | |
106 | label_text = 'Select a widget:', | |
107 | labelpos = 'nw', | |
108 | vscrollmode = 'dynamic', | |
109 | hscrollmode = 'none', | |
110 | listbox_exportselection = 0) | |
111 | self._widgetlist.pack(fill = 'both', expand = 1, padx = 8) | |
112 | ||
113 | panes.add('info') | |
114 | self._status = Tkinter.Label(panes.pane('info')) | |
115 | self._status.pack(padx = 8, anchor = 'w') | |
116 | ||
117 | self._example = Tkinter.Frame(panes.pane('info'), | |
118 | borderwidth = 2, | |
119 | relief = 'sunken', | |
120 | background = 'white') | |
121 | self._example.pack(fill = 'both', expand = 1, padx = 8) | |
122 | ||
123 | self.buttonBox = Pmw.ButtonBox(top) | |
124 | self.buttonBox.pack(fill = 'x') | |
125 | ||
126 | # Add the buttons and make them all the same width. | |
127 | self._traceText = 'Trace tk calls' | |
128 | self._stopTraceText = 'Stop trace' | |
129 | self.buttonBox.add('Trace', text = self._traceText, | |
130 | command = self.trace) | |
131 | self.buttonBox.add('Code', text = 'Show code', command = self.showCode) | |
132 | self.buttonBox.add('Exit', text = 'Exit', command = sys.exit) | |
133 | self.buttonBox.alignbuttons() | |
134 | ||
135 | # Create the window to display the python code. | |
136 | self.codeWindow = Pmw.TextDialog(parent, | |
137 | title = 'Python source', | |
138 | buttons = ('Dismiss',), | |
139 | scrolledtext_labelpos = 'n', | |
140 | label_text = 'Source') | |
141 | self.codeWindow.withdraw() | |
142 | self.codeWindow.insert('end', '') | |
143 | ||
144 | self.demoName = None | |
145 | self._loadDemos() | |
146 | ||
147 | # Check keywords and initialise options. | |
148 | self.initialiseoptions() | |
149 | ||
150 | def startDemo(self): | |
151 | # Import the selected module and create and instance of the module's | |
152 | # Demo class. | |
153 | ||
154 | sels = self._widgetlist.getcurselection() | |
155 | if len(sels) == 0: | |
156 | print 'No demonstrations to display' | |
157 | return | |
158 | demoName = sels[0] | |
159 | ||
160 | # Ignore if this if it is a sub title. | |
161 | if demoName[0] != ' ': | |
162 | self._widgetlist.bell() | |
163 | return | |
164 | ||
165 | # Strip the leading two spaces. | |
166 | demoName = demoName[2:] | |
167 | ||
168 | # Ignore if this demo is already being shown. | |
169 | if self.demoName == demoName: | |
170 | return | |
171 | ||
172 | self.demoName = demoName | |
173 | ||
174 | self.showStatus('Loading ' + demoName) | |
175 | # Busy cursor | |
176 | self.update_idletasks() | |
177 | ||
178 | for window in self._example.winfo_children(): | |
179 | window.destroy() | |
180 | ||
181 | frame = Tkinter.Frame(self._example) | |
182 | frame.pack(expand = 1) | |
183 | exec 'import ' + demoName | |
184 | # Need to keep a reference to the widget, so that variables, etc | |
185 | # are not deleted. | |
186 | self.widget = eval(demoName + '.Demo(frame)') | |
187 | title = eval(demoName + '.title') | |
188 | self.showStatus(title) | |
189 | ||
190 | if self.codeWindow.state() == 'normal': | |
191 | self.insertCode() | |
192 | ||
193 | def showStatus(self, text): | |
194 | self._status.configure(text = text) | |
195 | ||
196 | def showCode(self): | |
197 | if self.codeWindow.state() != 'normal': | |
198 | if self.demoName is None: | |
199 | print 'No demonstration selected' | |
200 | return | |
201 | self.insertCode() | |
202 | ||
203 | self.codeWindow.show() | |
204 | ||
205 | def insertCode(self): | |
206 | self.codeWindow.clear() | |
207 | fileName = os.path.join(script_dir, self.demoName + '.py') | |
208 | self.codeWindow.importfile(fileName) | |
209 | self.codeWindow.configure(label_text = self.demoName + ' source') | |
210 | ||
211 | def trace(self): | |
212 | text = self.buttonBox.component('Trace').cget('text') | |
213 | if text == self._traceText: | |
214 | self.buttonBox.configure(Trace_text = self._stopTraceText) | |
215 | Pmw.tracetk(root, 1) | |
216 | self.showStatus('Trace will appear on standard output') | |
217 | else: | |
218 | self.buttonBox.configure(Trace_text = self._traceText) | |
219 | Pmw.tracetk(root, 0) | |
220 | self.showStatus('Tk call tracing stopped') | |
221 | ||
222 | def _loadDemos(self): | |
223 | files = os.listdir(script_dir) | |
224 | files.sort() | |
225 | megawidgets = [] | |
226 | others = [] | |
227 | for file in files: | |
228 | if re.search('.py$', file) is not None and \ | |
229 | file not in ['All.py', 'DemoVersion.py', 'Args.py']: | |
230 | demoName = file[:-3] | |
231 | index = string.find(demoName, '_') | |
232 | if index < 0: | |
233 | testattr = demoName | |
234 | else: | |
235 | testattr = demoName[:index] | |
236 | if hasattr(Pmw, testattr): | |
237 | megawidgets.append(demoName) | |
238 | else: | |
239 | others.append(demoName) | |
240 | ||
241 | self._widgetlist.insert('end', 'Megawidget demos:') | |
242 | for name in megawidgets: | |
243 | self._widgetlist.insert('end', ' ' + name) | |
244 | self._widgetlist.insert('end', 'Other demos:') | |
245 | for name in others: | |
246 | self._widgetlist.insert('end', ' ' + name) | |
247 | self._widgetlist.select_set(1) | |
248 | ||
249 | class StdOut: | |
250 | def __init__(self, displayCommand): | |
251 | self.displayCommand = displayCommand | |
252 | self.text = '\n' | |
253 | ||
254 | def write(self, text): | |
255 | if self.text[-1] == '\n': | |
256 | self.text = text | |
257 | else: | |
258 | self.text = self.text + text | |
259 | if self.text[-1] == '\n': | |
260 | text = self.text[:-1] | |
261 | else: | |
262 | text = self.text | |
263 | self.displayCommand(text) | |
264 | ||
265 | if os.name == 'nt': | |
266 | defaultFontSize = 16 | |
267 | else: | |
268 | defaultFontSize = 12 | |
269 | ||
270 | commandLineArgSpecs = ( | |
271 | ('fontscheme', 0, 'scheme', 'fonts to use [eg pmw2] (Tk defaults)'), | |
272 | ('fontsize', 0, 'num', 'size of fonts to use with fontscheme', defaultFontSize), | |
273 | ('stdout', 0, Args.Bool, 'print messages rather than display in label'), | |
274 | ) | |
275 | ||
276 | program = 'All.py' | |
277 | msg = Args.parseArgs(program, sys.argv, commandLineArgSpecs, 0) | |
278 | if msg is not None: | |
279 | print msg | |
280 | sys.exit() | |
281 | ||
282 | size = Args.get('fontsize') | |
283 | fontScheme = Args.get('fontscheme') | |
284 | Pmw.initialise(root, size = size, fontScheme = fontScheme, useTkOptionDb = 1) | |
285 | ||
286 | root.title('Pmw ' + Pmw.version() + ' megawidget demonstration') | |
287 | if size < 18: | |
288 | geometry = '800x550' | |
289 | else: | |
290 | geometry = '1000x700' | |
291 | root.geometry(geometry) | |
292 | ||
293 | demo = Demo(root) | |
294 | demo.pack(fill = 'both', expand = 1) | |
295 | demo.focus() | |
296 | ||
297 | # Redirect standard output from demos to status line (unless -stdout | |
298 | # option given on command line). | |
299 | if not Args.get('stdout'): | |
300 | sys.stdout = StdOut(demo.showStatus) | |
301 | ||
302 | # Start the first demo. | |
303 | demo.startDemo() | |
304 | ||
305 | # Get rid of the splash screen | |
306 | root.deiconify() | |
307 | root.update() | |
308 | splash.destroy() | |
309 | ||
310 | root.mainloop() |