OSDN Git Service

glade: wrap concrete elastic container/content
authorAndrew Chadwick <andrewc-git@piffle.org>
Sat, 17 Sep 2011 00:25:17 +0000 (01:25 +0100)
committerAndrew Chadwick <andrewc-git@piffle.org>
Sun, 2 Oct 2011 17:38:15 +0000 (18:38 +0100)
Factor elastic containers and components out to their own module and add
a trivial ElasticWindow that can be built on later. Add the concrete
classes we have to the glade library, though it's mostly the expander /
window relationship we really care about.

12 files changed:
glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-expander.png [new file with mode: 0644]
glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-vbox.png [new file with mode: 0644]
glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-window.png [new file with mode: 0644]
glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-expander.png [new file with mode: 0644]
glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-vbox.png [new file with mode: 0644]
glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-window.png [new file with mode: 0644]
glade/mypaint_widgets.py
glade/mypaint_widgets.xml
gui/brushselectionwindow.py
gui/colorsamplerwindow.py
gui/elastic.py [new file with mode: 0644]
gui/layout.py

diff --git a/glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-expander.png b/glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-expander.png
new file mode 100644 (file)
index 0000000..279c857
Binary files /dev/null and b/glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-expander.png differ
diff --git a/glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-vbox.png b/glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-vbox.png
new file mode 100644 (file)
index 0000000..b17a134
Binary files /dev/null and b/glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-vbox.png differ
diff --git a/glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-window.png b/glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-window.png
new file mode 100644 (file)
index 0000000..7d165ec
Binary files /dev/null and b/glade/icons/hicolor/16x16/actions/widget-mypaint-elastic-window.png differ
diff --git a/glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-expander.png b/glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-expander.png
new file mode 100644 (file)
index 0000000..4bc28b7
Binary files /dev/null and b/glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-expander.png differ
diff --git a/glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-vbox.png b/glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-vbox.png
new file mode 100644 (file)
index 0000000..eee47af
Binary files /dev/null and b/glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-vbox.png differ
diff --git a/glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-window.png b/glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-window.png
new file mode 100644 (file)
index 0000000..59dfd89
Binary files /dev/null and b/glade/icons/hicolor/22x22/actions/widget-mypaint-elastic-window.png differ
index 75cc85d..ee082ba 100644 (file)
@@ -4,4 +4,4 @@
 
 from gui.tileddrawwidget import TiledDrawWidget
 from gui.pixbuflist import PixbufList
-
+from gui.elastic import ElasticWindow, ElasticVBox, ElasticExpander
index 0c74259..7a6caef 100644 (file)
                         generic-name="tdw" />
     <glade-widget-class name="PixbufList" title="Pixbuf List"
                         generic-name="pixbuflist" />
+    <glade-widget-class name="ElasticWindow" title="Elastic Window"
+                        generic-name="elastic-window" />
+    <glade-widget-class name="ElasticVBox" title="Elastic VBox"
+                        generic-name="elastic-vbox" />
+    <glade-widget-class name="ElasticExpander" title="Elastic Expander"
+                        generic-name="elastic-expander" />
   </glade-widget-classes>
 
   <glade-widget-group name="MyPaint" title="MyPaint Widgets">
     <glade-widget-class-ref name="TiledDrawWidget"/>
     <glade-widget-class-ref name="PixbufList"/>
+    <!-- ElasticWindow doesn't behave especially well in Glade, but it
+         can be built. That'll do. -->
+    <glade-widget-class-ref name="ElasticWindow"/>
+    <glade-widget-class-ref name="ElasticVBox"/>
+    <glade-widget-class-ref name="ElasticExpander"/>
   </glade-widget-group>
 
 </glade-catalog>
index c4b8941..52fc650 100644 (file)
@@ -14,7 +14,7 @@ from gettext import gettext as _
 import windowing
 import stock
 import pixbuflist, dialogs, brushmanager
-from layout import ElasticExpander
+from elastic import ElasticExpander
 from brushlib import brushsettings
 
 class ToolWidget (gtk.VBox):
index 53a05c6..95d4311 100755 (executable)
@@ -5,7 +5,7 @@ import struct
 import cairo
 import windowing
 import stock
-from layout import ElasticExpander
+from elastic import ElasticExpander
 from lib.helpers import rgb_to_hsv, hsv_to_rgb, clamp
 from gettext import gettext as _
 import gobject
diff --git a/gui/elastic.py b/gui/elastic.py
new file mode 100644 (file)
index 0000000..716fb9c
--- /dev/null
@@ -0,0 +1,169 @@
+# This file is part of MyPaint.
+# Copyright (C) 2011 by Andrew Chadwick <andrewc-git@piffle.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+import gtk
+from gtk import gdk
+
+
+class ElasticContainer:
+    """Mixin for containers which mirror certain size changes of descendents
+
+    Descendents which wish to report internally-generated size changes should
+    add the ElasticContent mixin, and should be packed into a container that
+    derives from ElasticContainer. More than one ElasticContent widget can be
+    packed under an ElasticContainer, and each can report different types of
+    resizes - however the sub-hierarchies cannot overlap. You -can- nest
+    ElasticContainers though: it's the outer one that receives the resize
+    request.
+    """
+
+    def __init__(self):
+        """Mixin constructor (construct as a gtk.Widget before calling)
+        """
+        self.__last_size = None
+        self.__saved_size_request = None
+
+    def mirror_elastic_content_resize(self, dx, dy):
+        """Resize by a given amount.
+
+        This is called by some ElasticContent widget below here in the
+        hierarchy when it notices a request-size change on itself.
+        """
+        p = self.parent
+        while p is not None:
+            if isinstance(p, ElasticContainer):
+                # propagate up and don't handle here
+                p.mirror_elastic_content_resize(dx, dy)
+                return
+            p = p.parent
+        self.__saved_size_request = self.get_size_request()
+        alloc = self.get_allocation()
+        w = alloc.width+dx
+        h = alloc.height+dy
+        if isinstance(self, gtk.Window):
+            self.resize(w, h)
+        self.set_size_request(w, h)
+        self.queue_resize()
+
+
+class ElasticContent:
+    """Mixin for GTK widgets which want some parent to change size to match.
+    """
+
+    def __init__(self, mirror_vertical=True, mirror_horizontal=True):
+        """Mixin constructor (construct as a gtk.Widget before calling)
+
+        The options control which size changes are reported to the
+        ElasticContainer ancestor and how:
+
+            `mirror_vertical`:
+                mirror vertical size changes
+
+            `mirror_horizontal`:
+                mirror horizontal size changes
+
+        """
+        self.__vertical = mirror_vertical
+        self.__horizontal = mirror_horizontal
+        if not mirror_horizontal and not mirror_vertical:
+            return
+        self.__last_req = None
+        self.__expose_connid = self.connect_after("expose-event",
+            self.__after_expose_event)
+        self.__notify_parent = False
+        self.connect_after("size-request", self.__after_size_request)
+
+    def __after_expose_event(self, widget, event):
+        # Begin notifying changes to the ancestor after the first expose event.
+        # It doesn't matter for widgets that know their size before hand.
+        # Assume widgets which initially don't know their size *do* know their
+        # proper size after their first draw, even if they drew themselves
+        # wrongly and now have to resize and do another size-request...
+        connid = self.__expose_connid
+        if not connid:
+            return
+        self.__expose_connid = None
+        self.__notify_parent = True
+        self.disconnect(connid)
+
+    def __after_size_request(self, widget, req):
+        # Catch the final value of each size-request, calculate the
+        # difference needed and throw it back up the widget hierarchy
+        # to interested parties.
+        if not self.__last_req:
+            dx, dy = 0, 0
+        else:
+            w0, h0 = self.__last_req
+            dx, dy = req.width - w0, req.height - h0
+        self.__last_req = (req.width, req.height)
+        if not self.__notify_parent:
+            return
+        p = self.parent
+        while p is not None:
+            if isinstance(p, ElasticContainer):
+                if not self.__vertical:
+                    dy = 0
+                if not self.__horizontal:
+                    dx = 0
+                if dy != 0 or dx != 0:
+                    p.mirror_elastic_content_resize(dx, dy)
+                break
+            if isinstance(p, ElasticContent):
+                break
+            p = p.parent
+
+
+# XXX unused, may remove
+class ElasticVBox (gtk.VBox, ElasticContainer):
+    __gtype_name__ = "ElasticVBox"
+
+    def __init__(self, *args, **kwargs):
+        gtk.VBox.__init__(self, *args, **kwargs)
+        ElasticContainer.__init__(self)
+
+
+class ElasticExpander (gtk.Expander, ElasticContent):
+    """Buildable elastic-content version of a regular GtkExpander.
+    """
+    __gtype_name__ = "ElasticExpander"
+
+    def __init__(self, *args, **kwargs):
+        gtk.Expander.__init__(self, *args, **kwargs)
+        ElasticContent.__init__(self, mirror_horizontal=False,
+                                mirror_vertical=True)
+
+
+class ElasticWindow (gtk.Window, ElasticContainer):
+    """Buildable elastic-container version of a regular gtk.Window.
+    """
+    __gtype_name__ = "ElasticWindow"
+
+    def __init__(self, *args, **kwargs):
+        gtk.Window.__init__(self, *args, **kwargs)
+        ElasticContainer.__init__(self)
+
+
+if __name__ == '__main__':
+    win1 = ElasticWindow()
+    vbox = gtk.VBox()
+    ee = ElasticExpander()
+    ee.set_label("expand (expands window)")
+
+    l1 = gtk.Label("Main content\ngoes here.")
+    l2 = gtk.Label("Extra content\n\nBlah blah")
+    vbox.pack_start(l1, True, True)
+    vbox.pack_start(ee, False, True)
+    ee.add(l2)
+    win1.add(vbox)
+    win1.set_title("elastic test")
+    win1.connect("destroy", lambda *a: gtk.main_quit())
+    win1.show_all()
+
+    gtk.main()
+
+
index 7516dab..8ee3835 100644 (file)
@@ -20,6 +20,8 @@ import pango
 import cairo
 from gettext import gettext as _
 
+from elastic import ElasticContainer
+
 
 class LayoutManager:
     """Keeps track of tool positions, and main window state.
@@ -212,127 +214,6 @@ class LayoutManager:
             func(*args, **kwargs)
 
 
-class ElasticContainer:
-    """Mixin for containers which mirror certain size changes of descendents
-
-    Descendents which wish to report internally-generated size changes should
-    add the ElasticContent mixin, and should be packed into a container that
-    derives from ElasticContainer. More than one ElasticContent widget can be
-    packed under an ElasticContainer, and each can report different types of
-    resizes - however the sub-hierarchies cannot overlap. You -can- nest
-    ElasticContainers though: it's the outer one that receives the resize
-    request.
-    """
-
-    def __init__(self):
-        """Mixin constructor (construct as a gtk.Widget before calling)
-        """
-        self.__last_size = None
-        self.__saved_size_request = None
-
-    def mirror_elastic_content_resize(self, dx, dy):
-        """Resize by a given amount.
-
-        This is called by some ElasticContent widget below here in the
-        hierarchy when it notices a request-size change on itself.
-        """
-        p = self.parent
-        while p is not None:
-            if isinstance(p, ElasticContainer):
-                # propagate up and don't handle here
-                p.mirror_elastic_content_resize(dx, dy)
-                return
-            p = p.parent
-        self.__saved_size_request = self.get_size_request()
-        alloc = self.get_allocation()
-        w = alloc.width+dx
-        h = alloc.height+dy
-        if isinstance(self, gtk.Window):
-            self.resize(w, h)
-        self.set_size_request(w, h)
-        self.queue_resize()
-
-
-class ElasticContent:
-    """Mixin for GTK widgets which want some parent to change size to match.
-    """
-
-    def __init__(self, mirror_vertical=True, mirror_horizontal=True):
-        """Mixin constructor (construct as a gtk.Widget before calling)
-
-        The options control which size changes are reported to the
-        ElasticContainer ancestor and how:
-
-            `mirror_vertical`:
-                mirror vertical size changes
-
-            `mirror_horizontal`:
-                mirror horizontal size changes
-
-        """
-        self.__vertical = mirror_vertical
-        self.__horizontal = mirror_horizontal
-        if not mirror_horizontal and not mirror_vertical:
-            return
-        self.__last_req = None
-        self.__expose_connid = self.connect_after("expose-event",
-            self.__after_expose_event)
-        self.__notify_parent = False
-        self.connect_after("size-request", self.__after_size_request)
-
-    def __after_expose_event(self, widget, event):
-        # Begin notifying changes to the ancestor after the first expose event.
-        # It doesn't matter for widgets that know their size before hand.
-        # Assume widgets which initially don't know their size *do* know their
-        # proper size after their first draw, even if they drew themselves
-        # wrongly and now have to resize and do another size-request...
-        connid = self.__expose_connid
-        if not connid:
-            return
-        self.__expose_connid = None
-        self.__notify_parent = True
-        self.disconnect(connid)
-
-    def __after_size_request(self, widget, req):
-        # Catch the final value of each size-request, calculate the
-        # difference needed and throw it back up the widget hierarchy
-        # to interested parties.
-        if not self.__last_req:
-            dx, dy = 0, 0
-        else:
-            w0, h0 = self.__last_req
-            dx, dy = req.width - w0, req.height - h0
-        self.__last_req = (req.width, req.height)
-        if not self.__notify_parent:
-            return
-        p = self.parent
-        while p is not None:
-            if isinstance(p, ElasticContainer):
-                if not self.__vertical:
-                    dy = 0
-                if not self.__horizontal:
-                    dx = 0
-                if dy != 0 or dx != 0:
-                    p.mirror_elastic_content_resize(dx, dy)
-                break
-            if isinstance(p, ElasticContent):
-                break
-            p = p.parent
-
-
-class ElasticVBox (gtk.VBox, ElasticContainer):
-    def __init__(self, *args, **kwargs):
-        gtk.VBox.__init__(self, *args, **kwargs)
-        ElasticContainer.__init__(self)
-
-
-class ElasticExpander (gtk.Expander, ElasticContent):
-    def __init__(self, *args, **kwargs):
-        gtk.Expander.__init__(self, *args, **kwargs)
-        ElasticContent.__init__(self, mirror_horizontal=False,
-                                mirror_vertical=True)
-
-
 class WindowWithSavedPosition:
     """Mixin for gtk.Windows which load/save their position via a LayoutManager.