8233f56f54c9050023376de1db8a498592df6b5c
[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 : function() {
83                                     return new Gtk.Image.from_stock (Gtk.STOCK_HOME, 100) 
84
85                                 },
86                                 packing : ['add' ],
87                                 ready : false,
88                                 init : function() {
89                                     XObject.prototype.init.call(this); 
90                                     // fixme!
91                                    
92                                     Gtk.drag_dest_set
93                                     (
94                                             this.el,              /* widget that will accept a drop */
95                                             Gtk.DestDefaults.MOTION  | Gtk.DestDefaults.HIGHLIGHT,
96                                             null,            /* lists of target to support */
97                                             0,              /* size of list */
98                                             Gdk.DragAction.COPY         /* what to do with data after dropped */
99                                     );
100                                     
101                                    // print("RB: TARGETS : " + LeftTree.atoms["STRING"]);
102                                     Gtk.drag_dest_set_target_list(this.el, LeftTree.targetList);
103                                     //Gtk.drag_dest_add_text_targets(this.el);
104                                 },   
105                                 listeners : {
106                                     
107                                       
108                                     
109                                     "drag-leave" : function () {
110                                         Seed.print("TARGET: drag-leave");
111                                         // stop monitoring of mouse montion in rendering..
112                                         return true;
113                                     },
114                                     'drag-motion' : function (w, ctx,  x,   y,   time, ud) 
115                                     {
116                                         
117                                     
118                                        // console.log('DRAG MOTION'); 
119                                         // status:
120                                         // if lastCurrentNode == this.currentNode.. -- don't change anything..
121                                          
122                                         
123                                         // A) find out from drag all the places that node could be dropped.
124                                         var src = Gtk.drag_get_source_widget(ctx);
125                                         if (!src.dropList) {
126                                             Gdk.drag_status(ctx, 0, time);
127                                             return true;
128                                         }
129                                         // b) get what we are over.. (from activeNode)
130                                         // tree is empty.. - list should be correct..
131                                         if (!LeftTree.get('model').currentTree) {
132                                             Gdk.drag_status(ctx, Gdk.DragAction.COPY,time);
133                                             return true;
134                                             
135                                         }
136                                         // c) ask tree where it should be dropped... - eg. parent.. (after node ontop)
137                                         var activeNode = this.getActiveNode(x, y);
138                                         
139                                         
140                                         var tg = LeftTree.get('model').findDropNode(activeNode, src.dropList);
141                                         console.dump(tg);
142                                         if (!tg.length) {
143                                             Gdk.drag_status(ctx, 0,time);
144                                             LeftTree.get('view').highlight(false);
145                                             return true;
146                                         }
147                                          
148                                         // if we have a target..
149                                         // -> highlight it! (in browser)
150                                         // -> highlight it! (in tree)
151                                         
152                                         Gdk.drag_status(ctx, Gdk.DragAction.COPY,time);
153                                         LeftTree.get('view').highlight(tg);
154                                         this.targetData = tg;
155                                         // for tree we should handle this...
156                                         return true;
157                                         
158                                     },
159                                     "drag-drop"  : function (w, ctx,x,y,time, ud) 
160                                     {
161                                                 
162                                         Seed.print("TARGET: drag-drop");
163                                         is_valid_drop_site = true;
164                                         
165                                          
166                                         Gtk.drag_get_data
167                                         (
168                                                 w,         /* will receive 'drag-data-received' signal */
169                                                 ctx,        /* represents the current state of the DnD */
170                                                 LeftTree.atoms["STRING"],    /* the target type we want */
171                                                 time            /* time stamp */
172                                         );
173                                         
174                                         
175                                         /* No target offered by source => error */
176                                        
177
178                                         return  is_valid_drop_site;
179                                         
180
181                                     },
182                                     "drag-data-received" : function (w, ctx,  x,  y, sel_data,  target_type,  time, ud) 
183                                     {
184                                         Seed.print("GtkView: drag-data-received");
185                                         var delete_selection_data = false;
186                                         var dnd_success = false;
187                                         /* Deal with what we are given from source */
188                                         if( sel_data && sel_data.length ) {
189                                             
190                                             if (ctx.action == Gdk.DragAction.ASK)  {
191                                                 /* Ask the user to move or copy, then set the ctx action. */
192                                             }
193
194                                             if (ctx.action == Gdk.DragAction.MOVE) {
195                                                 delete_selection_data = true;
196                                             }
197                                             var source = Gtk.drag_get_source_widget(ctx);
198
199                                             Seed.print("Browser: source.DRAGDATA? " + source.dragData);
200                                             if (this.targetData) {
201                                                 Seed.print(this.targetData);
202                                                 LeftTree.get('model').dropNode(this.targetData,  source.dragData);
203                                             }
204                                             
205                                             
206                                             
207                                             dnd_success = true;
208                  
209                                         }
210
211                                         if (dnd_success == false)
212                                         {
213                                                 Seed.print ("DnD data transfer failed!\n");
214                                         }
215                                         
216                                         Gtk.drag_finish (ctx, dnd_success, delete_selection_data, time);
217                                         return true;
218                                     }
219                                     
220                                    //'line-mark-activated' : line_mark_activated,
221                                    
222                                     
223                                 },
224                                  
225                                 getActiveNode : function(x,y)
226                                 {
227                                    // workout what node is here..
228                                     return '0'; // top..
229                                 }
230                             }
231                         ]
232                     }
233                 ]
234             }
235                 
236         ],
237         
238         showInWindow: function ()
239         {
240             
241             
242             var src= this.buildJS(this.get('/LeftTree.model').toJS()[0], true);
243             
244             
245             this.get('/Terminal').feed("Running\n");
246             
247             //var x = new imports.sandbox.Context();
248             //x.add_globals();
249             //print(src);
250             try {
251                 Seed.check_syntax('var e = ' + src);
252               //  x.eval(src);
253             } catch( e) {
254                 this.get('/Terminal').feed(e.message || e.toString() + "\n");
255                 this.get('/Terminal').feed(console._dump(e)+"\n");
256                 if (e.line) {
257                     var lines = src.split("\n");
258                     var start = Math.max(0, e.line - 10);
259                     var end = Math.min(lines.length, e.line + 10);
260                     for (var i =start ; i < end; i++) {
261                         if (i == e.line) {
262                             this.get('/Terminal').feed(">>>>>" + lines[i] + "\n");
263                             
264                           
265                             continue;
266                         }
267                         
268                         this.get('/Terminal').feed(lines[i] + "\n");
269                     }
270                     
271                 }
272                 
273                 return;
274             }
275             this.get('/BottomPane').el.set_current_page(1);
276             this.get('/Terminal').el.fork_command( null , [], [], "/tmp", false,false,false); 
277             var cmd = "/usr/bin/seed /tmp/BuilderGtkView.js\n";
278             this.get('/Terminal').el.feed_child(cmd, cmd.length);
279             //'/usr/bin/seed',  [ '/tmp/BuilderGtkView.js'], [], "/tmp", false,false,false);
280             /*
281             var _top = x.get_global_object()._top;
282             
283             _top.el.set_screen(Gdk.Screen.get_default()); // just in case..
284             _top.el.show_all();
285             if (_top.el.popup) {
286                 _top.el.popup(null, null, null, null, 3, null);
287             }
288             */
289         },
290         
291         buildJS: function(data,withDebug) {
292             var i = [ 'Gtk', 'Gdk', 'Pango', 'GLib', 'Gio', 'GObject', 'GtkSource', 'WebKit', 'Vte' ];
293             var src = "";
294             i.forEach(function(e) {
295                 src += e+" = imports.gi." + e +";\n";
296             });
297             
298             if (withDebug) {
299                src+= "imports.searchPath.push(" + JSON.stringify(GLib.path_get_dirname(__script_path__)) + ");\n";
300             }
301             
302             src += "console = imports.console;\n"; // path?!!?
303             src += "XObject = imports.XObject.XObject;\n"; // path?!!?
304             src += "XObject.cache = {};\n"; // reset cache!
305             if (withDebug) {
306                 
307                 
308                 
309                 src += "Gtk.init(null,null);\n"; 
310             }
311             if (withDebug) {
312                 src += "XObject.debug=true;\n"; 
313             }
314             
315             this.withDebug = withDebug;
316             src += '_top=new XObject('+ this.mungeToString(data) + ')\n;';
317             src += '_top.init();\n';
318             if (withDebug) {
319                 src += "_top.el.show_all();\n"; 
320                 src += "Gtk.main();\n"; 
321             }
322             File.write('/tmp/BuilderGtkView.js', src);
323             print("Test code  in /tmp/BuilderGtkView.js");
324             this.lastSrc = src;
325             return src;
326         },
327         
328         renderJS : function(data, withDebug)
329         {
330             // can we mess with data?!?!?
331             
332             /**
333              * first effort..
334              * sandbox it? - nope then will have dificulting passing. stuff aruond..
335              * 
336              */
337             if (!data) {
338                  return; 
339             }
340             this.withDebug = false;
341             
342             
343             var src = this.buildJS(data,withDebug);
344             var x = new imports.sandbox.Context();
345             x.add_globals();
346             //x.get_global_object().a = "hello world";
347             
348             try {
349                 Seed.check_syntax('var e = ' + src);
350                 x.eval(src);
351             } catch( e) {
352                 //if (!withDebug) {
353                 //   return this.renderJS(data,true);
354                // }
355                 print(e.message || e.toString());
356                 console.dump(e);
357                 return;
358             }
359             
360             var r = new Gdk.Rectangle();
361             var _top = x.get_global_object()._top;
362             
363             _top.el.set_screen(Gdk.Screen.get_default()); // just in case..
364             _top.el.show_all();
365               
366             
367             if (_top.el.popup) {
368                 _top.el.popup(null, null, null, null, 3, null);
369             }
370             
371             
372             
373             var pb = _top.items[0].el.get_snapshot(r);
374             _top.el.hide();
375             if (!pb) {
376                 return;
377             }
378             
379             _top.el.destroy();
380             x._top = false;
381             var Window = imports.Builder.Window.Window;
382             var gc = new Gdk.GC.c_new(Window.el.window);
383                 
384                 // 10 points all round..
385             var full = new Gdk.Pixmap.c_new (Window.el.window, r.width+20, r.height+20, pb.get_depth());
386             // draw a white background..
387            // gc.set_rgb_fg_color({ red: 0, white: 0, black : 0 });
388             Gdk.draw_rectangle(full, gc, true, 0, 0, r.width+20, r.height+20);
389             // paint image..
390             Gdk.draw_drawable (full, gc, pb, 0, 0, 10, 10, r.width, r.height);
391             // boxes..
392             //gc.set_rgb_fg_color({ red: 255, white: 255, black : 255 });
393             Gdk.draw_rectangle(full, gc, true, 0, 0, 10, 10);
394             this.get('view').el.set_from_pixmap(full, null);
395             //this.get('view-vbox').el.set_size_request( r.width+20, r.height+20);
396             //var img = new Gtk.Image.from_file("/home/alan/solarpanels.jpeg");
397             
398             
399             
400         },
401         mungeToString:  function(obj, isListener, pad)
402         {
403             pad = pad || '';
404             var keys = [];
405             var isArray = false;
406             isListener = isListener || false;
407              
408             // am I munging a object or array...
409             if (obj.constructor.toString() === Array.toString()) {
410                 for (var i= 0; i < obj.length; i++) {
411                     keys.push(i);
412                 }
413                 isArray = true;
414             } else {
415                 for (var i in obj) {
416                     keys.push(i);
417                 }
418             }
419             
420             
421             var els = []; 
422             var skip = [];
423             if (!isArray && 
424                     typeof(obj['|xns']) != 'undefined' &&
425                     typeof(obj['xtype']) != 'undefined'
426                 ) {
427                     els.push('xtype: '+ obj['|xns'] + '.' + obj['xtype']);
428                     skip.push('|xns','xtype');
429                 }
430             
431             var _this = this;
432             
433             
434             
435             keys.forEach(function(i) {
436                 var el = obj[i];
437                 if (!isArray && skip.indexOf(i) > -1) {
438                     return;
439                 }
440                 if (isListener) {
441                     if (!_this.withDebug) {
442                         // do not write listeners unless we are debug mode.
443                         return;
444                     }
445                     //if (obj[i].match(new RegExp("Gtk.main" + "_quit"))) { // we can not handle this very well..
446                     //    return;
447                    // }
448                     var str= ('' + obj[i]).replace(/^\s+|\s+$/g,"");
449                     var lines = str.split("\n");
450                     if (lines.length > 1) {
451                         str = lines.join("\n" + pad);
452                     }
453                     els.push(JSON.stringify(i) + ":" + str);
454                     return;
455                 }
456                 if (i[0] == '|') {
457                     // does not hapepnd with arrays..
458                     if (typeof(el) == 'string' && !obj[i].length) { //skip empty.
459                         return;
460                     }
461                     // this needs to go...
462                     //if (typeof(el) == 'string'  && obj[i].match(new RegExp("Gtk.main" + "_quit"))) { // we can not handle this very well..
463                     //    return;
464                     //}
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                     
472                     els.push(JSON.stringify(i.substring(1)) + ":" + str);
473                     return;
474                 }
475                 var left = isArray ? '' : (JSON.stringify(i) + " : " )
476                 if (typeof(el) == 'object') {
477                     els.push(left + _this.mungeToString(el, i == 'listeners', pad + '    '));
478                     return;
479                 }
480                 els.push(JSON.stringify(i) + ":" + JSON.stringify(obj[i]));
481             });
482             var spad = pad.substring(0, pad.length-4);
483             return (isArray ? '[' : '{') + "\n" +
484                 pad  + els.join(",\n" + pad ) + 
485                 "\n" + spad + (isArray ? ']' : '}');
486                
487             
488             
489         }
490         
491     }
492     
493     
494 );
495