summaryrefslogtreecommitdiff
path: root/examples/pygtk-demo/pygtk-demo.py
diff options
context:
space:
mode:
Diffstat (limited to 'examples/pygtk-demo/pygtk-demo.py')
-rw-r--r--examples/pygtk-demo/pygtk-demo.py279
1 files changed, 220 insertions, 59 deletions
diff --git a/examples/pygtk-demo/pygtk-demo.py b/examples/pygtk-demo/pygtk-demo.py
index d4f938b0..282a14d2 100644
--- a/examples/pygtk-demo/pygtk-demo.py
+++ b/examples/pygtk-demo/pygtk-demo.py
@@ -1,76 +1,186 @@
#!/usr/bin/env python
-import string
+'''
+ $Id$
-import pygtk
-pygtk.require('2.0')
+ pygtk-demo.py
+ 2004-07-18: Some enhancements for building the demolist like in gtk-demos of the
+ gtk+ distribution.
+ 2004-07-22: Simple syntaxhighlighting implemented, based on the tokenizer-module.
+'''
+import string
+import re
+try:
+ import pygtk
+ pygtk.require('2.0')
+except ImportError:
+ pass
import gobject
import gtk
-from gtk import TRUE, FALSE
+import pango
+
+# use for simple syntax highlighting ;-)
+import tokenize
+import keyword
import demos
+D_TEMPL = '%sDemo'
+
+# Some programmatic definition for the testgtk_demos list. This avoids extra
+# maintenance if the demo list grows up. The current definition requires
+# a class or function with a swapped case name+'Demo' like in the doc string.
+# Swapped case is build from the __doc__-string programatically.
+child_demos = {}
+testgtk_demos = []
+for descr, mod in demos.demo_list:
+ # Find some categorized demos
+ try:
+ main, child = descr.split('/')
+ except ValueError:
+ # No, only one application
+ demo_class = D_TEMPL % re.sub('(\S+) *',
+ lambda m:(m.group(1)[0].isupper() and m.group(1) or m.group(1).capitalize()),
+ descr)
+ testgtk_demos.append((descr, mod, demo_class))
+ else:
+ # Ok. Some more testing
+ demo_class = D_TEMPL % re.sub('(\S+) *',
+ lambda m:(m.group(1)[0].isupper() and m.group(1) or m.group(1).capitalize()),
+ child)
+ try:
+ # Applicationgroup already defined?
+ child_demos[main.upper()].append((child, mod, demo_class))
+ except KeyError:
+ # No. Start a new category
+ child_demos.setdefault(main.upper(), []).append((child, mod, demo_class))
+ testgtk_demos.append((main, None, None, child_demos[main.upper()]))
+
+(
+ TITLE_COLUMN,
+ MODULE_COLUMN,
+ FUNC_COLUMN,
+ ITALIC_COLUMN
+) = range(4)
+
+CHILDREN_COLUMN = 3
+
+class InputStream(object):
+ ''' Simple Wrapper for File-like objects. [c]StringIO doesn't provide
+ a readline function for use with generate_tokens.
+ Using a iterator-like interface doesn't succeed, because the readline
+ function isn't used in such a context. (see <python-lib>/tokenize.py)
+ '''
+ def __init__(self, data):
+ self.__data = [ '%s\n' % x for x in data.splitlines() ]
+ self.__lcount = 0
+ def readline(self):
+ try:
+ line = self.__data[self.__lcount]
+ self.__lcount += 1
+ except IndexError:
+ line = ''
+ self.__lcount = 0
+ return line
-TITLE_COLUMN = 0
-MODULE_COLUMN = 1
class PyGtkDemo(gtk.Window):
info_buffer = None
source_buffer = None
+ module_cache = {}
+
def __init__(self):
gtk.Window.__init__(self)
+ self.set_title("PyGTK+ Code Demos")
self.connect('destroy', lambda w: gtk.main_quit())
- self.set_default_size(600, 400)
+ self.set_default_size(800, 400)
- hbox = gtk.HBox(FALSE, 3)
+ hbox = gtk.HBox(False, 3)
self.add(hbox)
- treeview = self.create_treeview()
- hbox.pack_start(treeview, expand=FALSE)
+ treeview = self.__create_treeview()
+ hbox.pack_start(treeview, False, False)
self.notebook = gtk.Notebook()
- hbox.pack_start(self.notebook, expand=TRUE)
-
- scrolled_window, self.info_buffer = self.create_text(FALSE)
+ hbox.pack_start(self.notebook, expand=True)
+
+ scrolled_window, self.info_buffer = self.__create_text(False)
self._new_notebook_page(scrolled_window, '_Info')
tag = self.info_buffer.create_tag('title')
tag.set_property('font', 'Sans 18')
-
- scrolled_window, self.source_buffer = self.create_text(TRUE)
+
+ scrolled_window, self.source_buffer = self.__create_text(True)
self._new_notebook_page(scrolled_window, '_Source')
tag = self.source_buffer.create_tag('source')
- tag.set_property('font', 'Courier 10')
+ tag.set_property('font', 'monospace')
tag.set_property('pixels_above_lines', 0)
tag.set_property('pixels_below_lines', 0)
+ tag = self.source_buffer.create_tag('keyword', foreground='#00007F',
+ weight=pango.WEIGHT_BOLD)
+ tag = self.source_buffer.create_tag('string', foreground='#7F007F')
+ tag = self.source_buffer.create_tag('comment', foreground='#007F00',
+ style=pango.STYLE_ITALIC)
+
+ self.show_all()
+
+ def run(self):
+ gtk.main()
def _new_notebook_page(self, widget, label):
l = gtk.Label('')
l.set_text_with_mnemonic(label)
self.notebook.append_page(widget, l)
- def create_treeview(self):
- model = gtk.ListStore(gobject.TYPE_STRING,
- gobject.TYPE_STRING)
-
+ def __create_treeview(self):
+ model = gtk.TreeStore(
+ gobject.TYPE_STRING,
+ gobject.TYPE_STRING,
+ gobject.TYPE_STRING,
+ gobject.TYPE_BOOLEAN
+ )
+
treeview = gtk.TreeView(model)
- treeview.connect('row-activated', self.row_activated_cb)
selection = treeview.get_selection()
- selection.set_mode('single')
+ selection.set_mode(gtk.SELECTION_BROWSE)
treeview.set_size_request(200, -1)
-
- for title, module in demos.demos:
- iter = model.append()
- model.set_value(iter, TITLE_COLUMN, title)
- model.set_value(iter, MODULE_COLUMN, module)
+
+ for module in testgtk_demos:
+ iter = model.append(None)
+ model.set(iter,
+ TITLE_COLUMN, module[TITLE_COLUMN],
+ MODULE_COLUMN, module[MODULE_COLUMN],
+ FUNC_COLUMN, module[FUNC_COLUMN],
+ ITALIC_COLUMN, False
+ )
+
+ try:
+ children = module[CHILDREN_COLUMN]
+ for child_module in children:
+ child_iter = model.append(iter)
+ model.set(child_iter,
+ TITLE_COLUMN, child_module[TITLE_COLUMN],
+ MODULE_COLUMN, child_module[MODULE_COLUMN],
+ FUNC_COLUMN, child_module[FUNC_COLUMN],
+ ITALIC_COLUMN, False
+ )
+ except IndexError:
+ pass
cell = gtk.CellRendererText()
- column = gtk.TreeViewColumn("Widget", cell, text=TITLE_COLUMN)
+ cell.set_property('style', pango.STYLE_ITALIC)
+
+ column = gtk.TreeViewColumn("Widget (double click for demo)", cell,
+ text=TITLE_COLUMN, style_set=ITALIC_COLUMN)
+
treeview.append_column(column)
selection.connect('changed', self.selection_changed_cb)
- self.model = model
+ treeview.connect('row-activated', self.row_activated_cb)
+
+ treeview.expand_all()
+
return treeview
-
- def create_text(self, is_source=FALSE):
+
+ def __create_text(self, is_source=False):
scrolled_window = gtk.ScrolledWindow()
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scrolled_window.set_shadow_type(gtk.SHADOW_IN)
@@ -80,36 +190,55 @@ class PyGtkDemo(gtk.Window):
buffer = gtk.TextBuffer(None)
text_view.set_buffer(buffer)
- text_view.set_editable(FALSE)
- text_view.set_cursor_visible(FALSE)
+ text_view.set_editable(False)
+ text_view.set_cursor_visible(False)
text_view.set_wrap_mode(not is_source)
return scrolled_window, buffer
- def row_activated_cb(self, treeview, row, column):
- iter = self.model.get_iter(row)
- module_name = self.model.get_value(iter, MODULE_COLUMN)
- module = getattr(demos, module_name)
- module.main()
-
+ def row_activated_cb(self, treeview, path, column):
+ model = treeview.get_model()
+ iter = model.get_iter(path)
+ module_name = model.get_value(iter, MODULE_COLUMN)
+ func_name = model.get_value(iter, FUNC_COLUMN)
+ italic_value = model.get_value(iter, ITALIC_COLUMN)
+ try:
+ self.module_cache[module_name].present()
+ except KeyError:
+ module = getattr(demos, module_name)
+ model.set(iter, ITALIC_COLUMN, not italic_value)
+ cmd = 'demos.%s.%s' % (module_name, func_name)
+ #print cmd
+ window = eval(cmd)(self)
+ if window:
+ window.connect('destroy', self.window_closed_cb, model, path)
+ self.module_cache[module_name] = window
+
def selection_changed_cb(self, selection):
- selection = selection.get_selected()
- if not selection:
- return
-
- model, iter = selection
+ model, iter = selection.get_selected()
+ if not iter:
+ return False
name = model.get_value(iter, MODULE_COLUMN)
self.load_module(name)
+ def window_closed_cb (self, window, model, path):
+ iter = model.get_iter(path)
+ module_name = model.get_value(iter, MODULE_COLUMN)
+ del self.module_cache[module_name]
+ italic_value = model.get_value(iter, ITALIC_COLUMN)
+ if italic_value:
+ model.set(iter, ITALIC_COLUMN, not italic_value)
+
+
def read_module(self, module):
filename = module.__file__
if filename[-4:] == '.pyc':
filename = filename[:-1]
fd = open(filename)
return fd.read()
-
+
def insert_documentation(self, module):
buffer = self.info_buffer
iter = buffer.get_iter_at_offset(0)
@@ -133,25 +262,57 @@ class PyGtkDemo(gtk.Window):
def insert_source(self, data):
source_buffer = self.source_buffer
iter = source_buffer.get_iter_at_offset(0)
- source_buffer.insert(iter, data)
-
- start = source_buffer.get_iter_at_offset(0)
- source_buffer.apply_tag_by_name('source', start, iter)
-
+
+ last_erow, last_ecol = 0, 0
+ was_newline = False # multiline statement detection
+ for x in tokenize.generate_tokens(InputStream(data).readline):
+ # x has 5-tuples
+ tok_type, tok_str = x[0], x[1]
+ srow, scol = x[2]
+ erow, ecol = x[3]
+
+ # The tokenizer 'eats' the whitespaces, so we have to insert this again
+ # if needed.
+ if srow == last_erow:
+ # Same line, spaces between statements
+ if scol != last_ecol:
+ source_buffer.insert_with_tags_by_name(iter, ' '*(scol-last_ecol), 'source')
+ else:
+ # New line.
+ # First: Detect multiline statements. There is no special in the tokenizer stream.
+ if was_newline is False and last_erow != 0:
+ source_buffer.insert_with_tags_by_name(iter, ' \\\n', 'source')
+ # new line check if it starts with col 0
+ if scol != 0:
+ source_buffer.insert_with_tags_by_name(iter, ' '*scol, 'source')
+ last_erow = erow
+ last_ecol = ecol
+
+ if tok_type == tokenize.COMMENT:
+ was_newline = True # newline is in tok_str included.
+ source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'comment')
+ continue
+ elif tok_type == tokenize.NAME:
+ if tok_str in keyword.kwlist:
+ source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'keyword')
+ continue
+ elif tok_type == tokenize.STRING:
+ source_buffer.insert_with_tags_by_name(iter, tok_str, 'source', 'string')
+ continue
+
+ # No special format for use. Check for newline.
+ was_newline = tok_type in (tokenize.NEWLINE, tokenize.NL)
+ source_buffer.insert_with_tags_by_name(iter, tok_str, 'source')
+
def load_module(self, name):
self.clear_buffers()
-
+ if name is None: return
module = getattr(demos, name)
if module.__doc__:
self.insert_documentation(module)
-
+
source = self.read_module(module)
self.insert_source(source)
-
-d = PyGtkDemo()
-d.show_all()
-
-gtk.main()
-#if __name__ == '__main__':
-# main()
+if __name__ == '__main__':
+ PyGtkDemo().run()