summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Finlay <finlay@src.gnome.org>2004-10-01 23:35:38 +0000
committerJohn Finlay <finlay@src.gnome.org>2004-10-01 23:35:38 +0000
commitf0c4fccb74b1876073604e6367ddb7449af295ef (patch)
tree22cde104cfadaddd481c6242502d48ceca2d4322
parentf5debbde7c331fb13e1ffe154cf5f582a8707959 (diff)
downloadpygtk-f0c4fccb74b1876073604e6367ddb7449af295ef.tar.gz
examples/pygtk-demo/* Replace the pygtk-demo with the new version written
* examples/pygtk-demo/* Replace the pygtk-demo with the new version written by Maik Hertha. Fixes #138823.
-rw-r--r--ChangeLog5
-rw-r--r--examples/pygtk-demo/demos/__init__.py32
-rw-r--r--examples/pygtk-demo/demos/appwindow.py451
-rw-r--r--examples/pygtk-demo/demos/buttonbox.py106
-rw-r--r--examples/pygtk-demo/demos/changedisplay.py414
-rw-r--r--examples/pygtk-demo/demos/colorsel.py120
-rw-r--r--examples/pygtk-demo/demos/dialogs.py237
-rw-r--r--examples/pygtk-demo/demos/dnd.py367
-rw-r--r--examples/pygtk-demo/demos/editable_cells.py268
-rw-r--r--examples/pygtk-demo/demos/entry_completion.py77
-rw-r--r--examples/pygtk-demo/demos/entrycompletion.py72
-rw-r--r--examples/pygtk-demo/demos/expander.py48
-rw-r--r--examples/pygtk-demo/demos/hypertext.py185
-rw-r--r--examples/pygtk-demo/demos/images.py388
-rw-r--r--examples/pygtk-demo/demos/images/alphatest.png (renamed from examples/pygtk-demo/alphatest.png)bin26529 -> 26529 bytes
-rw-r--r--examples/pygtk-demo/demos/images/apple-red.pngbin0 -> 3545 bytes
-rw-r--r--examples/pygtk-demo/demos/images/background.jpgbin0 -> 22219 bytes
-rw-r--r--examples/pygtk-demo/demos/images/floppybuddy.gif (renamed from examples/pygtk-demo/floppybuddy.gif)bin5216 -> 5216 bytes
-rw-r--r--examples/pygtk-demo/demos/images/gnome-applets.pngbin0 -> 3090 bytes
-rw-r--r--examples/pygtk-demo/demos/images/gnome-calendar.pngbin0 -> 2755 bytes
-rw-r--r--examples/pygtk-demo/demos/images/gnome-foot.pngbin0 -> 2916 bytes
-rw-r--r--examples/pygtk-demo/demos/images/gnome-gimp.pngbin0 -> 3410 bytes
-rw-r--r--examples/pygtk-demo/demos/images/gnome-gmush.pngbin0 -> 3244 bytes
-rw-r--r--examples/pygtk-demo/demos/images/gnome-gsame.pngbin0 -> 4263 bytes
-rw-r--r--examples/pygtk-demo/demos/images/gnu-keys.pngbin0 -> 3852 bytes
-rw-r--r--examples/pygtk-demo/demos/images/gtk-logo-rgb.gif (renamed from examples/pygtk-demo/gtk-logo-rgb.gif)bin6427 -> 6427 bytes
-rw-r--r--examples/pygtk-demo/demos/itemfactory.py83
-rw-r--r--examples/pygtk-demo/demos/list_store.py242
-rw-r--r--examples/pygtk-demo/demos/menu.py126
-rw-r--r--examples/pygtk-demo/demos/panes.py206
-rw-r--r--examples/pygtk-demo/demos/pixbufs.py195
-rw-r--r--examples/pygtk-demo/demos/sizegroup.py174
-rw-r--r--examples/pygtk-demo/demos/stock_browser.py442
-rw-r--r--examples/pygtk-demo/demos/textview.py499
-rw-r--r--examples/pygtk-demo/demos/toolbar.py108
-rw-r--r--examples/pygtk-demo/demos/tree_store.py335
-rw-r--r--examples/pygtk-demo/demos/treemodel.py125
-rw-r--r--examples/pygtk-demo/demos/ui_manager.py190
-rw-r--r--examples/pygtk-demo/pygtk-demo.py279
39 files changed, 3999 insertions, 1775 deletions
diff --git a/ChangeLog b/ChangeLog
index 684f49ca..5b2bd3b1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2004-10-01 John Finlay <finlay@moeraki.com>
+
+ * examples/pygtk-demo/* Replace the pygtk-demo with the new
+ version written by Maik Hertha. Fixes #138823.
+
2004-09-27 John Ehresman <jpe@wingide.com>
* gobject/gobjectmodule.c (pyg_enable_threads): Allow gtk_main to
diff --git a/examples/pygtk-demo/demos/__init__.py b/examples/pygtk-demo/demos/__init__.py
index ee3fc5e7..44028ca4 100644
--- a/examples/pygtk-demo/demos/__init__.py
+++ b/examples/pygtk-demo/demos/__init__.py
@@ -1,18 +1,24 @@
import os
-_modlist = filter(lambda x: len(x) > 3 and x[-3:] == '.py',
- os.listdir(os.path.dirname(__file__)))
+_file_list = [
+ x for x in os.listdir(os.path.dirname(__file__))
+ if len(x) > 3 and x[-3:] == '.py']
-demos = []
-for _mod in _modlist:
- if _mod[0] != '_':
- _mod = _mod[:-3]
- try:
- exec 'import ' + _mod + '\n' + \
- '_description = ' + _mod + '.description'
- demos.append((_description, _mod))
- except:
- pass
-demos.sort()
+demo_list = []
+for _mod in _file_list:
+ # Leave underscored Modulnames.
+ if _mod.startswith('_'):
+ continue
+ _mod = _mod[:-3]
+ try:
+ exec 'import ' + _mod + '\n' + \
+ '_doc = ' + _mod + '.__doc__'
+ _description = _doc.splitlines()[0]
+ demo_list.append((_description, _mod))
+ except (ImportError, AttributeError), msg:
+ # ImportError or AttributeError (if _doc is None)
+ #print 'failed: ', _mod
+ pass
+demo_list.sort()
diff --git a/examples/pygtk-demo/demos/appwindow.py b/examples/pygtk-demo/demos/appwindow.py
index 7e96b635..c12b5b2b 100644
--- a/examples/pygtk-demo/demos/appwindow.py
+++ b/examples/pygtk-demo/demos/appwindow.py
@@ -1,180 +1,297 @@
#!/usr/bin/env python
-"""Application main window
+'''Application main window
-Demonstrates a typical application window, with menubar, toolbar, statusbar."""
-
-description = 'Application main window'
+Demonstrates a typical application window, with menubar, toolbar, statusbar.'''
+# pygtk version: Maik Hertha <maik.hertha@berlin.de>
+import gobject
import gtk
-def menuitem_cb(window, action, widget):
- dialog = gtk.MessageDialog(window, gtk.DIALOG_DESTROY_WITH_PARENT,
- gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE,
- 'You selected or toggled the menu item: '
- '"%s"' % (gtk.item_factory_path_from_widget(widget),))
- dialog.connect('response', lambda dialog, response: dialog.destroy())
- dialog.show()
-
-menu_items = (
- ('/_File', None, None, 0, '<Branch>' ),
- ('/File/tearoff1', None, menuitem_cb, 0, '<Tearoff>'),
- ('/File/_New', '<control>N', menuitem_cb, 0, '<StockItem>', gtk.STOCK_NEW),
- ('/File/_Open', '<control>O', menuitem_cb, 0, '<StockItem>', gtk.STOCK_OPEN),
- ('/File/_Save', '<control>S', menuitem_cb, 0, '<StockItem>', gtk.STOCK_SAVE),
- ('/File/Save _As...', None, menuitem_cb, 0, '<StockItem>', gtk.STOCK_SAVE),
- ('/File/sep1', None, menuitem_cb, 0, '<Separator>'),
- ('/File/_Quit', '<control>Q', menuitem_cb, 0, '<StockItem>', gtk.STOCK_QUIT),
-
- ('/_Preferences', None, None, 0, '<Branch>'),
- ('/_Preferences/_Color', None, None, 0, '<Branch>'),
- ('/_Preferences/Color/_Red', None, menuitem_cb, 0, '<RadioItem>'),
- ('/_Preferences/Color/_Green', None, menuitem_cb, 0, '/Preferences/Color/Red'),
- ('/_Preferences/Color/_Blue', None, menuitem_cb, 0, '/Preferences/Color/Red'),
- ('/_Preferences/_Shape', None, None, 0, '<Branch>'),
- ('/_Preferences/Shape/_Square', None, menuitem_cb, 0, '<RadioItem>'),
- ('/_Preferences/Shape/_Rectangle', None, menuitem_cb, 0, '/Preferences/Shape/Square'),
- ('/_Preferences/Shape/_Oval', None, menuitem_cb, 0, '/Preferences/Shape/Rectangle'),
-
- # If you wanted this to be right justified you would use
- # "<LastBranch>", not "<Branch>". Right justified help menu items
- # are generally considered a bad idea now days.
-
- ('/_Help', None, None, 0, '<Branch>'),
- ('/Help/_About', None, menuitem_cb, 0, ''),
- )
-
-def toolbar_cb(button, window):
- dialog = gtk.MessageDialog(window, gtk.DIALOG_DESTROY_WITH_PARENT,
- gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE,
- 'You selected a toolbar button')
- dialog.connect('response', lambda dialog, response: dialog.destroy())
- dialog.show()
-
-def register_stock_icons ():
+(
+ COLOR_RED,
+ COLOR_GREEN,
+ COLOR_BLUE
+) = range(3)
+
+(
+ SHAPE_SQUARE,
+ SHAPE_RECTANGLE,
+ SHAPE_OVAL,
+) = range(3)
+
+ui_info = \
+'''<ui>
+ <menubar name='MenuBar'>
+ <menu action='FileMenu'>
+ <menuitem action='New'/>
+ <menuitem action='Open'/>
+ <menuitem action='Save'/>
+ <menuitem action='SaveAs'/>
+ <separator/>
+ <menuitem action='Quit'/>
+ </menu>
+ <menu action='PreferencesMenu'>
+ <menu action='ColorMenu'>
+ <menuitem action='Red'/>
+ <menuitem action='Green'/>
+ <menuitem action='Blue'/>
+ </menu>
+ <menu action='ShapeMenu'>
+ <menuitem action='Square'/>
+ <menuitem action='Rectangle'/>
+ <menuitem action='Oval'/>
+ </menu>
+ <menuitem action='Bold'/>
+ </menu>
+ <menu action='HelpMenu'>
+ <menuitem action='About'/>
+ </menu>
+ </menubar>
+ <toolbar name='ToolBar'>
+ <toolitem action='Open'/>
+ <toolitem action='Quit'/>
+ <separator/>
+ <toolitem action='Logo'/>
+ </toolbar>
+</ui>'''
+
+
+# It's totally optional to do this, you could just manually insert icons
+# and have them not be themeable, especially if you never expect people
+# to theme your app.
+def register_stock_icons():
+ ''' This function registers our custom toolbar icons, so they
+ can be themed.
+ '''
items = [('demo-gtk-logo', '_GTK!', 0, 0, '')]
-
# Register our stock items
- gtk.stock_add (items)
-
+ gtk.stock_add(items)
+
# Add our custom icon factory to the list of defaults
- factory = gtk.IconFactory ()
- factory.add_default ()
-
- pixbuf = gtk.gdk.pixbuf_new_from_file ('gtk-logo-rgb.gif')
- pixbuf = pixbuf.add_alpha(True, chr(0xff), chr(0xff), chr(0xff))
-
- # Register icon to accompany stock item
- if pixbuf:
- icon_set = gtk.IconSet (pixbuf)
- factory.add ('demo-gtk-logo', icon_set)
- else:
- print 'failed to load GTK logo for toolbar'
-
-def update_statusbar(buffer, statusbar):
- # clear any previous message, underflow is allowed
- statusbar.pop(0)
- count = buffer.get_char_count()
- iter = buffer.get_iter_at_mark(buffer.get_insert())
- row = iter.get_line()
- col = iter.get_line_offset()
- statusbar.push(0, 'Cursor at row %d column %d - %d chars in document' %
- (row, col, count))
-
-mark_set_callback = (lambda buffer, new_location, mark, statusbar:
- update_statusbar(buffer, statusbar))
-
+ factory = gtk.IconFactory()
+ factory.add_default()
-def main():
- register_stock_icons ()
-
- # Create the toplevel window
- window = gtk.Window()
- window.set_title('Application Window')
- window.connect('destroy', lambda win: gtk.main_quit())
-
- table = gtk.Table(1, 4, gtk.FALSE)
- window.add(table)
-
- # Create the menubar
-
- accel_group = gtk.AccelGroup()
- window.add_accel_group(accel_group)
-
- item_factory = gtk.ItemFactory(gtk.MenuBar, '<main>', accel_group)
-
- # create menu items
-
- item_factory.create_items(menu_items, window)
-
- table.attach(item_factory.get_widget('<main>'),
- # X direction Y direction
- 0, 1, 0, 1,
- gtk.EXPAND | gtk.FILL, 0,
- 0, 0)
-
- # Create the toolbar
-
- toolbar = gtk.Toolbar()
- toolbar.insert_stock(gtk.STOCK_OPEN,
- "This is a demo button with an 'open' icon",
- None,
- toolbar_cb,
- window,
- -1)
- toolbar.insert_stock(gtk.STOCK_CLOSE,
- "This is a demo button with an 'close' icon",
- None,
- toolbar_cb,
- window,
- -1)
-
- toolbar.append_space()
-
- toolbar.insert_stock('demo-gtk-logo',
- "This is a demo button with a 'gtk' icon",
- None,
- toolbar_cb,
- window,
- -1)
-
- table.attach(toolbar,
- # X direction Y direction
- 0, 1, 1, 2,
- gtk.EXPAND | gtk.FILL, 0,
- 0, 0)
-
- # Create document
-
- sw = gtk.ScrolledWindow()
- sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- sw.set_shadow_type(gtk.SHADOW_IN)
- table.attach(sw,
- # X direction Y direction
- 0, 1, 2, 3,
- gtk.EXPAND | gtk.FILL, gtk.EXPAND | gtk.FILL,
- 0, 0)
-
- window.set_default_size(200, 200)
-
- contents = gtk.TextView()
- sw.add(contents)
-
- # Create statusbar
-
- statusbar = gtk.Statusbar();
- table.attach(statusbar,
- # X direction Y direction
- 0, 1, 3, 4,
- gtk.EXPAND | gtk.FILL, 0,
- 0, 0)
-
- buffer = contents.get_buffer()
- buffer.connect('changed', update_statusbar, statusbar)
- buffer.connect('mark_set', mark_set_callback, statusbar)
- update_statusbar(buffer, statusbar)
-
- window.show_all()
+ import os
+ img_dir = os.path.join(os.path.dirname(__file__), 'images')
+ img_path = os.path.join(img_dir, 'gtk-logo-rgb.gif')
+ try:
+ pixbuf = gtk.gdk.pixbuf_new_from_file(img_path)
+
+ # Register icon to accompany stock item
+
+ # The gtk-logo-rgb icon has a white background, make it transparent
+ # the call is wrapped to (gboolean, guchar, guchar, guchar)
+ transparent = pixbuf.add_alpha(True, chr(255), chr(255),chr(255))
+ icon_set = gtk.IconSet(transparent)
+ factory.add('demo-gtk-logo', icon_set)
+
+ except gobject.GError, error:
+ print 'failed to load GTK logo for toolbar'
+
+class ApplicationMainWindowDemo(gtk.Window):
+ def __init__(self, parent=None):
+ register_stock_icons()
+
+ # Create the toplevel window
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+
+ self.set_title(self.__class__.__name__)
+ self.set_default_size(200, 200)
+
+ merge = gtk.UIManager()
+ self.set_data("ui-manager", merge)
+ merge.insert_action_group(self.__create_action_group(), 0)
+ self.add_accel_group(merge.get_accel_group())
+
+ try:
+ mergeid = merge.add_ui_from_string(ui_info)
+ except gobject.GError, msg:
+ print "building menus failed: %s" % msg
+ bar = merge.get_widget("/MenuBar")
+ bar.show()
+
+ table = gtk.Table(1, 4, gtk.FALSE)
+ self.add(table)
+
+ table.attach(bar,
+ # X direction # # Y direction
+ 0, 1, 0, 1,
+ gtk.EXPAND | gtk.FILL, 0,
+ 0, 0);
+
+ bar = merge.get_widget("/ToolBar")
+ bar.set_tooltips(True)
+ bar.show()
+ table.attach(bar,
+ # X direction # # Y direction
+ 0, 1, 1, 2,
+ gtk.EXPAND | gtk.FILL, 0,
+ 0, 0)
+
+ # Create document
+ sw = gtk.ScrolledWindow()
+ sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ sw.set_shadow_type(gtk.SHADOW_IN)
+
+ table.attach(sw,
+ # X direction Y direction
+ 0, 1, 2, 3,
+ gtk.EXPAND | gtk.FILL, gtk.EXPAND | gtk.FILL,
+ 0, 0)
+
+ contents = gtk.TextView()
+ contents.grab_focus()
+ sw.add (contents)
+
+ # Create statusbar
+ self.statusbar = gtk.Statusbar()
+ table.attach(self.statusbar,
+ # X direction Y direction
+ 0, 1, 3, 4,
+ gtk.EXPAND | gtk.FILL, 0,
+ 0, 0)
+
+ # Show text widget info in the statusbar
+ buffer = contents.get_buffer()
+ buffer.connect("changed", self.update_statusbar)
+ mark_set_callback = (lambda buffer, new_location, mark:
+ self.update_statusbar(buffer))
+
+ # cursor moved
+ buffer.connect("mark_set", mark_set_callback)
+
+ self.connect("window_state_event", self.update_resize_grip)
+ self.update_statusbar(buffer)
+
+ self.show_all()
+
+ def __create_action_group(self):
+ # GtkActionEntry
+ entries = (
+ ( "FileMenu", None, "_File" ), # name, stock id, label
+ ( "PreferencesMenu", None, "_Preferences" ), # name, stock id, label
+ ( "ColorMenu", None, "_Color" ), # name, stock id, label
+ ( "ShapeMenu", None, "_Shape" ), # name, stock id, label
+ ( "HelpMenu", None, "_Help" ), # name, stock id, label
+ ( "New", gtk.STOCK_NEW, # name, stock id
+ "_New", "<control>N", # label, accelerator
+ "Create a new file", # tooltip
+ self.activate_action ),
+ ( "Open", gtk.STOCK_OPEN, # name, stock id
+ "_Open","<control>O", # label, accelerator
+ "Open a file", # tooltip
+ self.activate_action ),
+ ( "Save", gtk.STOCK_SAVE, # name, stock id
+ "_Save","<control>S", # label, accelerator
+ "Save current file", # tooltip
+ self.activate_action ),
+ ( "SaveAs", gtk.STOCK_SAVE, # name, stock id
+ "Save _As...", None, # label, accelerator
+ "Save to a file", # tooltip
+ self.activate_action ),
+ ( "Quit", gtk.STOCK_QUIT, # name, stock id
+ "_Quit", "<control>Q", # label, accelerator
+ "Quit", # tooltip
+ self.activate_action ),
+ ( "About", None, # name, stock id
+ "_About", "<control>A", # label, accelerator
+ "About", # tooltip
+ self.activate_action ),
+ ( "Logo", "demo-gtk-logo", # name, stock id
+ None, None, # label, accelerator
+ "GTK+", # tooltip
+ self.activate_action ),
+ );
+
+ # GtkToggleActionEntry
+ toggle_entries = (
+ ( "Bold", gtk.STOCK_BOLD, # name, stock id
+ "_Bold", "<control>B", # label, accelerator
+ "Bold", # tooltip
+ self.activate_action,
+ True ), # is_active
+ )
+
+ # GtkRadioActionEntry
+ color_entries = (
+ ( "Red", None, # name, stock id
+ "_Red", "<control><shift>R", # label, accelerator
+ "Blood", COLOR_RED ), # tooltip, value
+ ( "Green", None, # name, stock id
+ "_Green", "<control><shift>G", # label, accelerator
+ "Grass", COLOR_GREEN ), # tooltip, value
+ ( "Blue", None, # name, stock id
+ "_Blue", "<control><shift>B", # label, accelerator
+ "Sky", COLOR_BLUE ), # tooltip, value
+ )
+
+ # GtkRadioActionEntry
+ shape_entries = (
+ ( "Square", None, # name, stock id
+ "_Square", "<control><shift>S", # label, accelerator
+ "Square", SHAPE_SQUARE ), # tooltip, value
+ ( "Rectangle", None, # name, stock id
+ "_Rectangle", "<control><shift>R", # label, accelerator
+ "Rectangle", SHAPE_RECTANGLE ), # tooltip, value
+ ( "Oval", None, # name, stock id
+ "_Oval", "<control><shift>O", # label, accelerator
+ "Egg", SHAPE_OVAL ), # tooltip, value
+ )
+
+ # Create the menubar and toolbar
+ action_group = gtk.ActionGroup("AppWindowActions")
+ action_group.add_actions(entries)
+ action_group.add_toggle_actions(toggle_entries)
+ action_group.add_radio_actions(color_entries, COLOR_RED, self.activate_radio_action)
+ action_group.add_radio_actions(shape_entries, SHAPE_OVAL, self.activate_radio_action)
+
+ return action_group
+
+
+ def activate_action(self, action):
+ dialog = gtk.MessageDialog(self, gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE,
+ 'You activated action: "%s" of type "%s"' % (action.get_name(), type(action)))
+ # Close dialog on user response
+ dialog.connect ("response", lambda d, r: d.destroy())
+ dialog.show()
+
+ def activate_radio_action(self, action, current):
+ active = current.get_active()
+ value = current.get_current_value()
+
+ if active:
+ dialog = gtk.MessageDialog(self, gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE,
+ "You activated radio action: \"%s\" of type \"%s\".\nCurrent value: %d" %
+ (current.get_name(), type(current), value))
+
+ # Close dialog on user response
+ dialog.connect("response", lambda d, r: d.destroy())
+ dialog.show()
+
+ def update_statusbar(self, buffer):
+ # clear any previous message, underflow is allowed
+ self.statusbar.pop(0)
+ count = buffer.get_char_count()
+ iter = buffer.get_iter_at_mark(buffer.get_insert())
+ row = iter.get_line()
+ col = iter.get_line_offset()
+ self.statusbar.push(0,
+ 'Cursor at row %d column %d - %d chars in document' % (row, col, count))
+
+ def update_resize_grip(self, widget, event):
+ mask = gtk.gdk.WINDOW_STATE_MAXIMIZED | gtk.gdk.WINDOW_STATE_FULLSCREEN
+ if (event.changed_mask & mask):
+ self.statusbar.set_has_resize_grip(not (event.new_window_state & mask))
+
+def main():
+ ApplicationMainWindowDemo()
gtk.main()
if __name__ == '__main__':
diff --git a/examples/pygtk-demo/demos/buttonbox.py b/examples/pygtk-demo/demos/buttonbox.py
index 818508fa..cf201dfa 100644
--- a/examples/pygtk-demo/demos/buttonbox.py
+++ b/examples/pygtk-demo/demos/buttonbox.py
@@ -1,21 +1,19 @@
#!/usr/bin/env python
-'''Button Box Test
+'''Button Box
This demo shows various button box configurations available. It also
uses stock buttons, and use of mnemonics for navigation.'''
-description = 'Button Boxes'
-
import gtk
-def create_bbox(horizontal=gtk.TRUE, title=None, spacing=0,
- layout=gtk.BUTTONBOX_SPREAD):
+def create_bbox(horizontal=True, title=None, spacing=0,
+ layout=gtk.BUTTONBOX_SPREAD):
frame = gtk.Frame(title)
if horizontal:
- bbox = gtk.HButtonBox()
+ bbox = gtk.HButtonBox()
else:
- bbox = gtk.VButtonBox()
+ bbox = gtk.VButtonBox()
bbox.set_border_width(5)
bbox.set_layout(layout)
@@ -33,50 +31,58 @@ def create_bbox(horizontal=gtk.TRUE, title=None, spacing=0,
return frame
+class ButtonBoxDemo(gtk.Window):
+ def __init__(self, parent=None):
+ # Create the toplevel window
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+
+ self.set_title(self.__class__.__name__)
+ self.set_border_width(10)
+
+ main_vbox = gtk.VBox()
+ self.add(main_vbox)
+
+ frame_horiz = gtk.Frame("Horizontal Button Boxes")
+ main_vbox.pack_start(frame_horiz, padding=10)
+
+ vbox = gtk.VBox()
+ vbox.set_border_width(10)
+ frame_horiz.add(vbox)
+
+ vbox.pack_start(create_bbox(gtk.TRUE, "Spread", 40, gtk.BUTTONBOX_SPREAD),
+ padding=0)
+ vbox.pack_start(create_bbox(gtk.TRUE, "Edge", 40, gtk.BUTTONBOX_EDGE),
+ padding=5)
+ vbox.pack_start(create_bbox(gtk.TRUE, "Start", 40, gtk.BUTTONBOX_START),
+ padding=5)
+ vbox.pack_start(create_bbox(gtk.TRUE, "End", 40, gtk.BUTTONBOX_END),
+ padding=5)
+
+ frame_vert = gtk.Frame("Vertical Button Boxes")
+ main_vbox.pack_start(frame_vert, padding=10)
+
+ hbox = gtk.HBox()
+ hbox.set_border_width(10)
+ frame_vert.add(hbox)
+
+ hbox.pack_start(create_bbox(gtk.FALSE, "Spread", 40, gtk.BUTTONBOX_SPREAD),
+ padding=0)
+ hbox.pack_start(create_bbox(gtk.FALSE, "Edge", 40, gtk.BUTTONBOX_EDGE),
+ padding=5)
+ hbox.pack_start(create_bbox(gtk.FALSE, "Start", 40, gtk.BUTTONBOX_START),
+ padding=5)
+ hbox.pack_start(create_bbox(gtk.FALSE, "End", 40, gtk.BUTTONBOX_END),
+ padding=5)
+
+ self.show_all()
+
def main():
- win = gtk.Window()
- win.connect('destroy', lambda win: gtk.main_quit())
-
- win.set_title('Button Boxes')
- win.set_border_width(10)
-
- main_vbox = gtk.VBox()
- win.add(main_vbox)
-
- frame_horiz = gtk.Frame("Horizontal Button Boxes")
- main_vbox.pack_start(frame_horiz, padding=10)
-
- vbox = gtk.VBox()
- vbox.set_border_width(10)
- frame_horiz.add(vbox)
-
- vbox.pack_start(create_bbox(gtk.TRUE, "Spread", 40, gtk.BUTTONBOX_SPREAD),
- padding=0)
- vbox.pack_start(create_bbox(gtk.TRUE, "Edge", 40, gtk.BUTTONBOX_EDGE),
- padding=5)
- vbox.pack_start(create_bbox(gtk.TRUE, "Start", 40, gtk.BUTTONBOX_START),
- padding=5)
- vbox.pack_start(create_bbox(gtk.TRUE, "End", 40, gtk.BUTTONBOX_END),
- padding=5)
-
- frame_vert = gtk.Frame("Vertical Button Boxes")
- main_vbox.pack_start(frame_vert, padding=10)
-
- hbox = gtk.HBox()
- hbox.set_border_width(10)
- frame_vert.add(hbox)
-
- hbox.pack_start(create_bbox(gtk.FALSE, "Spread", 40, gtk.BUTTONBOX_SPREAD),
- padding=0)
- hbox.pack_start(create_bbox(gtk.FALSE, "Edge", 40, gtk.BUTTONBOX_EDGE),
- padding=5)
- hbox.pack_start(create_bbox(gtk.FALSE, "Start", 40, gtk.BUTTONBOX_START),
- padding=5)
- hbox.pack_start(create_bbox(gtk.FALSE, "End", 40, gtk.BUTTONBOX_END),
- padding=5)
-
- win.show_all()
+ ButtonBoxDemo()
gtk.main()
-
+
if __name__ == '__main__':
main()
diff --git a/examples/pygtk-demo/demos/changedisplay.py b/examples/pygtk-demo/demos/changedisplay.py
new file mode 100644
index 00000000..592a7e0f
--- /dev/null
+++ b/examples/pygtk-demo/demos/changedisplay.py
@@ -0,0 +1,414 @@
+#!/usr/bin/env python
+'''Change Display
+
+Demonstrates migrating a window between different displays and
+screens. A display is a mouse and keyboard with some number of
+associated monitors. A screen is a set of monitors grouped
+into a single physical work area. The neat thing about having
+multiple displays is that they can be on a completely separate
+computers, as long as there is a network connection to the
+computer where the application is running.
+
+Only some of the windowing systems where GTK+ runs have the
+concept of multiple displays and screens. (The X Window System
+is the main example.) Other windowing systems can only
+handle one keyboard and mouse, and combine all monitors into
+a single screen.
+
+This is a moderately complex example, and demonstrates:
+
+- Tracking the currently open displays and screens
+- Changing the screen for a window
+- Letting the user choose a window by clicking on it
+- Using GtkListStore and GtkTreeView
+- Using GtkDialog
+'''
+import gtk
+import gobject
+
+# These enumerations provide symbolic names for the columns
+# in the two GtkListStore models.
+#
+(
+ DISPLAY_COLUMN_NAME,
+ DISPLAY_COLUMN_DISPLAY,
+ DISPLAY_NUM_COLUMNS
+) = range(3)
+
+(
+ SCREEN_COLUMN_NUMBER,
+ SCREEN_COLUMN_SCREEN,
+ SCREEN_NUM_COLUMNS
+) = range(3)
+
+def find_toplevel_at_pointer(display):
+ ''' Finds the toplevel window under the mouse pointer, if any.
+ '''
+ pointer_window = display.get_window_at_pointer()[0]
+
+ # The user data field of a GdkWindow is used to store a pointer
+ # to the widget that created it.
+ #
+ if pointer_window:
+ widget = pointer_window.get_user_data()
+
+ return widget and widget.get_toplevel() or None
+
+class QueryForToplevel(gtk.Window):
+ ''' Asks the user to click on a window, then waits for them click
+ the mouse. When the mouse is released, returns the toplevel
+ window under the pointer, or NULL, if there is none.
+ '''
+
+ def __init__(self, screen, prompt):
+ gtk.Window.__init__(self, gtk.WINDOW_POPUP)
+ self.set_screen(screen)
+ self.set_modal(True)
+ self.set_position(gtk.WIN_POS_CENTER)
+
+ frame = gtk.Frame()
+ frame.set_shadow_type(gtk.SHADOW_OUT)
+ self.add(frame)
+
+ label = gtk.Label(prompt)
+ label.set_padding(10, 10)
+ frame.add(label)
+
+ self.show_all()
+
+ def run(self):
+ display = self.get_screen().get_display()
+ cursor = gtk.gdk.Cursor(display, gtk.gdk.CROSSHAIR)
+
+ main_context = gobject.main_context_default()
+ if (gtk.gdk.pointer_grab(self.window, False,
+ gtk.gdk.BUTTON_RELEASE_MASK, None, cursor) == gtk.gdk.GRAB_SUCCESS):
+ self.query_clicked = False
+ self.connect("button-release-event", self.button_release_event_cb)
+
+ # Process events until clicked is set by button_release_event_cb.
+ # We pass in may_block=TRUE since we want to wait if there
+ # are no events currently.
+ #
+ while self.query_clicked is False:
+ main_context.iteration(True)
+
+ toplevel = find_toplevel_at_pointer(display)
+ if (toplevel == self):
+ toplevel = None;
+
+ self.destroy()
+ gtk.gdk.flush() # Really release the grab
+
+ return toplevel
+
+ def button_release_event_cb(self, winref, event):
+ self.query_clicked = True
+ return True
+
+
+class LeftAlignButton(gtk.Button):
+ ''' If we have a stack of buttons, it often looks better if their contents
+ are left-aligned, rather than centered. This class creates a button
+ and left-aligns it contents.
+ '''
+ def __init__(self, label):
+ gtk.Button.__init__(self, label)
+ child = self.get_children()[0]
+ child.set_alignment(0., 0.5)
+
+
+# Main entry point. If the dialog for this demo doesn't yet exist, creates
+# it.
+#
+class ChangeDisplayDemo(gtk.Dialog):
+ size_group = None
+ display_model = None
+ screen_model = None
+ screen_selection = None
+ current_display = None
+ current_screen = None
+
+ def __init__(self, parent=None):
+ gtk.Dialog.__init__(self, "Change Screen or display", parent,
+ gtk.DIALOG_NO_SEPARATOR,
+ (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE,
+ "Change", gtk.RESPONSE_OK))
+ self.set_default_size(300, 400)
+
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+ self.connect("response", self.response_cb)
+ self.connect("destroy", self.destroy_cb)
+
+ vbox = gtk.VBox(False, 5)
+ vbox.set_border_width(8)
+
+ self.vbox.pack_start(vbox, True, True, 0)
+
+ frame = self.__create_display_frame()
+ vbox.pack_start(frame, True, True, 0)
+
+ frame = self.__create_screen_frame()
+ vbox.pack_start(frame, True, True, 0)
+
+ self.__initialize_displays()
+
+ self.show_all()
+
+ def __initialize_displays(self):
+ ''' Adds all currently open displays to our list of displays,
+ and set up a signal connection so that we'll be notified
+ when displays are opened in the future as well.
+ '''
+ manager = gtk.gdk.display_manager_get()
+ displays = manager.list_displays()
+
+ for item in displays:
+ self.add_display(item)
+ id = manager.connect("display_opened", self.display_opened_cb)
+ manager.set_data('user-callback', id)
+
+ def __create_frame(self, title):
+ ''' This function is used both for creating the "Display" and
+ "Screen" frames, since they have a similar structure. The
+ caller hooks up the right context for the value returned
+ in tree_view, and packs any relevant buttons into button_vbox.
+ '''
+ frame = gtk.Frame(title)
+
+ hbox = gtk.HBox(False, 8)
+ hbox.set_border_width(8)
+ frame.add(hbox)
+
+ scrollwin = gtk.ScrolledWindow();
+ scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+ scrollwin.set_shadow_type (gtk.SHADOW_IN)
+ hbox.pack_start(scrollwin, True, True, 0)
+
+ tree_view = gtk.TreeView()
+ tree_view.set_headers_visible(False)
+ scrollwin.add(tree_view)
+
+ selection = tree_view.get_selection()
+ selection.set_mode(gtk.SELECTION_BROWSE)
+
+ button_vbox = gtk.VBox(False, 5)
+ hbox.pack_start(button_vbox, False, False, 0)
+
+ if self.size_group is None:
+ self.size_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
+
+ self.size_group.add_widget(button_vbox)
+
+ return (frame, tree_view, button_vbox)
+
+
+ def __create_display_frame(self):
+ ''' Creates the "Display" frame in the main window.
+ '''
+ frame, tree_view, button_vbox = self.__create_frame("Display")
+
+ button = LeftAlignButton("_Open...")
+ button.connect("clicked", self.open_display_cb)
+ button_vbox.pack_start(button, False, False, 0)
+
+ button = LeftAlignButton("_Close")
+ button.connect ("clicked", self.close_display_cb)
+ button_vbox.pack_start(button, False, False, 0)
+
+ self.display_model = gtk.ListStore(str, object);
+ tree_view.set_model(self.display_model)
+
+ column = gtk.TreeViewColumn("Name", gtk.CellRendererText(),
+ text=DISPLAY_COLUMN_NAME)
+ tree_view.append_column(column)
+
+ selection = tree_view.get_selection()
+ selection.connect("changed", self.display_changed_cb)
+
+ return frame
+
+ def __create_screen_frame(self):
+ ''' Creates the "Screen" frame in the main window.
+ '''
+ frame, tree_view, button_vbox = self.__create_frame("Screen")
+
+ self.screen_model = gtk.ListStore(int, object);
+ tree_view.set_model(self.screen_model)
+
+ column = gtk.TreeViewColumn("Number", gtk.CellRendererText(),
+ text=SCREEN_COLUMN_NUMBER)
+ tree_view.append_column(column)
+
+ self.screen_selection = tree_view.get_selection()
+ self.screen_selection.connect("changed", self.screen_changed_cb)
+
+ return frame
+
+ def query_change_display(self):
+ ''' Prompts the user for a toplevel window to move, and then moves
+ that window to the currently selected display
+ '''
+ screen = self.window.get_screen()
+
+ toplevel = QueryForToplevel(screen,
+ "Please select the toplevel\nto move to the new screen").run()
+
+ if toplevel is not None:
+ toplevel.set_screen(self.current_screen)
+ else:
+ screen.get_display().beep()
+
+
+ def response_cb(self, dialog, response_id):
+ ''' Called when the user clicks on a button in our dialog or
+ closes the dialog through the window manager. Unless the
+ "Change" button was clicked, we destroy the dialog.
+ '''
+ if response_id == gtk.RESPONSE_OK:
+ self.query_change_display()
+ else:
+ dialog.destroy()
+
+ def open_display_cb(self, button):
+ ''' Called when the user clicks on "Open..." in the display
+ frame. Prompts for a new display, and then opens a connection
+ to that display.
+ '''
+ dialog = gtk.Dialog("Open Display", self, gtk.DIALOG_MODAL,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
+
+ dialog.set_default_response(gtk.RESPONSE_OK)
+ display_entry = gtk.Entry()
+ display_entry.set_activates_default(True)
+ dialog_label = gtk.Label("Please enter the name of\nthe new display\n")
+
+ dialog.vbox.add(dialog_label)
+ dialog.vbox.add(display_entry)
+
+ display_entry.grab_focus()
+ dialog.show_all()
+
+ result = None
+ while result is None:
+ response_id = dialog.run()
+ if response_id != gtk.RESPONSE_OK:
+ break;
+ new_screen_name = display_entry.get_chars(0, -1)
+ print new_screen_name
+ if new_screen_name != "":
+ result = gtk.gdk.Display(new_screen_name)
+ if result is None:
+ error_msg = (
+ "Can't open display :\n\t%s\nplease try another one\n" %
+ (new_screen_name,))
+ dialog_label.set_text(error_msg)
+
+ dialog.destroy()
+
+ def close_display_cb(self, button):
+ ''' Called when the user clicks on the "Close" button in the
+ "Display" frame. Closes the selected display.
+ '''
+ if self.current_display:
+ self.current_display.close()
+
+
+ def display_changed_cb(self, selection):
+ ''' Called when the selected row in the display list changes.
+ Updates info.current_display, then refills the list of
+ screens.
+ '''
+ model, iter = selection.get_selected()
+ if iter is not None:
+ self.current_display = model.get_value(iter, DISPLAY_COLUMN_DISPLAY)
+ else:
+ self.current_display = None
+ self.fill_screens()
+
+ def screen_changed_cb(self, selection):
+ ''' Called when the selected row in the sceen list changes.
+ Updates info->current_screen.
+ '''
+ model, iter = selection.get_selected()
+ if iter:
+ self.current_screen = model.get(iter, SCREEN_COLUMN_SCREEN)
+ else:
+ self.current_screen = None;
+
+ def destroy_cb(self, parent):
+ self.destroy_info()
+ if parent is None:
+ gtk.main_quit()
+
+
+ def fill_screens(self):
+ ''' Fills in the screen list based on the current display
+ '''
+ self.screen_model.clear()
+ if self.current_display is not None:
+ n_screens = self.current_display.get_n_screens()
+
+ for i in range(n_screens):
+ screen = self.current_display.get_screen(i);
+ iter = self.screen_model.append()
+ self.screen_model.set(iter,
+ SCREEN_COLUMN_NUMBER, i, SCREEN_COLUMN_SCREEN, screen)
+ if (i == 0):
+ self.screen_selection.select_iter(iter)
+
+ def display_closed_cb(self, display, is_error, info):
+ ''' Called when one of the currently open displays is closed.
+ Remove it from our list of displays.
+ '''
+ iter = self.display_model.get_iter_first()
+ while iter:
+ tmp_display = self.display_model.get_value(iter, DISPLAY_COLUMN_DISPLAY)
+ if (tmp_display == display):
+ info.display_model.remove(iter)
+ break;
+ iter = info.display_model.iter_next()
+
+ def add_display(self, display):
+ ''' Adds a new display to our list of displays, and connects
+ to the "closed" signal so that we can remove it from the
+ list of displays again.
+ '''
+ name = display.get_name()
+
+ iter = self.display_model.append()
+ self.display_model.set(iter,
+ DISPLAY_COLUMN_NAME, name, DISPLAY_COLUMN_DISPLAY, display)
+ id = display.connect("closed", self.display_closed_cb)
+ display.set_data('user-callback', id)
+
+ def display_opened_cb(self, manager, display):
+ ''' Called when a new display is opened
+ '''
+ self.add_display(display)
+
+ def destroy_info(self):
+ ''' Cleans up when the toplevel is destroyed; we remove the
+ connections we use to track currently open displays.
+ '''
+ manager = gtk.gdk.display_manager_get()
+ displays = manager.list_displays()
+
+ id = manager.get_data('user-callback')
+ manager.disconnect(id)
+
+ for tmp_list in displays:
+ id = tmp_list.get_data('user-callback')
+ tmp_list.disconnect(id)
+
+
+def main():
+ ChangeDisplayDemo()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
+
diff --git a/examples/pygtk-demo/demos/colorsel.py b/examples/pygtk-demo/demos/colorsel.py
index 444423fa..d3f6c904 100644
--- a/examples/pygtk-demo/demos/colorsel.py
+++ b/examples/pygtk-demo/demos/colorsel.py
@@ -4,71 +4,69 @@
GtkColorSelection lets the user choose a color. GtkColorSelectionDialog is a
prebuilt dialog containing a GtkColorSelection."""
-description = "Color Selector"
-
import gtk
-window = None
-color = None
-da = None
-
-def change_color_cb(w):
- global window, color, da
-
- dialog = gtk.ColorSelectionDialog("Changing color")
- dialog.set_transient_for(window)
- colorsel = dialog.colorsel
-
- colorsel.set_previous_color(color)
- colorsel.set_current_color(color)
- colorsel.set_has_palette(gtk.TRUE)
-
- response = dialog.run()
-
- if response == gtk.RESPONSE_OK:
- color = colorsel.get_current_color()
- da.modify_bg(gtk.STATE_NORMAL, color)
-
- dialog.destroy()
+class ColorSelectorDemo(gtk.Window):
+ color = gtk.gdk.color_parse("blue")
+
+ def __init__(self, parent=None):
+ # Create the toplevel window
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+
+ self.set_title(self.__class__.__name__)
+ self.set_border_width(8)
+ vbox = gtk.VBox()
+ vbox.set_border_width(8)
+ self.add(vbox)
+
+ # Create the color swatch area
+ frame = gtk.Frame()
+ frame.set_shadow_type(gtk.SHADOW_IN)
+ vbox.pack_start(frame, True, True, 8)
+
+ self.d_area = gtk.DrawingArea()
+ self.d_area.set_size_request(200, 200)
+ self.d_area.modify_bg(gtk.STATE_NORMAL, self.color)
+ frame.add(self.d_area)
+
+ alignment = gtk.Alignment(1.0, 0.5, 0.0, 0.0)
+
+ button = gtk.Button("_Change the above color")
+ alignment.add(button)
+
+ vbox.pack_start(alignment, True, True)
+
+ button.connect('clicked', self.on_change_color_clicked)
+ button.set_flags(gtk.CAN_DEFAULT)
+ button.grab_default()
+
+ self.show_all()
+
+ def on_change_color_clicked(self, button):
+
+ dialog = gtk.ColorSelectionDialog("Changing color")
+ dialog.set_transient_for(self)
+ colorsel = dialog.colorsel
+
+ colorsel.set_previous_color(self.color)
+ colorsel.set_current_color(self.color)
+ colorsel.set_has_palette(gtk.TRUE)
+
+ response = dialog.run()
+
+ if response == gtk.RESPONSE_OK:
+ self.color = colorsel.get_current_color()
+ self.d_area.modify_bg(gtk.STATE_NORMAL, self.color)
+
+ dialog.destroy()
+ return True
def main():
- global window, color, da
-
- color = gtk.gdk.color_parse("blue")
-
- window = gtk.Window()
- window.set_title("Color selection")
- window.set_border_width(8)
- window.connect('destroy', lambda win: gtk.main_quit())
-
- vbox = gtk.VBox()
- vbox.set_border_width(8)
- window.add(vbox)
-
- # Create the color swatch area
-
- frame = gtk.Frame()
- frame.set_shadow_type(gtk.SHADOW_IN)
- vbox.pack_start(frame, gtk.TRUE, gtk.TRUE, 8)
-
- da = gtk.DrawingArea()
- da.set_size_request(200, 200)
- da.modify_bg(gtk.STATE_NORMAL, color)
- frame.add(da)
-
- alignment = gtk.Alignment(1.0, 0.5, 0.0, 0.0)
-
- button = gtk.Button("_Change the above color")
- alignment.add(button)
-
- vbox.pack_start(alignment, gtk.TRUE, gtk.TRUE)
-
- button.connect('clicked', change_color_cb)
- button.set_flags(gtk.CAN_DEFAULT)
- button.grab_default()
-
- window.show_all()
-
+ ColorSelectorDemo()
gtk.main()
if __name__ == '__main__':
diff --git a/examples/pygtk-demo/demos/dialogs.py b/examples/pygtk-demo/demos/dialogs.py
index 9b90d3c2..edea0701 100644
--- a/examples/pygtk-demo/demos/dialogs.py
+++ b/examples/pygtk-demo/demos/dialogs.py
@@ -3,130 +3,127 @@
Dialog widgets are used to pop up a transient window for user feedback."""
-description = "Dialog and Message Boxes"
-
import gtk
-window = None
-entry1 = None
-entry2 = None
-counter = 1
-
-def message_dialog_clicked(w):
- global window, counter
-
- dialog = gtk.MessageDialog(window,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
- gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
- "This message box has been popped up %d time%s." %
- (counter, counter > 1 and 's' or ''))
- dialog.run()
- dialog.destroy()
- counter += 1
-
-def interactive_dialog_clicked(w):
- global window, entry1, entry2
-
- dialog = gtk.Dialog("Interactive Dialog", window, 0,
- (gtk.STOCK_OK, gtk.RESPONSE_OK,
- "_Non-stock button", gtk.RESPONSE_CANCEL))
-
- hbox = gtk.HBox(gtk.FALSE, 8)
- hbox.set_border_width(8)
- dialog.vbox.pack_start(hbox, gtk.FALSE, gtk.FALSE, 0)
-
- stock = gtk.image_new_from_stock(
- gtk.STOCK_DIALOG_QUESTION,
- gtk.ICON_SIZE_DIALOG)
- hbox.pack_start(stock, gtk.FALSE, gtk.FALSE, 0)
-
- table = gtk.Table(2, 2)
- table.set_row_spacings(4)
- table.set_col_spacings(4)
- hbox.pack_start(table, gtk.TRUE, gtk.TRUE, 0)
-
- label = gtk.Label("Entry _1")
- label.set_use_underline(gtk.TRUE)
- table.attach_defaults(label, 0, 1, 0, 1)
- local_entry1 = gtk.Entry()
- local_entry1.set_text(entry1.get_text())
- table.attach_defaults(local_entry1, 1, 2, 0, 1)
- label.set_mnemonic_widget(local_entry1)
-
- label = gtk.Label("Entry _2")
- label.set_use_underline(gtk.TRUE)
- table.attach_defaults(label, 0, 1, 1, 2)
- local_entry2 = gtk.Entry()
- local_entry2.set_text(entry2.get_text())
- table.attach_defaults(local_entry2, 1, 2, 1, 2)
- label.set_mnemonic_widget(local_entry2)
-
- dialog.show_all()
-
- response = dialog.run()
-
- if response == gtk.RESPONSE_OK:
- entry1.set_text(local_entry1.get_text())
- entry2.set_text(local_entry2.get_text())
-
- dialog.destroy()
+class DialogAndMessageBoxesDemo(gtk.Window):
+ counter = 1
+ def __init__(self, parent=None):
+ # Create the toplevel window
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+
+ self.set_title(self.__class__.__name__)
+ self.set_border_width(8)
+
+ frame = gtk.Frame("Dialogs")
+ self.add(frame)
+
+ vbox = gtk.VBox(False, 8)
+ vbox.set_border_width(8)
+ frame.add(vbox)
+
+ # Standard message dialog
+ hbox = gtk.HBox(False, 8)
+ vbox.pack_start(hbox)
+ button = gtk.Button("_Message Dialog")
+ button.connect('clicked', self.on_message_dialog_clicked)
+ hbox.pack_start(button, False, False, 0)
+ vbox.pack_start(gtk.HSeparator(), False, False, 0)
+
+ # Interactive dialog
+ hbox = gtk.HBox(False, 8)
+ vbox.pack_start(hbox, False, False, 0)
+ vbox2 = gtk.VBox()
+
+ button = gtk.Button("_Interactive Dialog")
+ button.connect('clicked', self.on_interactive_dialog_clicked)
+ hbox.pack_start(vbox2, False, False, 0)
+ vbox2.pack_start(button, False, False, 0)
+
+ table = gtk.Table(2, 2)
+ table.set_row_spacings(4)
+ table.set_col_spacings(4)
+ hbox.pack_start(table, False, False, 0)
+
+ label = gtk.Label("Entry _1")
+ label.set_use_underline(True)
+ table.attach(label, 0, 1, 0, 1)
+
+ self.entry1 = gtk.Entry()
+ table.attach(self.entry1, 1, 2, 0, 1)
+ label.set_mnemonic_widget(self.entry1)
+
+ label = gtk.Label("Entry _2")
+ label.set_use_underline(True)
+ table.attach(label, 0, 1, 1, 2)
+
+ self.entry2 = gtk.Entry()
+ table.attach(self.entry2, 1, 2, 1, 2)
+ label.set_mnemonic_widget(self.entry2)
+
+ self.show_all()
+
+ def on_message_dialog_clicked(self, button):
+ dialog = gtk.MessageDialog(self,
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
+ "This message box has been popped up %d time%s." %
+ (self.counter, self.counter > 1 and 's' or ''))
+ dialog.run()
+ dialog.destroy()
+ self.counter += 1
+
+ def on_interactive_dialog_clicked(self, button):
+
+ dialog = gtk.Dialog("Interactive Dialog", self, 0,
+ (gtk.STOCK_OK, gtk.RESPONSE_OK,
+ "_Non-stock button", gtk.RESPONSE_CANCEL))
+
+ hbox = gtk.HBox(False, 8)
+ hbox.set_border_width(8)
+ dialog.vbox.pack_start(hbox, False, False, 0)
+
+ stock = gtk.image_new_from_stock(
+ gtk.STOCK_DIALOG_QUESTION,
+ gtk.ICON_SIZE_DIALOG)
+ hbox.pack_start(stock, False, False, 0)
+
+ table = gtk.Table(2, 2)
+ table.set_row_spacings(4)
+ table.set_col_spacings(4)
+ hbox.pack_start(table, True, True, 0)
+
+ label = gtk.Label("Entry _1")
+ label.set_use_underline(True)
+ table.attach(label, 0, 1, 0, 1)
+ local_entry1 = gtk.Entry()
+ local_entry1.set_text(self.entry1.get_text())
+ table.attach(local_entry1, 1, 2, 0, 1)
+ label.set_mnemonic_widget(local_entry1)
+
+ label = gtk.Label("Entry _2")
+ label.set_use_underline(True)
+ table.attach(label, 0, 1, 1, 2)
+ local_entry2 = gtk.Entry()
+ local_entry2.set_text(self.entry2.get_text())
+ table.attach(local_entry2, 1, 2, 1, 2)
+ label.set_mnemonic_widget(local_entry2)
+
+ dialog.show_all()
+
+ response = dialog.run()
+
+ if response == gtk.RESPONSE_OK:
+ self.entry1.set_text(local_entry1.get_text())
+ self.entry2.set_text(local_entry2.get_text())
+
+ dialog.destroy()
def main():
- global window, entry1, entry2
-
- window = gtk.Window()
- window.set_title("Dialogs")
- window.set_border_width(8)
- window.connect('destroy', lambda win: gtk.main_quit())
-
- frame = gtk.Frame("Dialogs")
- window.add(frame)
-
- vbox = gtk.VBox(gtk.FALSE, 8)
- vbox.set_border_width(8)
- frame.add(vbox)
-
- # Standard message dialog
- hbox = gtk.HBox(gtk.FALSE, 8)
- vbox.pack_start(hbox)
- button = gtk.Button("_Message Dialog")
- button.connect('clicked', message_dialog_clicked)
- hbox.pack_start(button, gtk.FALSE, gtk.FALSE, 0)
- vbox.pack_start(gtk.HSeparator(), gtk.FALSE, gtk.FALSE, 0)
-
- # Interactive dialog
- hbox = gtk.HBox(gtk.FALSE, 8)
- vbox.pack_start(hbox, gtk.FALSE, gtk.FALSE, 0)
- vbox2 = gtk.VBox()
-
- button = gtk.Button("_Interactive Dialog")
- button.connect('clicked', interactive_dialog_clicked)
- hbox.pack_start(vbox2, gtk.FALSE, gtk.FALSE, 0)
- vbox2.pack_start(button, gtk.FALSE, gtk.FALSE, 0)
-
- table = gtk.Table(2, 2)
- table.set_row_spacings(4)
- table.set_col_spacings(4)
- hbox.pack_start(table, gtk.FALSE, gtk.FALSE, 0)
-
- label = gtk.Label("Entry _1")
- label.set_use_underline(gtk.TRUE)
- table.attach_defaults(label, 0, 1, 0, 1)
-
- entry1 = gtk.Entry()
- table.attach_defaults(entry1, 1, 2, 0, 1)
- label.set_mnemonic_widget(entry1)
-
- label = gtk.Label("Entry _2")
- label.set_use_underline(gtk.TRUE)
- table.attach_defaults(label, 0, 1, 1, 2)
-
- entry2 = gtk.Entry()
- table.attach_defaults(entry2, 1, 2, 1, 2)
- label.set_mnemonic_widget(entry2)
-
- window.show_all()
-
+ DialogAndMessageBoxesDemo()
gtk.main()
if __name__ == '__main__':
diff --git a/examples/pygtk-demo/demos/dnd.py b/examples/pygtk-demo/demos/dnd.py
index b1f386bb..44d4610b 100644
--- a/examples/pygtk-demo/demos/dnd.py
+++ b/examples/pygtk-demo/demos/dnd.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-'''Drag and Drop Test
+'''Drag and Drop
This is a test of the drag and drop capabilities of gtk. It is a
fairly straight forward port of the example distributed with gtk.
@@ -7,199 +7,200 @@ fairly straight forward port of the example distributed with gtk.
FIXME: there are still a few things missing since I converted the
GdkDragContext wrapper to being a GObject.'''
-description = 'Drag and Drop'
-
import gtk
from dndpixmap import *
-trashcan_open = None
-trashcan_open_mask = None
-trashcan_closed = None
-trashcan_closed_mask = None
-
-have_drag = gtk.FALSE
-popped_up = gtk.FALSE
-in_popup = gtk.FALSE
-popup_timer = 0
-popdown_timer = 0
-popup_win = None
-
-
TARGET_STRING = 0
TARGET_ROOTWIN = 1
target = [
('STRING', 0, TARGET_STRING),
('text/plain', 0, TARGET_STRING),
- ('application/x-rootwin-drop', 0, TARGET_ROOTWIN)]
-
-def target_drag_leave(w, context, time):
- global trashcan_closed, trashcan_closed_mask
- global have_drag
- print 'leave'
- have_drag = gtk.FALSE
- w.set_from_pixmap(trashcan_closed, trashcan_closed_mask)
-
-def target_drag_motion(w, context, x, y, time):
- global trashcan_open, trashcan_open_mask
- global have_drag
- if not have_drag:
- have_drag = gtk.TRUE
- w.set_from_pixmap(trashcan_open, trashcan_open_mask)
- source_widget = context.get_source_widget()
- print 'motion, source ',
- if source_widget:
- print source_widget.__class__.__name__
- else:
- print 'unknown'
- context.drag_status(context.suggested_action, time)
- return gtk.TRUE
-
-def target_drag_drop(w, context, x, y, time):
- global trashcan_closed, trashcan_closed_mask
- global have_drag
- print 'drop'
- have_drag = gtk.FALSE
- w.set_from_pixmap(trashcan_closed, trashcan_closed_mask)
- if context.targets:
- w.drag_get_data(context, context.targets[0], time)
- return gtk.TRUE
- return gtk.FALSE
-
-def target_drag_data_received(w, context, x, y, data, info, time):
- if data.format == 8:
- print 'Received "%s" in trashcan' % data.data
- context.finish(gtk.TRUE, gtk.FALSE, time)
- else:
- context.finish(gtk.FALSE, gtk.FALSE, time)
-
-def label_drag_data_received(w, context, x, y, data, info, time):
- if data and data.format == 8:
- print 'Received "%s" in label' % data.data
- context.finish(gtk.TRUE, gtk.FALSE, time)
- else:
- context.finish(gtk.FALSE, gtk.FALSE, time)
-
-def source_drag_data_get(w, context, selection_data, info, time):
- if info == TARGET_ROOTWIN:
- print 'I was dropped on the rootwin'
- else:
- selection_data.set(selection_data.target, 8, "I'm Data!")
-
-def popdown_cb():
- global popdown_timer, popped_up
- global popup_win
- popdown_timer = 0
- popup_win.hide()
- popped_up = gtk.FALSE
- return gtk.FALSE
-
-def popup_motion(w, context, x, y, time):
- global in_popup, popdown_timer
- if not in_popup:
- in_popup = gtk.TRUE
- if popdown_timer:
- print 'removed popdown'
- gtk.timeout_remove(popdown_timer)
- popdown_timer = 0
- return gtk.TRUE
-
-def popup_leave(w, context, time):
- global in_popup, popdown_timer
- print 'popup_leave'
- if in_popup:
- in_popup = gtk.FALSE
- if not popdown_timer:
- print 'added popdown'
- popdown_timer = gtk.timeout_add(500, popdown_cb)
-
-def popup_cb():
- global popped_up, popup_win
- global popup_timer, popdown_timer
- if not popped_up:
- if not popup_win:
- popup_win = gtk.Window(gtk.WINDOW_POPUP)
- popup_win.set_position(gtk.WIN_POS_MOUSE)
- table = gtk.Table(3, 3)
- for k in range(9):
- i, j = divmod(k, 3)
- b = gtk.Button("%d,%d" % (i,j))
- table.attach(b, i,i+1,j,j+1)
- b.drag_dest_set(gtk.DEST_DEFAULT_ALL, target,
- gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
- b.connect('drag_motion', popup_motion)
- b.connect('drag_leave', popup_leave)
- table.show_all()
- popup_win.add(table)
- popup_win.show()
- popped_up = gtk.TRUE
- popdown_timer = gtk.timeout_add(500, popdown_cb)
- print 'added popdown'
- popup_timer = 0
- return gtk.FALSE
-
-def popsite_motion(w, context, x, y, time):
- global popup_timer
- if not popup_timer:
- popup_timer = gtk.timeout_add(500, popup_cb)
- return gtk.TRUE
-
-def popsite_leave(w, context, time):
- global popup_timer
- if popup_timer:
- gtk.timeout_remove(popup_timer)
- popup_timer = 0
-
-def source_drag_data_delete(w, context, data):
- print 'Delete the data!'
-
-def create_pixmap(widget, xpm):
- return gtk.gdk.pixmap_colormap_create_from_xpm_d(None,
- widget.get_colormap(),
- None, xpm)
+ ('application/x-rootwin-drop', 0, TARGET_ROOTWIN)
+]
+
+def create_pixmap(widget, xpm_data):
+ return \
+ gtk.gdk.pixmap_colormap_create_from_xpm_d(
+ None, widget.get_colormap(), None, xpm_data)
+
+class DragAndDropDemo(gtk.Window):
+ trashcan_open = None
+ trashcan_open_mask = None
+ trashcan_closed = None
+ trashcan_closed_mask = None
+ drag_icon = None
+ drag_mask = None
+ have_drag = False
+ popped_up = False
+ in_popup = False
+ popup_timer = None
+ popdown_timer = 0
+ popup_win = None
+
+ def __init__(self, parent=None):
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+ self.set_title(self.__class__.__name__)
+
+ table = gtk.Table(2,2)
+ self.add(table)
+
+ self.drag_icon, self.drag_mask = \
+ create_pixmap(self, drag_icon_xpm)
+ self.trashcan_open, self.trashcan_open_mask = \
+ create_pixmap(self, trashcan_open_xpm)
+ self.trashcan_closed, self.trashcan_closed_mask = \
+ create_pixmap(self, trashcan_closed_xpm)
+
+ label = gtk.Label('Drop Here!\n')
+ label.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
+ gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
+ label.connect('drag_data_received', self.label_drag_data_received)
+ table.attach(label, 0, 1, 0, 1)
+
+ label = gtk.Label('Popup\n')
+ label.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
+ gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
+ table.attach(label, 1, 2, 1, 2)
+ label.connect('drag_motion', self.popsite_motion)
+ label.connect('drag_leave', self.popsite_leave)
+
+ image = gtk.Image()
+ image.set_from_pixmap(self.trashcan_closed, self.trashcan_closed_mask)
+ image.drag_dest_set(0, [], 0)
+ table.attach(image, 1, 2, 0, 1)
+ image.connect('drag_leave', self.target_drag_leave)
+ image.connect('drag_motion', self.target_drag_motion)
+ image.connect('drag_drop', self.target_drag_drop)
+ image.connect('drag_data_received', self.target_drag_data_received)
+
+ b = gtk.Button('Drag Here\n')
+ b.drag_source_set(gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK,
+ target, gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
+ b.drag_source_set_icon(self.get_colormap(), self.drag_icon, self.drag_mask)
+ table.attach(b, 0, 1, 1, 2)
+ b.connect('drag_data_get', self.source_drag_data_get)
+ b.connect('drag_data_delete', self.source_drag_data_delete)
+ self.show_all()
+
+ def label_drag_data_received(self, w, context, x, y, data, info, time):
+ if data and data.format == 8:
+ print 'Received "%s" in label' % data.data
+ context.finish(True, False, time)
+ else:
+ context.finish(False, False, time)
+
+ def popsite_motion(self, w, context, x, y, time):
+ if self.popup_timer is None:
+ self.popup_timer = gtk.timeout_add(500, self.popup_cb)
+ return True
+
+ def popsite_leave(self, w, context, time):
+ if self.popup_timer is not None:
+ gtk.timeout_remove(self.popup_timer)
+ self.popup_timer = None
+
+ def popup_motion(self, w, context, x, y, time):
+ print 'popup_motion'
+ if not self.in_popup:
+ self.in_popup = True
+ if self.popdown_timer is not None:
+ print 'removed popdown'
+ gtk.timeout_remove(self.popdown_timer)
+ self.popdown_timer = None
+ return True
+
+ def popup_leave(self, w, context, time):
+ print 'popup_leave'
+ if self.in_popup:
+ self.in_popup = False
+ if self.popdown_timer is None:
+ print 'added popdown'
+ self.popdown_timer = gtk.timeout_add(500, self.popdown_cb)
+
+ def popup_cb(self):
+ if not self.popped_up:
+ if self.popup_win is None:
+ self.popup_win = gtk.Window(gtk.WINDOW_POPUP)
+ self.popup_win.set_position(gtk.WIN_POS_MOUSE)
+ table = gtk.Table(3, 3)
+ for k in range(9):
+ i, j = divmod(k, 3)
+ b = gtk.Button("%d,%d" % (i,j))
+ b.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
+ gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
+ b.connect('drag_motion', self.popup_motion, None)
+ b.connect('drag_leave', self.popup_leave)
+ table.attach(b, i, i+1, j, j+1)
+ table.show_all()
+ self.popup_win.add(table)
+ self.popup_win.show()
+ self.popped_up = True
+ self.in_popup = True
+ self.popdown_timer = gtk.timeout_add(500, self.popdown_cb)
+ print 'added popdown'
+ self.popup_timer = None
+ return False
+
+ def popdown_cb(self):
+ print 'popdown'
+ #if self.in_popup:
+ # return True
+ self.popdown_timer = None
+ self.popup_win.hide()
+ self.popped_up = False
+ return False
+
+ def target_drag_leave(self, img, context, time):
+ print 'leave'
+ self.have_drag = False
+ img.set_from_pixmap(self.trashcan_closed, self.trashcan_closed_mask)
+
+ def target_drag_motion(self, img, context, x, y, time):
+ if self.have_drag is False:
+ self.have_drag = True
+ img.set_from_pixmap(self.trashcan_open, self.trashcan_open_mask)
+ source_widget = context.get_source_widget()
+ print 'motion, source ',
+ if source_widget:
+ print source_widget.__class__.__name__
+ else:
+ print 'unknown'
+ context.drag_status(context.suggested_action, time)
+ return True
+
+ def target_drag_drop(self, img, context, x, y, time):
+ print 'drop'
+ self.have_drag = False
+ img.set_from_pixmap(self.trashcan_closed, self.trashcan_closed_mask)
+ if context.targets:
+ img.drag_get_data(context, context.targets[0], time)
+ return True
+ return False
+
+ def target_drag_data_received(self, img, context, x, y, data, info, time):
+ if data.format == 8:
+ print 'Received "%s" in trashcan' % data.data
+ context.finish(True, False, time)
+ else:
+ context.finish(False, False, time)
+
+ def source_drag_data_get(self, btn, context, selection_data, info, time):
+ if info == TARGET_ROOTWIN:
+ print 'I was dropped on the rootwin'
+ else:
+ selection_data.set(selection_data.target, 8, "I'm Data!")
+
+ def source_drag_data_delete(self, btn, context, data):
+ print 'Delete the data!'
def main():
- global trashcan_open, trashcan_open_mask
- global trashcan_closed, trashcan_closed_mask
- global drag_icon, drag_mask
- win = gtk.Window()
- win.connect('destroy', lambda win: gtk.main_quit())
- table = gtk.Table(2,2)
- win.add(table)
- drag_icon, drag_mask = create_pixmap(win, drag_icon_xpm)
- trashcan_open, trashcan_open_mask = create_pixmap(win, trashcan_open_xpm)
- trashcan_closed, trashcan_closed_mask = create_pixmap(win, trashcan_closed_xpm)
- label = gtk.Label('Drop Here!\n')
- label.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
- gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
- label.connect('drag_data_received', label_drag_data_received)
- table.attach(label, 0, 1, 0, 1)
-
- label = gtk.Label('Popup\n')
- label.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
- gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
- table.attach(label, 1, 2, 1, 2)
- label.connect('drag_motion', popsite_motion)
- label.connect('drag_leave', popsite_leave)
-
- image = gtk.Image()
- image.set_from_pixmap(trashcan_closed, trashcan_closed_mask)
- image.drag_dest_set(0, [], 0)
- table.attach(image, 1, 2, 0, 1)
- image.connect('drag_leave', target_drag_leave)
- image.connect('drag_motion', target_drag_motion)
- image.connect('drag_drop', target_drag_drop)
- image.connect('drag_data_received', target_drag_data_received)
-
- b = gtk.Button('Drag Here\n')
- b.drag_source_set(gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK,
- target, gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
- b.drag_source_set_icon(win.get_colormap(), drag_icon, drag_mask)
- table.attach(b, 0, 1, 1, 2)
- b.connect('drag_data_get', source_drag_data_get)
- b.connect('drag_data_delete', source_drag_data_delete)
- win.show_all()
+ DragAndDropDemo()
gtk.main()
-
+
if __name__ == '__main__':
main()
diff --git a/examples/pygtk-demo/demos/editable_cells.py b/examples/pygtk-demo/demos/editable_cells.py
index 07d198d9..a8acb5c3 100644
--- a/examples/pygtk-demo/demos/editable_cells.py
+++ b/examples/pygtk-demo/demos/editable_cells.py
@@ -1,144 +1,166 @@
-"""Tree View/Editable Cells
+#!/usr/bin/env python
+'''Tree View/Editable Cells
-This demo demonstrates the use of editable cells in a GtkTreeView. If
-you're new to the GtkTreeView widgets and associates, look into
-the GtkListStore example first.
-
-"""
-
-description = 'Editable cells'
+This demo demonstrates the use of editable cells in a GtkTreeView.
+If you're new to the GtkTreeView widgets and associates, look into the
+GtkListStore example first.'''
+# pygtk version: Maik Hertha <maik.hertha@berlin.de>
import gobject
import gtk
-from gtk import TRUE, FALSE
-
-COLUMN_NUMBER = 0
-COLUMN_PRODUCT = 1
-COLUMN_EDITABLE = 2
-
-ARTICLES = [
- [3, "bottles of coke", TRUE],
- [5, "packages of noodles", TRUE],
- [2, "packages of chocolate chip cookies", TRUE],
- [1, "can vanilla ice cream", TRUE],
- [6, "eggs", TRUE]
+
+# columns
+(
+ COLUMN_NUMBER,
+ COLUMN_PRODUCT,
+ COLUMN_EDITABLE
+) = range(3)
+
+# data
+articles = [
+ [ 3, "bottles of coke", True ],
+ [ 5, "packages of noodles", True ],
+ [ 2, "packages of chocolate chip cookies", True ],
+ [ 1, "can vanilla ice cream", True ],
+ [ 6, "eggs", True ]
]
-def create_model():
- # create model
- model = gtk.ListStore(gobject.TYPE_INT,
- gobject.TYPE_STRING,
- gobject.TYPE_BOOLEAN)
+class EditableCellsDemo(gtk.Window):
+ def __init__(self, parent=None):
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+ self.set_title(self.__class__.__name__)
+ self.set_border_width(5)
+ self.set_default_size(320, 200)
+
+ vbox = gtk.VBox(False, 5)
+ self.add(vbox)
+
+ label = gtk.Label("Shopping list (you can edit the cells!)")
+ vbox.pack_start(label, False, False)
+
+ sw = gtk.ScrolledWindow()
+ sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
+ sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ vbox.pack_start(sw)
+
+ # create model
+ model = self.__create_model()
+
+ # create tree view
+ treeview = gtk.TreeView(model)
+ treeview.set_rules_hint(True)
+ treeview.get_selection().set_mode(gtk.SELECTION_SINGLE)
+
+ self.__add_columns(treeview)
+
+ sw.add(treeview)
+
+ # some buttons
+ hbox = gtk.HBox(True, 4)
+ vbox.pack_start(hbox, False, False)
+
+ button = gtk.Button("Add item")
+ button.connect("clicked", self.on_add_item_clicked, model)
+ hbox.pack_start(button)
+
+ button = gtk.Button("Remove item")
+ button.connect("clicked", self.on_remove_item_clicked, treeview)
+ hbox.pack_start(button)
+
+ self.show_all()
+
+ def __create_model(self):
+
+ # create list store
+ model = gtk.ListStore(
+ gobject.TYPE_INT,
+ gobject.TYPE_STRING,
+ gobject.TYPE_BOOLEAN
+ )
+
+ # add items
+ for item in articles:
+ iter = model.append()
+
+ model.set (iter,
+ COLUMN_NUMBER, item[COLUMN_NUMBER],
+ COLUMN_PRODUCT, item[COLUMN_PRODUCT],
+ COLUMN_EDITABLE, item[COLUMN_EDITABLE]
+ )
+ return model
+
+
+ def __add_columns(self, treeview):
+
+ model = treeview.get_model()
+
+ # number column
+ renderer = gtk.CellRendererText()
+ renderer.connect("edited", self.on_cell_edited, model)
+ renderer.set_data("column", COLUMN_NUMBER)
+
+ column = gtk.TreeViewColumn("Number", renderer, text=COLUMN_NUMBER,
+ editable=COLUMN_EDITABLE)
+ treeview.append_column(column)
+
+ # product column
+ renderer = gtk.CellRendererText()
+ renderer.connect("edited", self.on_cell_edited, model)
+ renderer.set_data("column", COLUMN_PRODUCT)
+
+ column = gtk.TreeViewColumn("Product", renderer, text=COLUMN_PRODUCT,
+ editable=COLUMN_EDITABLE)
+ treeview.append_column(column)
+
+
+ def on_add_item_clicked(self, button, model):
+ new_item = [0, "Description here", True]
+ articles.append(new_item)
- # insert articles
- for article in ARTICLES:
iter = model.append()
- model.set(iter,
- COLUMN_NUMBER, article[0],
- COLUMN_PRODUCT, article[1],
- COLUMN_EDITABLE, article[2])
- return model
-
-def add_item(button, model):
- item = [0, "Description here", TRUE]
-
- ARTICLES.append(item)
-
- iter = model.append()
- model.set(iter,
- COLUMN_NUMBER, item[0],
- COLUMN_PRODUCT, item[1],
- COLUMN_EDITABLE, item[2])
-
-def remove_item(button, treeview):
- selection = treeview.get_selection()
- selected = selection.get_selected()
- if selected:
- model, iter = selected
- i = model.get_path(iter)[0]
- model.remove(iter)
- ARTICLES.pop(i)
-
-def cell_edited (cell, row, new_text, model):
- article = ARTICLES[int(row)]
- iter = model.get_iter_from_string(row)
-
- column = cell.get_data("column")
- if column == COLUMN_NUMBER:
- article[column] = int(new_text)
- model.set(iter, column, article[column])
- elif column == COLUMN_PRODUCT:
- article[column] = new_text
- model.set(iter, column, article[column])
-
-def add_columns(treeview):
- model = treeview.get_model()
-
- # number column
- renderer = gtk.CellRendererText()
- renderer.connect('edited', cell_edited, model)
- renderer.set_data('column', COLUMN_NUMBER)
- treeview.insert_column_with_attributes(-1, 'Number', renderer,
- text=COLUMN_NUMBER,
- editable=COLUMN_EDITABLE)
- # product column
- renderer = gtk.CellRendererText()
- renderer.connect('edited', cell_edited, model)
- renderer.set_data('column', COLUMN_PRODUCT)
-
- treeview.insert_column_with_attributes(-1, 'Number', renderer,
- text=COLUMN_PRODUCT,
- editable=COLUMN_EDITABLE)
-
-def main():
- # create window, etc
- window = gtk.Window()
- window.set_title('Shopping list')
- window.set_border_width(5)
- window.connect('destroy', lambda win: gtk.mainquit())
+ model.set (iter,
+ COLUMN_NUMBER, new_item[COLUMN_NUMBER],
+ COLUMN_PRODUCT, new_item[COLUMN_PRODUCT],
+ COLUMN_EDITABLE, new_item[COLUMN_EDITABLE]
+ )
- vbox = gtk.VBox()
- window.add(vbox)
- label = gtk.Label("Shopping list (you can edit the cells!)")
- vbox.pack_start(label, FALSE, FALSE)
+ def on_remove_item_clicked(self, button, treeview):
- sw = gtk.ScrolledWindow()
- sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
- sw.set_policy(gtk.POLICY_AUTOMATIC,
- gtk.POLICY_AUTOMATIC)
- vbox.pack_start(sw)
+ selection = treeview.get_selection()
+ model, iter = selection.get_selected()
- # create model
- model = create_model()
+ if iter:
+ path = model.get_path(iter)[0]
+ model.remove(iter)
- # create tree view
- treeview = gtk.TreeView(model)
- treeview.set_rules_hint(TRUE)
- treeview.set_headers_visible(TRUE)
- selection = treeview.get_selection()
- selection.set_mode(gtk.SELECTION_SINGLE)
+ del articles[ path ]
- add_columns(treeview)
- sw.add(treeview)
+ def on_cell_edited(self, cell, path_string, new_text, model):
- # some buttons
- hbox = gtk.HBox()
- vbox.pack_start(hbox, FALSE, FALSE)
+ iter = model.get_iter_from_string(path_string)
+ path = model.get_path(iter)[0]
+ column = cell.get_data("column")
- button = gtk.Button('Add item')
- button.connect('clicked', add_item, model)
- hbox.pack_start(button)
-
- button = gtk.Button('Remove item')
- button.connect('clicked', remove_item, treeview)
- hbox.pack_start(button)
+ if column == COLUMN_NUMBER:
+ articles[path][COLUMN_NUMBER] = int(new_text)
- window.set_default_size(330, 220)
- window.show_all()
+ model.set(iter, column, articles[path][COLUMN_NUMBER])
+ elif column == COLUMN_PRODUCT:
+ old_text = model.get_value(iter, column)
+ articles[path][COLUMN_PRODUCT] = new_text
+
+ model.set(iter, column, articles[path][COLUMN_PRODUCT])
+
+def main():
+ EditableCellsDemo()
gtk.main()
-
-if __name__=="__main__":
+
+if __name__ == '__main__':
main()
diff --git a/examples/pygtk-demo/demos/entry_completion.py b/examples/pygtk-demo/demos/entry_completion.py
new file mode 100644
index 00000000..52e8568c
--- /dev/null
+++ b/examples/pygtk-demo/demos/entry_completion.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+'''Entry Completion
+
+GtkEntryCompletion provides a mechanism for adding support for
+completion in GtkEntry.
+'''
+# pygtk version: Maik Hertha <maik.hertha@berlin.de>
+
+import gtk
+
+class EntryCompletionDemo(gtk.Dialog):
+
+ def __init__(self, parent=None):
+ gtk.Dialog.__init__(self, self.__class__.__name__, parent,
+ 0,
+ (gtk.STOCK_CLOSE, gtk.RESPONSE_NONE))
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+ self.connect("response", lambda d, r: d.destroy())
+ self.set_resizable(False)
+
+ vbox = gtk.VBox(False, 5)
+ self.vbox.pack_start(vbox, True, True, 0)
+ vbox.set_border_width(5)
+
+ label = gtk.Label()
+ label.set_markup("Completion demo, try writing <b>total</b> "
+ "or <b>gnome</b> for example.")
+ vbox.pack_start(label, False, False, 0)
+
+ # Create our entry
+ entry = gtk.Entry()
+ vbox.pack_start(entry, False, False, 0)
+
+ # Create the completion object
+ completion = gtk.EntryCompletion()
+
+ # Assign the completion to the entry
+ entry.set_completion(completion)
+
+ # Create a tree model and use it as the completion model
+ completion_model = self.__create_completion_model()
+ completion.set_model(completion_model)
+
+ # Use model column 0 as the text column
+ completion.set_text_column(0)
+
+ self.show_all()
+
+ def __create_completion_model(self):
+ ''' Creates a tree model containing the completions.
+ '''
+ store = gtk.ListStore(str)
+
+ # Append one word
+ iter = store.append()
+ store.set(iter, 0, "GNOME")
+
+ # Append another word
+ iter = store.append()
+ store.set(iter, 0, "total")
+
+ # And another word
+ iter = store.append()
+ store.set(iter, 0, "totally")
+
+ return store
+
+def main():
+ EntryCompletionDemo()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
+
diff --git a/examples/pygtk-demo/demos/entrycompletion.py b/examples/pygtk-demo/demos/entrycompletion.py
deleted file mode 100644
index 3148aad8..00000000
--- a/examples/pygtk-demo/demos/entrycompletion.py
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-"""Entry Completion
-
- gtk.EntryCompletion Test
- (c) Fernando San Martín Woerner 2004
- snmartin@galilea.cl
-
- A simple test for gtk.EntryCompletion widget
-"""
-description = 'Entry Completion'
-
-
-import pygtk; pygtk.require("2.0")
-import gobject
-import gtk
-
-def on_match_selected(completion, model, iter):
- month = model.get_value(iter,0)
- print "You have selected " + month
-
-def main():
- # The window...
- window = gtk.Window()
- window.set_title("EntryCompletion Test")
- window.connect('delete-event', gtk.main_quit)
-
- # The entry to fill with autocompletion
- entry = gtk.Entry()
-
- # The EntryCompletion Widget
- compl = gtk.EntryCompletion()
-
- # Connected to on_match_selected
- compl.connect("match-selected", on_match_selected)
-
- # The model with autocompletion
- model = gtk.ListStore(str)
-
- # A model and a text column
- compl.set_model(model)
- compl.set_text_column(0)
-
- # Adding rows
- model.append(["JANUARY"])
- model.append(["FEBRUARY"])
- model.append(["MARCH"])
- model.append(["APRIL"])
- model.append(["MAY"])
- model.append(["JUN"])
- model.append(["JULY"])
- model.append(["AUGUST"])
- model.append(["SEPTEMBER"])
- model.append(["OCTOBER"])
- model.append(["NOVEMBER"])
- model.append(["DECEMBER"])
-
- # Setting the widgets together
- entry.set_completion(compl)
-
- vbox = gtk.VBox()
- window.add(vbox)
- vbox.pack_start(gtk.Label("Type a month:"))
- vbox.pack_start(entry)
- window.show_all()
- # Running
- gtk.main()
-
-
-if __name__ == '__main__':
- main()
diff --git a/examples/pygtk-demo/demos/expander.py b/examples/pygtk-demo/demos/expander.py
new file mode 100644
index 00000000..37f6b5b7
--- /dev/null
+++ b/examples/pygtk-demo/demos/expander.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+'''Expander
+
+GtkExpander allows to provide additional content that is initially hidden.
+This is also known as "disclosure triangle".
+'''
+# pygtk version: Maik Hertha <maik.hertha@berlin.de>
+
+import gtk
+
+class ExpanderDemo(gtk.Dialog):
+
+ def __init__(self, parent=None):
+ gtk.Dialog.__init__(self, self.__class__.__name__, parent,
+ 0,
+ (gtk.STOCK_CLOSE, gtk.RESPONSE_NONE))
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+ self.connect("response", lambda d, r: d.destroy())
+ self.set_resizable(False)
+
+ vbox = gtk.VBox(False, 5)
+ self.vbox.pack_start(vbox, True, True, 0)
+ vbox.set_border_width(5)
+
+ label = gtk.Label()
+ label.set_markup("Expander demo. Click on the triangle for details.")
+ vbox.pack_start(label, False, False, 0)
+
+ # Create the expander
+ expander = gtk.Expander("Details")
+ vbox.pack_start(expander, False, False, 0)
+
+ # The Label for the expander
+ label = gtk.Label("Details can be shown or hidden.")
+ expander.add(label)
+
+ self.show_all()
+
+def main():
+ ExpanderDemo()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
+
diff --git a/examples/pygtk-demo/demos/hypertext.py b/examples/pygtk-demo/demos/hypertext.py
new file mode 100644
index 00000000..d7386b3d
--- /dev/null
+++ b/examples/pygtk-demo/demos/hypertext.py
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+'''Text Widget/Hypertext
+
+Usually, tags modify the appearance of text in the view, e.g. making it
+bold or colored or underlined. But tags are not restricted to appearance.
+They can also affect the behavior of mouse and key presses, as this demo
+shows.'''
+# pygtk version: Maik Hertha <maik.hertha@berlin.de>
+
+import gtk
+import pango
+
+class HypertextDemo(gtk.Window):
+ hovering_over_link = False
+ hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2)
+ regular_cursor = gtk.gdk.Cursor(gtk.gdk.XTERM)
+
+ def __init__(self, parent=None):
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+
+ self.set_title(self.__class__.__name__)
+ self.set_default_size(450, 450)
+ self.set_border_width(0)
+
+ view = gtk.TextView()
+ view.set_wrap_mode(gtk.WRAP_WORD)
+ view.connect("key-press-event", self.key_press_event)
+ view.connect("event-after", self.event_after)
+ view.connect("motion-notify-event", self.motion_notify_event)
+ view.connect("visibility-notify-event", self.visibility_notify_event)
+
+ buffer = view.get_buffer()
+
+ sw = gtk.ScrolledWindow()
+ sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ self.add(sw)
+ sw.add(view)
+
+ self.show_page(buffer, 1)
+
+ self.show_all()
+
+ # Links can be activated by pressing Enter.
+ def key_press_event(self, text_view, event):
+ if event.keyval == gtk.gdk.Return or \
+ event.keyval == gtk.gdk.KP_Enter:
+ buffer = text_view.get_buffer()
+ iter = buffer.get_iter_at_mark(buffer.get_insert())
+ follow_if_link(text_view, iter)
+ return False
+
+ # Links can also be activated by clicking.
+ def event_after(self, text_view, event):
+ if event.type != gtk.gdk.BUTTON_RELEASE:
+ return False
+ if event.button != 1:
+ return False
+ buffer = text_view.get_buffer()
+
+ # we shouldn't follow a link if the user has selected something
+ try:
+ start, end = buffer.get_selection_bounds()
+ except ValueError:
+ # If there is nothing selected, None is return
+ pass
+ else:
+ if start.get_offset() != end.get_offset():
+ return False
+
+ x, y = text_view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
+ int(event.x), int(event.y))
+ iter = text_view.get_iter_at_location(x, y)
+
+ self.follow_if_link(text_view, iter)
+ return False
+
+
+ # Looks at all tags covering the position (x, y) in the text view,
+ # and if one of them is a link, change the cursor to the "hands" cursor
+ # typically used by web browsers.
+ def set_cursor_if_appropriate(self, text_view, x, y):
+ hovering = False
+
+ buffer = text_view.get_buffer()
+ iter = text_view.get_iter_at_location(x, y)
+
+ tags = iter.get_tags()
+ for tag in tags:
+ page = tag.get_data("page")
+ if page != 0:
+ hovering = True
+ break
+
+ if hovering != self.hovering_over_link:
+ self.hovering_over_link = hovering
+
+ if self.hovering_over_link:
+ text_view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(self.hand_cursor)
+ else:
+ text_view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(self.regular_cursor)
+
+ # Update the cursor image if the pointer moved.
+ def motion_notify_event(self, text_view, event):
+ x, y = text_view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET,
+ int(event.x), int(event.y))
+ self.set_cursor_if_appropriate(text_view, x, y)
+ text_view.window.get_pointer()
+ return False
+
+ # Also update the cursor image if the window becomes visible
+ # (e.g. when a window covering it got iconified).
+ def visibility_notify_event(self, text_view, event):
+ wx, wy, mod = text_view.window.get_pointer()
+ bx, by = text_view.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, wx, wy)
+
+ self.set_cursor_if_appropriate (text_view, bx, by)
+ return False
+
+ def insert_link(self, buffer, iter, text, page):
+ ''' Inserts a piece of text into the buffer, giving it the usual
+ appearance of a hyperlink in a web browser: blue and underlined.
+ Additionally, attaches some data on the tag, to make it recognizable
+ as a link.
+ '''
+ tag = buffer.create_tag(None,
+ foreground="blue", underline=pango.UNDERLINE_SINGLE)
+ tag.set_data("page", page)
+ buffer.insert_with_tags(iter, text, tag)
+
+
+ def show_page(self, buffer, page):
+ ''' Fills the buffer with text and interspersed links. In any real
+ hypertext app, this method would parse a file to identify the links.
+ '''
+ buffer.set_text("", 0)
+ iter = buffer.get_iter_at_offset(0)
+ if page == 1:
+ buffer.insert(iter, "Some text to show that simple ")
+ self.insert_link(buffer, iter, "hypertext", 3)
+ buffer.insert(iter, " can easily be realized with ")
+ self.insert_link(buffer, iter, "tags", 2)
+ buffer.insert(iter, ".")
+
+ elif page == 2:
+ buffer.insert(iter,
+ "A tag is an attribute that can be applied to some range of text. "
+ "For example, a tag might be called \"bold\" and make the text inside "
+ "the tag bold. However, the tag concept is more general than that "
+ "tags don't have to affect appearance. They can instead affect the "
+ "behavior of mouse and key presses, \"lock\" a range of text so the "
+ "user can't edit it, or countless other things.\n", -1)
+ self.insert_link(buffer, iter, "Go back", 1)
+ elif page == 3:
+ tag = buffer.create_tag(None, weight=pango.WEIGHT_BOLD)
+ buffer.insert_with_tags(iter, "hypertext:\n", tag)
+ buffer.insert(iter,
+ "machine-readable text that is not sequential but is organized "
+ "so that related items of information are connected.\n")
+ self.insert_link(buffer, iter, "Go back", 1)
+
+
+ def follow_if_link(self, text_view, iter):
+ ''' Looks at all tags covering the position of iter in the text view,
+ and if one of them is a link, follow it by showing the page identified
+ by the data attached to it.
+ '''
+ tags = iter.get_tags()
+ for tag in tags:
+ page = tag.get_data("page")
+ if page != 0:
+ self.show_page(text_view.get_buffer(), page)
+ break
+
+
+def main():
+ HypertextDemo()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
+
diff --git a/examples/pygtk-demo/demos/images.py b/examples/pygtk-demo/demos/images.py
index e6cc7cb7..d3f0a7c3 100644
--- a/examples/pygtk-demo/demos/images.py
+++ b/examples/pygtk-demo/demos/images.py
@@ -1,164 +1,306 @@
#!/usr/bin/env python
-#
-# Copyright (C) 2004 Joey Tsai <joeytsai@joeytsai.com>
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
-"""Images
+'''Images
GtkImage is used to display an image; the image can be in a number of formats.
Typically, you load an image into a GdkPixbuf, then display the pixbuf.
-
This demo code shows some of the more obscure cases, in the simple case a call
-to gtk.Image's set_from_file() is all you need.
-"""
-
-import sys
-
-import pygtk
-pygtk.require("2.0")
+to gtk_image_new_from_file() is all you need.
+If you want to put image data in your program as a C variable, use the
+make-inline-pixbuf program that comes with GTK+. This way you won't need to
+depend on loading external files, your application binary can be self-contained.'''
+# pygtk version: Maik Hertha <maik.hertha@berlin.de>
+import os
import gobject
import gtk
-description = "Images"
+IMAGEDIR = os.path.join(os.path.dirname(__file__), 'images')
+ALPHA_IMAGE = os.path.join(IMAGEDIR, 'alphatest.png')
+GTKLOGO_IMAGE = os.path.join(IMAGEDIR, 'gtk-logo-rgb.gif')
+BUDDY_IMAGE = os.path.join(IMAGEDIR, 'floppybuddy.gif')
-def error_dialog(message, parent=None):
- dialog = gtk.MessageDialog(parent,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
- gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, message)
- dialog.run()
- dialog.destroy()
+def progressive_prepared_callback(loader, image):
+ pixbuf = loader.get_pixbuf()
-def on_timeout(loader, fileobject):
- run_again = True
+ # Avoid displaying random memory contents, since the pixbuf
+ # isn't filled in yet.
+ #images.c -> gdk_pixbuf_fill(pixbuf, 0xaaaaaaff)
+ pixbuf.fill(0)
+ image.set_from_pixbuf(pixbuf)
- try:
- bytes = fileobject.read(256)
- loader.write(bytes)
- except (IOError, gobject.GError), e:
- error_dialog(str(e))
- run_again = False
- if not bytes:
- run_again = False
+def progressive_updated_callback(loader, x, y, width, height, image):
+ ''' We know the pixbuf inside the GtkImage has changed, but the image
+ itself doesn't know this; so queue a redraw. If we wanted to be
+ really efficient, we could use a drawing area or something
+ instead of a GtkImage, so we could control the exact position of
+ the pixbuf on the display, then we could queue a draw for only
+ the updated area of the image.
+ '''
+ image.queue_draw()
- if not run_again:
- try:
- fileobject.close()
- loader.close()
- except gobject.GError, e:
- # bug 136989, loader.close() will throw an exception
- pass
+class ImagesDemo(gtk.Window):
+ pixbuf_loader = None
+ load_timeout = None
+ image_stream = None
- return run_again
+ def __init__(self, parent=None):
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+ self.connect("destroy", self.cleanup_callback)
+ self.set_title(self.__class__.__name__)
+ self.set_border_width(8)
-def on_area_prepared(loader, image):
- pixbuf = loader.get_pixbuf()
- image.set_from_pixbuf(pixbuf)
+ vbox = gtk.VBox(False, 8)
+ vbox.set_border_width(8)
+ self.add(vbox)
-def on_area_updated(loader, x, y, w, h, image):
- image.queue_draw()
+ label = gtk.Label();
+ label.set_markup("<u>Image loaded from a file</u>")
+ vbox.pack_start(label, False, False, 0)
-def get_progressive_image(filename):
- try:
- fileobject = open(filename, "r")
- except IOError, e:
- error_dialog(str(e))
- return
+ frame = gtk.Frame()
+ frame.set_shadow_type(gtk.SHADOW_IN)
- image = gtk.Image()
+ # The alignment keeps the frame from growing when users resize
+ # the window
+ align = gtk.Alignment(0.5, 0.5, 0, 0)
+ align.add(frame)
+ vbox.pack_start(align, False, False, 0)
- loader = gtk.gdk.PixbufLoader()
- loader.connect("area_prepared", on_area_prepared, image)
- loader.connect("area_updated", on_area_updated, image)
-
- gobject.timeout_add(150, on_timeout, loader, fileobject)
+ image = gtk.Image()
- return image
+ # use the current directory for the file
+ try:
+ pixbuf = gtk.gdk.pixbuf_new_from_file(GTKLOGO_IMAGE)
+ image.set_from_pixbuf(pixbuf)
-def get_image(filename):
- try:
- anim = gtk.gdk.PixbufAnimation(filename)
- except gobject.GError, e:
- error_dialog(str(e))
- return
+ except gobject.GError, error:
- image = gtk.Image()
+ # This code shows off error handling. You can just use
+ # gtk_image_new_from_file() instead if you don't want to report
+ # errors to the user. If the file doesn't load when using
+ # gtk_image_new_from_file(), a "missing image" icon will
+ # be displayed instead.
- if anim.is_static_image():
- image.set_from_pixbuf( anim.get_static_image() )
- else:
- image.set_from_animation( anim )
+ dialog = gtk.MessageDialog(self,
+ gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_ERROR,
+ gtk.BUTTONS_CLOSE,
+ "Unable to open image file 'gtk-logo-rgb.gif': \n%s" % error)
- return image
+ dialog.connect("response", lambda dlg, resp: dlg.destroy())
+ dialog.show()
-def align_image(image, label_text):
- label = gtk.Label()
- label.set_markup("<u>%s</u>" % label_text)
+ frame.add(image)
- frame = gtk.Frame()
- frame.set_shadow_type(gtk.SHADOW_IN)
+ # Animation
- if image:
- frame.add(image)
- else:
- frame.add(gtk.Label("(No image)"))
+ label = gtk.Label()
+ label.set_markup("<u>Animation loaded from a file</u>")
+ vbox.pack_start(label, False, False, 0)
- align = gtk.Alignment(0.5, 0.5, 0, 0)
- align.add(frame)
+ frame = gtk.Frame()
+ frame.set_shadow_type(gtk.SHADOW_IN)
- vbox = gtk.VBox(spacing=8)
- vbox.set_border_width(4)
- vbox.pack_start(label)
- vbox.pack_start(align)
+ # The alignment keeps the frame from growing when users resize
+ # the window
- return vbox
+ align = gtk.Alignment(0.5, 0.5, 0, 0)
+ align.add(frame)
+ vbox.pack_start(align, False, False, 0)
-def on_button_toggled(button, vbox):
- for widget in vbox.get_children():
- if widget != button:
- widget.set_sensitive(not button.get_active())
+ image = gtk.Image()
+ image.set_from_file(BUDDY_IMAGE);
+ frame.add(image)
-def main():
- vbox = gtk.VBox()
+ # Progressive
- button = gtk.ToggleButton("_Insensitive")
- button.connect("toggled", on_button_toggled, vbox)
+ label = gtk.Label()
+ label.set_markup("<u>Progressive image loading</u>")
+ vbox.pack_start(label, False, False, 0)
- i1 = get_image("gtk-logo-rgb.gif")
- i2 = get_image("floppybuddy.gif")
- i3 = get_progressive_image("alphatest.png")
+ frame = gtk.Frame()
+ frame.set_shadow_type(gtk.SHADOW_IN)
- vbox.pack_start(align_image(i1, "Image loaded from a file"))
- vbox.pack_start(align_image(i2, "Animation loaded from a file"))
- vbox.pack_start(align_image(i3, "Progressive image loading"))
- vbox.pack_start(button)
+ # The alignment keeps the frame from growing when users resize
+ # the window
- win = gtk.Window()
- win.set_title("Images")
- win.set_border_width(8)
- win.connect("destroy", gtk.main_quit)
- win.add(vbox)
- win.show_all()
+ align = gtk.Alignment(0.5, 0.5, 0, 0)
+ align.add(frame)
+ vbox.pack_start(align, False, False, 0)
- gtk.main()
+ # Create an empty image for now; the progressive loader
+ # will create the pixbuf and fill it in.
+
+ image = gtk.Image()
+ image.set_from_pixbuf(None)
+ frame.add(image)
+
+ self.start_progressive_loading(image)
+
+ # Sensitivity control
+
+ button = gtk.ToggleButton("_Insensitive");
+ vbox.pack_start(button, False, False, 0)
+
+ button.connect("toggled", self.on_sensitivity_toggled, vbox)
+
+ self.show_all()
+
+ def cleanup_callback(self, win):
+ if self.load_timeout != 0:
+ gtk.timeout_remove(self.load_timeout)
+ self.load_timeout = 0
+
+ if self.pixbuf_loader is not None:
+ self.pixbuf_loader.close()
+ self.pixbuf_loader = None
+
+ if self.image_stream is not None:
+ self.image_stream.close()
+ self.image_stream = None
+
+
+ def on_sensitivity_toggled(self, togglebutton, container):
+ children = container.get_children()
+
+ for child in children:
+
+ # don't disable our toggle
+ if type(child) != type(togglebutton):
+ child.set_sensitive(not togglebutton.get_active())
+
+ def start_progressive_loading(self, image):
+ ''' This is obviously totally contrived(we slow down loading
+ on purpose to show how incremental loading works).
+ The real purpose of incremental loading is the case where
+ you are reading data from a slow source such as the network.
+ The timeout simply simulates a slow data source by inserting
+ pauses in the reading process.
+ '''
+ self.load_timeout = gtk.timeout_add(150, self.progressive_timeout, image)
+
+ def progressive_timeout(self, image):
+
+ # This shows off fully-paranoid error handling, so looks scary.
+ # You could factor out the error handling code into a nice separate
+ # function to make things nicer.
+
+ if self.image_stream is not None: # file is already opened
+ try:
+ buf = self.image_stream.read(256)
+ bytes_read = len(buf)
+
+ except IOError, error:
+ dialog = gtk.MessageDialog(self,
+ gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_ERROR,
+ gtk.BUTTONS_CLOSE,
+ "Failure reading image file 'alphatest.png': %s" % error)
+
+ dialog.connect("response", lambda d, r: d.destroy())
+
+ self.image_stream.close()
+ self.image_stream = None
+
+ dialog.show()
- return 0
+ self.load_timeout = 0
+
+ return False; # uninstall the timeout
+
+ if not self.pixbuf_loader.write(buf, bytes_read):
+
+ dialog = gtk.MessageDialog(self,
+ gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_ERROR,
+ gtk.BUTTONS_CLOSE,
+ "Failed to load image")
+
+ dialog.connect("response", lambda d, r: d.destroy())
+
+ self.image_stream.close()
+ self.image_stream = None
+
+ dialog.show()
+
+ self.load_timeout = 0
+
+ return False # uninstall the timeout
+
+ #if(feof(image_stream)):
+ if bytes_read == 0:
+
+ self.image_stream.close()
+ self.image_stream = None
+
+ # Errors can happen on close, e.g. if the image
+ # file was truncated we'll know on close that
+ # it was incomplete.
+
+ if not self.pixbuf_loader.close():
+
+ dialog = gtk.MessageDialog(self,
+ gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_ERROR,
+ gtk.BUTTONS_CLOSE,
+ "Failed to load image")
+
+ dialog.connect("response", lambda d, r: dlg.destroy())
+ dialog.show()
+
+ self.pixbuf_loader = None
+
+ self.load_timeout = 0
+
+ return False # uninstall the timeout
+
+ # if feof(image_stream)
+ self.pixbuf_loader = None
+
+ else: # if(image_stream) ...
+ try:
+ self.image_stream = open(ALPHA_IMAGE, "rb")
+
+ except IOError, error:
+ error_message = "Unable to open image file 'alphatest.png' : %s"
+
+ dialog = gtk.MessageDialog(self,
+ gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_ERROR,
+ gtk.BUTTONS_CLOSE,
+ error_message % error)
+
+ dialog.connect("response", lambda d, r: d.destroy())
+ dialog.show()
+
+ self.load_timeout = 0
+
+ return False # uninstall the timeout
+
+ if self.pixbuf_loader is not None:
+ self.pixbuf_loader.close()
+ self.pixbuf_loader = None
+
+ self.pixbuf_loader = gtk.gdk.PixbufLoader()
+
+ self.pixbuf_loader.connect("area_prepared",
+ progressive_prepared_callback, image)
+
+ self.pixbuf_loader.connect("area_updated",
+ progressive_updated_callback, image)
+
+ # leave timeout installed
+ return True;
+
+def main():
+ ImagesDemo()
+ gtk.main()
-if __name__ == "__main__":
- sys.exit(main())
+if __name__ == '__main__':
+ main()
diff --git a/examples/pygtk-demo/alphatest.png b/examples/pygtk-demo/demos/images/alphatest.png
index eb5885f8..eb5885f8 100644
--- a/examples/pygtk-demo/alphatest.png
+++ b/examples/pygtk-demo/demos/images/alphatest.png
Binary files differ
diff --git a/examples/pygtk-demo/demos/images/apple-red.png b/examples/pygtk-demo/demos/images/apple-red.png
new file mode 100644
index 00000000..b0a24e94
--- /dev/null
+++ b/examples/pygtk-demo/demos/images/apple-red.png
Binary files differ
diff --git a/examples/pygtk-demo/demos/images/background.jpg b/examples/pygtk-demo/demos/images/background.jpg
new file mode 100644
index 00000000..86c006aa
--- /dev/null
+++ b/examples/pygtk-demo/demos/images/background.jpg
Binary files differ
diff --git a/examples/pygtk-demo/floppybuddy.gif b/examples/pygtk-demo/demos/images/floppybuddy.gif
index ac986c8e..ac986c8e 100644
--- a/examples/pygtk-demo/floppybuddy.gif
+++ b/examples/pygtk-demo/demos/images/floppybuddy.gif
Binary files differ
diff --git a/examples/pygtk-demo/demos/images/gnome-applets.png b/examples/pygtk-demo/demos/images/gnome-applets.png
new file mode 100644
index 00000000..8d3549e9
--- /dev/null
+++ b/examples/pygtk-demo/demos/images/gnome-applets.png
Binary files differ
diff --git a/examples/pygtk-demo/demos/images/gnome-calendar.png b/examples/pygtk-demo/demos/images/gnome-calendar.png
new file mode 100644
index 00000000..889f329a
--- /dev/null
+++ b/examples/pygtk-demo/demos/images/gnome-calendar.png
Binary files differ
diff --git a/examples/pygtk-demo/demos/images/gnome-foot.png b/examples/pygtk-demo/demos/images/gnome-foot.png
new file mode 100644
index 00000000..04766585
--- /dev/null
+++ b/examples/pygtk-demo/demos/images/gnome-foot.png
Binary files differ
diff --git a/examples/pygtk-demo/demos/images/gnome-gimp.png b/examples/pygtk-demo/demos/images/gnome-gimp.png
new file mode 100644
index 00000000..f6bbc6d3
--- /dev/null
+++ b/examples/pygtk-demo/demos/images/gnome-gimp.png
Binary files differ
diff --git a/examples/pygtk-demo/demos/images/gnome-gmush.png b/examples/pygtk-demo/demos/images/gnome-gmush.png
new file mode 100644
index 00000000..0a4b0d04
--- /dev/null
+++ b/examples/pygtk-demo/demos/images/gnome-gmush.png
Binary files differ
diff --git a/examples/pygtk-demo/demos/images/gnome-gsame.png b/examples/pygtk-demo/demos/images/gnome-gsame.png
new file mode 100644
index 00000000..01c06115
--- /dev/null
+++ b/examples/pygtk-demo/demos/images/gnome-gsame.png
Binary files differ
diff --git a/examples/pygtk-demo/demos/images/gnu-keys.png b/examples/pygtk-demo/demos/images/gnu-keys.png
new file mode 100644
index 00000000..58a33770
--- /dev/null
+++ b/examples/pygtk-demo/demos/images/gnu-keys.png
Binary files differ
diff --git a/examples/pygtk-demo/gtk-logo-rgb.gif b/examples/pygtk-demo/demos/images/gtk-logo-rgb.gif
index 63c622b9..63c622b9 100644
--- a/examples/pygtk-demo/gtk-logo-rgb.gif
+++ b/examples/pygtk-demo/demos/images/gtk-logo-rgb.gif
Binary files differ
diff --git a/examples/pygtk-demo/demos/itemfactory.py b/examples/pygtk-demo/demos/itemfactory.py
deleted file mode 100644
index cc049600..00000000
--- a/examples/pygtk-demo/demos/itemfactory.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python
-"""Item Factory
-
-The GtkItemFactory object allows the easy creation of menus
-from an array of descriptions of menu items."""
-
-description = 'Item Factory'
-
-import gtk
-
-def ifactory_cb(action, widget):
- print 'ItemFactory: activated "%s"' % (gtk.item_factory_path_from_widget(widget),)
-
-menu_items = (
- ('/_File', None, None, 0, '<Branch>' ),
- ('/File/tearoff1', None, ifactory_cb, 0, '<Tearoff>'),
- ('/File/_New', '<control>N', ifactory_cb, 0, ''),
- ('/File/_Open', '<control>O', ifactory_cb, 0, ''),
- ('/File/_Save', '<control>S', ifactory_cb, 0, ''),
- ('/File/Save _As...', None, ifactory_cb, 0, ''),
- ('/File/sep1', None, ifactory_cb, 0, '<Separator>'),
- ('/File/_Quit', '<control>Q', ifactory_cb, 0, ''),
-
- ('/_Preferences', None, None, 0, '<Branch>'),
- ('/_Preferences/_Color', None, None, 0, '<Branch>'),
- ('/_Preferences/Color/_Red', None, ifactory_cb, 0, '<RadioItem>'),
- ('/_Preferences/Color/_Green', None, ifactory_cb, 0, '/Preferences/Color/Red'),
- ('/_Preferences/Color/_Blue', None, ifactory_cb, 0, '/Preferences/Color/Red'),
- ('/_Preferences/_Shape', None, None, 0, '<Branch>'),
- ('/_Preferences/Shape/_Square', None, ifactory_cb, 0, '<RadioItem>'),
- ('/_Preferences/Shape/_Rectangle', None, ifactory_cb, 0, '/Preferences/Shape/Square'),
- ('/_Preferences/Shape/_Oval', None, ifactory_cb, 0, '/Preferences/Shape/Rectangle'),
-
- ('/_Help', None, None, 0, '<LastBranch>'),
- ('/Help/_About', None, ifactory_cb, 0, ''),
- )
-
-def main():
- win = gtk.Window()
- win.connect('destroy', lambda win: gtk.main_quit())
-
- win.set_title('Item Factory')
- win.set_border_width(10)
-
- box1 = gtk.VBox()
- win.add(box1)
- win.set_title('Item Factory')
- win.set_border_width(0)
-
- accelgroup = gtk.AccelGroup()
- win.add_accel_group(accelgroup)
-
- item_factory = gtk.ItemFactory(gtk.MenuBar, '<main>', accelgroup)
- item_factory.create_items(menu_items)
- # this is required so that the item factory doesn't get freed when
- # it goes out of scope.
- win.item_factory = item_factory
-
- menubar = item_factory.get_widget('<main>')
- box1.pack_start(menubar)
-
- label = gtk.Label('Type\n<F10>\nto start')
- label.set_size_request(200, 200);
- box1.pack_start(label)
-
- separator = gtk.HSeparator()
- box1.pack_start(separator)
-
- box2 = gtk.VBox(gtk.FALSE, 10)
- box2.set_border_width(10)
- box1.pack_start(box2)
-
- button = gtk.Button('close')
- button.connect('clicked', lambda button, win=win: win.destroy())
- box2.pack_start(button, gtk.TRUE, gtk.TRUE)
- button.set_flags(gtk.CAN_DEFAULT)
- button.grab_default()
-
- win.show_all()
- gtk.main()
-
-if __name__ == '__main__':
- main()
diff --git a/examples/pygtk-demo/demos/list_store.py b/examples/pygtk-demo/demos/list_store.py
index 8162433f..1d920bb3 100644
--- a/examples/pygtk-demo/demos/list_store.py
+++ b/examples/pygtk-demo/demos/list_store.py
@@ -1,130 +1,142 @@
#!/usr/bin/env python
'''Tree View/List Store
-The GtkListStore is used to store data in list form, to be used
+The GtkListStore is used to store data in list form, to be used
later on by a GtkTreeView to display it. This demo builds a
simple GtkListStore and displays it. See the Stock Browser
-demo for a more advanced example.''' # "
-
-description = 'List Store'
+demo for a more advanced example.'''
import gobject
import gtk
-from gtk import TRUE, FALSE
-COLUMN_FIXED = 0
-COLUMN_NUMBER = 1
-COLUMN_SEVERITY = 2
-COLUMN_DESCRIPTION = 3
+(
+ COLUMN_FIXED,
+ COLUMN_NUMBER,
+ COLUMN_SEVERITY,
+ COLUMN_DESCRIPTION
+) = range(4)
data = \
-[[FALSE, 60482, 'Normal', 'scrollable notebooks and hidden tabs'],
- [FALSE, 60620, 'Critical',
- 'gdk_window_clear_area (gdkwindow-win32.c) is not thread-safe'],
- [FALSE, 50214, 'Major', 'Xft support does not clean up correctly'],
- [TRUE, 52877, 'Major', 'GtkFileSelection needs a refresh method. '],
- [FALSE, 56070, 'Normal', "Can't click button after setting in sensitive"],
- [TRUE, 56355, 'Normal', 'GtkLabel - Not all changes propagate correctly'],
- [FALSE, 50055, 'Normal', 'Rework width/height computations for TreeView'],
- [FALSE, 58278, 'Normal', "gtk_dialog_set_response_sensitive () doesn't work"],
- [FALSE, 55767, 'Normal', 'Getters for all setters'],
- [FALSE, 56925, 'Normal', 'Gtkcalender size'],
- [FALSE, 56221, 'Normal', 'Selectable label needs right-click copy menu'],
- [TRUE, 50939, 'Normal', 'Add shift clicking to GtkTextView'],
- [FALSE, 6112, 'Enhancement', 'netscape-like collapsable toolbars'],
- [FALSE, 1, 'Normal', 'First bug :=)']]
-
-def create_model():
- store = gtk.ListStore(gobject.TYPE_BOOLEAN,
- gobject.TYPE_UINT,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING)
- for item in data:
- iter = store.append()
- store.set(iter, COLUMN_FIXED, item[0],
- COLUMN_NUMBER, item[1],
- COLUMN_SEVERITY, item[2],
- COLUMN_DESCRIPTION, item[3])
- return store
-
-def fixed_toggled(cell, path, model):
- # get toggled iter
- iter = model.get_iter((int(path),))
- fixed = model.get_value(iter, COLUMN_FIXED)
-
- # do something with the value
- fixed = not fixed
-
- # set new value
- model.set(iter, COLUMN_FIXED, fixed)
-
-def add_columns(treeview):
- model = treeview.get_model()
-
- # column for fixed toggles
- renderer = gtk.CellRendererToggle()
- renderer.connect('toggled', fixed_toggled, model)
-
- column = gtk.TreeViewColumn('Fixed?', renderer, active=COLUMN_FIXED)
- column.set_clickable(TRUE)
-
- # set this column to a fixed sizing(of 50 pixels)
- column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
- column.set_fixed_width(50)
- column.set_clickable(TRUE)
-
- treeview.append_column(column)
-
- # column for bug numbers
- column = gtk.TreeViewColumn('Bug Number', gtk.CellRendererText(),
- text=COLUMN_NUMBER)
- treeview.append_column(column)
-
- # columns for severities
- column = gtk.TreeViewColumn('Severity', gtk.CellRendererText(),
- text=COLUMN_SEVERITY)
- treeview.append_column(column)
-
- # column for description
- column = gtk.TreeViewColumn('Description', gtk.CellRendererText(),
- text=COLUMN_DESCRIPTION)
- treeview.append_column(column)
-
+((False, 60482, 'Normal', 'scrollable notebooks and hidden tabs'),
+ (False, 60620, 'Critical',
+ 'gdk_window_clear_area(gdkwindow-win32.c) is not thread-safe'),
+ (False, 50214, 'Major', 'Xft support does not clean up correctly'),
+ (True, 52877, 'Major', 'GtkFileSelection needs a refresh method. '),
+ (False, 56070, 'Normal', "Can't click button after setting in sensitive"),
+ (True, 56355, 'Normal', 'GtkLabel - Not all changes propagate correctly'),
+ (False, 50055, 'Normal', 'Rework width/height computations for TreeView'),
+ (False, 58278, 'Normal', "gtk_dialog_set_response_sensitive() doesn't work"),
+ (False, 55767, 'Normal', 'Getters for all setters'),
+ (False, 56925, 'Normal', 'Gtkcalender size'),
+ (False, 56221, 'Normal', 'Selectable label needs right-click copy menu'),
+ (True, 50939, 'Normal', 'Add shift clicking to GtkTextView'),
+ (False, 6112, 'Enhancement', 'netscape-like collapsable toolbars'),
+ (False, 1, 'Normal', 'First bug :=)'))
+
+class ListStoreDemo(gtk.Window):
+ def __init__(self, parent=None):
+ # create window, etc
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+ self.set_title(self.__class__.__name__)
+
+ self.set_border_width(8)
+ self.set_default_size(300, 250)
+
+ vbox = gtk.VBox(False, 8)
+ self.add(vbox)
+
+ label = gtk.Label('This is the bug list (note: not based on real data, '
+ 'it would be nice to have a nice ODBC interface to bugzilla or so, though).')
+ vbox.pack_start(label, False, False)
+
+ sw = gtk.ScrolledWindow()
+ sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
+ sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+ vbox.pack_start(sw)
+
+ # create tree model
+ model = self.__create_model()
+
+ # create tree view
+ treeview = gtk.TreeView(model)
+ treeview.set_rules_hint(True)
+ treeview.set_search_column(COLUMN_DESCRIPTION)
+
+ sw.add(treeview)
+
+ # add columns to the tree view
+ self.__add_columns(treeview)
+
+ self.show_all()
+
+ def __create_model(self):
+ lstore = gtk.ListStore(
+ gobject.TYPE_BOOLEAN,
+ gobject.TYPE_UINT,
+ gobject.TYPE_STRING,
+ gobject.TYPE_STRING)
+
+ for item in data:
+ iter = lstore.append()
+ lstore.set(iter,
+ COLUMN_FIXED, item[COLUMN_FIXED],
+ COLUMN_NUMBER, item[COLUMN_NUMBER],
+ COLUMN_SEVERITY, item[COLUMN_SEVERITY],
+ COLUMN_DESCRIPTION, item[COLUMN_DESCRIPTION])
+ return lstore
+
+ def fixed_toggled(self, cell, path, model):
+ # get toggled iter
+ iter = model.get_iter((int(path),))
+ fixed = model.get_value(iter, COLUMN_FIXED)
+
+ # do something with the value
+ fixed = not fixed
+
+ # set new value
+ model.set(iter, COLUMN_FIXED, fixed)
+
+ def __add_columns(self, treeview):
+ model = treeview.get_model()
+
+ # column for fixed toggles
+ renderer = gtk.CellRendererToggle()
+ renderer.connect('toggled', self.fixed_toggled, model)
+
+ column = gtk.TreeViewColumn('Fixed?', renderer, active=COLUMN_FIXED)
+
+ # set this column to a fixed sizing(of 50 pixels)
+ column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+ column.set_fixed_width(50)
+
+ treeview.append_column(column)
+
+ # column for bug numbers
+ column = gtk.TreeViewColumn('Bug Number', gtk.CellRendererText(),
+ text=COLUMN_NUMBER)
+ column.set_sort_column_id(COLUMN_NUMBER)
+ treeview.append_column(column)
+
+ # columns for severities
+ column = gtk.TreeViewColumn('Severity', gtk.CellRendererText(),
+ text=COLUMN_SEVERITY)
+ column.set_sort_column_id(COLUMN_SEVERITY)
+ treeview.append_column(column)
+
+ # column for description
+ column = gtk.TreeViewColumn('Description', gtk.CellRendererText(),
+ text=COLUMN_DESCRIPTION)
+ column.set_sort_column_id(COLUMN_DESCRIPTION)
+ treeview.append_column(column)
+
def main():
- win = gtk.Window()
- win.connect('destroy', lambda win: gtk.main_quit())
-
- win.set_title('GtkListStore demo')
- win.set_border_width(8)
-
- vbox = gtk.VBox(FALSE, 8)
- win.add(vbox)
-
- label = gtk.Label('This is the bug list (note: not based on real data, '+\
- 'it would be nice to have a nice ODBC interface to bugzilla or so, though).')
- vbox.pack_start(label, FALSE, FALSE)
-
- sw = gtk.ScrolledWindow()
- sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
- sw.set_policy(gtk.POLICY_NEVER,
- gtk.POLICY_AUTOMATIC)
- vbox.pack_start(sw)
-
- model = create_model()
-
- treeview = gtk.TreeView(model)
- treeview.set_rules_hint(TRUE)
- treeview.set_search_column(COLUMN_DESCRIPTION)
-
- sw.add(treeview)
-
- add_columns(treeview)
-
- win.set_default_size(280, 250)
-
- win.show_all()
+ ListStoreDemo()
gtk.main()
-
+
if __name__ == '__main__':
main()
-
+
diff --git a/examples/pygtk-demo/demos/menu.py b/examples/pygtk-demo/demos/menu.py
index cc99e00e..3a61a427 100644
--- a/examples/pygtk-demo/demos/menu.py
+++ b/examples/pygtk-demo/demos/menu.py
@@ -1,76 +1,88 @@
#!/usr/bin/env python
-'''Menus Test
+'''Menu
This example demonstrates the use of various menu types in gtk. It
demonstrates the new submenu navigation and scrolling menu features of
gtk 2.0.'''
-description = 'Menus'
-
import gtk
def create_menu(depth, length=5):
if depth < 1:
- return None
+ return None
+
menu = gtk.Menu()
group= None
+
for i in range(length):
- menuitem = gtk.RadioMenuItem(group, 'item %2d - %d' % (depth, i))
- group = menuitem
- menu.add(menuitem)
- menuitem.show()
- if depth > 1:
- submenu = create_menu(depth - 1)
- menuitem.set_submenu(submenu)
+ menuitem = gtk.RadioMenuItem(group, 'item %2d - %d' % (depth, i))
+ group = menuitem
+ menu.add(menuitem)
+ menuitem.show()
+ if depth > 1:
+ submenu = create_menu(depth - 1)
+ menuitem.set_submenu(submenu)
return menu
+class MenuDemo(gtk.Window):
+ def __init__(self, parent=None):
+ # Create the toplevel window
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+
+ self.set_title(self.__class__.__name__)
+
+ vbox = gtk.VBox()
+ self.add(vbox)
+
+ menubar = gtk.MenuBar()
+ vbox.pack_start(menubar, expand=False)
+
+ menuitem = gtk.MenuItem('test\nline2')
+ menuitem.set_submenu(create_menu(2, 50))
+ menubar.add(menuitem)
+
+ menuitem = gtk.MenuItem('foo')
+ menuitem.set_submenu(create_menu(2))
+ menubar.add(menuitem)
+
+ menuitem = gtk.MenuItem('bar')
+ menuitem.set_submenu(create_menu(2))
+ menuitem.set_right_justified(True)
+ menubar.add(menuitem)
+
+ vbox2 = gtk.VBox(spacing=10)
+ vbox2.set_border_width(10)
+ vbox.pack_start(vbox2)
+
+ combo_box = gtk.combo_box_new_text()
+ combo_box.set_wrap_width(2)
+ for i in range(50):
+ combo_box.append_text('item - %d' % i)
+ combo_box.set_active(0)
+ vbox2.pack_start(combo_box)
+
+ separator = gtk.HSeparator()
+ vbox.pack_start(separator, expand=False)
+
+ vbox2 = gtk.VBox(spacing=10)
+ vbox2.set_border_width(10)
+ vbox.pack_start(vbox2, expand=False)
+
+ button = gtk.Button('close')
+ button.connect('clicked', lambda button, w=self: w.destroy())
+ vbox2.pack_start(button)
+ button.set_flags(gtk.CAN_DEFAULT)
+ button.grab_default()
+
+ self.show_all()
+
def main():
- window = gtk.Window()
- window.connect('destroy', lambda win: gtk.main_quit())
- window.set_title('Menus')
-
- vbox = gtk.VBox()
- window.add(vbox)
-
- menubar = gtk.MenuBar()
- vbox.pack_start(menubar, expand=gtk.FALSE)
-
- menuitem = gtk.MenuItem('test\nline2')
- menuitem.set_submenu(create_menu(2, 50))
- menubar.add(menuitem)
-
- menuitem = gtk.MenuItem('foo')
- menuitem.set_submenu(create_menu(2))
- menubar.add(menuitem)
-
- menuitem = gtk.MenuItem('bar')
- menuitem.set_submenu(create_menu(2))
- menuitem.set_right_justified(gtk.TRUE)
- menubar.add(menuitem)
-
- vbox2 = gtk.VBox(spacing=10)
- vbox2.set_border_width(10)
- vbox.pack_start(vbox2)
-
- optionmenu = gtk.OptionMenu()
- optionmenu.set_menu(create_menu(1,50))
- vbox2.pack_start(optionmenu)
-
- separator = gtk.HSeparator()
- vbox.pack_start(separator, expand=gtk.FALSE)
-
- vbox2 = gtk.VBox(spacing=10)
- vbox2.set_border_width(10)
- vbox.pack_start(vbox2, expand=gtk.FALSE)
-
- button = gtk.Button('close')
- button.connect('clicked', lambda widget, window=window: window.destroy())
- vbox2.pack_start(button)
- button.set_flags(gtk.CAN_DEFAULT)
- button.grab_default()
-
- window.show_all()
+ MenuDemo()
gtk.main()
-
+
if __name__ == '__main__':
main()
diff --git a/examples/pygtk-demo/demos/panes.py b/examples/pygtk-demo/demos/panes.py
index 1553ab4e..007ec077 100644
--- a/examples/pygtk-demo/demos/panes.py
+++ b/examples/pygtk-demo/demos/panes.py
@@ -5,111 +5,119 @@ The GtkHPaned and GtkVPaned Widgets divide their content area into two panes
with a divider in between that the user can adjust. A separate child is placed
into each pane.
There are a number of options that can be set for each pane. This test contains
-both a horizontal (HPaned) and a vertical (VPaned) widget, and allows you to
+both a horizontal(HPaned) and a vertical(VPaned) widget, and allows you to
adjust the options for each side of each widget."""
-description = "Paned Widgets"
-
import gtk
-def toggle_resize(w, child):
- paned = child.parent
-
- if child == paned.get_children()[0]:
- paned.remove(child)
- paned.pack1(child, w.get_active(), 0)
- else:
- paned.remove(child)
- paned.pack2(child, w.get_active(), 0)
-
-def toggle_shrink(w, child):
- paned = child.parent
-
- if child == paned.get_children()[0]:
- paned.remove(child)
- paned.pack1(child, 0, w.get_active())
- else:
- paned.remove(child)
- paned.pack2(child, 0, w.get_active())
-
-def create_pane_options(paned, frame_label, label1, label2):
- frame = gtk.Frame(frame_label)
- frame.set_border_width(4)
-
- table = gtk.Table(3, 2, gtk.TRUE)
- frame.add(table)
-
- label = gtk.Label(label1)
- table.attach_defaults(label, 0, 1, 0, 1)
-
- check_button = gtk.CheckButton("_Resize")
- check_button.connect('toggled', toggle_resize, paned.get_children()[0])
- table.attach_defaults(check_button, 0, 1, 1, 2)
-
- check_button = gtk.CheckButton("_Shrink")
- check_button.set_active(gtk.TRUE)
- check_button.connect('toggled', toggle_shrink, paned.get_children()[0])
- table.attach_defaults(check_button, 0, 1, 2, 3)
-
- label = gtk.Label(label2)
- table.attach_defaults(label, 1, 2, 0, 1)
-
- check_button = gtk.CheckButton("_Resize")
- check_button.set_active(gtk.TRUE)
- check_button.connect('toggled', toggle_resize, paned.get_children()[1])
- table.attach_defaults(check_button, 1, 2, 1, 2)
-
- check_button = gtk.CheckButton("_Shrink")
- check_button.set_active(gtk.TRUE)
- check_button.connect('toggled', toggle_shrink, paned.get_children()[1])
- table.attach_defaults(check_button, 1, 2, 2, 3)
-
- return frame
+class PanedWidgetsDemo(gtk.Window):
+ def __init__(self, parent=None):
+ # Create the toplevel window
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+
+ self.set_title(self.__class__.__name__)
+ self.set_border_width(0)
+
+ vbox = gtk.VBox(False, 0)
+ self.add(vbox)
+
+ vpaned = gtk.VPaned()
+ vbox.pack_start(vpaned, True, True)
+ vpaned.set_border_width(5)
+
+ hpaned = gtk.HPaned()
+ vpaned.add1(hpaned)
+
+ frame = gtk.Frame()
+ frame.set_shadow_type(gtk.SHADOW_IN)
+ frame.set_size_request(60, 60)
+ hpaned.add1(frame)
+
+ button = gtk.Button("_Hi there")
+ frame.add(button)
+
+ frame = gtk.Frame()
+ frame.set_shadow_type(gtk.SHADOW_IN)
+ frame.set_size_request(80, 60)
+ hpaned.add2(frame)
+
+ frame = gtk.Frame()
+ frame.set_shadow_type(gtk.SHADOW_IN)
+ frame.set_size_request(60, 80)
+ vpaned.add2(frame)
+
+ # Now create toggle buttons to control sizing
+
+ vbox.pack_start(
+ self.__create_pane_options(hpaned, "Horizontal", "Left", "Right"),
+ False, False, 0)
+
+ vbox.pack_start(
+ self.__create_pane_options(vpaned, "Vertical", "Top", "Bottom"),
+ False, False, 0)
+
+ self.show_all()
+
+ def on_resize_toggled(self, tbutton, child):
+ paned = child.parent
+
+ if child == paned.get_children()[0]:
+ paned.remove(child)
+ paned.pack1(child, tbutton.get_active(), 0)
+ else:
+ paned.remove(child)
+ paned.pack2(child, tbutton.get_active(), 0)
+
+ def on_shrink_toggled(self, tbutton, child):
+ paned = child.parent
+
+ if child == paned.get_children()[0]:
+ paned.remove(child)
+ paned.pack1(child, 0, tbutton.get_active())
+ else:
+ paned.remove(child)
+ paned.pack2(child, 0, tbutton.get_active())
+
+ def __create_pane_options(self, paned, frame_label, label1, label2):
+ frame = gtk.Frame(frame_label)
+ frame.set_border_width(4)
+
+ table = gtk.Table(3, 2, True)
+ frame.add(table)
+
+ label = gtk.Label(label1)
+ table.attach(label, 0, 1, 0, 1)
+
+ check_button = gtk.CheckButton("_Resize")
+ check_button.connect('toggled', self.on_resize_toggled, paned.get_children()[0])
+ table.attach(check_button, 0, 1, 1, 2)
+
+ check_button = gtk.CheckButton("_Shrink")
+ check_button.set_active(True)
+ check_button.connect('toggled', self.on_shrink_toggled, paned.get_children()[0])
+ table.attach(check_button, 0, 1, 2, 3)
+
+ label = gtk.Label(label2)
+ table.attach(label, 1, 2, 0, 1)
+
+ check_button = gtk.CheckButton("_Resize")
+ check_button.set_active(True)
+ check_button.connect('toggled', self.on_resize_toggled, paned.get_children()[1])
+ table.attach(check_button, 1, 2, 1, 2)
+
+ check_button = gtk.CheckButton("_Shrink")
+ check_button.set_active(True)
+ check_button.connect('toggled', self.on_shrink_toggled, paned.get_children()[1])
+ table.attach(check_button, 1, 2, 2, 3)
+
+ return frame
def main():
- window = gtk.Window()
- window.set_title("Paned Widgets")
- window.set_border_width(0)
- window.connect('destroy', lambda win: gtk.main_quit())
-
- vbox = gtk.VBox(gtk.FALSE, 0)
- window.add(vbox)
-
- vpaned = gtk.VPaned()
- vbox.pack_start(vpaned, gtk.TRUE, gtk.TRUE)
- vpaned.set_border_width(5)
-
- hpaned = gtk.HPaned()
- vpaned.add1(hpaned)
-
- frame = gtk.Frame()
- frame.set_shadow_type(gtk.SHADOW_IN)
- frame.set_size_request(60, 60)
- hpaned.add1(frame)
-
- button = gtk.Button("_Hi there")
- frame.add(button)
-
- frame = gtk.Frame()
- frame.set_shadow_type(gtk.SHADOW_IN)
- frame.set_size_request(80, 60)
- hpaned.add2(frame)
-
- frame = gtk.Frame()
- frame.set_shadow_type(gtk.SHADOW_IN)
- frame.set_size_request(60, 80)
- vpaned.add2(frame)
-
- # Now create toggle buttons to control sizing
-
- vbox.pack_start(create_pane_options(hpaned, "Horizontal", "Left", "Right"),
- gtk.FALSE, gtk.FALSE, 0)
-
- vbox.pack_start(create_pane_options(vpaned, "Vertical", "Top", "Bottom"),
- gtk.FALSE, gtk.FALSE, 0)
-
- window.show_all()
-
+ PanedWidgetsDemo()
gtk.main()
if __name__ == '__main__':
diff --git a/examples/pygtk-demo/demos/pixbufs.py b/examples/pygtk-demo/demos/pixbufs.py
new file mode 100644
index 00000000..538a0209
--- /dev/null
+++ b/examples/pygtk-demo/demos/pixbufs.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python
+'''Pixbufs
+
+A GdkPixbuf represents an image, normally in RGB or RGBA format.
+Pixbufs are normally used to load files from disk and perform image scaling.
+This demo is not all that educational, but looks cool. It was written by
+Extreme Pixbuf Hacker Federico Mena Quintero. It also shows off how to use
+GtkDrawingArea to do a simple animation.
+Look at the Image demo for additional pixbuf usage examples.'''
+# pygtk version: Maik Hertha <maik.hertha@berlin.de>
+
+import os
+import math
+import gobject
+import gtk
+
+FRAME_DELAY = 50
+CYCLE_LEN = 60
+IMAGE_DIR = os.path.join(os.path.dirname(__file__), 'images')
+BACKGROUND_NAME = "background.jpg"
+
+image_names = [
+ "apple-red.png",
+ "gnome-applets.png",
+ "gnome-calendar.png",
+ "gnome-foot.png",
+ "gnome-gmush.png",
+ "gnome-gimp.png",
+ "gnome-gsame.png",
+ "gnu-keys.png"
+]
+
+class PixbufsDemo(gtk.Window):
+ frame = None # frame of the background image
+ background = None # background-pixbuf
+ images = [] # list of pixbufs
+ back_width = 0 # width of background image
+ back_height = 0 # height of background image
+ timeout_id = 0 # timeout id
+ frame_num = 0 # number of the current frame
+ timeout_id = None
+
+ def __init__(self, parent=None):
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect("destroy", lambda *w: gtk.main_quit())
+ self.connect("destroy", self.cleanup_callback)
+ self.set_title(self.__class__.__name__)
+ self.set_resizable(False)
+
+ if not self.load_pixbufs():
+ dialog = gtk.MessageDialog(self,
+ gtk.DIALOG_DESTROY_WITH_PARENT,
+ gtk.MESSAGE_ERROR,
+ gtk.BUTTONS_CLOSE,
+ "Failed to load an image")
+ dialog.connect("response", lambda d, r: dlg.destroy())
+ dialog.show()
+
+ else:
+ self.set_size_request(self.back_width, self.back_height)
+
+ self.frame = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8,
+ self.back_width, self.back_height)
+
+ da = gtk.DrawingArea()
+ da.connect("expose_event", self.expose_cb)
+ self.add(da)
+
+ self.timeout_id = gtk.timeout_add(FRAME_DELAY, self.timeout)
+
+ self.show_all()
+
+ def load_pixbufs(self):
+ ''' Loads the images for the demo and returns whether the
+ operation succeeded.
+ '''
+ if self.background is not None:
+ return True # already loaded earlier
+
+ # look in the the current directory where the file is installed
+ try:
+ self.background = gtk.gdk.pixbuf_new_from_file(
+ os.path.join(IMAGE_DIR, BACKGROUND_NAME))
+ except gobject.GError, error:
+ return False
+
+ self.back_width = self.background.get_width()
+ self.back_height = self.background.get_height()
+
+ for filename in image_names:
+ try:
+ self.images.append(gtk.gdk.pixbuf_new_from_file(
+ os.path.join(IMAGE_DIR, filename)))
+ except gobject.GError, error:
+ return False
+
+ return True
+
+ def expose_cb(self, draw_area, event):
+ ''' Expose callback for the drawing area. '''
+ rowstride = self.frame.get_rowstride()
+
+ # FIXME: what should be the result, string guchar an integer result?
+ #pixels = frame.get_pixels() + rowstride * event.area.y + event.area.x * 3
+ #pixels = frame.get_pixels()[len(frame.get_pixels()) + rowstride * event.area.y + event.area.x * 3]
+ pixels = self.frame.get_pixels()
+
+ # FIXME: draw_rgb_image_dithalign seems not to be available
+ #draw_area.window.draw_rgb_image_dithalign(widget.style.black_gc,
+ draw_area.window.draw_rgb_image(
+ draw_area.style.black_gc,
+ event.area.x, event.area.y,
+ event.area.width, event.area.height,
+ 'normal',
+ pixels, rowstride,
+ event.area.x, event.area.y)
+
+ return True
+
+ def cleanup_callback(self, win):
+ if self.timeout_id is not None:
+ gtk.timeout_remove(self.timeout_id)
+ self.timeout_id = None
+
+ def timeout(self):
+ ''' Timeout handler to regenerate the frame. '''
+ self.background.copy_area(0, 0, self.back_width, self.back_height,
+ self.frame, 0, 0)
+
+ f = float(self.frame_num % CYCLE_LEN) / float(CYCLE_LEN)
+
+ xmid = self.back_width / 2.0
+ ymid = self.back_height / 2.0
+
+ radius = min(xmid, ymid) / 2.0
+
+ N_IMAGES = len(image_names)
+ for i_name in image_names:
+ i = image_names.index(i_name)
+
+ ang = 2.0 * math.pi * i / N_IMAGES - f * 2.0 * math.pi
+
+ iw = self.images[i].get_width()
+ ih = self.images[i].get_height()
+
+ r = radius +(radius / 3.0) * math.sin(f * 2.0 * math.pi)
+
+ xpos = math.floor(xmid + r * math.cos(ang) - iw / 2.0 + 0.5)
+ ypos = math.floor(ymid + r * math.sin(ang) - ih / 2.0 + 0.5)
+
+ k = (i & 1) and math.sin(f * 2.0 * math.pi) or math.cos(f * 2.0 * math.pi)
+ k = 2.0 * k * k
+ k = max(0.25, k)
+
+ # satisfy the c-source
+ r1 = gtk.gdk.Rectangle()
+ r1.x = int(xpos)
+ r1.y = int(ypos)
+ r1.width = iw * k
+ r1.height = ih * k
+
+ r2 = gtk.gdk.Rectangle()
+ r2.x = 0
+ r2.y = 0
+ r2.width = self.back_width
+ r2.height = self.back_height
+
+ dest = r1.intersect(r2)
+ if dest is not None:
+ self.images[i].composite(
+ self.frame,
+ dest.x, dest.y,
+ dest.width, dest.height,
+ xpos, ypos,
+ k, k,
+ gtk.gdk.INTERP_NEAREST,
+ ((i & 1)
+ and int(max(127, math.fabs(255 * math.sin(f * 2.0 * math.pi))))
+ or int(max(127, math.fabs(255 * math.cos(f * 2.0 * math.pi))))))
+
+ if self is not None:
+ self.queue_draw()
+
+ self.frame_num += 1
+ return True
+
+def main():
+ PixbufsDemo()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
diff --git a/examples/pygtk-demo/demos/sizegroup.py b/examples/pygtk-demo/demos/sizegroup.py
index d4a99c54..a780390e 100644
--- a/examples/pygtk-demo/demos/sizegroup.py
+++ b/examples/pygtk-demo/demos/sizegroup.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-"""Size Groups
+"""Size Group
GtkSizeGroup provides a mechanism for grouping a number of widgets together so
they all request the same amount of space. This is typically useful when you
@@ -12,96 +12,96 @@ actually be the same size, you need to pack them in such a way that they get
the size they request and not more. For example, if you are packing your
widgets into a table, you would not include the GTK_FILL flag."""
-description = "Size Groups"
-
import gtk
-def create_option_menu(options):
- menu = gtk.Menu()
- for str in options:
- menu_item = gtk.MenuItem(str)
- menu_item.show()
- gtk.MenuShell.append(menu, menu_item)
-
- option_menu = gtk.OptionMenu()
- option_menu.set_menu(menu)
-
- return option_menu
-
-def add_row(table, row, size_group, label_text, options):
- label = gtk.Label(label_text)
- label.set_use_underline(gtk.TRUE)
- label.set_alignment(0, 1)
- table.attach(label, 0, 1, row, row + 1, gtk.EXPAND + gtk.FILL, 0, 0, 0)
-
- option_menu = create_option_menu(options)
- label.set_mnemonic_widget(option_menu)
- size_group.add_widget(option_menu)
- table.attach(option_menu, 1, 2, row, row + 1, 0, 0, 0, 0)
-
-def toggle_grouping(check_button, size_group):
- # gtk.SIZE_GROUP_NONE is not generally useful, but is useful
- # here to show the effect of gtk.SIZE_GROUP_HORIZONTAL by
- # contrast.
- if check_button.get_active():
- size_group.set_mode(gtk.SIZE_GROUP_HORIZONTAL)
- else:
- size_group.set_mode(gtk.SIZE_GROUP_NONE)
+class SizeGroupDemo(gtk.Dialog):
+ def __init__(self, parent=None):
+ gtk.Dialog.__init__(self, "Size Groups", parent,
+ 0,
+ (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+ self.connect('response', lambda d, r: d.destroy())
+ self.set_resizable(False)
+
+ vbox = gtk.VBox(False, 5)
+ self.vbox.pack_start(vbox, True, True, 0)
+ vbox.set_border_width(5)
+
+ self.size_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
+
+ # Create one frame holding color options
+ frame = gtk.Frame("Color options")
+ vbox.pack_start(frame, True, True, 0)
+
+ table = gtk.Table(2, 2, False)
+ table.set_border_width(5)
+ table.set_row_spacings(5)
+ table.set_col_spacings(10)
+ frame.add(table)
+
+ color_options = ("Red", "Green", "Blue")
+ self.__add_row(table, 0, "_Foreground", color_options)
+ self.__add_row(table, 1, "_Background", color_options)
+
+ # And another frame holding line style options
+ frame = gtk.Frame("Line options")
+ vbox.pack_start(frame, False, False, 0)
+
+ table = gtk.Table(2, 2, False)
+ table.set_border_width(5)
+ table.set_row_spacings(5)
+ table.set_col_spacings(10)
+ frame.add(table)
+
+ dash_options = ("Solid", "Dashed", "Dotted")
+ end_options = ("Square", "Round", "Arrow")
+ self.__add_row(table, 0, "_Dashing", dash_options)
+ self.__add_row(table, 1, "_Line ends", end_options)
+
+ # And a check button to turn grouping on and off
+
+ check_button = gtk.CheckButton("_Enable grouping")
+ vbox.pack_start(check_button, False, False, 0)
+ check_button.set_active(True)
+ check_button.connect('toggled', self.on_toggle_grouping)
+
+ self.show_all()
+
+ def __create_option_menu(self, options):
+
+ option_menu = gtk.combo_box_new_text()
+ for opt in options:
+ option_menu.append_text(opt)
+
+ option_menu.set_active(0)
+ return option_menu
+
+ def __add_row(self, table, row, label_text, options):
+ label = gtk.Label(label_text)
+ label.set_use_underline(True)
+ label.set_alignment(0, 1)
+ table.attach(label, 0, 1, row, row + 1, gtk.EXPAND | gtk.FILL, 0, 0, 0)
+
+ option_menu = self.__create_option_menu(options)
+ label.set_mnemonic_widget(option_menu)
+ self.size_group.add_widget(option_menu)
+ table.attach(option_menu, 1, 2, row, row + 1, 0, 0, 0, 0)
+
+ def on_toggle_grouping(self, check_button):
+
+ # gtk.SIZE_GROUP_NONE is not generally useful, but is useful
+ # here to show the effect of gtk.SIZE_GROUP_HORIZONTAL by
+ # contrast.
+ if check_button.get_active():
+ self.size_group.set_mode(gtk.SIZE_GROUP_HORIZONTAL)
+ else:
+ self.size_group.set_mode(gtk.SIZE_GROUP_NONE)
def main():
- color_options = ["Red", "Green", "Blue"]
- dash_options = ["Solid", "Dashed", "Dotted"]
- end_options = ["Square", "Round", "Arrow"]
-
- window = gtk.Dialog("GtkSizeGroups", None, 0,
- (gtk.STOCK_CLOSE, gtk.RESPONSE_NONE))
- window.set_resizable(gtk.FALSE)
- window.connect('response', lambda w, d: window.destroy())
- window.connect('destroy', lambda win: gtk.main_quit())
-
- vbox = gtk.VBox(gtk.FALSE, 5)
- window.vbox.pack_start(vbox, gtk.TRUE, gtk.TRUE, 0)
- vbox.set_border_width(5)
-
- size_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
-
- # Create one frame holding color options
-
- frame = gtk.Frame("Color options")
- vbox.pack_start(frame, gtk.TRUE, gtk.TRUE, 0)
-
- table = gtk.Table(2, 2, gtk.FALSE)
- table.set_border_width(5)
- table.set_row_spacings(5)
- table.set_col_spacings(10)
- frame.add(table)
-
- add_row(table, 0, size_group, "_Foreground", color_options)
- add_row(table, 1, size_group, "_Background", color_options)
-
- # And another frame holding line style options
-
- frame = gtk.Frame("Line options")
- vbox.pack_start(frame, gtk.FALSE, gtk.FALSE, 0)
-
- table = gtk.Table(2, 2, gtk.FALSE)
- table.set_border_width(5)
- table.set_row_spacings(5)
- table.set_col_spacings(10)
- frame.add(table)
-
- add_row(table, 0, size_group, "_Dashing", dash_options)
- add_row(table, 1, size_group, "_Line ends", end_options)
-
- # And a check button to turn grouping on and off
-
- check_button = gtk.CheckButton("_Enable grouping")
- vbox.pack_start(check_button, gtk.FALSE, gtk.FALSE, 0)
- check_button.set_active(gtk.TRUE)
- check_button.connect('toggled', toggle_grouping, size_group)
-
- window.show_all()
-
+ SizeGroupDemo()
gtk.main()
if __name__ == '__main__':
diff --git a/examples/pygtk-demo/demos/stock_browser.py b/examples/pygtk-demo/demos/stock_browser.py
index 179125cf..1689230f 100644
--- a/examples/pygtk-demo/demos/stock_browser.py
+++ b/examples/pygtk-demo/demos/stock_browser.py
@@ -1,218 +1,270 @@
-"""Stock Item and Icon Browser
+#!/usr/bin/env python
+'''Stock Item and Icon Browser
-This source code for this demo doesn't demonstrate anything
-particularly useful in applications. The purpose of the "demo" is
- just to provide a handy place to browse the available stock icons
- and stock items."""
-
-description = "Stock Browser"
+This source code for this demo doesn't demonstrate anything particularly
+useful in applications. The purpose of the "demo" is just to provide a
+handy place to browse the available stock icons and stock items.
+'''
+# pygtk version: Maik Hertha <maik.hertha@berlin.de>
import gobject
import gtk
+import re
-window = None
-
-class StockItemInfo(gobject.GObject):
- id = ''
- item = None
- small_icon = None
- macro = ''
- accel_str = ''
-gobject.type_register(StockItemInfo)
-
-class StockItemDisplay:
- pass
-
-def id_to_macro(str):
- if str.startswith('gtk-'):
- str = str.replace('gtk-', 'gtk-stock-')
- str = str.upper()
- return str.replace('-', '_')
-
-def create_model():
- store = gtk.ListStore(StockItemInfo)
-
- ids = gtk.stock_list_ids()
- ids.sort()
-
- for id in ids:
- info = StockItemInfo()
- info.id = id
- item = gtk.stock_lookup(info.id)
- if item:
- info.item = item
- else:
- info.item = [None, None, 0, 0, None]
-
- icon_set = gtk.icon_factory_lookup_default(info.id)
- if icon_set:
- sizes = icon_set.get_sizes()
- if gtk.ICON_SIZE_MENU in sizes:
- size = gtk.ICON_SIZE_MENU
- else:
- size = sizes[0]
-
- info.small_icon = window.render_icon(info.id,
- size)
- if size != gtk.ICON_SIZE_MENU:
- #w, h = gtk.icon_size_lookup(gtk.ICON_SIZE_MENU)
- raise NotImplementedError
-
- if info.item[2]:
- info.accel_str = gtk.accelerator_name(info.item[3],
- info.item[2])
-
- info.macro = id_to_macro(info.id)
-
- iter = store.append()
- store.set(iter, 0, info)
-
- return store
-
-def get_largest_size(id):
- set = gtk.icon_factory_lookup_default(id)
+def id_to_macro(stock_id):
+ if stock_id == '':
+ return ''
+ if stock_id.startswith('gtk'):
+ # gtk-foo-bar -> gtk.STOCK_FOO_BAR
+ macro = 'gtk.STOCK' + \
+ re.sub('-([^-]+)', lambda m:('_' + m.group(1).upper()), stock_id[3:])
+
+ else:
+ # demo-gtk-logo -> DEMO_GTK_LOGO as with custom icon-factories
+ macro = re.sub('([^-]+)-?', lambda m:('_' + m.group(1).upper()), stock_id)
+ macro = macro[1:] # there is a leading '_' always
+
+ return macro
+
+
+class StockItemInfo(object):
+ def __init__(self, stock_id=''):
+ self.stock_id = stock_id
+ self.stock_item = None
+ self.small_icon = None
+ self.macro = id_to_macro(stock_id)
+ self.accel_str = ''
+
+class StockItemDisplay(object):
+ def __init__(self):
+ self.type_label = None
+ self.macro_label = None
+ self.id_label = None
+ self.label_accel_label = None
+ self.icon_image = None
+
+
+def get_largest_size(stockid):
+ ''' Finds the largest size at which the given image stock id is
+ available. This would not be useful for a normal application.
+ '''
+ set = gtk.icon_factory_lookup_default(stockid)
best_size = gtk.ICON_SIZE_INVALID
best_pixels = 0
-
- for size in set.get_sizes():
- width, height = gtk.icon_size_lookup(size)
- if width * height > best_pixels:
- best_size = size
- best_pixels = width * height
- return best_size
+ sizes = set.get_sizes()
+ n_sizes = len(sizes)
-def selection_changed(selection):
- treeview = selection.get_tree_view()
- display = treeview.get_data('stock-display')
- value = selection.get_selected()
- if value:
- model, iter = value
- info = model.get_value(iter, 0)
-
- if info.small_icon and info.item[1]:
- display.type_label.set_text('Icon and Item')
- elif info.small_icon:
- display.type_label.set_text('Icon only')
- elif info.item[1]:
- display.type_label.set_text('Item only')
- else:
- display.type_label.set_text('???????')
+ i = 0
+ while(i < n_sizes):
+ width, height = gtk.icon_size_lookup(sizes[i])
- display.macro_label.set_text(info.macro)
- display.id_label.set_text(info.id)
+ if(width * height > best_pixels):
+ best_size = sizes[i]
+ best_pixels = width * height
- if info.item[1]:
- display.label_accel_label.set_text_with_mnemonic('%s %s' % \
- (info.item[1],
- info.accel_str))
- else:
- display.label_accel_label.set_text('')
+ i += 1
- if info.small_icon:
- display.icon_image.set_from_stock(info.id, get_largest_size(info.id))
- else:
- display.icon_image.set_from_pixbuf(None)
- else:
- display.type_label.set_text('No selected item')
- display.macro_label.set_text('')
- display.id_label.set_text('')
- display.label_accel_label.set_text('')
- display.icon_image.set_from_pixbuf(None)
-
-def macro_set_func_text(tree, cell, model, iter):
- info = model.get_value(iter, 0)
- cell.set_property('text', info.macro)
+ return best_size
-def macro_set_func_pixbuf(tree, cell, model, iter):
+
+def macro_set_func_text(tree_column, cell, model, iter):
info = model.get_value(iter, 0)
- cell.set_property('pixbuf', info.small_icon)
-
-def id_set_func(tree, cell, model, iter):
+ cell.set_property("text", info.macro)
+
+def id_set_func(tree_column, cell, model, iter):
info = model.get_value(iter, 0)
- cell.set_property('text', info.id)
+ cell.set_property("text", info.stock_id)
-def accel_set_func(tree, cell, model, iter):
+def accel_set_func(tree_column, cell, model, iter):
info = model.get_value(iter, 0)
- cell.set_property('text', info.accel_str)
+ cell.set_property("text", info.accel_str)
-def label_set_func(tree, cell, model, iter):
+def label_set_func(tree_column, cell, model, iter):
info = model.get_value(iter, 0)
- cell.set_property('text', info.item[1])
-
+ cell.set_property("text", info.stock_item[1])
+
+
+class StockItemAndIconBrowserDemo(gtk.Window):
+ def __init__(self, parent=None):
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+
+ self.set_title(self.__class__.__name__)
+ self.set_default_size(-1, 500)
+ self.set_border_width(8)
+
+ hbox = gtk.HBox(False, 8)
+ self.add(hbox)
+
+ sw = gtk.ScrolledWindow()
+ sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
+ sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+ hbox.pack_start(sw, False, False, 0)
+
+ model = self.__create_model()
+ treeview = gtk.TreeView(model)
+ sw.add(treeview)
+
+ column = gtk.TreeViewColumn()
+ column.set_title("Macro")
+
+ cell_renderer = gtk.CellRendererPixbuf()
+ column.pack_start(cell_renderer, False)
+ column.set_attributes(cell_renderer, stock_id=1)
+
+ cell_renderer = gtk.CellRendererText()
+ column.pack_start(cell_renderer, True)
+ column.set_cell_data_func(cell_renderer, macro_set_func_text)
+
+ treeview.append_column(column)
+
+ cell_renderer = gtk.CellRendererText()
+ treeview.insert_column_with_data_func(-1, "Label", cell_renderer, label_set_func)
+
+ cell_renderer = gtk.CellRendererText()
+ treeview.insert_column_with_data_func(-1, "Accel", cell_renderer, accel_set_func)
+
+ cell_renderer = gtk.CellRendererText()
+ treeview.insert_column_with_data_func(-1, "ID", cell_renderer, id_set_func)
+
+ align = gtk.Alignment(0.5, 0.0, 0.0, 0.0)
+ hbox.pack_end(align, False, False, 0)
+
+ frame = gtk.Frame("Selected Item")
+ align.add(frame)
+
+ vbox = gtk.VBox(False, 8)
+ vbox.set_border_width(4)
+ frame.add(vbox)
+
+ display = StockItemDisplay()
+ treeview.set_data("stock-display", display)
+
+ display.type_label = gtk.Label()
+ display.macro_label = gtk.Label()
+ display.id_label = gtk.Label()
+ display.label_accel_label = gtk.Label()
+ display.icon_image = gtk.Image(); # empty image
+
+ vbox.pack_start(display.type_label, False, False, 0)
+ vbox.pack_start(display.icon_image, False, False, 0)
+ vbox.pack_start(display.label_accel_label, False, False, 0)
+ vbox.pack_start(display.macro_label, False, False, 0)
+ vbox.pack_start(display.id_label, False, False, 0)
+
+ selection = treeview.get_selection()
+ selection.set_mode(gtk.SELECTION_SINGLE)
+
+ selection.connect("changed", self.on_selection_changed)
+
+ self.show_all()
+
+ def __create_model(self):
+ store = gtk.ListStore(
+ gobject.TYPE_PYOBJECT,
+ gobject.TYPE_STRING)
+
+ ids = gtk.stock_list_ids()
+ ids.sort()
+
+ for data in ids:
+ info = StockItemInfo(stock_id=data)
+ stock_item = gtk.stock_lookup(data)
+
+ if stock_item:
+ info.stock_item = stock_item
+ else:
+ # stock_id, label, modifier, keyval, translation_domain
+ info.stock_item =('', '', 0, 0, '')
+
+ # only show icons for stock IDs that have default icons
+ icon_set = gtk.icon_factory_lookup_default(info.stock_id)
+ if icon_set is None:
+ info.small_icon = None
+ else:
+ # See what sizes this stock icon really exists at
+ sizes = icon_set.get_sizes()
+ n_sizes = len(sizes)
+
+ # Use menu size if it exists, otherwise first size found
+ size = sizes[0];
+ i = 0;
+ while(i < n_sizes):
+ if(sizes[i] == gtk.ICON_SIZE_MENU):
+ size = gtk.ICON_SIZE_MENU
+ break
+ i += 1
+
+ info.small_icon = self.render_icon(info.stock_id, size)
+
+ if(size != gtk.ICON_SIZE_MENU):
+ # Make the result the proper size for our thumbnail
+ w, h = gtk.icon_size_lookup(gtk.ICON_SIZE_MENU)
+
+ scaled = info.small_icon.scale_simple(w, h, 'bilinear')
+ info.small_icon = scaled
+
+ if info.stock_item[3] == 0:
+ info.accel_str = ""
+ else:
+ info.accel_str = \
+ gtk.accelerator_name(info.stock_item[3], info.stock_item[2])
+
+ iter = store.append()
+ store.set(iter, 0, info, 1, info.stock_id)
+
+ return store
+
+ def on_selection_changed(self, selection):
+ treeview = selection.get_tree_view()
+ display = treeview.get_data("stock-display")
+
+ model, iter = selection.get_selected()
+ if iter:
+ info = model.get_value(iter, 0)
+
+ if(info.small_icon and info.stock_item[1]):
+ display.type_label.set_text("Icon and Item")
+
+ elif(info.small_icon):
+ display.type_label.set_text("Icon Only")
+
+ elif(info.stock_item[1]):
+ display.type_label.set_text("Item Only")
+
+ else:
+ display.type_label.set_text("???????")
+
+ display.macro_label.set_text(info.macro)
+ display.id_label.set_text(info.stock_id)
+
+ if(info.stock_item[1]):
+ s = "%s %s" % (info.stock_item[1], info.accel_str)
+ display.label_accel_label.set_text_with_mnemonic(s)
+
+ else:
+ display.label_accel_label.set_text("")
+
+ if(info.small_icon):
+ display.icon_image.set_from_stock(info.stock_id,
+ get_largest_size(info.stock_id))
+ else:
+ display.icon_image.set_from_pixbuf(None)
+
+ else:
+ display.type_label.set_text("No selected item")
+ display.macro_label.set_text("")
+ display.id_label.set_text("")
+ display.label_accel_label.set_text("")
+ display.icon_image.set_from_pixbuf(None)
+
def main():
- global window
-
- window = gtk.Window(gtk.WINDOW_TOPLEVEL)
- window.set_title('Stock Icons and Items')
- window.set_default_size(-1, 500)
-
- window.connect('destroy', lambda *x: gtk.mainquit())
- window.set_border_width(8)
-
- hbox = gtk.HBox(False, 8)
- window.add(hbox)
-
- sw = gtk.ScrolledWindow()
- sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
- hbox.pack_start(sw)
-
- model = create_model()
-
- treeview = gtk.TreeView(model)
- sw.add(treeview)
-
- column = gtk.TreeViewColumn()
- column.set_title('Macro')
-
- cell_renderer = gtk.CellRendererPixbuf()
- column.pack_start(cell_renderer, False)
- column.set_cell_data_func(cell_renderer, macro_set_func_pixbuf)
- cell_renderer = gtk.CellRendererText()
- column.pack_start(cell_renderer, True)
- column.set_cell_data_func(cell_renderer, macro_set_func_text)
- treeview.append_column(column)
-
- cell_renderer = gtk.CellRendererText()
- treeview.insert_column_with_data_func(-1, "Label", cell_renderer,
- label_set_func)
- treeview.insert_column_with_data_func(-1, "Accel", cell_renderer,
- accel_set_func)
- treeview.insert_column_with_data_func(-1, "ID", cell_renderer,
- id_set_func)
-
- align = gtk.Alignment(0.5, 0.0, 0.0, 0.0)
- hbox.pack_start(align)
-
- frame = gtk.Frame("Selected Item")
- align.add(frame)
-
- vbox = gtk.VBox(False, 8)
- vbox.set_border_width(4)
- frame.add(vbox)
-
-
- display = StockItemDisplay()
- treeview.set_data('stock-display', display)
- display.type_label = gtk.Label()
- display.macro_label = gtk.Label()
- display.id_label = gtk.Label()
- display.label_accel_label = gtk.Label()
- display.icon_image = gtk.Image()
-
- vbox.pack_start(display.type_label)
- vbox.pack_start(display.icon_image)
- vbox.pack_start(display.label_accel_label)
- vbox.pack_start(display.macro_label)
- vbox.pack_start(display.id_label)
-
- selection = treeview.get_selection()
- selection.set_mode(gtk.SELECTION_SINGLE)
- selection.connect('changed', selection_changed)
-
- window.show_all()
+ StockItemAndIconBrowserDemo()
+ gtk.main()
if __name__ == '__main__':
main()
- gtk.main()
-
diff --git a/examples/pygtk-demo/demos/textview.py b/examples/pygtk-demo/demos/textview.py
new file mode 100644
index 00000000..833d2302
--- /dev/null
+++ b/examples/pygtk-demo/demos/textview.py
@@ -0,0 +1,499 @@
+#!/usr/bin/env python
+"""Text Widget/TextView
+
+The GtkTextView widget displays a GtkTextBuffer. One GtkTextBuffer can be displayed
+by multiple GtkTextViews. This demo has two views displaying a single buffer, and
+shows off the widget's text formatting features."""
+# pygtk version: Maik Hertha <maik.hertha@berlin.de>
+
+import sys
+import os
+
+import gobject
+import gtk
+import pango
+
+gray50_width = 2
+gray50_height = 2
+gray50_bits = '\x02\x01'
+GTKLOGO_IMAGE = os.path.join(os.path.dirname(__file__),
+ 'images', 'gtk-logo-rgb.gif')
+FLOPPYBUDDY_IMAGE = os.path.join(os.path.dirname(__file__),
+ 'images', 'floppybuddy.gif')
+
+class TextViewDemo(gtk.Window):
+ def __init__(self, parent=None):
+ # Create the toplevel window
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+
+ self.set_title(self.__class__.__name__)
+ self.set_default_size(450, 450)
+ self.set_border_width(0)
+
+ vpaned = gtk.VPaned()
+ vpaned.set_border_width(5)
+ self.add(vpaned)
+
+ # For convenience, we just use the autocreated buffer from
+ # the first text view; you could also create the buffer
+ # by itself with gtk.text_buffer_new(), then later create
+ # a view widget.
+
+ view1 = gtk.TextView();
+ buffer_1 = view1.get_buffer()
+ view2 = gtk.TextView(buffer_1)
+
+ sw = gtk.ScrolledWindow()
+ sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
+ sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+
+ vpaned.add1(sw)
+
+ sw.add(view1)
+
+ sw = gtk.ScrolledWindow()
+ sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
+ sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+
+ vpaned.add2(sw)
+
+ sw.add(view2)
+
+ self.create_tags(buffer_1)
+ self.insert_text(buffer_1)
+
+ self.attach_widgets(view1)
+ self.attach_widgets(view2)
+ self.win = None
+ self.show_all()
+
+ def create_tags(self, text_buffer):
+ '''
+ Create a bunch of tags. Note that it's also possible to
+ create tags with gtk.text_tag_new() then add them to the
+ tag table for the buffer, text_buffer.create_tag() is
+ just a convenience function. Also note that you don't have
+ to give tags a name; pass None for the name to create an
+ anonymous tag.
+
+ In any real app, another useful optimization would be to create
+ a GtkTextTagTable in advance, and reuse the same tag table for
+ all the buffers with the same tag set, instead of creating
+ new copies of the same tags for every buffer.
+
+ Tags are assigned default priorities in order of addition to the
+ tag table. That is, tags created later that affect the same text
+ property affected by an earlier tag will override the earlier
+ tag. You can modify tag priorities with
+ gtk.text_tag_set_priority().
+ '''
+
+ import pango
+ text_buffer.create_tag("heading",
+ weight=pango.WEIGHT_BOLD,
+ size=15 * pango.SCALE)
+
+ text_buffer.create_tag("italic", style=pango.STYLE_ITALIC)
+
+ text_buffer.create_tag("bold", weight=pango.WEIGHT_BOLD)
+
+ # points times the pango.SCALE factor
+ text_buffer.create_tag("big", size=20 * pango.SCALE)
+
+ text_buffer.create_tag("xx-small", scale=pango.SCALE_XX_SMALL)
+
+ text_buffer.create_tag("x-large", scale=pango.SCALE_X_LARGE)
+
+ text_buffer.create_tag("monospace", family="monospace")
+
+ text_buffer.create_tag("blue_foreground", foreground="blue")
+
+ text_buffer.create_tag("red_background", background="red")
+
+ stipple = gtk.gdk.bitmap_create_from_data(None,
+ gray50_bits, gray50_width, gray50_height)
+
+ text_buffer.create_tag("background_stipple", background_stipple=stipple)
+
+ text_buffer.create_tag("foreground_stipple", foreground_stipple=stipple)
+
+ text_buffer.create_tag("big_gap_before_line", pixels_above_lines=30)
+
+ text_buffer.create_tag("big_gap_after_line", pixels_below_lines=30)
+
+ text_buffer.create_tag("double_spaced_line", pixels_inside_wrap=10)
+
+ text_buffer.create_tag("not_editable", editable=False)
+
+ text_buffer.create_tag("word_wrap", wrap_mode=gtk.WRAP_WORD)
+
+ text_buffer.create_tag("char_wrap", wrap_mode=gtk.WRAP_CHAR)
+
+ text_buffer.create_tag("no_wrap", wrap_mode=gtk.WRAP_NONE)
+
+ text_buffer.create_tag("center", justification=gtk.JUSTIFY_CENTER)
+
+ text_buffer.create_tag("right_justify", justification=gtk.JUSTIFY_RIGHT)
+
+ text_buffer.create_tag("wide_margins",
+ left_margin=50, right_margin=50)
+
+ text_buffer.create_tag("strikethrough", strikethrough=True)
+
+ text_buffer.create_tag("underline",
+ underline=pango.UNDERLINE_SINGLE)
+
+ text_buffer.create_tag("double_underline",
+ underline=pango.UNDERLINE_DOUBLE)
+
+ text_buffer.create_tag("superscript",
+ rise=10 * pango.SCALE, # 10 pixels
+ size=8 * pango.SCALE) # 8 points
+
+ text_buffer.create_tag("subscript",
+ rise=-10 * pango.SCALE, # 10 pixels
+ size=8 * pango.SCALE) # 8 points
+
+ text_buffer.create_tag("rtl_quote",
+ wrap_mode=gtk.WRAP_WORD, direction=gtk.TEXT_DIR_RTL,
+ indent=30, left_margin=20, right_margin=20)
+
+ def insert_text(self, text_buffer):
+ # use the current directory for the file
+ try:
+ pixbuf = gtk.gdk.pixbuf_new_from_file(GTKLOGO_IMAGE)
+ except gobject.GError, error:
+ sys.exit("Failed to load image file gtk-logo-rgb.gif\n")
+
+ scaled = pixbuf.scale_simple(32, 32, 'bilinear')
+ pixbuf = scaled
+
+ # get start of buffer; each insertion will revalidate the
+ # iterator to point to just after the inserted text.
+ iter = text_buffer.get_iter_at_offset(0)
+
+ text_buffer.insert(iter, "The text widget can display text with "
+ "all kinds of nifty attributes. It also supports multiple views "
+ "of the same buffer; this demo is showing the same buffer in "
+ "two places.\n\n")
+
+ text_buffer.insert_with_tags_by_name(iter, "Font styles. ", "heading")
+
+ text_buffer.insert(iter, "For example, you can have ")
+ text_buffer.insert_with_tags_by_name(iter,
+ "italic", "italic")
+ text_buffer.insert(iter, ", ");
+ text_buffer.insert_with_tags_by_name(iter,
+ "bold", "bold")
+ text_buffer.insert(iter, ", or ", -1)
+ text_buffer.insert_with_tags_by_name(iter,
+ "monospace(typewriter)", "monospace")
+ text_buffer.insert(iter, ", or ")
+ text_buffer.insert_with_tags_by_name(iter,
+ "big", "big")
+ text_buffer.insert(iter, " text. ")
+ text_buffer.insert(iter, "It's best not to hardcode specific text "
+ "sizes; you can use relative sizes as with CSS, such as ")
+ text_buffer.insert_with_tags_by_name(iter,
+ "xx-small", "xx-small")
+ text_buffer.insert(iter, " or ")
+ text_buffer.insert_with_tags_by_name(iter,
+ "x-large", "x-large")
+ text_buffer.insert(iter, " to ensure that your program properly "
+ "adapts if the user changes the default font size.\n\n")
+
+ text_buffer.insert_with_tags_by_name(iter, "Colors. ", "heading")
+
+ text_buffer.insert(iter, "Colors such as ");
+ text_buffer.insert_with_tags_by_name(iter,
+ "a blue foreground", "blue_foreground")
+ text_buffer.insert(iter, " or ");
+ text_buffer.insert_with_tags_by_name(iter,
+ "a red background",
+ "red_background")
+ text_buffer.insert(iter, " or even ", -1);
+ text_buffer.insert_with_tags_by_name(iter,
+ "a stippled red background",
+ "red_background",
+ "background_stipple")
+
+ text_buffer.insert(iter, " or ", -1);
+ text_buffer.insert_with_tags_by_name(iter,
+ "a stippled blue foreground on solid red background",
+ "blue_foreground",
+ "red_background",
+ "foreground_stipple")
+ text_buffer.insert(iter, "(select that to read it) can be used.\n\n", -1);
+
+ text_buffer.insert_with_tags_by_name(iter,
+ "Underline, strikethrough, and rise. ", "heading")
+
+ text_buffer.insert_with_tags_by_name(iter,
+ "Strikethrough",
+ "strikethrough")
+ text_buffer.insert(iter, ", ", -1)
+ text_buffer.insert_with_tags_by_name(iter,
+ "underline",
+ "underline")
+ text_buffer.insert(iter, ", ", -1)
+ text_buffer.insert_with_tags_by_name(iter,
+ "double underline",
+ "double_underline")
+ text_buffer.insert(iter, ", ", -1)
+ text_buffer.insert_with_tags_by_name(iter,
+ "superscript",
+ "superscript")
+ text_buffer.insert(iter, ", and ", -1)
+ text_buffer.insert_with_tags_by_name(iter,
+ "subscript",
+ "subscript")
+ text_buffer.insert(iter, " are all supported.\n\n", -1)
+
+ text_buffer.insert_with_tags_by_name(iter, "Images. ",
+ "heading")
+
+ text_buffer.insert(iter, "The buffer can have images in it: ", -1)
+ text_buffer.insert_pixbuf(iter, pixbuf)
+ text_buffer.insert_pixbuf(iter, pixbuf)
+ text_buffer.insert_pixbuf(iter, pixbuf)
+ text_buffer.insert(iter, " for example.\n\n", -1)
+
+ text_buffer.insert_with_tags_by_name(iter, "Spacing. ",
+ "heading")
+
+ text_buffer.insert(iter,
+ "You can adjust the amount of space before each line.\n", -1)
+
+ text_buffer.insert_with_tags_by_name(iter,
+ "This line has a whole lot of space before it.\n",
+ "big_gap_before_line", "wide_margins")
+ text_buffer.insert_with_tags_by_name(iter,
+ "You can also adjust the amount of space after each line; "
+ "this line has a whole lot of space after it.\n",
+ "big_gap_after_line", "wide_margins")
+
+ text_buffer.insert_with_tags_by_name(iter,
+ "You can also adjust the amount of space between wrapped "
+ "lines; this line has extra space between each wrapped line "
+ "in the same paragraph. To show off wrapping, some filler "
+ "text: the quick brown fox jumped over the lazy dog. Blah "
+ "blah blah blah blah blah blah blah blah.\n",
+ "double_spaced_line", "wide_margins")
+
+ text_buffer.insert(iter, "Also note that those lines have "
+ "extra-wide margins.\n\n", -1)
+
+ text_buffer.insert_with_tags_by_name(iter, "Editability. ", "heading")
+
+ text_buffer.insert_with_tags_by_name(iter,
+ "This line is 'locked down' and can't be edited by the "
+ "user - just try it! You can't delete this line.\n\n",
+ "not_editable")
+
+ text_buffer.insert_with_tags_by_name(iter, "Wrapping. ", "heading")
+
+ text_buffer.insert(iter,
+ "This line(and most of the others in this buffer) is "
+ "word-wrapped, using the proper Unicode algorithm. Word "
+ "wrap should work in all scripts and languages that GTK+ "
+ "supports. Let's make this a long paragraph to demonstrate: "
+ "blah blah blah blah blah blah blah blah blah blah blah "
+ "blah blah blah blah blah blah blah blah\n\n", -1);
+
+ text_buffer.insert_with_tags_by_name(iter,
+ "This line has character-based wrapping, and can wrap "
+ "between any two character glyphs. Let's make this a long "
+ "paragraph to demonstrate: blah blah blah blah blah blah "
+ "blah blah blah blah blah blah blah blah blah blah blah "
+ "blah blah\n\n", "char_wrap")
+
+ text_buffer.insert_with_tags_by_name(iter,
+ "This line has all wrapping turned off, so it makes the "
+ "horizontal scrollbar appear.\n\n\n", "no_wrap")
+
+ text_buffer.insert_with_tags_by_name(iter, "Justification. ",
+ "heading");
+
+ text_buffer.insert_with_tags_by_name(iter,
+ "\nThis line has center justification.\n", "center")
+
+ text_buffer.insert_with_tags_by_name(iter,
+ "This line has right justification.\n", "right_justify")
+
+ text_buffer.insert_with_tags_by_name(iter,
+ "\nThis line has big wide margins. Text text text text "
+ "text text text text text text text text text text text "
+ "text text text text text text text text text text text "
+ "text text text text text text text text text text.\n",
+ "wide_margins");
+
+ text_buffer.insert_with_tags_by_name(iter,
+ "Internationalization. ", "heading")
+
+ text_buffer.insert(iter,
+ "You can put all sorts of Unicode text in the buffer.\n\n"
+ "German(Deutsch S\303\274d) Gr\303\274\303\237 Gott\nGreek"
+ "(\316\225\316\273\316\273\316\267\316\275\316\271\316\272"
+ "\316\254) \316\223\316\265\316\271\316\254 \317\203\316\261"
+ "\317\202\nHebrew \327\251\327\234\327\225\327\235\n"
+ "Japanese(\346\227\245\346\234\254\350\252\236)\n\nThe "
+ "widget properly handles bidirectional text, word wrapping, "
+ "DOS/UNIX/Unicode paragraph separators, grapheme boundaries, "
+ "and so on using the Pango internationalization framework.\n", -1)
+
+ text_buffer.insert(iter, "Here's a word-wrapped quote in a "
+ "right-to-left language:\n", -1)
+ text_buffer.insert_with_tags_by_name(iter,
+ "\331\210\331\202\330\257 \330\250\330\257\330\243 "
+ "\330\253\331\204\330\247\330\253 \331\205\331\206 "
+ "\330\243\331\203\330\253\330\261 \330\247\331\204\331"
+ "\205\330\244\330\263\330\263\330\247\330\252 \330\252"
+ "\331\202\330\257\331\205\330\247 \331\201\331\212 \330"
+ "\264\330\250\331\203\330\251 \330\247\331\203\330\263"
+ "\331\212\331\210\331\206 \330\250\330\261\330\247\331"
+ "\205\330\254\331\207\330\247 \331\203\331\205\331\206"
+ "\330\270\331\205\330\247\330\252 \331\204\330\247 \330"
+ "\252\330\263\330\271\331\211 \331\204\331\204\330\261"
+ "\330\250\330\255\330\214 \330\253\331\205 \330\252\330"
+ "\255\331\210\331\204\330\252 \331\201\331\212 \330\247"
+ "\331\204\330\263\331\206\331\210\330\247\330\252 \330"
+ "\247\331\204\330\256\331\205\330\263 \330\247\331\204"
+ "\331\205\330\247\330\266\331\212\330\251 \330\245\331"
+ "\204\331\211 \331\205\330\244\330\263\330\263\330\247"
+ "\330\252 \331\205\330\247\331\204\331\212\330\251 \331"
+ "\205\331\206\330\270\331\205\330\251\330\214 \331\210"
+ "\330\250\330\247\330\252\330\252 \330\254\330\262\330\241"
+ "\330\247 \331\205\331\206 \330\247\331\204\331\206\330\270"
+ "\330\247\331\205 \330\247\331\204\331\205\330\247\331\204"
+ "\331\212 \331\201\331\212 \330\250\331\204\330\257\330\247"
+ "\331\206\331\207\330\247\330\214 \331\210\331\204\331\203"
+ "\331\206\331\207\330\247 \330\252\330\252\330\256\330\265"
+ "\330\265 \331\201\331\212 \330\256\330\257\331\205\330\251 "
+ "\331\202\330\267\330\247\330\271 \330\247\331\204\331\205\330"
+ "\264\330\261\331\210\330\271\330\247\330\252 \330\247\331\204"
+ "\330\265\330\272\331\212\330\261\330\251. \331\210\330\243"
+ "\330\255\330\257 \330\243\331\203\330\253\330\261 \331\207"
+ "\330\260\331\207 \330\247\331\204\331\205\330\244\330\263"
+ "\330\263\330\247\330\252 \331\206\330\254\330\247\330\255"
+ "\330\247 \331\207\331\210 \302\273\330\250\330\247\331\206"
+ "\331\203\331\210\330\263\331\210\331\204\302\253 \331\201"
+ "\331\212 \330\250\331\210\331\204\331\212\331\201\331\212"
+ "\330\247.\n\n", "rtl_quote")
+
+ text_buffer.insert(iter, "You can put widgets in the buffer: "
+ "Here's a button: ", -1)
+
+ anchor = text_buffer.create_child_anchor(iter)
+ text_buffer.insert(iter, " and a menu: ", -1)
+ anchor = text_buffer.create_child_anchor(iter)
+ text_buffer.insert(iter, " and a scale: ", -1)
+ anchor = text_buffer.create_child_anchor(iter)
+ text_buffer.insert(iter, " and an animation: ", -1)
+ anchor = text_buffer.create_child_anchor(iter)
+ text_buffer.insert(iter, " finally a text entry: ", -1)
+ anchor = text_buffer.create_child_anchor(iter)
+ text_buffer.insert(iter, ".\n", -1)
+
+ text_buffer.insert(iter, "\n\nThis demo doesn't demonstrate all "
+ "the GtkTextBuffer features; it leaves out, for example: "
+ "invisible/hidden text(doesn't work in GTK 2, but planned), "
+ "tab stops, application-drawn areas on the sides of the "
+ "widget for displaying breakpoints and such...", -1)
+
+ # Apply word_wrap tag to whole buffer */
+ start, end = text_buffer.get_bounds()
+ text_buffer.apply_tag_by_name("word_wrap", start, end)
+
+ def attach_widgets(self, text_view):
+ buffer = text_view.get_buffer()
+ iter = buffer.get_start_iter()
+ i = 0
+ while self.find_anchor(iter):
+ anchor = iter.get_child_anchor()
+ if i == 0:
+ widget = gtk.Button("Click Me")
+ widget.connect("clicked", self.easter_egg_callback)
+ elif i == 1:
+ widget = gtk.combo_box_new_text()
+ widget.append_text("Option 1")
+ widget.append_text("Option 2")
+ widget.append_text("Option 3")
+ elif i == 2:
+ widget = gtk.HScale()
+ widget.set_range(0, 100)
+ widget.set_size_request(70, -1)
+ elif i == 3:
+ widget = gtk.Image()
+ widget.set_from_file(FLOPPYBUDDY_IMAGE)
+ elif i == 4:
+ widget = gtk.Entry()
+ else:
+ raise ValueError
+
+ text_view.add_child_at_anchor(widget, anchor)
+ widget.show_all()
+ i += 1
+ return
+
+ def find_anchor(self, iter):
+ while iter.forward_char():
+ if iter.get_child_anchor():
+ return True
+ return False
+
+ def easter_egg_callback(self, button):
+ if self.win:
+ self.win.present()
+ return
+
+ buffer = gtk.TextBuffer()
+ iter = buffer.get_start_iter()
+ buffer.insert(iter,
+ "This buffer is shared by a set of nested text views.\n Nested view:\n")
+ anchor = buffer.create_child_anchor(iter)
+ buffer.insert(iter,
+ "\nDon't do this in real applications, please.\n")
+
+ view = gtk.TextView(buffer)
+
+ self.recursive_attach_view(0, view, anchor)
+
+ self.win = gtk.Window()
+ sw = gtk.ScrolledWindow()
+ sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+
+ self.win.add(sw)
+ sw.add(view)
+ self.win.set_default_size(300, 400)
+ self.win.show_all()
+ return
+
+ def recursive_attach_view(self, depth, view, anchor):
+ if depth > 4:
+ return
+ child_view = gtk.TextView(view.get_buffer())
+ # Event box is needed to add a black border around each child view
+ event_box = gtk.EventBox()
+ color = gtk.gdk.color_parse("black")
+ event_box.modify_bg(gtk.STATE_NORMAL, color)
+ align = gtk.Alignment(0.5, 0.5, 1.0, 1.0)
+ align.set_border_width(1)
+
+ event_box.add(align)
+ align.add(child_view)
+
+ view.add_child_at_anchor(event_box, anchor)
+
+ self.recursive_attach_view(depth + 1, child_view, anchor)
+ return
+
+def main():
+ TextViewDemo()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
diff --git a/examples/pygtk-demo/demos/toolbar.py b/examples/pygtk-demo/demos/toolbar.py
deleted file mode 100644
index 9a889a8c..00000000
--- a/examples/pygtk-demo/demos/toolbar.py
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/env python
-'''Toolbar Demo
-
-This demonstration demonstrates the use of toolbars in GTK+'''
-
-description = 'Toolbars'
-
-import gtk
-
-folder_icon = [
- "20 19 5 1",
- " c None",
- ". c #000000",
- "X c #FFFFFF",
- "o c #FFFF00",
- "O c #7F7F00",
- " ",
- " ",
- " ",
- " ... ",
- " . . . ",
- " .. ",
- " ... ... ",
- " .oXo....... ",
- " .XoXoXoXoX. ",
- " .oXoXoXoXo. ",
- " .XoXo........... ",
- " .oXo.OOOOOOOOO. ",
- " .Xo.OOOOOOOOO. ",
- " .o.OOOOOOOOO. ",
- " ..OOOOOOOOO. ",
- " ........... ",
- " ",
- " ",
- " "
-]
-
-def set_orient_cb(button, toolbar, orient):
- toolbar.set_orientation(orient)
-def set_style_cb(button, toolbar, style):
- toolbar.set_style(style)
-def set_tooltips_cb(button, toolbar, enable):
- toolbar.set_tooltips(enable)
-
-def Image(pix, mask):
- image = gtk.Image()
- image.set_from_pixmap(pix, mask)
- return image
-
-def main():
- win = gtk.Window()
- win.connect('destroy', lambda win: gtk.main_quit())
-
- win.set_title("Toolbar")
- win.set_resizable(gtk.FALSE)
- win.set_border_width(5)
-
- pix, mask = gtk.gdk.pixmap_colormap_create_from_xpm_d(None,
- win.get_colormap(),
- None, folder_icon)
- toolbar = gtk.Toolbar()
- win.add(toolbar)
-
- button = toolbar.append_item("Horizontal", "Horizontal toolbar layout",
- None, Image(pix, mask), None, None)
- button.connect("clicked", set_orient_cb, toolbar,
- gtk.ORIENTATION_HORIZONTAL)
-
- button = toolbar.append_item("Vertical", "Vertical toolbar layout",
- None, Image(pix, mask), None, None)
- button.connect("clicked", set_orient_cb, toolbar,
- gtk.ORIENTATION_VERTICAL)
-
- toolbar.append_space()
-
- button = toolbar.append_item("Icons", "Only show toolbar icons",
- None, Image(pix, mask), None, None)
- button.connect("clicked", set_style_cb, toolbar, gtk.TOOLBAR_ICONS)
-
- button = toolbar.append_item("Text", "Only show toolbar texts",
- None, Image(pix, mask), None, None)
- button.connect("clicked", set_style_cb, toolbar, gtk.TOOLBAR_TEXT)
-
- button = toolbar.append_item("Both", "Show toolbar icons and text",
- None, Image(pix, mask), None, None)
- button.connect("clicked", set_style_cb, toolbar, gtk.TOOLBAR_BOTH)
-
- toolbar.append_space()
-
- entry = gtk.Entry()
- toolbar.append_widget(entry, None, None)
-
- toolbar.append_space()
-
- button = toolbar.append_item("Enable", "Enable tooltips",
- None, Image(pix, mask), None, None)
- button.connect("clicked", set_tooltips_cb, toolbar, gtk.TRUE)
-
- button = toolbar.append_item("Disable", "Disable tooltips",
- None, Image(pix, mask), None, None)
- button.connect("clicked", set_tooltips_cb, toolbar, gtk.FALSE)
-
- win.show_all()
-
- gtk.main()
-
-if __name__ == '__main__':
- main()
diff --git a/examples/pygtk-demo/demos/tree_store.py b/examples/pygtk-demo/demos/tree_store.py
new file mode 100644
index 00000000..c7d0b709
--- /dev/null
+++ b/examples/pygtk-demo/demos/tree_store.py
@@ -0,0 +1,335 @@
+#!/usr/bin/env python
+'''Tree View/Tree Store
+
+The GtkTreeStore is used to store data in tree form, to be used
+later on by a GtkTreeView to display it. This demo builds a simple
+GtkTreeStore and displays it. If you're new to the GtkTreeView widgets
+and associates, look into the GtkListStore example first.'''
+# pygtk version: Maik Hertha <maik.hertha@berlin.de>
+
+import gobject
+import gtk
+
+# columns
+(
+ HOLIDAY_NAME_COLUMN,
+ ALEX_COLUMN,
+ HAVOC_COLUMN,
+ TIM_COLUMN,
+ OWEN_COLUMN,
+ DAVE_COLUMN,
+ VISIBLE_COLUMN,
+ WORLD_COLUMN,
+ NUM_COLUMNS
+) = range(9)
+
+# tree data
+january = \
+[
+ ["New Years Day", True, True, True, True, False, True ],
+ ["Presidential Inauguration", False, True, False, True, False, False ],
+ ["Martin Luther King Jr. day", False, True, False, True, False, False ]
+]
+
+february = \
+[
+ [ "Presidents' Day", False, True, False, True, False, False ],
+ [ "Groundhog Day", False, False, False, False, False, False ],
+ [ "Valentine's Day", False, False, False, False, True, True ]
+]
+
+march = \
+[
+ [ "National Tree Planting Day", False, False, False, False, False, False ],
+ [ "St Patrick's Day", False, False, False, False, False, True ]
+]
+april = \
+[
+ [ "April Fools' Day", False, False, False, False, False, True ],
+ [ "Army Day", False, False, False, False, False, False ],
+ [ "Earth Day", False, False, False, False, False, True ],
+ [ "Administrative Professionals' Day", False, False, False, False, False, False ]
+]
+
+may = \
+[
+ [ "Nurses' Day", False, False, False, False, False, False ],
+ [ "National Day of Prayer", False, False, False, False, False, False ],
+ [ "Mothers' Day", False, False, False, False, False, True ],
+ [ "Armed Forces Day", False, False, False, False, False, False ],
+ [ "Memorial Day", True, True, True, True, False, True ]
+]
+
+june = \
+[
+ [ "June Fathers' Day", False, False, False, False, False, True ],
+ [ "Juneteenth(Liberation of Slaves)", False, False, False, False, False, False ],
+ [ "Flag Day", False, True, False, True, False, False ]
+]
+
+july = \
+[
+ [ "Parents' Day", False, False, False, False, False, True ],
+ [ "Independence Day", False, True, False, True, False, False ]
+]
+
+august = \
+[
+ [ "Air Force Day", False, False, False, False, False, False ],
+ [ "Coast Guard Day", False, False, False, False, False, False ],
+ [ "Friendship Day", False, False, False, False, False, False ]
+]
+
+september = \
+[
+ [ "Grandparents' Day", False, False, False, False, False, True ],
+ [ "Citizenship Day or Constitution Day", False, False, False, False, False, False ],
+ [ "Labor Day", True, True, True, True, False, True ]
+]
+
+october = \
+[
+ [ "National Children's Day", False, False, False, False, False, False ],
+ [ "Bosses' Day", False, False, False, False, False, False ],
+ [ "Sweetest Day", False, False, False, False, False, False ],
+ [ "Mother-in-Law's Day", False, False, False, False, False, False ],
+ [ "Navy Day", False, False, False, False, False, False ],
+ [ "Columbus Day", False, True, False, True, False, False ],
+ [ "Halloween", False, False, False, False, False, True ]
+]
+
+november = \
+[
+ [ "Marine Corps Day", False, False, False, False, False, False ],
+ [ "Veterans' Day", True, True, True, True, False, True ],
+ [ "Thanksgiving", False, True, False, True, False, False ]
+]
+
+december = \
+[
+ [ "Pearl Harbor Remembrance Day", False, False, False, False, False, False ],
+ [ "Christmas", True, True, True, True, False, True ],
+ [ "Kwanzaa", False, False, False, False, False, False ]
+]
+
+
+toplevel = \
+[
+ ["January", False, False, False, False, False, False, january],
+ ["February", False, False, False, False, False, False, february],
+ ["March", False, False, False, False, False, False, march],
+ ["April", False, False, False, False, False, False, april],
+ ["May", False, False, False, False, False, False, may],
+ ["June", False, False, False, False, False, False, june],
+ ["July", False, False, False, False, False, False, july],
+ ["August", False, False, False, False, False, False, august],
+ ["September", False, False, False, False, False, False, september],
+ ["October", False, False, False, False, False, False, october],
+ ["November", False, False, False, False, False, False, november],
+ ["December", False, False, False, False, False, False, december]
+]
+
+class TreeStoreDemo(gtk.Window):
+ def __init__(self, parent=None):
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+ self.set_title(self.__class__.__name__)
+ self.set_default_size(650, 400)
+ self.set_border_width(8)
+
+ vbox = gtk.VBox(False, 8)
+ self.add(vbox)
+
+ label = gtk.Label("Jonathan's Holiday Card Planning Sheet")
+ vbox.pack_start(label, False, False)
+
+ sw = gtk.ScrolledWindow()
+ sw.set_shadow_type(gtk.SHADOW_ETCHED_IN)
+ sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ vbox.pack_start(sw)
+
+ # create model
+ model = self.__create_model()
+
+ # create treeview
+ treeview = gtk.TreeView(model)
+ treeview.set_rules_hint(True)
+
+ self.__add_columns(treeview)
+
+ sw.add(treeview)
+
+ # expand all rows after the treeview widget has been realized
+ treeview.connect('realize', lambda tv: tv.expand_all())
+
+ self.show_all()
+
+ def __create_model(self):
+
+ # create tree store
+ model = gtk.TreeStore(
+ gobject.TYPE_STRING,
+ gobject.TYPE_BOOLEAN,
+ gobject.TYPE_BOOLEAN,
+ gobject.TYPE_BOOLEAN,
+ gobject.TYPE_BOOLEAN,
+ gobject.TYPE_BOOLEAN,
+ gobject.TYPE_BOOLEAN,
+ gobject.TYPE_BOOLEAN)
+
+ # add data to the tree store
+ for month in toplevel:
+ iter = model.append(None)
+ model.set(iter,
+ HOLIDAY_NAME_COLUMN, month[HOLIDAY_NAME_COLUMN],
+ ALEX_COLUMN, False,
+ HAVOC_COLUMN, False,
+ TIM_COLUMN, False,
+ OWEN_COLUMN, False,
+ DAVE_COLUMN, False,
+ VISIBLE_COLUMN, False,
+ WORLD_COLUMN, False
+ )
+
+ # add children
+ for holiday in month[-1]:
+ child_iter = model.append(iter);
+ model.set(child_iter,
+ HOLIDAY_NAME_COLUMN, holiday[HOLIDAY_NAME_COLUMN],
+ ALEX_COLUMN, holiday[ALEX_COLUMN],
+ HAVOC_COLUMN, holiday[HAVOC_COLUMN],
+ TIM_COLUMN, holiday[TIM_COLUMN],
+ OWEN_COLUMN, holiday[OWEN_COLUMN],
+ DAVE_COLUMN, holiday[DAVE_COLUMN],
+ VISIBLE_COLUMN, True,
+ WORLD_COLUMN, holiday[WORLD_COLUMN-1]
+ )
+
+ return model
+
+ def on_item_toggled(self, cell, path_str, model):
+
+ # get selected column
+ column = cell.get_data('column')
+
+ # get toggled iter
+ iter = model.get_iter_from_string(path_str)
+ toggle_item = model.get_value(iter, column)
+
+ # do something with the value
+ toggle_item = not toggle_item
+
+ # set new value
+ model.set(iter, column, toggle_item)
+
+
+ def __add_columns(self, treeview):
+ model = treeview.get_model()
+
+ # column for holiday names
+ renderer = gtk.CellRendererText()
+ renderer.set_property("xalign", 0.0)
+
+ #col_offset = gtk.TreeViewColumn("Holiday", renderer, text=HOLIDAY_NAME_COLUMN)
+ column = gtk.TreeViewColumn("Holiday", renderer, text=HOLIDAY_NAME_COLUMN)
+ #column = gtk_tree_view_get_column(GTK_TREE_VIEW(treeview), col_offset - 1);
+ column.set_clickable(True)
+
+ treeview.append_column(column)
+
+ # alex column */
+ renderer = gtk.CellRendererToggle()
+ renderer.set_property("xalign", 0.0)
+ renderer.set_data("column", ALEX_COLUMN)
+
+ renderer.connect("toggled", self.on_item_toggled, model)
+
+ column = gtk.TreeViewColumn("Alex", renderer, active=ALEX_COLUMN,
+ visible=VISIBLE_COLUMN, activatable=WORLD_COLUMN)
+
+ # set this column to a fixed sizing(of 50 pixels)
+ #column = gtk_tree_view_get_column(GTK_TREE_VIEW(treeview), col_offset - 1);
+ column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+ column.set_fixed_width(50)
+ column.set_clickable(True)
+
+ treeview.append_column(column)
+
+ # havoc column
+ renderer = gtk.CellRendererToggle();
+ renderer.set_property("xalign", 0.0)
+ renderer.set_data("column", HAVOC_COLUMN)
+
+ renderer.connect("toggled", self.on_item_toggled, model)
+
+ column = gtk.TreeViewColumn("Havoc", renderer, active=HAVOC_COLUMN,
+ visible=VISIBLE_COLUMN)
+
+ #column = treeview.get_column(col_offset - 1)
+ column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+ column.set_fixed_width(50)
+ column.set_clickable(True)
+
+ treeview.append_column(column)
+
+ # tim column
+ renderer = gtk.CellRendererToggle();
+ renderer.set_property("xalign", 0.0)
+ renderer.set_data("column", TIM_COLUMN)
+
+ renderer.connect("toggled", self.on_item_toggled, model)
+
+ column = gtk.TreeViewColumn("Tim", renderer, active=TIM_COLUMN,
+ visible=VISIBLE_COLUMN, activatable=WORLD_COLUMN)
+
+ #column = treeview.get_column(col_offset - 1)
+ column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+ column.set_fixed_width(50)
+ column.set_clickable(True)
+
+ treeview.append_column(column)
+
+ # owen column
+ renderer = gtk.CellRendererToggle();
+ renderer.set_property("xalign", 0.0)
+ renderer.set_data("column", OWEN_COLUMN)
+
+ renderer.connect("toggled", self.on_item_toggled, model)
+
+ column = gtk.TreeViewColumn("Owen", renderer, active=OWEN_COLUMN,
+ visible=VISIBLE_COLUMN)
+
+ #column = treeview.get_column(col_offset - 1)
+ column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+ column.set_fixed_width(50)
+ column.set_clickable(True)
+
+ treeview.append_column(column)
+
+ # dave column
+ renderer = gtk.CellRendererToggle();
+ renderer.set_property("xalign", 0.0)
+ renderer.set_data("column", DAVE_COLUMN)
+
+ renderer.connect("toggled", self.on_item_toggled, model)
+
+ column = gtk.TreeViewColumn("Dave", renderer, active=DAVE_COLUMN,
+ visible=VISIBLE_COLUMN)
+
+ #column = treeview.get_column(col_offset - 1)
+ column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+ column.set_fixed_width(50)
+ column.set_clickable(True)
+
+ treeview.append_column(column)
+
+def main():
+ TreeStoreDemo()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
+
diff --git a/examples/pygtk-demo/demos/treemodel.py b/examples/pygtk-demo/demos/treemodel.py
index 13d2c817..b8195db6 100644
--- a/examples/pygtk-demo/demos/treemodel.py
+++ b/examples/pygtk-demo/demos/treemodel.py
@@ -1,9 +1,8 @@
#!/usr/bin/env python
-'''Tree Model Test
+'''Tree View/Generic Tree Model
This test is designed to demonstrate creating a new type of tree model
in python for use with the new tree widget in gtk 2.0.'''
-description = 'Tree Model'
import gtk
import gobject
@@ -25,87 +24,93 @@ class MyTreeModel(gtk.GenericTreeModel):
TREE_DEPTH = 4
TREE_SIBLINGS = 5
def __init__(self):
- '''constructor for the model. Make sure you call
- PyTreeModel.__init__'''
- gtk.GenericTreeModel.__init__(self)
+ '''constructor for the model. Make sure you call
+ PyTreeModel.__init__'''
+ gtk.GenericTreeModel.__init__(self)
# the implementations for TreeModel methods are prefixed with on_
def on_get_flags(self):
- '''returns the GtkTreeModelFlags for this particular type of model'''
- return 0
+ '''returns the GtkTreeModelFlags for this particular type of model'''
+ return 0
def on_get_n_columns(self):
- '''returns the number of columns in the model'''
- return 1
+ '''returns the number of columns in the model'''
+ return 1
def on_get_column_type(self, index):
- '''returns the type of a column in the model'''
- return gobject.TYPE_STRING
+ '''returns the type of a column in the model'''
+ return gobject.TYPE_STRING
def on_get_path(self, node):
- '''returns the tree path (a tuple of indices at the various
- levels) for a particular node.'''
- return node
+ '''returns the tree path(a tuple of indices at the various
+ levels) for a particular node.'''
+ return node
def on_get_iter(self, path):
'''returns the node corresponding to the given path. In our
case, the node is the path'''
return path
def on_get_value(self, node, column):
- '''returns the value stored in a particular column for the node'''
- assert column == 0
- return `node`
+ '''returns the value stored in a particular column for the node'''
+ assert column == 0
+ return `node`
def on_iter_next(self, node):
- '''returns the next node at this level of the tree'''
- if node[-1] == self.TREE_SIBLINGS - 1: # last node at level
- return None
- return node[:-1] + (node[-1]+1,)
+ '''returns the next node at this level of the tree'''
+ if node[-1] == self.TREE_SIBLINGS - 1: # last node at level
+ return None
+ return node[:-1] +(node[-1]+1,)
def on_iter_children(self, node):
- '''returns the first child of this node'''
- if node == None: # top of tree
- return (0,)
- if len(node) >= self.TREE_DEPTH: # no more levels
- return None
- return node + (0,)
+ '''returns the first child of this node'''
+ if node == None: # top of tree
+ return(0,)
+ if len(node) >= self.TREE_DEPTH: # no more levels
+ return None
+ return node +(0,)
def on_iter_has_child(self, node):
- '''returns true if this node has children'''
- return len(node) < self.TREE_DEPTH
+ '''returns true if this node has children'''
+ return len(node) < self.TREE_DEPTH
def on_iter_n_children(self, node):
- '''returns the number of children of this node'''
- if len(node) < self.TREE_DEPTH:
- return self.TREE_SIBLINGS
- else:
- return 0
+ '''returns the number of children of this node'''
+ if len(node) < self.TREE_DEPTH:
+ return self.TREE_SIBLINGS
+ else:
+ return 0
def on_iter_nth_child(self, node, n):
- '''returns the nth child of this node'''
+ '''returns the nth child of this node'''
if node == None:
- return (n,)
- if len(node) < self.TREE_DEPTH and n < self.TREE_SIBLINGS:
- return node + (n,)
- else:
- return None
+ return(n,)
+ if len(node) < self.TREE_DEPTH and n < self.TREE_SIBLINGS:
+ return node +(n,)
+ else:
+ return None
def on_iter_parent(self, node):
- '''returns the parent of this node'''
- if len(node) == 0:
- return None
- else:
- return node[:-1]
+ '''returns the parent of this node'''
+ if len(node) == 0:
+ return None
+ else:
+ return node[:-1]
-def main():
- window = gtk.Window()
- window.connect('destroy', lambda win: gtk.main_quit())
- window.set_title('Menus')
+class GenericTreeModelDemo(gtk.Window):
+ def __init__(self, parent=None):
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+ self.set_title(self.__class__.__name__)
- scrolled_window = gtk.ScrolledWindow()
- scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- window.add(scrolled_window)
+ scrolled_window = gtk.ScrolledWindow()
+ scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+ self.add(scrolled_window)
- model = MyTreeModel()
- tree_view = gtk.TreeView(model)
- cell = gtk.CellRendererText()
- # the text in the column comes from column 0
- column = gtk.TreeViewColumn("tuples", cell, text=0)
- tree_view.append_column(column)
+ model = MyTreeModel()
+ tree_view = gtk.TreeView(model)
+ cell = gtk.CellRendererText()
+ # the text in the column comes from column 0
+ column = gtk.TreeViewColumn("tuples", cell, text=0)
+ tree_view.append_column(column)
- scrolled_window.add(tree_view)
- window.show_all()
+ scrolled_window.add(tree_view)
+ self.show_all()
+def main():
+ GenericTreeModelDemo()
gtk.main()
if __name__ == '__main__':
diff --git a/examples/pygtk-demo/demos/ui_manager.py b/examples/pygtk-demo/demos/ui_manager.py
new file mode 100644
index 00000000..c473f08c
--- /dev/null
+++ b/examples/pygtk-demo/demos/ui_manager.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+'''UI Manager
+
+The GtkUIManager object allows the easy creation of menus
+from an array of actions and a description of the menu hierarchy.
+'''
+# pygtk version: Maik Hertha <maik.hertha@berlin.de>
+
+import gtk
+
+def activate_action(action):
+ print 'Action "%s" activated' % action.get_name()
+
+def activate_radio_action(action, current):
+ print 'Radio action "%s" selected'% current.get_name()
+
+entries = (
+ ( "FileMenu", None, "_File" ), # name, stock id, label
+ ( "PreferencesMenu", None, "_Preferences" ), # name, stock id, label
+ ( "ColorMenu", None, "_Color" ), # name, stock id, label
+ ( "ShapeMenu", None, "_Shape" ), # name, stock id, label
+ ( "HelpMenu", None, "_Help" ), # name, stock id, label
+ ( "New", gtk.STOCK_NEW, # name, stock id
+ "_New", "<control>N", # label, accelerator
+ "Create a new file", # tooltip
+ activate_action ),
+ ( "Open", gtk.STOCK_OPEN, # name, stock id
+ "_Open","<control>O", # label, accelerator
+ "Open a file", # tooltip
+ activate_action ),
+ ( "Save", gtk.STOCK_SAVE, # name, stock id
+ "_Save","<control>S", # label, accelerator
+ "Save current file", # tooltip
+ activate_action ),
+ ( "SaveAs", gtk.STOCK_SAVE, # name, stock id
+ "Save _As...", None, # label, accelerator
+ "Save to a file", # tooltip
+ activate_action ),
+ ( "Quit", gtk.STOCK_QUIT, # name, stock id
+ "_Quit", "<control>Q", # label, accelerator
+ "Quit", # tooltip
+ activate_action ),
+ ( "About", None, # name, stock id
+ "_About", "<control>A", # label, accelerator
+ "About", # tooltip
+ activate_action ),
+ ( "Logo", "demo-gtk-logo", # name, stock id
+ None, None, # label, accelerator
+ "GTK+", # tooltip
+ activate_action ),
+)
+
+toggle_entries = (
+ ( "Bold", gtk.STOCK_BOLD, # name, stock id
+ "_Bold", "<control>B", # label, accelerator
+ "Bold", # tooltip
+ activate_action,
+ True ), # is_active
+)
+
+(
+ COLOR_RED,
+ COLOR_GREEN,
+ COLOR_BLUE
+) = range(3)
+
+color_entries = (
+ ( "Red", None, # name, stock id
+ "_Red", "<control>R", # label, accelerator
+ "Blood", COLOR_RED ), # tooltip, value
+ ( "Green", None, # name, stock id
+ "_Green", "<control>G", # label, accelerator
+ "Grass", COLOR_GREEN ), # tooltip, value
+ ( "Blue", None, # name, stock id
+ "_Blue", "<control>B", # label, accelerator
+ "Sky", COLOR_BLUE ), # tooltip, value
+)
+
+(
+ SHAPE_SQUARE,
+ SHAPE_RECTANGLE,
+ SHAPE_OVAL,
+) = range(3)
+
+# GtkRadioActionEntry
+shape_entries = (
+ ( "Square", None, # name, stock id
+ "_Square", "<control>S", # label, accelerator
+ "Square", SHAPE_SQUARE ), # tooltip, value
+ ( "Rectangle", None, # name, stock id
+ "_Rectangle", "<control>R", # label, accelerator
+ "Rectangle", SHAPE_RECTANGLE ), # tooltip, value
+ ( "Oval", None, # name, stock id
+ "_Oval", "<control>O", # label, accelerator
+ "Egg", SHAPE_OVAL ), # tooltip, value
+)
+
+ui_info = \
+'''<ui>
+ <menubar name='MenuBar'>
+ <menu action='FileMenu'>
+ <menuitem action='New'/>
+ <menuitem action='Open'/>
+ <menuitem action='Save'/>
+ <menuitem action='SaveAs'/>
+ <separator/>
+ <menuitem action='Quit'/>
+ </menu>
+ <menu action='PreferencesMenu'>
+ <menu action='ColorMenu'>
+ <menuitem action='Red'/>
+ <menuitem action='Green'/>
+ <menuitem action='Blue'/>
+ </menu>
+ <menu action='ShapeMenu'>
+ <menuitem action='Square'/>
+ <menuitem action='Rectangle'/>
+ <menuitem action='Oval'/>
+ </menu>
+ <menuitem action='Bold'/>
+ </menu>
+ <menu action='HelpMenu'>
+ <menuitem action='About'/>
+ </menu>
+ </menubar>
+ <toolbar name='ToolBar'>
+ <toolitem action='Open'/>
+ <toolitem action='Quit'/>
+ <separator action='Sep1'/>
+ <toolitem action='Logo'/>
+ </toolbar>
+</ui>'''
+
+class UIManagerDemo(gtk.Window):
+
+ def __init__(self, parent=None):
+ gtk.Window.__init__(self)
+ try:
+ self.set_screen(parent.get_screen())
+ except AttributeError:
+ self.connect('destroy', lambda *w: gtk.main_quit())
+ self.set_title(self.__class__.__name__)
+ self.set_border_width(0)
+
+ actions = gtk.ActionGroup("Actions")
+ actions.add_actions(entries)
+ actions.add_toggle_actions(toggle_entries)
+ actions.add_radio_actions(color_entries, COLOR_RED, activate_radio_action)
+ actions.add_radio_actions(shape_entries, SHAPE_OVAL, activate_radio_action)
+
+ ui = gtk.UIManager()
+ ui.insert_action_group(actions, 0)
+ self.add_accel_group(ui.get_accel_group())
+
+ try:
+ mergeid = ui.add_ui_from_string(ui_info)
+ except gobject.GError, msg:
+ print "building menus failed: %s" % msg
+
+ box1 = gtk.VBox(False, 0)
+ self.add(box1)
+
+ box1.pack_start(ui.get_widget("/MenuBar"), False, False, 0)
+
+ label = gtk.Label("Type\n<alt>\nto start")
+ label.set_size_request(200, 200)
+ label.set_alignment(0.5, 0.5)
+ box1.pack_start(label, True, True, 0)
+
+ separator = gtk.HSeparator()
+ box1.pack_start(separator, False, True, 0)
+
+ box2 = gtk.VBox(False, 10)
+ box2.set_border_width(10)
+ box1.pack_start(box2, False, True, 0)
+
+ button = gtk.Button("close")
+ button.connect("clicked", lambda b, w=self: w.destroy())
+ box2.pack_start(button, True, True, 0)
+ button.set_flags(gtk.CAN_DEFAULT)
+ button.grab_default()
+
+ self.show_all()
+
+def main():
+ UIManagerDemo()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
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()