src/Builder4/WindowRooView.bjs
[app.Builder.js] / src / Builder4 / WindowRooView.vala
1 static Xcls_WindowRooView  _WindowRooView;
2
3 public class Xcls_WindowRooView : Object
4 {
5     public Gtk.Paned el;
6     private Xcls_WindowRooView  _this;
7
8     public static Xcls_WindowRooView singleton()
9     {
10         if (_WindowRooView == null) {
11             _WindowRooView= new Xcls_WindowRooView();
12         }
13         return _WindowRooView;
14     }
15     public Xcls_viewbox viewbox;
16     public Xcls_AutoRedraw AutoRedraw;
17     public Xcls_viewcontainer viewcontainer;
18     public Xcls_view view;
19     public Xcls_inspectorcontainer inspectorcontainer;
20
21         // my vars (def)
22     public JsRender.JsRender file;
23
24     // ctor
25     public Xcls_WindowRooView()
26     {
27         _this = this;
28         this.el = new Gtk.Paned( Gtk.Orientation.VERTICAL );
29
30         // my vars (dec)
31
32         // set gobject values
33         var child_0 = new Xcls_viewbox( _this );
34         child_0.ref();
35         this.el.pack1 (  child_0.el , true,true );
36         var child_1 = new Xcls_inspectorcontainer( _this );
37         child_1.ref();
38         this.el.pack2 (  child_1.el , true,true );
39     }
40
41     // user defined functions
42     public void loadFile (JsRender.JsRender file)
43     {
44         this.file = file;
45         this.view.renderJS(true);
46     }
47     public void createThumb () {
48         
49         
50         if (this.file == null) {
51             return;
52         }
53         var filename = this.file.getIconFileName(false);
54         
55         var  win = this.el.get_parent_window();
56         var width = win.get_width();
57         var height = win.get_height();
58     
59         Gdk.Pixbuf screenshot = Gdk.pixbuf_get_from_window(win, 0, 0, width, this.el.position);
60     
61         screenshot.save(filename,"png");
62         return;
63         
64         
65         
66         
67         
68         
69         
70         var p = new WebKit.PrintOperation(_this.view.el);
71          
72         var ps = new Gtk.PrintSettings();
73         ps.set_printer("Print to File");
74         ps.set("output-file-format", "pdf");
75         ps.set("output-uri", "file://" + filename + ".pdf");
76     
77         // find the printer...
78         
79         /*
80         var ar = Gtk.PaperSize.get_paper_sizes(false);
81         var psetup = new Gtk.PageSetup();
82         for(var i = 0; i < ar.length(); i++) {
83             if (ar.nth_data(i).get_name() =="iso_a4") {
84                 psetup.set_paper_size(ar.nth_data(i));
85             }
86         }
87         psetup.set_orientation(Gtk.PageOrientation.LANDSCAPE);
88         
89          
90         p.set_page_setup(psetup);
91         */
92         p.set_print_settings(ps);
93         
94         p.finished.connect(() => {
95             print("creating thumbnail for " + filename + ".pdf\n"); 
96             var s = new Cairo.PdfSurface(filename + ".pdf", 400,400);
97         
98             s.write_to_png (filename);
99             
100            // var f = GLib.File.new_for_path (filename + ".pdf");
101            // f.delete();
102         });
103         
104         
105         p.print();
106         
107         // should we hold until it's printed...
108         
109           
110     
111         
112         
113     
114     
115         
116          
117     }
118     public void requestRedraw () {
119         this.view.renderJS(false);
120     }
121     public class Xcls_viewbox : Object
122     {
123         public Gtk.Box el;
124         private Xcls_WindowRooView  _this;
125
126
127             // my vars (def)
128
129         // ctor
130         public Xcls_viewbox(Xcls_WindowRooView _owner )
131         {
132             _this = _owner;
133             _this.viewbox = this;
134             this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 );
135
136             // my vars (dec)
137
138             // set gobject values
139             this.el.homogeneous = false;
140             var child_0 = new Xcls_Box3( _this );
141             child_0.ref();
142             this.el.pack_start (  child_0.el , false,true,0 );
143             var child_1 = new Xcls_viewcontainer( _this );
144             child_1.ref();
145             this.el.pack_end (  child_1.el , true,true,0 );
146         }
147
148         // user defined functions
149     }
150     public class Xcls_Box3 : Object
151     {
152         public Gtk.Box el;
153         private Xcls_WindowRooView  _this;
154
155
156             // my vars (def)
157
158         // ctor
159         public Xcls_Box3(Xcls_WindowRooView _owner )
160         {
161             _this = _owner;
162             this.el = new Gtk.Box( Gtk.Orientation.HORIZONTAL, 0 );
163
164             // my vars (dec)
165
166             // set gobject values
167             this.el.homogeneous = true;
168             this.el.height_request = 20;
169             this.el.vexpand = false;
170             var child_0 = new Xcls_Button4( _this );
171             child_0.ref();
172             this.el.pack_start (  child_0.el , false,false,0 );
173             var child_1 = new Xcls_AutoRedraw( _this );
174             child_1.ref();
175             this.el.pack_start (  child_1.el , false,false,0 );
176             var child_2 = new Xcls_Button6( _this );
177             child_2.ref();
178             this.el.pack_start (  child_2.el , false,false,0 );
179         }
180
181         // user defined functions
182     }
183     public class Xcls_Button4 : Object
184     {
185         public Gtk.Button el;
186         private Xcls_WindowRooView  _this;
187
188
189             // my vars (def)
190
191         // ctor
192         public Xcls_Button4(Xcls_WindowRooView _owner )
193         {
194             _this = _owner;
195             this.el = new Gtk.Button();
196
197             // my vars (dec)
198
199             // set gobject values
200             this.el.label = "Redraw";
201
202             //listeners
203             this.el.clicked.connect( ( ) => {
204                 _this.view.renderJS(  true);
205             });
206         }
207
208         // user defined functions
209     }
210
211     public class Xcls_AutoRedraw : Object
212     {
213         public Gtk.CheckButton el;
214         private Xcls_WindowRooView  _this;
215
216
217             // my vars (def)
218
219         // ctor
220         public Xcls_AutoRedraw(Xcls_WindowRooView _owner )
221         {
222             _this = _owner;
223             _this.AutoRedraw = this;
224             this.el = new Gtk.CheckButton();
225
226             // my vars (dec)
227
228             // set gobject values
229             this.el.active = true;
230             this.el.label = "Auto Redraw On";
231
232             //listeners
233             this.el.toggled.connect( (state) => {
234                 this.el.set_label(this.el.active  ? "Auto Redraw On" : "Auto Redraw Off");
235             });
236         }
237
238         // user defined functions
239     }
240
241     public class Xcls_Button6 : Object
242     {
243         public Gtk.Button el;
244         private Xcls_WindowRooView  _this;
245
246
247             // my vars (def)
248
249         // ctor
250         public Xcls_Button6(Xcls_WindowRooView _owner )
251         {
252             _this = _owner;
253             this.el = new Gtk.Button();
254
255             // my vars (dec)
256
257             // set gobject values
258             this.el.label = "Full Redraw";
259
260             //listeners
261             this.el.clicked.connect( () => {
262               _this.view.redraws = 99;
263                 _this.view.el.web_context.clear_cache();  
264               //_this.view.renderJS(true);
265               FakeServerCache.clear();
266               _this.view.reInit();
267             
268             });
269         }
270
271         // user defined functions
272     }
273
274
275     public class Xcls_viewcontainer : Object
276     {
277         public Gtk.ScrolledWindow el;
278         private Xcls_WindowRooView  _this;
279
280
281             // my vars (def)
282
283         // ctor
284         public Xcls_viewcontainer(Xcls_WindowRooView _owner )
285         {
286             _this = _owner;
287             _this.viewcontainer = this;
288             this.el = new Gtk.ScrolledWindow( null, null );
289
290             // my vars (dec)
291
292             // set gobject values
293             this.el.shadow_type = Gtk.ShadowType.IN;
294             var child_0 = new Xcls_view( _this );
295             child_0.ref();
296             this.el.add (  child_0.el  );
297
298             // init method
299
300             this.el.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
301         }
302
303         // user defined functions
304     }
305     public class Xcls_view : Object
306     {
307         public WebKit.WebView el;
308         private Xcls_WindowRooView  _this;
309
310
311             // my vars (def)
312         public string renderedData;
313         public bool refreshRequired;
314         public WebKit.WebInspector inspector;
315         public string runjs;
316         public int redraws;
317         public GLib.DateTime lastRedraw;
318         public string runhtml;
319         public bool pendingRedraw;
320
321         // ctor
322         public Xcls_view(Xcls_WindowRooView _owner )
323         {
324             _this = _owner;
325             _this.view = this;
326             this.el = new WebKit.WebView();
327
328             // my vars (dec)
329             this.renderedData = "";
330             this.refreshRequired = false;
331             this.runjs = "";
332             this.redraws = 0;
333             this.lastRedraw = null;
334             this.runhtml = "";
335             this.pendingRedraw = false;
336
337             // set gobject values
338
339             // init method
340
341             {
342                 // this may not work!?
343                 var settings =  this.el.get_settings();
344                 settings.enable_developer_extras = true;
345                 
346                 
347                 var fs= new FakeServer(this.el);
348                 fs.ref();
349                 // this was an attempt to change the url perms.. did not work..
350                 // settings.enable_file_access_from_file_uris = true;
351                 // settings.enable_offline_web_application_cache - true;
352                 // settings.enable_universal_access_from_file_uris = true;
353                
354                  
355                 
356                 
357                 
358             
359                  // FIXME - base url of script..
360                  // we need it so some of the database features work.
361                 this.el.load_html( "Render not ready" , 
362                         //fixme - should be a config option!
363                         // or should we catch stuff and fix it up..
364                         "http://localhost/app.Builder/"
365                 );
366                     
367                     
368                //this.el.open('file:///' + __script_path__ + '/../builder.html');
369                 /*
370                 Gtk.drag_dest_set
371                 (
372                         this.el,              //
373                         Gtk.DestDefaults.MOTION  | Gtk.DestDefaults.HIGHLIGHT,
374                         null,            // list of targets
375                         Gdk.DragAction.COPY         // what to do with data after dropped 
376                 );
377                                         
378                // print("RB: TARGETS : " + LeftTree.atoms["STRING"]);
379                 Gtk.drag_dest_set_target_list(this.el, this.get('/Window').targetList);
380                 */
381                 GLib.Timeout.add_seconds(1,  ()  =>{
382                      //print("run refresh?");
383                      if (this.el == null) {
384                         return false;
385                      }
386                      this.runRefresh(); 
387                      return true;
388                  });
389                 
390                 
391             }
392
393             //listeners
394             this.el.script_dialog.connect( (dialog) => {
395                 if (this.el == null) {
396                     return true;
397                 }
398                 
399                  var msg = dialog.get_message();
400                  if (msg.length < 4) {
401                     return false;
402                  }
403                  if (msg.substring(0,4) != "IPC:") {
404                      return false;
405                  }
406                  var ar = msg.split(":", 3);
407                 if (ar.length < 3) {
408                     return false;
409                 }
410                 switch(ar[1]) {
411                     case "SAVEHTML":
412                         _this.file.saveHTML(ar[2]);
413                         return true;
414                     default:
415                         return false;
416                 }
417                 
418             });
419             this.el.show.connect( ( ) => {
420                 this.initInspector();;
421             });
422             this.el.drag_drop.connect( ( ctx, x, y,time, ud) => {
423                 return false;
424                 /*
425                 print("TARGET: drag-drop");
426                     var is_valid_drop_site = true;
427                     
428                      
429                     Gtk.drag_get_data
430                     (
431                             w,         // will receive 'drag-data-received' signal 
432                             ctx,        /* represents the current state of the DnD 
433                             this.get('/Window').atoms["STRING"],    /* the target type we want 
434                             time            /* time stamp 
435                     );
436                                     
437                                     
438                                     /* No target offered by source => error 
439                                    
440             
441                 return  is_valid_drop_site;
442                 */
443             });
444             this.el.load_changed.connect( (le) => {
445                 if (le != WebKit.LoadEvent.FINISHED) {
446                     return;
447                 }
448                 if (this.runjs.length < 1) {
449                     return;
450                 }
451               //  this.el.run_javascript(this.runjs, null);
452                  FakeServerCache.remove(    this.runjs);
453                 this.runjs = "";
454             });
455         }
456
457         // user defined functions
458         public void reInit () {
459            print("reInit?");
460                  // if this happens destroy the webkit..
461                  // recreate it..
462              this.el.stop_loading();
463                  
464              if (_this.viewbox.el.get_parent() == null) {
465                 return;
466              }
467                  
468                  
469             _this.viewbox.el.remove(_this.viewcontainer.el);
470             _this.el.remove(_this.inspectorcontainer.el);        
471                  
472                  // destory seems to cause problems.
473                  //this.el.destroy();
474                 //_this.viewcontainer.el.destroy();
475                  //_this.inspectorcontainer.el.destroy();
476              var  inv =new Xcls_inspectorcontainer(_this);
477               inv.ref();
478               _this.el.pack2(inv.el,true,true);
479               
480               
481              this.el = null;         
482              var nv =new Xcls_viewcontainer(_this);
483              nv.ref();
484              _this.viewbox.el.pack_end(nv.el,true,true,0);
485                  
486                  
487              inv.el.show_all();
488              nv.el.show_all();
489                  //while(Gtk.events_pending ()) Gtk.main_iteration ();
490                  //_this.view.renderJS(true); 
491              _this.view.refreshRequired  = true;
492         }
493         public void runRefresh () 
494         {
495             // this is run every 2 seconds from the init..
496         
497           
498             
499             if (!this.refreshRequired) {
500                // print("no refresh required");
501                 return;
502             }
503         
504             if (this.lastRedraw != null) {
505                // do not redraw if last redraw was less that 5 seconds ago.
506                if ((int64)(new DateTime.now_local()).difference(this.lastRedraw) < 5000 ) {
507                     return;
508                 }
509             }
510             
511             if (_this.file == null) {
512                 return;
513             }
514             
515             
516              this.refreshRequired = false;
517            //  print("HTML RENDERING");
518              
519              
520              //this.get('/BottomPane').el.show();
521              //this.get('/BottomPane').el.set_current_page(2);// webkit inspector
522             _this.file.webkit_page_id  = this.el.get_page_id();
523             
524             var js = _this.file.toSourcePreview();
525         
526             if (js.length < 1) {
527                 print("no data");
528                 return;
529             }
530         //    var  data = js[0];
531             this.redraws++;
532           
533             var project = _this.file.project;  
534         
535              //print (project.fn);
536              // set it to non-empty.
537              
538         //     runhtml = runhtml.length ?  runhtml : '<script type="text/javascript"></script>'; 
539         
540         
541         //   this.runhtml  = this.runhtml || '';
542          
543          
544             // then we need to reload the browser using
545             // load_html_string..
546         
547             // then trigger a redraw once it's loaded..
548             this.pendingRedraw = true;
549         
550             var runhtml = "<script type=\"text/javascript\">\n" ;
551             string builderhtml;
552             
553             try {
554                 GLib.FileUtils.get_contents(BuilderApplication.configDirectory() + "/resources/roo.builder.js", out builderhtml);
555             } catch (Error e) {
556                 builderhtml = "";
557             }
558         
559             runhtml += builderhtml + "\n";
560             runhtml += "</script>\n" ;
561         
562             // fix to make sure they are the same..
563             this.runhtml = project.runhtml;
564             // need to modify paths
565         
566             string inhtml;
567             var base_template = _this.file.project.base_template;
568             
569             if (base_template.length > 0 && !FileUtils.test(
570                 BuilderApplication.configDirectory() + "/resources/" +  base_template, FileTest.EXISTS)  
571                 ) {
572                    print("invalid base_template name - using default:  %s\n", base_template);
573                    base_template = "";
574             
575             }
576             try {
577                 GLib.FileUtils.get_contents(
578                     BuilderApplication.configDirectory() + "/resources/" + 
579                         (base_template.length > 0 ? base_template :  "roo.builder.html")
580                         , out inhtml);
581             
582             } catch (Error e) {
583                 inhtml = "";
584             }    
585             this.renderedData = js;
586         
587         
588             string js_src = js + "\n" +
589                 "Roo.onReady(function() {\n" +
590                 "if (" + _this.file.name +".show) " +  _this.file.name +".show({});\n" +
591                 "Roo.XComponent.build();\n" +
592                 "});\n";
593                 
594            // print("render js: " + js);
595             //if (!this.ready) {
596           //      console.log('not loaded yet');
597             //}
598             this.lastRedraw = new DateTime.now_local();
599         
600         
601             //this.runjs = js_src;
602             var fc =    FakeServerCache.factory_with_data(js_src);
603             this.runjs = fc.fname;
604             
605                 var html = inhtml.replace("</head>", runhtml + this.runhtml + 
606                     "<script type=\"text/javascript\" src=\"xhttp://localhost" + fc.fname + "\"></script>" +   
607                       //  "<script type=\"text/javascript\">\n" +
608                       //  js_src + "\n" + 
609                       //  "</script>" + 
610                                 
611                 "</head>");
612                 //print("LOAD HTML " + html);
613                 
614                  var rootURL = _this.file.project.rootURL;
615            
616                 
617                 
618                 this.el.load_html( html , 
619                     //fixme - should be a config option!
620                     (rootURL.length > 0 ? rootURL : "xhttp://localhost/app.Builder.js/")
621                 );
622                 
623             // force the inspector...        
624                //   this.initInspector();
625                 
626                 // - no need for this, the builder javascript will call it when build is complete
627                 //GLib.Timeout.add_seconds(1, () => {
628                 //    this.el.run_javascript("Builder.saveHTML()",null);
629                 //    return false;
630                 //});
631         //     print( "before render" +    this.lastRedraw);
632         //    print( "after render" +    (new Date()));
633             
634         }
635         public void initInspector () {
636             
637            /* if (this.inspector == this.el.get_inspector()) {
638                 this.inspector.show();
639                 this.inspector.open_window();        
640                 print("init inspecter called, and inspector is the same as existing\n");
641                 return;
642             }
643             print("new inspector?\n");
644         */
645             this.inspector = this.el.get_inspector();
646             this.inspector.ref();
647             
648             // got a new inspector...
649                 
650             this.inspector.open_window.connect(() => {
651                  this.inspector = this.el.get_inspector();
652                 print("inspector attach\n");
653                 var wv = this.inspector.get_web_view();
654                 if (wv != null) {
655                     print("got inspector web view\n");
656                     
657                     var cn = _this.inspectorcontainer.el.get_child();
658                     if (cn != null) {
659                          _this.inspectorcontainer.el.remove(cn);
660                      }
661                     
662                     _this.inspectorcontainer.el.add(wv);
663                     wv.show();
664                 } else {
665                     //this.inspector.close();
666                     
667                     //this.inspector = null;
668                    
669          
670                 }
671                 return true;
672                
673             });
674             /*
675             this.inspector.closed.connect(() => {
676                  print("inspector closed?!?");
677                  // if this happens destroy the webkit..
678                  // recreate it..
679                  this.el.stop_loading();
680                  
681                  if (_this.viewbox.el.get_parent() == null) {
682                     return;
683                  }
684                  
685                  
686                 _this.viewbox.el.remove(_this.viewcontainer.el);
687                 _this.el.remove(_this.inspectorcontainer.el);        
688                  
689                  // destory seems to cause problems.
690                  //this.el.destroy();
691                 //_this.viewcontainer.el.destroy();
692                  //_this.inspectorcontainer.el.destroy();
693         
694                  this.el = null;         
695                  var nv =new Xcls_viewcontainer(_this);
696                  nv.ref();
697                  _this.viewbox.el.pack_end(nv.el,true,true,0);
698                  
699                   var  inv =new Xcls_inspectorcontainer(_this);
700                   inv.ref();
701                   _this.el.pack2(inv.el,true,true);
702                  
703                  inv.el.show_all();
704                  nv.el.show_all();
705                  //while(Gtk.events_pending ()) Gtk.main_iteration ();
706                  //_this.view.renderJS(true); 
707                  _this.view.refreshRequired  = true;
708                
709             }); 
710             */
711             
712             this.inspector.show();
713         }
714         public void renderJS (bool force) {
715         
716             // this is the public redraw call..
717             // we refresh in a loop privately..
718             var autodraw = _this.AutoRedraw.el.active;
719             if (!autodraw && !force) {
720                 print("Skipping redraw - no force, and autodraw off");
721                 return;
722             }
723              
724             this.refreshRequired  = true;
725         }
726     }
727
728
729
730     public class Xcls_inspectorcontainer : Object
731     {
732         public Gtk.ScrolledWindow el;
733         private Xcls_WindowRooView  _this;
734
735
736             // my vars (def)
737
738         // ctor
739         public Xcls_inspectorcontainer(Xcls_WindowRooView _owner )
740         {
741             _this = _owner;
742             _this.inspectorcontainer = this;
743             this.el = new Gtk.ScrolledWindow( null, null );
744
745             // my vars (dec)
746
747             // set gobject values
748             this.el.shadow_type = Gtk.ShadowType.IN;
749
750             // init method
751
752             this.el.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);
753         }
754
755         // user defined functions
756     }
757
758 }