[gjs/wip/ptomato/classes: 9/10] Gtk: Use GObject.registerClass() for Gtk.Widgets



commit 584a56f3605c2432a2b3ca4bb165dc7b16e1f5c9
Author: Philip Chimento <philip endlessm com>
Date:   Thu Aug 3 04:42:39 2017 +0100

    Gtk: Use GObject.registerClass() for Gtk.Widgets
    
    This extends the GObject.registerClass() API to deal with the magic
    properties from Gtk.WidgetClass: CssName, Template, Children, and
    InternalChildren.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=785652

 installed-tests/js/testGtk.js |   40 ++++++++++++--------------------
 modules/_legacy.js            |    9 ++++---
 modules/overrides/GObject.js  |   19 +++++++++++++++
 modules/overrides/Gtk.js      |   51 ++++++++++++++++++++++++++++++++++++++--
 4 files changed, 87 insertions(+), 32 deletions(-)
---
diff --git a/installed-tests/js/testGtk.js b/installed-tests/js/testGtk.js
index db97108..8e76605 100755
--- a/installed-tests/js/testGtk.js
+++ b/installed-tests/js/testGtk.js
@@ -1,8 +1,8 @@
 imports.gi.versions.Gtk = '3.0';
 
 const ByteArray = imports.byteArray;
+const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
-const Lang = imports.lang;
 
 // This is ugly here, but usually it would be in a resource
 const template = ' \
@@ -34,40 +34,30 @@ const template = ' \
   </template> \
 </interface>';
 
-const MyComplexGtkSubclass = new Lang.Class({
-    Name: 'MyComplexGtkSubclass',
-    Extends: Gtk.Grid,
+const MyComplexGtkSubclass = GObject.registerClass({
     Template: ByteArray.fromString(template),
     Children: ['label-child', 'label-child2'],
     InternalChildren: ['internal-label-child'],
     CssName: 'complex-subclass',
+}, class MyComplexGtkSubclass extends Gtk.Grid {});
 
-    // _init: function(params) {
-    //     this.parent(params);
-    // },
+// Sadly, putting this in the body of the class will prevent calling
+// get_template_child, since MyComplexGtkSubclass will be bound to the ES6
+// class name without the GObject goodies in it
+MyComplexGtkSubclass.prototype.testChildrenExist = function() {
+    this._internalLabel = this.get_template_child(MyComplexGtkSubclass, 'label-child');
+    expect(this._internalLabel).toEqual(jasmine.anything());
 
-    testChildrenExist: function () {
-        this._internalLabel = this.get_template_child(MyComplexGtkSubclass, 'label-child');
-        expect(this._internalLabel).toEqual(jasmine.anything());
+    expect(this.label_child2).toEqual(jasmine.anything());
+    expect(this._internal_label_child).toEqual(jasmine.anything());
+};
 
-        expect(this.label_child2).toEqual(jasmine.anything());
-        expect(this._internal_label_child).toEqual(jasmine.anything());
-    }
-});
-
-
-const MyComplexGtkSubclassFromResource = new Lang.Class({
-    Name: 'MyComplexGtkSubclassFromResource',
-    Extends: Gtk.Grid,
+const MyComplexGtkSubclassFromResource = GObject.registerClass({
     Template: 'resource:///org/gjs/jsunit/complex.ui',
     Children: ['label-child', 'label-child2'],
     InternalChildren: ['internal-label-child'],
-
-    // _init: function(params) {
-    //     this.parent(params);
-    // },
-
-    testChildrenExist: function () {
+}, class MyComplexGtkSubclassFromResource extends Gtk.Grid {
+    testChildrenExist() {
         expect(this.label_child).toEqual(jasmine.anything());
         expect(this.label_child2).toEqual(jasmine.anything());
         expect(this._internal_label_child).toEqual(jasmine.anything());
diff --git a/modules/_legacy.js b/modules/_legacy.js
index 92fe4b3..6f73ade 100644
--- a/modules/_legacy.js
+++ b/modules/_legacy.js
@@ -1,5 +1,6 @@
 /* -*- mode: js; indent-tabs-mode: nil; -*- */
-/* exported Class, Interface, defineGObjectLegacyObjects */
+/* exported Class, Interface, defineGObjectLegacyObjects,
+defineGtkLegacyObjects */
 // Copyright 2008  litl, LLC
 // Copyright 2011  Jasper St. Pierre
 
@@ -657,9 +658,9 @@ function defineGtkLegacyObjects(GObject, Gtk) {
                     Gtk.Widget.set_template.call(this, template);
             }
 
-            this.Template = template;
-            this.Children = children;
-            this.InternalChildren = internalChildren;
+            this[Gtk.template] = template;
+            this[Gtk.children] = children;
+            this[Gtk.internalChildren] = internalChildren;
 
             if (children) {
                 for (let i = 0; i < children.length; i++)
diff --git a/modules/overrides/GObject.js b/modules/overrides/GObject.js
index 2d021d6..abcbd23 100644
--- a/modules/overrides/GObject.js
+++ b/modules/overrides/GObject.js
@@ -32,6 +32,12 @@ var properties = Symbol('GObject properties');
 var requires = Symbol('GObject interface requires');
 var signals = Symbol('GObject signals');
 
+// These four will be aliased to GTK
+var _children = Symbol('GTK widget template children');
+var _cssName = Symbol('GTK widget CSS name');
+var _internalChildren = Symbol('GTK widget template internal children');
+var _template = Symbol('GTK widget template');
+
 function registerClass(klass) {
     if (arguments.length == 2) {
         // The two-argument form is the convenient syntax without ESnext
@@ -60,6 +66,14 @@ function registerClass(klass) {
             klass[signals] = metaInfo.Signals;
         if ('Requires' in metaInfo)
             klass[requires] = metaInfo.Requires;
+        if ('CssName' in metaInfo)
+            klass[_cssName] = metaInfo.CssName;
+        if ('Template' in metaInfo)
+            klass[_template] = metaInfo.Template;
+        if ('Children' in metaInfo)
+            klass[_children] = metaInfo.Children;
+        if ('InternalChildren' in metaInfo)
+            klass[_internalChildren] = metaInfo.InternalChildren;
     }
 
     if (!(klass.prototype instanceof GObject.Object) &&
@@ -422,6 +436,11 @@ function _init() {
         get name() { return 'NotImplementedError'; }
     };
 
+    GObject._cssName = _cssName;
+    GObject._template = _template;
+    GObject._children = _children;
+    GObject._internalChildren = _internalChildren;
+
     // fake enum for signal accumulators, keep in sync with gi/object.c
     this.AccumulatorType = {
         NONE: 0,
diff --git a/modules/overrides/Gtk.js b/modules/overrides/Gtk.js
index 4816a9c..a1f427e 100644
--- a/modules/overrides/Gtk.js
+++ b/modules/overrides/Gtk.js
@@ -30,8 +30,14 @@ function _init() {
 
     Gtk = this;
 
+    Gtk.children = GObject._children;
+    Gtk.cssName = GObject._cssName;
+    Gtk.internalChildren = GObject._internalChildren;
+    Gtk.template = GObject._template;
+
     let {GtkWidgetClass} = Legacy.defineGtkLegacyObjects(GObject, Gtk);
     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);
@@ -41,18 +47,57 @@ function _init() {
     Gtk.Widget.prototype._init = function(params) {
         GObject.Object.prototype._init.call(this, params);
 
-        if (this.constructor.Template) {
-            let children = this.constructor.Children || [];
+        if (this.constructor[Gtk.template]) {
+            let children = this.constructor[Gtk.children] || [];
             for (let child of children) {
                 this[child.replace(/-/g, '_')] =
                     this.get_template_child(this.constructor, child);
             }
 
-            let internalChildren = this.constructor.InternalChildren || [];
+            let internalChildren = this.constructor[Gtk.internalChildren] || [];
             for (let child of internalChildren) {
                 this['_' + child.replace(/-/g, '_')] =
                     this.get_template_child(this.constructor, child);
             }
         }
     };
+
+    Gtk.Widget._classInit = function(klass) {
+        let template = klass[Gtk.template];
+        let cssName = klass[Gtk.cssName];
+        let children = klass[Gtk.children];
+        let internalChildren = klass[Gtk.internalChildren];
+
+        if (template) {
+            klass.prototype._instance_init = function() {
+                this.init_template();
+            };
+        }
+
+        klass = GObject.Object._classInit(klass);
+
+        if (cssName)
+            Gtk.Widget.set_css_name.call(klass, cssName);
+
+        if (template) {
+            if (typeof template === 'string' &&
+                template.startsWith('resource:///'))
+                Gtk.Widget.set_template_from_resource.call(klass,
+                    template.slice(11));
+            else
+                Gtk.Widget.set_template.call(klass, template);
+        }
+
+        if (children) {
+            children.forEach(child =>
+                Gtk.Widget.bind_template_child_full.call(klass, child, false, 0));
+        }
+
+        if (internalChildren) {
+            internalChildren.forEach(child =>
+                Gtk.Widget.bind_template_child_full.call(klass, child, true, 0));
+        }
+
+        return klass;
+    };
 }


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