Favorites support
[gonvert] / src / hildonize.py
1 #!/usr/bin/env python
2
3 """
4 Open Issues
5         @bug not all of a message is shown
6         @bug Buttons are too small
7 """
8
9
10 import gobject
11 import gtk
12 import dbus
13
14
15 class _NullHildonModule(object):
16         pass
17
18
19 try:
20         import hildon as _hildon
21         hildon  = _hildon # Dumb but gets around pyflakiness
22 except (ImportError, OSError):
23         hildon = _NullHildonModule
24
25
26 IS_HILDON_SUPPORTED = hildon is not _NullHildonModule
27
28
29 class _NullHildonProgram(object):
30
31         def add_window(self, window):
32                 pass
33
34
35 def _hildon_get_app_class():
36         return hildon.Program
37
38
39 def _null_get_app_class():
40         return _NullHildonProgram
41
42
43 try:
44         hildon.Program
45         get_app_class = _hildon_get_app_class
46 except AttributeError:
47         get_app_class = _null_get_app_class
48
49
50 def _hildon_set_application_name(name):
51         gtk.set_application_name(name)
52
53
54 def _null_set_application_name(name):
55         pass
56
57
58 try:
59         gtk.set_application_name
60         set_application_name = _hildon_set_application_name
61 except AttributeError:
62         set_application_name = _null_set_application_name
63
64
65 def _fremantle_hildonize_window(app, window):
66         oldWindow = window
67         newWindow = hildon.StackableWindow()
68         if oldWindow.get_child() is not None:
69                 oldWindow.get_child().reparent(newWindow)
70         app.add_window(newWindow)
71         return newWindow
72
73
74 def _hildon_hildonize_window(app, window):
75         oldWindow = window
76         newWindow = hildon.Window()
77         if oldWindow.get_child() is not None:
78                 oldWindow.get_child().reparent(newWindow)
79         app.add_window(newWindow)
80         return newWindow
81
82
83 def _null_hildonize_window(app, window):
84         return window
85
86
87 try:
88         hildon.StackableWindow
89         hildonize_window = _fremantle_hildonize_window
90 except AttributeError:
91         try:
92                 hildon.Window
93                 hildonize_window = _hildon_hildonize_window
94         except AttributeError:
95                 hildonize_window = _null_hildonize_window
96
97
98 def _fremantle_hildonize_menu(window, gtkMenu):
99         appMenu = hildon.AppMenu()
100         window.set_app_menu(appMenu)
101         gtkMenu.get_parent().remove(gtkMenu)
102         return appMenu
103
104
105 def _hildon_hildonize_menu(window, gtkMenu):
106         hildonMenu = gtk.Menu()
107         for child in gtkMenu.get_children():
108                 child.reparent(hildonMenu)
109         window.set_menu(hildonMenu)
110         gtkMenu.destroy()
111         return hildonMenu
112
113
114 def _null_hildonize_menu(window, gtkMenu):
115         return gtkMenu
116
117
118 try:
119         hildon.AppMenu
120         GTK_MENU_USED = False
121         IS_FREMANTLE_SUPPORTED = True
122         hildonize_menu = _fremantle_hildonize_menu
123 except AttributeError:
124         GTK_MENU_USED = True
125         IS_FREMANTLE_SUPPORTED = False
126         if IS_HILDON_SUPPORTED:
127                 hildonize_menu = _hildon_hildonize_menu
128         else:
129                 hildonize_menu = _null_hildonize_menu
130
131
132 def _hildon_set_button_auto_selectable(button):
133         button.set_theme_size(hildon.HILDON_SIZE_AUTO_HEIGHT)
134
135
136 def _null_set_button_auto_selectable(button):
137         pass
138
139
140 try:
141         hildon.HILDON_SIZE_AUTO_HEIGHT
142         gtk.Button.set_theme_size
143         set_button_auto_selectable = _hildon_set_button_auto_selectable
144 except AttributeError:
145         set_button_auto_selectable = _null_set_button_auto_selectable
146
147
148 def _hildon_set_button_finger_selectable(button):
149         button.set_theme_size(hildon.HILDON_SIZE_FINGER_HEIGHT)
150
151
152 def _null_set_button_finger_selectable(button):
153         pass
154
155
156 try:
157         hildon.HILDON_SIZE_FINGER_HEIGHT
158         gtk.Button.set_theme_size
159         set_button_finger_selectable = _hildon_set_button_finger_selectable
160 except AttributeError:
161         set_button_finger_selectable = _null_set_button_finger_selectable
162
163
164 def _hildon_set_button_thumb_selectable(button):
165         button.set_theme_size(hildon.HILDON_SIZE_THUMB_HEIGHT)
166
167
168 def _null_set_button_thumb_selectable(button):
169         pass
170
171
172 try:
173         hildon.HILDON_SIZE_THUMB_HEIGHT
174         gtk.Button.set_theme_size
175         set_button_thumb_selectable = _hildon_set_button_thumb_selectable
176 except AttributeError:
177         set_button_thumb_selectable = _null_set_button_thumb_selectable
178
179
180 def _hildon_set_cell_thumb_selectable(renderer):
181         renderer.set_property("scale", 1.5)
182
183
184 def _null_set_cell_thumb_selectable(renderer):
185         pass
186
187
188 if IS_HILDON_SUPPORTED:
189         set_cell_thumb_selectable = _hildon_set_cell_thumb_selectable
190 else:
191         set_cell_thumb_selectable = _null_set_cell_thumb_selectable
192
193
194 def _hildon_set_pix_cell_thumb_selectable(renderer):
195         renderer.set_property("stock-size", 48)
196
197
198 def _null_set_pix_cell_thumb_selectable(renderer):
199         pass
200
201
202 if IS_HILDON_SUPPORTED:
203         set_pix_cell_thumb_selectable = _hildon_set_pix_cell_thumb_selectable
204 else:
205         set_pix_cell_thumb_selectable = _null_set_pix_cell_thumb_selectable
206
207
208 def _fremantle_show_information_banner(parent, message):
209         hildon.hildon_banner_show_information(parent, "", message)
210
211
212 def _hildon_show_information_banner(parent, message):
213         hildon.hildon_banner_show_information(parent, None, message)
214
215
216 def _null_show_information_banner(parent, message):
217         pass
218
219
220 if IS_FREMANTLE_SUPPORTED:
221         show_information_banner = _fremantle_show_information_banner
222 else:
223         try:
224                 hildon.hildon_banner_show_information
225                 show_information_banner = _hildon_show_information_banner
226         except AttributeError:
227                 show_information_banner = _null_show_information_banner
228
229
230 def _fremantle_show_busy_banner_start(parent, message):
231         hildon.hildon_gtk_window_set_progress_indicator(parent, True)
232         return parent
233
234
235 def _fremantle_show_busy_banner_end(banner):
236         hildon.hildon_gtk_window_set_progress_indicator(banner, False)
237
238
239 def _hildon_show_busy_banner_start(parent, message):
240         return hildon.hildon_banner_show_animation(parent, None, message)
241
242
243 def _hildon_show_busy_banner_end(banner):
244         banner.destroy()
245
246
247 def _null_show_busy_banner_start(parent, message):
248         return None
249
250
251 def _null_show_busy_banner_end(banner):
252         assert banner is None
253
254
255 try:
256         hildon.hildon_gtk_window_set_progress_indicator
257         show_busy_banner_start = _fremantle_show_busy_banner_start
258         show_busy_banner_end = _fremantle_show_busy_banner_end
259 except AttributeError:
260         try:
261                 hildon.hildon_banner_show_animation
262                 show_busy_banner_start = _hildon_show_busy_banner_start
263                 show_busy_banner_end = _hildon_show_busy_banner_end
264         except AttributeError:
265                 show_busy_banner_start = _null_show_busy_banner_start
266                 show_busy_banner_end = _null_show_busy_banner_end
267
268
269 def _hildon_hildonize_text_entry(textEntry):
270         textEntry.set_property('hildon-input-mode', 7)
271
272
273 def _null_hildonize_text_entry(textEntry):
274         pass
275
276
277 if IS_HILDON_SUPPORTED:
278         hildonize_text_entry = _hildon_hildonize_text_entry
279 else:
280         hildonize_text_entry = _null_hildonize_text_entry
281
282
283 def _hildon_window_to_portrait(window):
284         # gtk documentation is unclear whether this does a "=" or a "|="
285         flags = hildon.PORTRAIT_MODE_SUPPORT | hildon.PORTRAIT_MODE_REQUEST
286         hildon.hildon_gtk_window_set_portrait_flags(window, flags)
287
288
289 def _hildon_window_to_landscape(window):
290         # gtk documentation is unclear whether this does a "=" or a "&= ~"
291         flags = hildon.PORTRAIT_MODE_SUPPORT
292         hildon.hildon_gtk_window_set_portrait_flags(window, flags)
293
294
295 def _null_window_to_portrait(window):
296         pass
297
298
299 def _null_window_to_landscape(window):
300         pass
301
302
303 try:
304         hildon.PORTRAIT_MODE_SUPPORT
305         hildon.PORTRAIT_MODE_REQUEST
306         hildon.hildon_gtk_window_set_portrait_flags
307
308         window_to_portrait = _hildon_window_to_portrait
309         window_to_landscape = _hildon_window_to_landscape
310 except AttributeError:
311         window_to_portrait = _null_window_to_portrait
312         window_to_landscape = _null_window_to_landscape
313
314
315 def get_device_orientation():
316         bus = dbus.SystemBus()
317         try:
318                 rawMceRequest = bus.get_object("com.nokia.mce", "/com/nokia/mce/request")
319                 mceRequest = dbus.Interface(rawMceRequest, dbus_interface="com.nokia.mce.request")
320                 orientation, standState, faceState, xAxis, yAxis, zAxis = mceRequest.get_device_orientation()
321         except dbus.exception.DBusException:
322                 # catching for documentation purposes that when a system doesn't
323                 # support this, this is what to expect
324                 raise
325
326         if orientation == "":
327                 return gtk.ORIENTATION_HORIZONTAL
328         elif orientation == "":
329                 return gtk.ORIENTATION_VERTICAL
330         else:
331                 raise RuntimeError("Unknown orientation: %s" % orientation)
332
333
334 def _hildon_hildonize_password_entry(textEntry):
335         textEntry.set_property('hildon-input-mode', 7 | (1 << 29))
336
337
338 def _null_hildonize_password_entry(textEntry):
339         pass
340
341
342 if IS_HILDON_SUPPORTED:
343         hildonize_password_entry = _hildon_hildonize_password_entry
344 else:
345         hildonize_password_entry = _null_hildonize_password_entry
346
347
348 def _hildon_hildonize_combo_entry(comboEntry):
349         comboEntry.set_property('hildon-input-mode', 1 << 4)
350
351
352 def _null_hildonize_combo_entry(textEntry):
353         pass
354
355
356 if IS_HILDON_SUPPORTED:
357         hildonize_combo_entry = _hildon_hildonize_combo_entry
358 else:
359         hildonize_combo_entry = _null_hildonize_combo_entry
360
361
362 def _null_create_seekbar():
363         adjustment = gtk.Adjustment(0, 0, 101, 1, 5, 1)
364         seek = gtk.HScale(adjustment)
365         seek.set_draw_value(False)
366         return seek
367
368
369 def _fremantle_create_seekbar():
370         seek = hildon.Seekbar()
371         seek.set_range(0.0, 100)
372         seek.set_draw_value(False)
373         seek.set_update_policy(gtk.UPDATE_DISCONTINUOUS)
374         return seek
375
376
377 try:
378         hildon.Seekbar
379         create_seekbar = _fremantle_create_seekbar
380 except AttributeError:
381         create_seekbar = _null_create_seekbar
382
383
384 def _fremantle_hildonize_scrollwindow(scrolledWindow):
385         pannableWindow = hildon.PannableArea()
386
387         child = scrolledWindow.get_child()
388         scrolledWindow.remove(child)
389         pannableWindow.add(child)
390
391         parent = scrolledWindow.get_parent()
392         if parent is not None:
393                 parent.remove(scrolledWindow)
394                 parent.add(pannableWindow)
395
396         return pannableWindow
397
398
399 def _hildon_hildonize_scrollwindow(scrolledWindow):
400         hildon.hildon_helper_set_thumb_scrollbar(scrolledWindow, True)
401         return scrolledWindow
402
403
404 def _null_hildonize_scrollwindow(scrolledWindow):
405         return scrolledWindow
406
407
408 try:
409         hildon.PannableArea
410         hildonize_scrollwindow = _fremantle_hildonize_scrollwindow
411         hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
412 except AttributeError:
413         try:
414                 hildon.hildon_helper_set_thumb_scrollbar
415                 hildonize_scrollwindow = _hildon_hildonize_scrollwindow
416                 hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
417         except AttributeError:
418                 hildonize_scrollwindow = _null_hildonize_scrollwindow
419                 hildonize_scrollwindow_with_viewport = _null_hildonize_scrollwindow
420
421
422 def _hildon_request_number(parent, title, range, default):
423         spinner = hildon.NumberEditor(*range)
424         spinner.set_value(default)
425
426         dialog = gtk.Dialog(
427                 title,
428                 parent,
429                 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
430                 (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
431         )
432         dialog.set_default_response(gtk.RESPONSE_CANCEL)
433         dialog.get_child().add(spinner)
434
435         try:
436                 dialog.show_all()
437                 response = dialog.run()
438
439                 if response == gtk.RESPONSE_OK:
440                         return spinner.get_value()
441                 elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
442                         raise RuntimeError("User cancelled request")
443                 else:
444                         raise RuntimeError("Unrecognized response %r", response)
445         finally:
446                 dialog.hide()
447                 dialog.destroy()
448
449
450 def _null_request_number(parent, title, range, default):
451         adjustment = gtk.Adjustment(default, range[0], range[1], 1, 5, 0)
452         spinner = gtk.SpinButton(adjustment, 0, 0)
453         spinner.set_wrap(False)
454
455         dialog = gtk.Dialog(
456                 title,
457                 parent,
458                 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
459                 (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
460         )
461         dialog.set_default_response(gtk.RESPONSE_CANCEL)
462         dialog.get_child().add(spinner)
463
464         try:
465                 dialog.show_all()
466                 response = dialog.run()
467
468                 if response == gtk.RESPONSE_OK:
469                         return spinner.get_value_as_int()
470                 elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
471                         raise RuntimeError("User cancelled request")
472                 else:
473                         raise RuntimeError("Unrecognized response %r", response)
474         finally:
475                 dialog.hide()
476                 dialog.destroy()
477
478
479 try:
480         hildon.NumberEditor # TODO deprecated in fremantle
481         request_number = _hildon_request_number
482 except AttributeError:
483         request_number = _null_request_number
484
485
486 def _hildon_touch_selector(parent, title, items, defaultIndex):
487         model = gtk.ListStore(gobject.TYPE_STRING)
488         for item in items:
489                 model.append((item, ))
490
491         selector = hildon.TouchSelector()
492         selector.append_text_column(model, True)
493         selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
494         selector.set_active(0, defaultIndex)
495
496         dialog = hildon.PickerDialog(parent)
497         dialog.set_selector(selector)
498
499         try:
500                 dialog.show_all()
501                 response = dialog.run()
502
503                 if response == gtk.RESPONSE_OK:
504                         return selector.get_active(0)
505                 elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
506                         raise RuntimeError("User cancelled request")
507                 else:
508                         raise RuntimeError("Unrecognized response %r", response)
509         finally:
510                 dialog.hide()
511                 dialog.destroy()
512
513
514 def _on_null_touch_selector_activated(treeView, path, column, dialog, pathData):
515         dialog.response(gtk.RESPONSE_OK)
516         pathData[0] = path
517
518
519 def _null_touch_selector(parent, title, items, defaultIndex = -1):
520         parentSize = parent.get_size()
521
522         model = gtk.ListStore(gobject.TYPE_STRING)
523         for item in items:
524                 model.append((item, ))
525
526         cell = gtk.CellRendererText()
527         set_cell_thumb_selectable(cell)
528         column = gtk.TreeViewColumn(title)
529         column.pack_start(cell, expand=True)
530         column.add_attribute(cell, "text", 0)
531
532         treeView = gtk.TreeView()
533         treeView.set_model(model)
534         treeView.append_column(column)
535         selection = treeView.get_selection()
536         selection.set_mode(gtk.SELECTION_SINGLE)
537         if 0 < defaultIndex:
538                 selection.select_path((defaultIndex, ))
539
540         scrolledWin = gtk.ScrolledWindow()
541         scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
542         scrolledWin.add(treeView)
543
544         dialog = gtk.Dialog(
545                 title,
546                 parent,
547                 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
548                 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
549         )
550         dialog.set_default_response(gtk.RESPONSE_CANCEL)
551         dialog.get_child().add(scrolledWin)
552         dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
553
554         scrolledWin = hildonize_scrollwindow(scrolledWin)
555         pathData = [None]
556         treeView.connect("row-activated", _on_null_touch_selector_activated, dialog, pathData)
557
558         try:
559                 dialog.show_all()
560                 response = dialog.run()
561
562                 if response == gtk.RESPONSE_OK:
563                         if pathData[0] is None:
564                                 raise RuntimeError("No selection made")
565                         return pathData[0][0]
566                 elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
567                         raise RuntimeError("User cancelled request")
568                 else:
569                         raise RuntimeError("Unrecognized response %r", response)
570         finally:
571                 dialog.hide()
572                 dialog.destroy()
573
574
575 try:
576         hildon.PickerDialog
577         hildon.TouchSelector
578         touch_selector = _hildon_touch_selector
579 except AttributeError:
580         touch_selector = _null_touch_selector
581
582
583 def _hildon_touch_selector_entry(parent, title, items, defaultItem):
584         # Got a segfault when using append_text_column with TouchSelectorEntry, so using this way
585         try:
586                 selector = hildon.TouchSelectorEntry(text=True)
587         except TypeError:
588                 selector = hildon.hildon_touch_selector_entry_new_text()
589         defaultIndex = -1
590         for i, item in enumerate(items):
591                 selector.append_text(item)
592                 if item == defaultItem:
593                         defaultIndex = i
594
595         dialog = hildon.PickerDialog(parent)
596         dialog.set_selector(selector)
597
598         if 0 < defaultIndex:
599                 selector.set_active(0, defaultIndex)
600         else:
601                 selector.get_entry().set_text(defaultItem)
602
603         try:
604                 dialog.show_all()
605                 response = dialog.run()
606         finally:
607                 dialog.hide()
608
609         if response == gtk.RESPONSE_OK:
610                 return selector.get_entry().get_text()
611         elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
612                 raise RuntimeError("User cancelled request")
613         else:
614                 raise RuntimeError("Unrecognized response %r", response)
615
616
617 def _on_null_touch_selector_entry_entry_changed(entry, result, selection, defaultIndex):
618         custom = entry.get_text().strip()
619         if custom:
620                 result[0] = custom
621                 selection.unselect_all()
622         else:
623                 result[0] = None
624                 selection.select_path((defaultIndex, ))
625
626
627 def _on_null_touch_selector_entry_entry_activated(customEntry, dialog, result):
628         dialog.response(gtk.RESPONSE_OK)
629         result[0] = customEntry.get_text()
630
631
632 def _on_null_touch_selector_entry_tree_activated(treeView, path, column, dialog, result):
633         dialog.response(gtk.RESPONSE_OK)
634         model = treeView.get_model()
635         itr = model.get_iter(path)
636         if itr is not None:
637                 result[0] = model.get_value(itr, 0)
638
639
640 def _null_touch_selector_entry(parent, title, items, defaultItem):
641         parentSize = parent.get_size()
642
643         model = gtk.ListStore(gobject.TYPE_STRING)
644         defaultIndex = -1
645         for i, item in enumerate(items):
646                 model.append((item, ))
647                 if item == defaultItem:
648                         defaultIndex = i
649
650         cell = gtk.CellRendererText()
651         set_cell_thumb_selectable(cell)
652         column = gtk.TreeViewColumn(title)
653         column.pack_start(cell, expand=True)
654         column.add_attribute(cell, "text", 0)
655
656         treeView = gtk.TreeView()
657         treeView.set_model(model)
658         treeView.append_column(column)
659         selection = treeView.get_selection()
660         selection.set_mode(gtk.SELECTION_SINGLE)
661
662         scrolledWin = gtk.ScrolledWindow()
663         scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
664         scrolledWin.add(treeView)
665
666         customEntry = gtk.Entry()
667
668         layout = gtk.VBox()
669         layout.pack_start(customEntry, expand=False)
670         layout.pack_start(scrolledWin)
671
672         dialog = gtk.Dialog(
673                 title,
674                 parent,
675                 gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
676                 (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
677         )
678         dialog.set_default_response(gtk.RESPONSE_CANCEL)
679         dialog.get_child().add(layout)
680         dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
681
682         scrolledWin = hildonize_scrollwindow(scrolledWin)
683
684         result = [None]
685         if 0 < defaultIndex:
686                 selection.select_path((defaultIndex, ))
687                 result[0] = defaultItem
688         else:
689                 customEntry.set_text(defaultItem)
690
691         customEntry.connect("activate", _on_null_touch_selector_entry_entry_activated, dialog, result)
692         customEntry.connect("changed", _on_null_touch_selector_entry_entry_changed, result, selection, defaultIndex)
693         treeView.connect("row-activated", _on_null_touch_selector_entry_tree_activated, dialog, result)
694
695         try:
696                 dialog.show_all()
697                 response = dialog.run()
698
699                 if response == gtk.RESPONSE_OK:
700                         _, itr = selection.get_selected()
701                         if itr is not None:
702                                 return model.get_value(itr, 0)
703                         else:
704                                 enteredText = customEntry.get_text().strip()
705                                 if enteredText:
706                                         return enteredText
707                                 elif result[0] is not None:
708                                         return result[0]
709                                 else:
710                                         raise RuntimeError("No selection made")
711                 elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
712                         raise RuntimeError("User cancelled request")
713                 else:
714                         raise RuntimeError("Unrecognized response %r", response)
715         finally:
716                 dialog.hide()
717                 dialog.destroy()
718
719
720 try:
721         hildon.PickerDialog
722         hildon.TouchSelectorEntry
723         touch_selector_entry = _hildon_touch_selector_entry
724 except AttributeError:
725         touch_selector_entry = _null_touch_selector_entry
726
727
728 if __name__ == "__main__":
729         app = get_app_class()()
730
731         label = gtk.Label("Hello World from a Label!")
732
733         win = gtk.Window()
734         win.add(label)
735         win = hildonize_window(app, win)
736         if False and IS_FREMANTLE_SUPPORTED:
737                 appMenu = hildon.AppMenu()
738                 for i in xrange(5):
739                         b = gtk.Button(str(i))
740                         appMenu.append(b)
741                 win.set_app_menu(appMenu)
742                 win.show_all()
743                 appMenu.show_all()
744                 gtk.main()
745         elif False:
746                 print touch_selector(win, "Test", ["A", "B", "C", "D"], 2)
747         elif False:
748                 print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "C")
749                 print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "Blah")
750         elif False:
751                 import pprint
752                 name, value = "", ""
753                 goodLocals = [
754                         (name, value) for (name, value) in locals().iteritems()
755                         if not name.startswith("_")
756                 ]
757                 pprint.pprint(goodLocals)
758         elif False:
759                 import time
760                 show_information_banner(win, "Hello World")
761                 time.sleep(5)
762         elif False:
763                 import time
764                 banner = show_busy_banner_start(win, "Hello World")
765                 time.sleep(5)
766                 show_busy_banner_end(banner)