home *** CD-ROM | disk | FTP | other *** search
/ tusportal.tus.k12.pa.us / tusportal.tus.k12.pa.us.tar / tusportal.tus.k12.pa.us / Wyse / latest-image.raw / 0.img / usr / lib / pygtk / 2.0 / pygtk-demo.py next >
Text File  |  2010-05-11  |  11KB  |  321 lines

  1. #!/usr/bin/env python
  2. '''
  3.   $Id$
  4.  
  5.   pygtk-demo.py
  6.   2004-07-18: Some enhancements for building the demolist like in gtk-demos of the
  7.     gtk+ distribution.
  8.   2004-07-22: Simple syntaxhighlighting implemented, based on the tokenizer-module.
  9. '''
  10.  
  11. import string
  12. import re
  13. try:
  14.     import pygtk
  15.     pygtk.require('2.0')
  16. except ImportError:
  17.     pass
  18. import gobject
  19. import gtk
  20. import pango
  21.  
  22. # use for simple syntax highlighting ;-)
  23. import tokenize
  24. import keyword
  25.  
  26. import demos
  27. D_TEMPL = '%sDemo'
  28.  
  29. # Some programmatic definition for the testgtk_demos list. This avoids extra
  30. # maintenance if the demo list grows up. The current definition requires
  31. # a class or function with a swapped case name+'Demo' like in the doc string.
  32. # Swapped case is build from the __doc__-string programatically.
  33. child_demos = {}
  34. testgtk_demos = []
  35. for descr, mod in demos.demo_list:
  36.     # Find some categorized demos
  37.     try:
  38.         main, child = descr.split('/')
  39.     except ValueError:
  40.         # No, only one application
  41.         demo_class = D_TEMPL % re.sub('(\S+) *',
  42.             lambda m:(m.group(1)[0].isupper() and m.group(1) or m.group(1).capitalize()),
  43.             descr)
  44.         testgtk_demos.append((descr, mod, demo_class))
  45.     else:
  46.         # Ok. Some more testing
  47.         demo_class = D_TEMPL % re.sub('(\S+) *',
  48.             lambda m:(m.group(1)[0].isupper() and m.group(1) or m.group(1).capitalize()),
  49.             child)
  50.         try:
  51.             # Applicationgroup already defined?
  52.             child_demos[main.upper()].append((child, mod, demo_class))
  53.         except KeyError:
  54.             # No. Start a new category
  55.             child_demos.setdefault(main.upper(), []).append((child, mod, demo_class))
  56.             testgtk_demos.append((main, None, None, child_demos[main.upper()]))
  57.  
  58. (
  59.    TITLE_COLUMN,
  60.    MODULE_COLUMN,
  61.    FUNC_COLUMN,
  62.    ITALIC_COLUMN
  63. ) = range(4)
  64.  
  65. CHILDREN_COLUMN = 3
  66.  
  67. class InputStream(object):
  68.     ''' Simple Wrapper for File-like objects. [c]StringIO doesn't provide
  69.         a readline function for use with generate_tokens.
  70.         Using a iterator-like interface doesn't succeed, because the readline
  71.         function isn't used in such a context. (see <python-lib>/tokenize.py)
  72.     '''
  73.     def __init__(self, data):
  74.         self.__data = [ '%s\n' % x for x in data.splitlines() ]
  75.         self.__lcount = 0
  76.     def readline(self):
  77.         try:
  78.             line = self.__data[self.__lcount]
  79.             self.__lcount += 1
  80.         except IndexError:
  81.             line = ''
  82.             self.__lcount = 0
  83.         return line
  84.  
  85.  
  86. class PyGtkDemo(gtk.Window):
  87.     info_buffer = None
  88.     source_buffer = None
  89.     module_cache  = {}
  90.  
  91.     def __init__(self):
  92.         gtk.Window.__init__(self)
  93.         self.set_title("PyGTK+ Code Demos")
  94.         self.connect('destroy', lambda w: gtk.main_quit())
  95.         self.set_default_size(800, 400)
  96.  
  97.         hbox = gtk.HBox(False, 3)
  98.         self.add(hbox)
  99.  
  100.         treeview = self.__create_treeview()
  101.         hbox.pack_start(treeview, False, False)
  102.  
  103.         self.notebook = gtk.Notebook()
  104.         hbox.pack_start(self.notebook, expand=True)
  105.  
  106.         scrolled_window, self.info_buffer = self.__create_text(False)
  107.         self._new_notebook_page(scrolled_window, '_Info')
  108.         tag = self.info_buffer.create_tag('title')
  109.         tag.set_property('font', 'Sans 18')
  110.  
  111.         scrolled_window, self.source_buffer = self.__create_text(True)
  112.         self._new_notebook_page(scrolled_window, '_Source')
  113.         tag = self.source_buffer.create_tag('source')
  114.         tag.set_property('font', 'monospace')
  115.         tag.set_property('pixels_above_lines', 0)
  116.         tag.set_property('pixels_below_lines', 0)
  117.         tag = self.source_buffer.create_tag('keyword', foreground='#00007F',
  118.             weight=pango.WEIGHT_BOLD)
  119.         tag = self.source_buffer.create_tag('string', foreground='#7F007F')
  120.         tag = self.source_buffer.create_tag('comment', foreground='#007F00',
  121.             style=pango.STYLE_ITALIC)
  122.  
  123.         self.show_all()
  124.  
  125.     def run(self):
  126.         gtk.main()
  127.  
  128.     def _new_notebook_page(self, widget, label):
  129.         l = gtk.Label('')
  130.         l.set_text_with_mnemonic(label)
  131.         self.notebook.append_page(widget, l)
  132.  
  133.     def __create_treeview(self):
  134.         model = gtk.TreeStore(
  135.             gobject.TYPE_STRING,
  136.             gobject.TYPE_STRING,
  137.             gobject.TYPE_STRING,
  138.             gobject.TYPE_BOOLEAN
  139.         )
  140.  
  141.         treeview = gtk.TreeView(model)
  142.         selection = treeview.get_selection()
  143.         selection.set_mode(gtk.SELECTION_BROWSE)
  144.         treeview.set_size_request(200, -1)
  145.  
  146.         for module in testgtk_demos:
  147.             iter = model.append(None)
  148.             model.set(iter,
  149.                 TITLE_COLUMN, module[TITLE_COLUMN],
  150.                 MODULE_COLUMN, module[MODULE_COLUMN],
  151.                 FUNC_COLUMN, module[FUNC_COLUMN],
  152.                 ITALIC_COLUMN, False
  153.             )
  154.  
  155.             try:
  156.                 children = module[CHILDREN_COLUMN]
  157.                 for child_module in children:
  158.                     child_iter = model.append(iter)
  159.                     model.set(child_iter,
  160.                         TITLE_COLUMN, child_module[TITLE_COLUMN],
  161.                         MODULE_COLUMN, child_module[MODULE_COLUMN],
  162.                         FUNC_COLUMN, child_module[FUNC_COLUMN],
  163.                         ITALIC_COLUMN, False
  164.                     )
  165.             except IndexError:
  166.                 pass
  167.  
  168.         cell = gtk.CellRendererText()
  169.         cell.set_property('style', pango.STYLE_ITALIC)
  170.  
  171.         column = gtk.TreeViewColumn("Widget (double click for demo)", cell,
  172.             text=TITLE_COLUMN, style_set=ITALIC_COLUMN)
  173.  
  174.         treeview.append_column(column)
  175.  
  176.         selection.connect('changed', self.selection_changed_cb)
  177.         treeview.connect('row-activated', self.row_activated_cb)
  178.  
  179.         treeview.expand_all()
  180.  
  181.         return treeview
  182.  
  183.     def __create_text(self, is_source=False):
  184.         scrolled_window = gtk.ScrolledWindow()
  185.         scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  186.         scrolled_window.set_shadow_type(gtk.SHADOW_IN)
  187.  
  188.         text_view = gtk.TextView()
  189.         scrolled_window.add(text_view)
  190.  
  191.         buffer = gtk.TextBuffer(None)
  192.         text_view.set_buffer(buffer)
  193.         text_view.set_editable(False)
  194.         text_view.set_cursor_visible(False)
  195.  
  196.         text_view.set_wrap_mode(not is_source)
  197.  
  198.         return scrolled_window, buffer
  199.  
  200.     def row_activated_cb(self, treeview, path, column):
  201.         model = treeview.get_model()
  202.         iter  = model.get_iter(path)
  203.         module_name  = model.get_value(iter, MODULE_COLUMN)
  204.         func_name    = model.get_value(iter, FUNC_COLUMN)
  205.         italic_value = model.get_value(iter, ITALIC_COLUMN)
  206.         if module_name is None:  # a "category" row is activated
  207.             return True
  208.         try:
  209.             self.module_cache[module_name].present()
  210.         except KeyError:
  211.             module = getattr(demos, module_name)
  212.             model.set(iter, ITALIC_COLUMN, not italic_value)
  213.             cmd = 'demos.%s.%s' % (module_name, func_name)
  214.             #print cmd
  215.             window = eval(cmd)(self)
  216.             if window:
  217.                 window.connect('destroy', self.window_closed_cb, model, path)
  218.                 self.module_cache[module_name] = window
  219.  
  220.     def selection_changed_cb(self, selection):
  221.         model, iter = selection.get_selected()
  222.         if not iter:
  223.             return False
  224.  
  225.         name = model.get_value(iter, MODULE_COLUMN)
  226.         if name is not None:
  227.             self.load_module(name)
  228.  
  229.     def window_closed_cb (self, window, model, path):
  230.         iter = model.get_iter(path)
  231.         module_name  = model.get_value(iter, MODULE_COLUMN)
  232.         del self.module_cache[module_name]
  233.         italic_value = model.get_value(iter, ITALIC_COLUMN)
  234.         if italic_value:
  235.             model.set(iter, ITALIC_COLUMN, not italic_value)
  236.  
  237.  
  238.     def read_module(self, module):
  239.         filename = module.__file__
  240.         if filename[-4:] == '.pyc':
  241.             filename = filename[:-1]
  242.         fd = open(filename)
  243.         return fd.read()
  244.  
  245.     def insert_documentation(self, module):
  246.         buffer = self.info_buffer
  247.         iter = buffer.get_iter_at_offset(0)
  248.  
  249.         lines = string.split(module.__doc__ or '', '\n')
  250.         buffer.insert(iter, lines[0])
  251.         start = buffer.get_iter_at_offset(0)
  252.         buffer.apply_tag_by_name('title', start, iter)
  253.         buffer.insert(iter, '\n')
  254.         for line in lines[1:]:
  255.             buffer.insert(iter, line)
  256.             buffer.insert(iter, '\n')
  257.  
  258.     def clear_buffers(self):
  259.         start, end = self.info_buffer.get_bounds()
  260.         self.info_buffer.delete(start, end)
  261.  
  262.         start, end = self.source_buffer.get_bounds()
  263.         self.source_buffer.delete(start, end)
  264.  
  265.     def insert_source(self, data):
  266.         source_buffer = self.source_buffer
  267.         iter = source_buffer.get_iter_at_offset(0)
  268.  
  269.         last_erow, last_ecol = 0, 0
  270.         was_newline = False # multiline statement detection
  271.         for x in tokenize.generate_tokens(InputStream(data).readline):
  272.             # x has 5-tuples
  273.             tok_type, tok_str = x[0], x[1]
  274.             srow, scol = x[2]
  275.             erow, ecol = x[3]
  276.  
  277.             # The tokenizer 'eats' the whitespaces, so we have to insert this again
  278.             # if needed.
  279.             if srow == last_erow:
  280.                 # Same line, spaces between statements
  281.                 if scol != last_ecol:
  282.                     source_buffer.insert_with_tags_by_name(iter, ' '*(scol-last_ecol), 'source')
  283.             else:
  284.                 # New line.
  285.                 # First: Detect multiline statements. There is no special in the tokenizer stream.
  286.                 if was_newline is False and last_erow != 0:
  287.                     source_buffer.insert_with_tags_by_name(iter, ' \\\n', 'source')
  288.                 # new line check if it starts with col 0
  289.                 if scol != 0:
  290.                     source_buffer.insert_with_tags_by_name(iter, ' '*scol, 'source')
  291.             last_erow = erow
  292.             last_ecol = ecol
  293.  
  294.             if tok_type == tokenize.COMMENT:
  295.                 was_newline = True # newline is in tok_str included.
  296.                 source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'comment')
  297.                 continue
  298.             elif tok_type == tokenize.NAME:
  299.                 if tok_str in keyword.kwlist:
  300.                     source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'keyword')
  301.                     continue
  302.             elif tok_type == tokenize.STRING:
  303.                 source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'string')
  304.                 continue
  305.  
  306.             # No special format for use. Check for newline.
  307.             was_newline = tok_type in (tokenize.NEWLINE, tokenize.NL)
  308.             source_buffer.insert_with_tags_by_name(iter, tok_str, 'source')
  309.  
  310.     def load_module(self, name):
  311.         self.clear_buffers()
  312.         module = getattr(demos, name)
  313.         if module.__doc__:
  314.             self.insert_documentation(module)
  315.  
  316.         source = self.read_module(module)
  317.         self.insert_source(source)
  318.  
  319. if __name__ == '__main__':
  320.     PyGtkDemo().run()
  321.