Published 2010-01-19 17:36:52


Unfortunately my internet line died over the weekend, and I was left without a connection until Tuesday. I had a bit of offline time to have a look at some interesting new(ish) technology.

If you have paid any attention to Gnome development, there are mentions of gnome-shell, and something about making it easier to develop add-on/applets etc. using Javascript. I have not really had time to look at this much, however given the fact I had downloaded all the components prior to my loss of connectivity, I spent some time over the weekend and monday looking at this in more detail.

It looks like there are obviously things going on in IRC and mailing lists, so most of my impressions are from the websites, and code. There are basically 2 projects currently.

GJS - This is the mozilla Javascript engine bound to the gobject introspection system
Seed - This is the webkit Javascript engine bound to the gobject introspection system

Of the two, Seed apears to be a little more advanced and more time has gone into it, based on the fact there appear to be more core features in Seed (eg. I could not find anything like Seed.print() in GJS), and there are very few examples in GJS

Both of these use the GObject introspection method to bind to Gtk, and a large and growing number of other libraries. This is something I found very interesting having gone through a similar process with rooscript.

The fundimental issue of creating bindings to Gtk (and anything that uses the GObject system) is that historically, almost everyone (PHP, Python etc.) who did it used this method.

* Parse the HTML documentation, or the .h files (extracting the classes, enums, methods, arguments etc.)
* Generate Binding code for each library, which wraps these methods, loads the '.so' libraries and links it all together.
* Compile a Module (or statically link it in some cases)
* Run... Test.. Fix bugs in wrapping code... Run ... Test.

What GObject inspection introduces is an very thin layer that can be used to expose any of these methods without writing any binding code (other than to GObject inspection). The result is that to add more features (linking to another library) - you just have to generate a XML file describing the interface, compile it with g-ir-compile and put it in the right folder, and you have magically added support to a new Library, without generating an C code!

This also means that fixing the binding is considerably simpler (fix the XML file, re-compile etc.) and you have solved bugs in any language that is using it... (as I found with gtk_tree_store_set_column_types()

Playing with the languages.


GJS and Seed present the Gtk API very slightly differently, which at present appears to be a bit of a blocker for deciding which to use (or even to bother for some). The key differences are for authoring

* Javascript 'let' features in GJS - not available in Seed.. - This is rather a big blocker as code designed for GJS will fail in Seed totally.. (and visa-versa probably)
* Different call signatures to signals� � �  SEED:OBJECT.signal.connect(method)�  vs�  GJS:OBJECT.connect('signal', method)�  - I think personally that GJS way is more true to the concept and cleaner, however as you can see below there are ways around this.

Seed has a git repo on gnome 'seed-examples', which contains a large number of examples, although their depth is rather thin unfortunatly.. (code coverage is probably 1% at best)...
Both have pretty much Zero in the documentation stakes.. - A rather trivial task to create - which I'm tempted to have a go at....

Anyway back to my playing around..


I've been doing some serious shit in Javascript recently, GUI builders, Code generators, Hacking GTK bindings etc. so I've seen the good, bad and ugly as far as Javascript goes (Bad sometimes being my code).�  I've been slowly moving to what I regard as an effecient, productive use of Javascript, most of which can be seen in the xtype support in RooJS

After runing the first few examples in seed-examples, I decided to see if using an xtype / Roo structure could be done with Seed. After a bit of tweaking, and bugfixing of Seed, I finally got this code to work.



var win = XN.xnew({
xtype : Gtk.Window,
type: Gtk.WindowType.TOPLEVEL,
listeners : {
'delete-event' : function (widget, event) {
return false;
},
destroy : function (widget) {
Gtk.main_quit();
}
},

set : {
set_border_width : [ 10 ],
resize : [300, 300],
show_all : []
},
items : [
{
xtype : Gtk.VBox,

items : [
{
xtype : Gtk.TreeView,



onRender : function()
{
this.column = XN.xnew({
xtype : Gtk.TreeViewColumn,
items : [
{
xtype : Gtk.CellRendererText
}
]
});

this.column.add_attribute(this.column.items[0], "text", 0);
this.append_column(this.column);

this.set_model( XN.xnew( {

xtype : Gtk.TreeStore,

onRender : function() {

this.set_column_types ( 1, [GObject.TYPE_INT] );
this.iter = new Gtk.TreeIter();
this.append(this.iter);

this.set_value(this.iter, 0, [GObject.TYPE_INT, 3]);
this.append(this.iter);
this.set_value(this.iter, 0, [GObject.TYPE_INT, 2]);
this.append(this.iter);
this.set_value(this.iter, 0, [GObject.TYPE_INT, 9]);
}
}));
}

}

]
}
]

});




While you may say, so what, it's a bit prettier than the standard examples, but not exactly much different... While that is true, the use of this nested tree, and xtype method is that it enables you to use code and ui builders to put together an interface, and re-use the components very easily. It also solves one of the GJS/Seed issues of signal binding issues (as we wrap up all listeners).

The backend code to make this happen is here.. - It's pretty trivial again, but obvously could be expanded to handle the different binding methods for how different components are combined (add/pack_start/append etc...)



createDelegate = function(method, obj, args, appendArgs){

return function() {
var callArgs = args || arguments;
if(appendArgs === true){
callArgs = Array.prototype.slice.call(arguments, 0);
callArgs = callArgs.concat(args);
}else if(typeof appendArgs == "number"){
callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
var applyArgs = [appendArgs, 0].concat(args); // create method call params
Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
}
return method.apply(obj || window, callArgs);
};
};


xnew = function(o)
{
var ret = o.self || new o.xtype(o);

o.items = o.items || [];
//Seed.print(o.pack.length);
// packing
var addm = typeof(ret['add']) == 'undefined' ? 'pack_start' : 'add';
ret.items = [];
for( var i =0; i < o.items.length;i++) {
ret.items[i] = xnew(o.items[i]);
ret[ o.items.length == 1 ? addm : 'pack_start'](ret.items[i]);
ret.items[i].xparent = ret;
}
o.set = o.set || {};
for (var i in o.set) {

ret[i].apply(ret, o.set[i]);
}


o.listeners = o.listeners || {};
for (var i in o.listeners) {
var _li = createDelegate(o.listeners[i],ret);
Seed.print(typeof(_li));
ret.signal[i].connect(_li);
}

// apply functions..
for(var i in o) {
if (typeof(ret[i]) == 'undefined') {
ret[i] = o[i];
}
}
if (ret.onRender) {
ret.onRender.call(ret);
}

return ret;

}

Missing Features


One area that I was quite interested in, unfortuntatly did not look to easy, that being Javascript tokenizing. In rooscript, I hacked in the ability to retrieve the tokens of a Javascript file and expose it to a Javascript interface. This enabled me to write Javascript compressors, and hack jstoolkit to use this. Leaving�  the painfull task of parsing javascript to the compiled part, and not having to deal with a messy parser in Javascript. Looking at Webkit code, It was not immediatly obvious how this could be done however.

For the time being I will leave that component of my Roo Builder application using rooscript.
















Mentioned By:
stackoverflow.com : Is it possible to build application using Javascript on Linux platforms? - Stack Overflow (350 referals)
www.planet-php.net : Planet PHP (29 referals)
www.angeloluput.com : Javascript on the Desktop (well Linux Mostly) - Angelo Luput's Personal Website (19 referals)
google.com : javascript desktop (15 referals)
www.phpeye.com : Javascript on the Desktop (well Linux Mostly) - Alan Knowles - PHP教程|PHP5|PEAR|框架 - Powered by HappyCMS (13 referals)
google.com : gobject methods (4 referals)
google.com : desktop well (2 referals)
google.com : seed xnew javascript (2 referals)
blog.astrumfutura.com : Maugrim The Reaper's Blog (2 referals)
my.kerovia.net : Home Page (1 referals)
google.com : 310 (1 referals)
google.com : ak vbox (1 referals)
google.com : call javascipt from linux (1 referals)
google.com : gtk introspection php (1 referals)
google.com : javascript introspection of function arguments (1 referals)
google.com : linux javascript timer (1 referals)
google.com : slice.call( this, 0 ); (1 referals)
google.com : well linux (1 referals)
google.com : www.akbkhome.com Javascript_on_the_Desktop_well_Linux_Mostly (1 referals)

Add Your Comment