summaryrefslogtreecommitdiff
path: root/examples/gtk/scrollable.py
diff options
context:
space:
mode:
authorJohan Dahlin <johan@src.gnome.org>2006-01-19 19:12:11 +0000
committerJohan Dahlin <johan@src.gnome.org>2006-01-19 19:12:11 +0000
commitec718aaf077d2fabe791cb6a00acfd12454ce4cc (patch)
tree1b8f1ffe104cc4ee4ec476faea244a69f546a897 /examples/gtk/scrollable.py
parent6b5a8a60c481e162f1947fb82992156b2155b5b1 (diff)
downloadpygtk-ec718aaf077d2fabe791cb6a00acfd12454ce4cc.tar.gz
Install examples
* examples/Makefile.am: Install examples * examples/gtk/widget.py: Call unrealize too * examples/gtk/scrollable.py: Add example of a scrollable widget
Diffstat (limited to 'examples/gtk/scrollable.py')
-rw-r--r--examples/gtk/scrollable.py278
1 files changed, 278 insertions, 0 deletions
diff --git a/examples/gtk/scrollable.py b/examples/gtk/scrollable.py
new file mode 100644
index 00000000..6df15e55
--- /dev/null
+++ b/examples/gtk/scrollable.py
@@ -0,0 +1,278 @@
+#
+# Reimplementation of gtk.Layout in python
+# Example on how to implement a scrollable container in python
+#
+# Johan Dahlin <johan@gnome.org>, 2006
+#
+# Requires PyGTK 2.8.0 or later
+
+import gobject
+import gtk
+from gtk import gdk
+
+class Child:
+ widget = None
+ x = 0
+ y = 0
+
+def set_adjustment_upper(adj, upper, always_emit):
+ changed = False
+ value_changed = False
+
+ min = max(0.0, upper - adj.page_size)
+
+ if upper != adj.upper:
+ adj.upper = upper
+ changed = True
+
+ if adj.value > min:
+ adj.value = min
+ value_changed = True
+
+ if changed or always_emit:
+ adj.changed()
+ if value_changed:
+ adj.value_changed()
+
+def new_adj():
+ return gtk.Adjustment(0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0)
+
+class Layout(gtk.Container):
+ __gsignals__ = dict(set_scroll_adjustments=
+ (gobject.SIGNAL_RUN_LAST, None,
+ (gtk.Adjustment, gtk.Adjustment)))
+ def __init__(self):
+ self._children = []
+ self._width = 100
+ self._height = 100
+ self._hadj = None
+ self._vadj = None
+ self._bin_window = None
+ self._hadj_changed_id = -1
+ self._vadj_changed_id = -1
+ gtk.Container.__init__(self)
+
+ if not self._hadj or not self._vadj:
+ self._set_adjustments(self._vadj or new_adj(),
+ self._hadj or new_adj())
+
+ # Public API
+
+ def put(self, widget, x=0, y=0):
+ child = Child()
+ child.widget = widget
+ child.x = x
+ child.y = y
+ self._children.append(child)
+
+ if self.flags() & gtk.REALIZED:
+ widget.set_parent_window(self._bin_window)
+
+ widget.set_parent(self)
+
+ def set_size(self, width, height):
+ if self._width != width:
+ self._width = width
+ if self._height != height:
+ self._height = height
+ if self._hadj:
+ set_adjustment_upper(self._hadj, self._width, False)
+ if self._vadj:
+ set_adjustment_upper(self._vadj, self._height, False)
+
+ if self.flags() & gtk.REALIZED:
+ self._bin_window.resize(max(width, self.allocation.width),
+ max(height, self.allocation.height))
+
+ # GtkWidget
+
+ def do_realize(self):
+ self.set_flags(self.flags() | gtk.REALIZED)
+
+ self.window = gdk.Window(
+ self.get_parent_window(),
+ window_type=gdk.WINDOW_CHILD,
+ x=self.allocation.x,
+ y=self.allocation.y,
+ width=self.allocation.width,
+ height=self.allocation.height,
+ wclass=gdk.INPUT_OUTPUT,
+ colormap=self.get_colormap(),
+ event_mask=gdk.VISIBILITY_NOTIFY_MASK)
+ self.window.set_user_data(self)
+
+ self._bin_window = gdk.Window(
+ self.window,
+ window_type=gdk.WINDOW_CHILD,
+ x=int(-self._hadj.value),
+ y=int(-self._vadj.value),
+ width=max(self._width, self.allocation.width),
+ height=max(self._height, self.allocation.height),
+ colormap=self.get_colormap(),
+ wclass=gdk.INPUT_OUTPUT,
+ event_mask=(self.get_events() | gdk.EXPOSURE_MASK |
+ gdk.SCROLL_MASK))
+ self._bin_window.set_user_data(self)
+
+ self.set_style(self.style.attach(self.window))
+ self.style.set_background(self.window, gtk.STATE_NORMAL)
+ self.style.set_background(self._bin_window, gtk.STATE_NORMAL)
+
+ for child in self._children:
+ child.widget.set_parent_window(self._bin_window)
+ self.queue_resize()
+
+ def do_unrealize(self):
+ self._bin_window.set_user_data(None)
+ self._bin_window = None
+ gtk.Container.do_unrealize(self)
+
+ def _do_style_set(self, style):
+ gtk.Widget.do_style_set(self, style)
+
+ if self.flags() & gtk.REALIZED:
+ self.style.set_background(self._bin_window, gtk.STATE_NORMAL)
+
+ def do_expose_event(self, event):
+ if event.window != self._bin_window:
+ return False
+ gtk.Container.do_expose_event(self, event)
+ return False
+
+ def do_map(self):
+ self.set_flags(self.flags() | gtk.MAPPED)
+ for child in self._children:
+ flags = child.widget.flags()
+ if flags & gtk.VISIBLE:
+ if not (flags & gtk.MAPPED):
+ child.widget.map()
+ self._bin_window.show()
+ self.window.show()
+
+ def do_size_request(self, req):
+ req.width = 0
+ req.height = 0
+ for child in self._children:
+ child.widget.size_request()
+
+ def do_size_allocate(self, allocation):
+ for child in self._children:
+ self._allocate_child(child)
+
+ if self.flags() & gtk.REALIZED:
+ self.window.move_resize(*allocation)
+ self._bin_window.resize(max(self._width, allocation.width),
+ max(self._height, allocation.height))
+
+ self._hadj.page_size = allocation.width
+ self._hadj.page_increment = allocation.width * 0.9
+ self._hadj.lower = 0
+ set_adjustment_upper(self._hadj,
+ max(allocation.width, self._width), True)
+
+ self._vadj.page_size = allocation.height
+ self._vadj.page_increment = allocation.height * 0.9
+ self._vadj.lower = 0
+ self._vadj.upper = max(allocation.height, self._height)
+ set_adjustment_upper(self._vadj,
+ max(allocation.height, self._height), True)
+
+ def do_set_scroll_adjustments(self, hadj, vadj):
+ self._set_adjustments(hadj, vadj)
+
+ # GtkContainer
+
+ def do_forall(self, include_internals, callback, data):
+ for child in self._children:
+ callback(child.widget, data)
+
+ def do_add(self, widget):
+ self.put(widget)
+
+ def do_remove(self, widget):
+ child = self._get_child_from_widget(widget)
+ self._children.remove(child)
+ widget.unparent()
+
+ # Private
+
+ def _set_adjustments(self, hadj, vadj):
+ if not hadj and self._hadj:
+ hadj = new_adj()
+
+ if not vadj and self._vadj:
+ vadj = new_adj()
+
+ if self._hadj and self._hadj != hadj:
+ self._hadj.disconnect(self._hadj_changed_id)
+
+ if self._vadj and self._vadj != vadj:
+ self._vadj.disconnect(self._vadj_changed_id)
+
+ need_adjust = False
+
+ if self._hadj != hadj:
+ self._hadj = hadj
+ set_adjustment_upper(hadj, self._width, False)
+ self._hadj_changed_id = hadj.connect(
+ "value-changed",
+ self._adjustment_changed)
+ need_adjust = True
+
+ if self._vadj != vadj:
+ self._vadj = vadj
+ set_adjustment_upper(vadj, self._height, False)
+ self._vadj_changed_id = vadj.connect(
+ "value-changed",
+ self._adjustment_changed)
+ need_adjust = True
+
+ if need_adjust and vadj and hadj:
+ self._adjustment_changed()
+
+ def _adjustment_changed(self, adj=None):
+ if self.flags() & gtk.REALIZED:
+ self._bin_window.move(int(-self._hadj.value),
+ int(-self._vadj.value))
+ self._bin_window.process_updates(True)
+
+ def _get_child_from_widget(self, widget):
+ for child in self._children:
+ if child.widget == widget:
+ return child
+ else:
+ raise AssertionError
+
+ def _allocate_child(self, child):
+ allocation = gdk.Rectangle()
+ allocation.x = child.x
+ allocation.y = child.y
+ req = child.widget.get_child_requisition()
+ allocation.width = req[0]
+ allocation.height = req[1]
+ child.widget.size_allocate(allocation)
+
+Layout.set_set_scroll_adjustments_signal('set-scroll-adjustments')
+
+def main():
+ window = gtk.Window()
+ window.set_size_request(300, 300)
+ window.connect('delete-event', gtk.main_quit)
+
+ sw = gtk.ScrolledWindow()
+ sw.set_policy(gtk.POLICY_ALWAYS, gtk.POLICY_ALWAYS)
+ window.add(sw)
+
+ layout = Layout()
+ layout.set_size(1000, 1000)
+ sw.add(layout)
+
+ b = gtk.Button('foobar')
+ layout.put(b, 100, 100)
+
+ window.show_all()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()