I think that basically sums up my reaction to Jack's GPLv3'ing a library. For those who are not aware, As I was not, when I visited the extjs web site a few days ago to grab a copy of the old 1.1 version and found all references to download it had disappeared. Digging a bit deeper on the site, I started spotting a few comments about the new licensing.
While I can say that Jack as the author (of I presume most of extjs?) has the right to change the license to whatever he likes, I think he has probably just destroyed the project. I could not commit to writing new code with a "Library" that is GPL, unless I was working on a GPL project (which is unlikely at present - got bills to pay). And for commercial or spec projects, that are not turning revenues yet, I can't really justify my time in committing to develop stuff that may, or may-not be able to fund today's and whatever Jack feels like charging in the future for the non-commercial license.
I've seen too many people burned by this closed source dependencies that they build their businesses around, only to have the effective rental for their office yanked through the roof, and no other option than a huge effort moving to another library or software causing chaos.
All that said, I'm not sure if v2.0 and v2.1 are really worth bothering with anyway, I've tried them on 2 projects so far, and the general sense I get, is that compared to v1.1 they are a little finicky, and tend to produce slightly unpredictable results. Which is tempting me to stick with 1.1..
The problem I see though is that the community that has built up around extjs has been supported by quite a few handy tools, the wiki, the doc's and the rather nasty forum (which is a good way to waste time finding answers to issues). So I guess someone setting up a openext? (I saw something on the net about it) should probably sort out those issues first, then start solving the technical issues about how to replace all the images and css in extjs which where not previouslylicensed under LGPL.
I would hate to have to go looking at the alternatives again, So sticking with v1.1+ hacks may be the best long term plan for me anyway.
var data = File.read(fname);
var x = Script.tokenize(data);
for(var i =0; i < x.length; i++) {
if (x[i].tok == "whitespace") {
if (x[i].val.indexOf("\n") > -1) {
print("\n");
continue;
}
print(" ");
continue;
}
print(x[i].val);
}
print(";\n");
for(var i =0; i < x.length; i++) {
if (x[i].tok == "string") {
println("got string: " + x[i].val);
}
}
#djs ScriptCrusher.js -- --strings /tmp/Hello.js > /tmp/zh_HK.jsWhich can be edited and translated.
Would generate a file:
"Hello.js" : {
"Hello": "Hello",
"World": "World",
}
#djs ScriptCrusher.js -- --langfile /tmp/zh_HK.js /tmp/Hello.js \
> /tmp/Hello.zh_HK.js
#djs ScriptCrusher.js --/tmp/Hello.js > /tmp/Hello.en.js
(I've not done the merging of old/new yet, but it should be pretty trivial).
djs should be pretty simple to build: (requires gdc - available in Debian and Ubuntu + probably others)
#svn co http://www.akbkhome.com/svn/gtkDS
#cd gtkDS
#sh djs.gdc.sh
var store = new Gtk.ListStore(At present I've used the Gtype names to define what is being stored where. - This may need simplifying, and integrating somehow with the writing mechanism as validating data types written to the tree is a bit haphazard at present.
"gchararray",
"gfloat",
"gpointer",
"gboolean",
"GdkPixbuf");
var iter = new Gtk.TreeIter();The append method loads the Row reader writer, so that it can access the new row.
store.append(iter);
store.set(iter, 0, new G.Value("test"));all this could easily be abstracted by defining a simple prototype
store.set(iter, 1, new G.Value(1.0));
store.set(iter, 2, new G.Value({ a: 1, c: 2}));
store.set(iter, 3, new G.Value(true) );
var pixbuf = Gdk.Pixbuf.newFromFile("gnome-logo-icon.png");
store.set(iter, 4, new G.Value(pixbuf) );
Gtk.ListStore.prototype.appendRow = function(rdata) {Next step is to build the Widget. And the renderers (the classes that turn the data into visable data). Gtk comes with a few renderers, It will be interesting to see if creating them in Javascript is feasible.
var iter = new Gtk.TreeIter();
this.append(iter);
for(var i =0;i<rdata.length;i++) {
this.set(iter,i, new G.Value(rdata[i]));
}
}
.....
store.appendRow(["test", 1.0, {a: 1}, true, Gtk.Pixbuf.newFromFile(....)]);
var view = new Gtk.TreeView();Adding columns is again a little raw, as we cant use the varargs methods the C does, so we have to combine a few calls.
var renderer = new Gtk.CellRendererText ();
var pixrenderer = new Gtk.CellRendererPixbuf ();
Again a nice wrapper could be written.
var col = new Gtk.TreeViewColumn();
col.setTitle("Name");
col.packStart(renderer, true);
col.addAttribute(renderer, "text", 0);
view.insertColumn( col, -1);
Gtk.TreeView.prototype.insertColumnAuto = function(config) {
var col = new Gtk.TreeViewColumn();
col.setTitle(config.title);
col.packStart(config.renderer, true);
col.addAttribute(config.renderer,
config.renderer.isPrototypeOf(GtkCellRenderText) ?
"text" : "pixbuf", 0);
this.insertColumn( col, -1);
}
...
view.insertColumnAuto({
title: "text here",
renderer: new GtkCellRendererText(),
}
view.setModel ( store );
window.add(view); // add it to a GtkWindow..
window.showAll();
Gtk.main();
view.connect("row-activated", function(view, path, col) {At present this is a little klunky, but again with some prototype modifications it should be pretty easy to solve.
var model = view.getModel();
var iter = new Gtk.TreeIter();
if (model.getIter(iter, path)) {
var name = new G.Value();
var name2 = new G.Value();
model.getValue(iter, 0, name);
model.getValue(iter, 1, name2);
println (
"The row containing the name '"+
name.getString() +
"' has been double-clicked. holding" +
name2.getFloat()
);
model = new Gtk.ListStore(model);
model.remove(iter);
println ("removed?");
}
});
var menuBar = new Gtk.MenuBar.quick([In the above example, I've created an extended class Gtk.MenuItem.quick, and Gtk.MenuBar.quick (it could just be Ext.MenuBar / Ext.MenuItem...) - Just adding it to the Gtk.Menubar Class namespace seemed clever at the time.
new Gtk.MenuItem.quick("File" , function () {
println("File");
}),
new Gtk.MenuItem.quick("Edit" , function () {
println("Edit");
}),
new Gtk.MenuItem.quick("Search" , function () {
println("Search");
})
]);
new Gtk.MenuItem.quick({This morphing of the Gtk bindings is all done in the Javascript code,
title: "Search" ,
icon: Gtk.Stock.SEARCH, // this doesnt work yet!
handler: function () {
println("Search");
}
})
Gtk.MenuItem.quick = function(label, activate) {(using snippets of code from Extjs) to implement the extending.
Gtk.MenuItem.quick.superclass.constructor.call(this,label);
this.connect("activate", activate);
}
Ext.extend(Gtk.MenuItem.quick, Gtk.MenuItem, {});
Gtk.MenuBar.quick = function(ar)
{
Gtk.MenuBar.quick.superclass.constructor.call(this,label);
for (var i in ar) {
this.append(ar[i]);
}
}
Ext.extend(Gtk.MenuBar.quick , Gtk.MenuBar, {});
var a = new Gtk.Window(0);
a.connect("delete", function() { Gtk.exit(1); });
Gtk.Widget.prototype.on = function (sig, call) { return this.connect(sig,call); }
run with
Gtk.init();
var w = new Gtk.Window(0);
w.setTitle("hello world");
w.showAll();
Gtk.main();
/tmp/gtkjs hello.ds
svn co http://www.akbkhome.com/svn/gtkDSNow I just wonder what use it is ;)
cd gtkDS/wrap
#download API Files (needs curl / tar etc.)
sh downloadFiles.sh
#compile it - needs dmd installed..
sh buildit.sh
cd ..
#build the bindings - requires compd from dsource.org/projects/dool
compd gdkds.compd
/tmp/gtkjs test/hello.ds