[gjs] Gtk: add override to handle GtkWidget templates



commit 3e28510522d819b2106047580d2742efc0100952
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Tue May 14 22:33:15 2013 +0200

    Gtk: add override to handle GtkWidget templates
    
    Add a new override module for Gtk, which provides a custom metaclass
    to all GtkWidget derived classes.
    This metaclass accepts an additional parameter, Template, which is either
    a resource:/// URI or a bare XML string, and takes care of calling
    gtk_widget_class_set_template() and gtk_widget_init_template()
    
    https://bugzilla.gnome.org/show_bug.cgi?id=700347

 Makefile-test.am            |    4 ++
 modules/overrides/Gtk.js    |   85 ++++++++++++++++++++++++++++++++++++++++++-
 test/interactive/testGtk.js |   54 +++++++++++++++++++++++++++
 3 files changed, 142 insertions(+), 1 deletions(-)
---
diff --git a/Makefile-test.am b/Makefile-test.am
index b91840b..9673d91 100644
--- a/Makefile-test.am
+++ b/Makefile-test.am
@@ -2,6 +2,10 @@ EXTRA_DIST += \
        test/run-with-dbus \
        test/test-bus.conf
 
+# Other custom tests, not automated
+dist_noinst_DATA =
+       test/interactive/testGtk.js
+
 RUN_WITH_DBUS = ${top_srcdir}/test/run-with-dbus --session --system
 GTESTER = ${TESTS_ENVIRONMENT} ${RUN_WITH_DBUS} gtester
 CLEANFILES += uninstalled-system-test-bus.conf uninstalled-test-bus.conf
diff --git a/modules/overrides/Gtk.js b/modules/overrides/Gtk.js
index 16fac20..c8668c7 100644
--- a/modules/overrides/Gtk.js
+++ b/modules/overrides/Gtk.js
@@ -1,9 +1,92 @@
+// application/javascript;version=1.8
+// Copyright 2013 Giovanni Campagna
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+
+const Lang = imports.lang;
+const GObject = imports.gi.GObject;
+
 var GjsPrivate = imports.gi.GjsPrivate;
-var Gtk;
+
+let Gtk;
+
+const GtkWidgetClass = new Lang.Class({
+    Name: 'GtkWidgetClass',
+    Extends: GObject.Class,
+
+    _init: function(params) {
+        let template = params.Template;
+        delete params.Template;
+
+        let children = params.Children;
+        delete params.children;
+
+        let internalChildren = params.InternalChildren;
+        delete params.internalChildren;
+
+        params._instance_init = function() {
+            this.init_template();
+        };
+
+        this.parent(params);
+
+        if (template) {
+            if (typeof template == 'string' &&
+                template.startsWith('resource:///'))
+                Gtk.Widget.set_template_from_resource.call(this, template);
+            else
+                Gtk.Widget.set_template.call(this, template);
+        }
+
+        this.Template = template;
+
+        if (children) {
+            for (let i = 0; i < children.length; i++)
+                Gtk.Widget.bind_template_child_full.call(this, children[i], false, 0);
+        }
+
+        if (internalChildren) {
+            for (let i = 0; i < internalChildren.length; i++)
+                Gtk.Widget.bind_template_child_full.call(this, internalChildren[i], true, 0);
+        }
+    },
+
+    _isValidClass: function(klass) {
+        let proto = klass.prototype;
+
+        if (!proto)
+            return false;
+
+        // If proto == Gtk.Widget.prototype, then
+        // proto.__proto__ is GObject.InitiallyUnowned, so
+        // "proto instanceof Gtk.Widget"
+        // will return false.
+        return proto == Gtk.Widget.prototype ||
+            proto instanceof Gtk.Widget;
+    },
+});
 
 function _init() {
+
     Gtk = this;
 
+    Gtk.Widget.prototype.__metaclass__ = GtkWidgetClass;
     if (GjsPrivate.gtk_container_child_set_property) {
         Gtk.Container.prototype.child_set_property = function(child, property, value) {
             GjsPrivate.gtk_container_child_set_property(this, child, property, value);
diff --git a/test/interactive/testGtk.js b/test/interactive/testGtk.js
new file mode 100755
index 0000000..acaf457
--- /dev/null
+++ b/test/interactive/testGtk.js
@@ -0,0 +1,54 @@
+#!/usr/bin/env gjs
+
+const ByteArray = imports.byteArray;
+const Gio = imports.gi.Gio;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+// This is ugly here, but usually it would be in a resource
+const template = ' \
+<interface> \
+  <template class="Gjs_MyComplexGtkSubclass" parent="GtkGrid"> \
+    <property name="margin_top">10</property> \
+    <property name="margin_bottom">10</property> \
+    <property name="margin_start">10</property> \
+    <property name="margin_end">10</property> \
+    <property name="visible">True</property> \
+    <child> \
+      <object class="GtkLabel" id="label-child"> \
+        <property name="label">Complex!</property> \
+        <property name="visible">True</property> \
+      </object> \
+    </child> \
+  </template> \
+</interface>';
+
+const MyComplexGtkSubclass = new Lang.Class({
+    Name: 'MyComplexGtkSubclass',
+    Extends: Gtk.Grid,
+    Template: ByteArray.fromString(template),
+    Children: ['label-child'],
+
+    _init: function(params) {
+        this.parent(params);
+
+        this._internalLabel = this.get_template_child(MyComplexGtkSubclass, 'label-child');
+        log(this._internalLabel);
+    }
+});
+
+function main() {
+    let app = new Gtk.Application({ application_id: 'org.gnome.gjs.TestApplication' });
+
+    app.connect('activate', function() {
+        let win = new Gtk.ApplicationWindow({ application: app });
+        let content = new MyComplexGtkSubclass();
+
+        win.add(content);
+        win.show();
+    });
+
+    app.run(null);
+}
+
+main();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]