a664ac2a42611588302950f5946461b4703dd8cb
[app.Builder.js] / Builder / RightGtkView.js
1 //<script type="text/javascript">
2 Gio = imports.gi.Gio;
3 Gtk = imports.gi.Gtk;
4 Gdk = imports.gi.Gdk;
5 GObject = imports.gi.GObject;
6  GLib= imports.gi.GLib;
7
8 /**
9 * we use a hidden window to render the created dialog...
10 * then use snapshot to render it to an image...
11
12 */
13  
14
15 XObject = imports.XObject.XObject;
16 File = imports.File.File;
17 console = imports.console;
18
19 LeftTree = imports.Builder.LeftTree.LeftTree ;
20 LeftPanel = imports.Builder.LeftPanel.LeftPanel;
21  //console.dump(imports.Builder.LeftTree);
22  //Seed.quit();
23
24 RightGtkView = new XObject({
25         xtype : Gtk.VBox,
26         lastSrc : '',
27         pack : [ 'append_page', new Gtk.Label({ label : "Gtk View" })  ],
28         items : [
29         
30             {
31                 xtype: Gtk.HBox,
32                 pack : [ 'pack_start', false, true, 0 ],
33                 items : [       
34                     {
35                         
36                         
37                         xtype: Gtk.Button,
38                         label : 'Show in New Window',
39                         pack : [ 'pack_start', false, false, 0 ],
40                         listeners : {
41                             // pressed...
42                             'button-press-event' : function(w, ev ){
43                                 /// dump..
44                                 RightGtkView.showInWindow();
45                                 return true;
46                                 // show the MidPropTree..
47                             }
48                           
49                         }
50                     }
51                 ]
52             }, 
53             {
54             
55                      
56                 renderedData : false, 
57                 xtype: Gtk.ScrolledWindow,
58                 id: 'view-sw',
59                 smooth_scroll : true,
60                 shadow_type : Gtk.ShadowType.IN ,
61                 init : function() {
62                     XObject.prototype.init.call(this); 
63                      
64                     this.el.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
65                 },
66                 
67                 items : [
68                     {
69                         
70                         id : 'view-vbox',
71                         xtype : Gtk.Viewport,
72                         init : function () {
73                             XObject.prototype.init.call(this); 
74                             this.el.set_hadjustment(this.parent.el.get_hadjustment());
75                             this.el.set_vadjustment(this.parent.el.get_vadjustment());
76                                 
77                         },
78                         packing : ['add' ],
79                         items: [
80                             {
81                                 id : 'view',
82                                 xtype : Gtk.VBox,
83                                 /*
84                                 xtype : function() {
85                                     return new Gtk.Image.from_stock (Gtk.STOCK_HOME, 100) 
86
87                                 },
88                                 */
89                                 packing : ['add' ],
90                                 ready : false,
91                                 init : function() {
92                                     XObject.prototype.init.call(this); 
93                                     // fixme!
94                                    
95                                     Gtk.drag_dest_set
96                                     (
97                                             this.el,              /* widget that will accept a drop */
98                                             Gtk.DestDefaults.MOTION  | Gtk.DestDefaults.HIGHLIGHT,
99                                             null,            /* lists of target to support */
100                                             0,              /* size of list */
101                                             Gdk.DragAction.COPY         /* what to do with data after dropped */
102                                     );
103                                     
104                                    // print("RB: TARGETS : " + LeftTree.atoms["STRING"]);
105                                     Gtk.drag_dest_set_target_list(this.el, LeftTree.targetList);
106                                     //Gtk.drag_dest_add_text_targets(this.el);
107                                 },   
108                                 listeners : {
109                                     
110                                       
111                                     
112                                     "drag-leave" : function () {
113                                         Seed.print("TARGET: drag-leave");
114                                         // stop monitoring of mouse montion in rendering..
115                                         return true;
116                                     },
117                                     'drag-motion' : function (w, ctx,  x,   y,   time, ud) 
118                                     {
119                                         
120                                     
121                                        // console.log('DRAG MOTION'); 
122                                         // status:
123                                         // if lastCurrentNode == this.currentNode.. -- don't change anything..
124                                          
125                                         
126                                         // A) find out from drag all the places that node could be dropped.
127                                         var src = Gtk.drag_get_source_widget(ctx);
128                                         if (!src.dropList) {
129                                             Gdk.drag_status(ctx, 0, time);
130                                             return true;
131                                         }
132                                         // b) get what we are over.. (from activeNode)
133                                         // tree is empty.. - list should be correct..
134                                         if (!LeftTree.get('model').currentTree) {
135                                             Gdk.drag_status(ctx, Gdk.DragAction.COPY,time);
136                                             return true;
137                                             
138                                         }
139                                         // c) ask tree where it should be dropped... - eg. parent.. (after node ontop)
140                                         var activeNode = this.getActiveNode(x, y);
141                                         
142                                         
143                                         var tg = LeftTree.get('model').findDropNode(activeNode, src.dropList);
144                                         console.dump(tg);
145                                         if (!tg.length) {
146                                             Gdk.drag_status(ctx, 0,time);
147                                             LeftTree.get('view').highlight(false);
148                                             return true;
149                                         }
150                                          
151                                         // if we have a target..
152                                         // -> highlight it! (in browser)
153                                         // -> highlight it! (in tree)
154                                         
155                                         Gdk.drag_status(ctx, Gdk.DragAction.COPY,time);
156                                         LeftTree.get('view').highlight(tg);
157                                         this.targetData = tg;
158                                         // for tree we should handle this...
159                                         return true;
160                                         
161                                     },
162                                     "drag-drop"  : function (w, ctx,x,y,time, ud) 
163                                     {
164                                                 
165                                         Seed.print("TARGET: drag-drop");
166                                         is_valid_drop_site = true;
167                                         
168                                          
169                                         Gtk.drag_get_data
170                                         (
171                                                 w,         /* will receive 'drag-data-received' signal */
172                                                 ctx,        /* represents the current state of the DnD */
173                                                 LeftTree.atoms["STRING"],    /* the target type we want */
174                                                 time            /* time stamp */
175                                         );
176                                         
177                                         
178                                         /* No target offered by source => error */
179                                        
180
181                                         return  is_valid_drop_site;
182                                         
183
184                                     },
185                                     "drag-data-received" : function (w, ctx,  x,  y, sel_data,  target_type,  time, ud) 
186                                     {
187                                         Seed.print("GtkView: drag-data-received");
188                                         var delete_selection_data = false;
189                                         var dnd_success = false;
190                                         /* Deal with what we are given from source */
191                                         if( sel_data && sel_data.length ) {
192                                             
193                                             if (ctx.action == Gdk.DragAction.ASK)  {
194                                                 /* Ask the user to move or copy, then set the ctx action. */
195                                             }
196
197                                             if (ctx.action == Gdk.DragAction.MOVE) {
198                                                 delete_selection_data = true;
199                                             }
200                                             var source = Gtk.drag_get_source_widget(ctx);
201
202                                             Seed.print("Browser: source.DRAGDATA? " + source.dragData);
203                                             if (this.targetData) {
204                                                 Seed.print(this.targetData);
205                                                 LeftTree.get('model').dropNode(this.targetData,  source.dragData);
206                                             }
207                                             
208                                             
209                                             
210                                             dnd_success = true;
211                  
212                                         }
213
214                                         if (dnd_success == false)
215                                         {
216                                                 Seed.print ("DnD data transfer failed!\n");
217                                         }
218                                         
219                                         Gtk.drag_finish (ctx, dnd_success, delete_selection_data, time);
220                                         return true;
221                                     }
222                                     
223                                    //'line-mark-activated' : line_mark_activated,
224                                    
225                                     
226                                 },
227                                  
228                                 getActiveNode : function(x,y)
229                                 {
230                                    // workout what node is here..
231                                     return '0'; // top..
232                                 }
233                             }
234                         ]
235                     }
236                 ]
237             }
238                 
239         ],
240         
241         showInWindow: function ()
242         {
243             
244             
245             var src= this.buildJS(this.get('/LeftTree.model').toJS()[0], true);
246             
247             
248             this.get('/Terminal').feed("Running\n");
249             
250             //var x = new imports.sandbox.Context();
251             //x.add_globals();
252             //print(src);
253             try {
254                 Seed.check_syntax('var e = ' + src);
255               //  x.eval(src);
256             } catch( e) {
257                 this.get('/Terminal').feed(e.message || e.toString() + "\n");
258                 this.get('/Terminal').feed(console._dump(e)+"\n");
259                 if (e.line) {
260                     var lines = src.split("\n");
261                     var start = Math.max(0, e.line - 10);
262                     var end = Math.min(lines.length, e.line + 10);
263                     for (var i =start ; i < end; i++) {
264                         if (i == e.line) {
265                             this.get('/Terminal').feed(">>>>>" + lines[i] + "\n");
266                             
267                           
268                             continue;
269                         }
270                         
271                         this.get('/Terminal').feed(lines[i] + "\n");
272                     }
273                     
274                 }
275                 
276                 return;
277             }
278             this.get('/BottomPane').el.set_current_page(1);
279             this.get('/Terminal').el.fork_command( null , [], [], "/tmp", false,false,false); 
280             var cmd = "/usr/bin/seed /tmp/BuilderGtkView.js\n";
281             this.get('/Terminal').el.feed_child(cmd, cmd.length);
282             //'/usr/bin/seed',  [ '/tmp/BuilderGtkView.js'], [], "/tmp", false,false,false);
283             /*
284             var _top = x.get_global_object()._top;
285             
286             _top.el.set_screen(Gdk.Screen.get_default()); // just in case..
287             _top.el.show_all();
288             if (_top.el.popup) {
289                 _top.el.popup(null, null, null, null, 3, null);
290             }
291             */
292         },
293         
294         buildJS: function(data,withDebug) 
295         {
296             var i = [ 'Gtk', 'Gdk', 'Pango', 'GLib', 'Gio', 'GObject', 'GtkSource', 'WebKit', 'Vte' ];
297             var src = "";
298             i.forEach(function(e) {
299                 src += e+" = imports.gi." + e +";\n";
300             });
301             
302             if (withDebug) {
303                src+= "imports.searchPath.push(" + JSON.stringify(GLib.path_get_dirname(__script_path__)) + ");\n";
304             }
305             
306             src += "console = imports.console;\n"; // path?!!?
307             src += "XObject = imports.XObject.XObject;\n"; // path?!!?
308             src += "XObject.cache = {};\n"; // reset cache!
309             if (withDebug) {
310                 
311                 
312                 
313                 src += "Gtk.init(null,null);\n"; 
314             }
315             if (withDebug) {
316                 src += "XObject.debug=true;\n"; 
317             }
318             
319             this.withDebug = withDebug;
320             src += '_top=new XObject('+ this.mungeToString(data) + ')\n;';
321             src += '_top.init();\n';
322             if (withDebug) {
323                 src += "_top.el.show_all();\n"; 
324                 src += "Gtk.main();\n"; 
325             }
326             File.write('/tmp/BuilderGtkView.js', src);
327             print("Test code  in /tmp/BuilderGtkView.js");
328             this.lastSrc = src;
329             return src;
330         },
331         
332         renderJS : function(data, withDebug)
333         {
334             // can we mess with data?!?!?
335             
336             /**
337              * first effort..
338              * sandbox it? - nope then will have dificulting passing. stuff aruond..
339              * 
340              */
341             if (!data) {
342                  return; 
343             }
344             this.withDebug = false;
345             
346             if (this.renderedEl) {
347                 this.get('view').el.remove(this.renderedEl);
348                 this.renderedEl.destroy();
349                 this.renderedEl = false;
350             }
351             
352             var tree =  this.get('/LeftTree.model').toJS()[0];
353             // in theory tree is actually window..
354             this.renderedEl = this.viewAdd(tree.items[0], this.get('view').el);
355             
356             this.get('view').el.show_all();
357             
358             return;
359             
360             
361             var src = this.buildJS(data,withDebug);
362             var x = new imports.sandbox.Context();
363             x.add_globals();
364             //x.get_global_object().a = "hello world";
365             
366             try {
367                 Seed.check_syntax('var e = ' + src);
368                 x.eval(src);
369             } catch( e) {
370                 //if (!withDebug) {
371                 //   return this.renderJS(data,true);
372                // }
373                 print(e.message || e.toString());
374                 console.dump(e);
375                 return;
376             }
377             
378             var r = new Gdk.Rectangle();
379             var _top = x.get_global_object()._top;
380             
381             _top.el.set_screen(Gdk.Screen.get_default()); // just in case..
382             _top.el.show_all();
383               
384             
385             if (_top.el.popup) {
386                 _top.el.popup(null, null, null, null, 3, null);
387             }
388             
389             
390             
391             var pb = _top.items[0].el.get_snapshot(r);
392             _top.el.hide();
393             if (!pb) {
394                 return;
395             }
396             
397             _top.el.destroy();
398             x._top = false;
399             var Window = imports.Builder.Window.Window;
400             var gc = new Gdk.GC.c_new(Window.el.window);
401                 
402                 // 10 points all round..
403             var full = new Gdk.Pixmap.c_new (Window.el.window, r.width+20, r.height+20, pb.get_depth());
404             // draw a white background..
405            // gc.set_rgb_fg_color({ red: 0, white: 0, black : 0 });
406             Gdk.draw_rectangle(full, gc, true, 0, 0, r.width+20, r.height+20);
407             // paint image..
408             Gdk.draw_drawable (full, gc, pb, 0, 0, 10, 10, r.width, r.height);
409             // boxes..
410             //gc.set_rgb_fg_color({ red: 255, white: 255, black : 255 });
411             Gdk.draw_rectangle(full, gc, true, 0, 0, 10, 10);
412             this.get('view').el.set_from_pixmap(full, null);
413             //this.get('view-vbox').el.set_size_request( r.width+20, r.height+20);
414             //var img = new Gtk.Image.from_file("/home/alan/solarpanels.jpeg");
415             
416             
417             
418         },
419         mungeToString:  function(obj, isListener, pad)
420         {
421             pad = pad || '';
422             var keys = [];
423             var isArray = false;
424             isListener = isListener || false;
425              
426             // am I munging a object or array...
427             if (obj.constructor.toString() === Array.toString()) {
428                 for (var i= 0; i < obj.length; i++) {
429                     keys.push(i);
430                 }
431                 isArray = true;
432             } else {
433                 for (var i in obj) {
434                     keys.push(i);
435                 }
436             }
437             
438             
439             var els = []; 
440             var skip = [];
441             if (!isArray && 
442                     typeof(obj['|xns']) != 'undefined' &&
443                     typeof(obj['xtype']) != 'undefined'
444                 ) {
445                     els.push('xtype: '+ obj['|xns'] + '.' + obj['xtype']);
446                     skip.push('|xns','xtype');
447                 }
448             
449             var _this = this;
450             
451             
452             
453             keys.forEach(function(i) {
454                 var el = obj[i];
455                 if (!isArray && skip.indexOf(i) > -1) {
456                     return;
457                 }
458                 if (isListener) {
459                     if (!_this.withDebug) {
460                         // do not write listeners unless we are debug mode.
461                         return;
462                     }
463                     //if (obj[i].match(new RegExp("Gtk.main" + "_quit"))) { // we can not handle this very well..
464                     //    return;
465                    // }
466                     var str= ('' + obj[i]).replace(/^\s+|\s+$/g,"");
467                     var lines = str.split("\n");
468                     if (lines.length > 1) {
469                         str = lines.join("\n" + pad);
470                     }
471                     els.push(JSON.stringify(i) + ":" + str);
472                     return;
473                 }
474                 if (i[0] == '|') {
475                     // does not hapepnd with arrays..
476                     if (typeof(el) == 'string' && !obj[i].length) { //skip empty.
477                         return;
478                     }
479                     // this needs to go...
480                     //if (typeof(el) == 'string'  && obj[i].match(new RegExp("Gtk.main" + "_quit"))) { // we can not handle this very well..
481                     //    return;
482                     //}
483                     
484                     var str= ('' + obj[i]).replace(/^\s+|\s+$/g,"");;
485                     var lines = str.split("\n");
486                     if (lines.length > 1) {
487                         str = lines.join("\n" + pad);
488                     }
489                     
490                     els.push(JSON.stringify(i.substring(1)) + ":" + str);
491                     return;
492                 }
493                 var left = isArray ? '' : (JSON.stringify(i) + " : " )
494                 if (typeof(el) == 'object') {
495                     els.push(left + _this.mungeToString(el, i == 'listeners', pad + '    '));
496                     return;
497                 }
498                 els.push(JSON.stringify(i) + ":" + JSON.stringify(obj[i]));
499             });
500             var spad = pad.substring(0, pad.length-4);
501             return (isArray ? '[' : '{') + "\n" +
502                 pad  + els.join(",\n" + pad ) + 
503                 "\n" + spad + (isArray ? ']' : '}');
504                
505             
506             
507         },
508         
509         buildView : function()
510         {
511             
512             
513         },
514         viewAdd : function(item, par)
515         {
516             // does something similar to xobject..
517             item.pack = (typeof(item.pack) == 'undefined') ?  'add' : item.pack;
518             
519             if (item.pack===false || item.pack === 'false') {  // no ;
520                 return;
521             }
522             print("CREATE: " + item['|xns'] + '.' + item['xtype']);
523             var ns = imports.gi[item['|xns']];
524             var ctr = ns[item['xtype']];
525             var ctr_args = { };
526             for(var k in item) {
527                 var kv = item[k];
528                 if (typeof(kv) == 'object' || typeof(kv) == 'function') {
529                     continue;
530                 }
531                 if ( 
532                     k == 'pack' ||
533                     k == 'items' ||
534                     k == 'id' ||
535                     k == 'xtype' ||
536                     k == 'xdebug' ||
537                     k == 'xns' ||
538                     k == '|xns'
539                 ) {
540                     continue;
541                 }
542                 ctr_args[k] = kv;
543                 
544             } 
545             
546             
547             var el = new ctr(ctr_args);
548             
549             print("PACK");
550             console.dump(item.pack);
551             
552             
553             
554             
555             var args = [];
556             var pack_m  = false;
557             if (typeof(item.pack) == 'string') {
558                  
559                 item.pack.split(',').forEach(function(e, i) {
560                     
561                     if (e == 'false') { args.push( false); return; }
562                     if (e == 'true') {  args.push( true);  return; }
563                     if (!isNaN(parseInt(e))) { args.push( parseInt(e)); return; }
564                     args.push(e);
565                 });
566                 //print(args.join(","));
567                 
568                 pack_m = args.shift();
569             } else {
570                 pack_m = item.pack.shift();
571                 args = item.pack;
572             }
573             
574             // handle error.
575             if (pack_m && typeof(par[pack_m]) == 'undefined') {
576                 Seed.print('pack method not available : ' + item.xtype + '.' +  pack_m);
577                 return;
578             }
579             
580             console.dump(args);
581             args.unshift(el);
582             //if (XObject.debug) print(pack_m + '[' + args.join(',') +']');
583             //Seed.print('args: ' + args.length);
584             if (pack_m) {
585                 par[pack_m].apply(par, args);
586             }
587             
588             var _this = this;
589             item.items = item.items || [];
590             item.items.forEach(function(ch) {
591                 _this.viewAdd(ch, el);
592             });
593             
594             return el;
595             
596         }
597         
598         
599         
600     }
601     
602     
603 );
604