| 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() |