Fix #7963 - add gda back in
[roobuilder] / src / Application.vala
1
2  
3         public class AppSettings : Object
4         {
5
6                 
7                 
8                 // what are we going to have as settings?
9                 public string roo_html_dir { get; set; }
10
11                 public AppSettings()
12                 {
13                         this.notify.connect(() => {
14                                 this.save();
15                         });
16                 }
17  
18                 public static AppSettings factory()
19                 {
20                          
21                         var setting_file = BuilderApplication.configDirectory() + "/builder.settings";
22                         
23                         if (!FileUtils.test(setting_file, FileTest.EXISTS)) {
24                                  return new AppSettings();
25                         }
26                         string data; 
27                         try { 
28                                 FileUtils.get_contents(setting_file, out data);
29                                 return Json.gobject_from_data (typeof (AppSettings), data) as AppSettings;
30                         } catch (Error e) {
31                         }
32                         return new AppSettings();
33                 }
34                 public void save()
35                 {
36                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
37                         var setting_file = dirname + "/builder.settings";
38                         string data = Json.gobject_to_data (this, null);
39                         GLib.debug("saving application settings\n");
40                         try {
41                                 FileUtils.set_contents(setting_file,   data);
42                         } catch (Error e) {
43                                 print("Error saving app settings");
44                         }
45                 }
46
47                 
48         }
49         
50         
51         public static BuilderApplication application = null;
52         
53         public class BuilderApplication : Gtk.Application
54         {
55                 
56                 // options - used when builder is run as a compiler
57                 // we have to spawn ourself as a compiler as just running libvala
58                 // as a task to check syntax causes memory leakage..
59                 // 
60                 const OptionEntry[] options = {
61                 
62                         
63                         { "project", 0, 0, OptionArg.STRING, ref opt_compile_project, "select a project", null },
64                         { "target", 0, 0, OptionArg.STRING, ref opt_compile_target, "Target to build", null },
65                         { "skip-linking", 0, 0, OptionArg.NONE, ref opt_skip_linking, "Do not link the files and make a binary - used to do syntax checking", null },
66                         { "skip-file", 0, 0, OptionArg.STRING, ref opt_compile_skip ,"For test compiles do not add this (usually used in conjunction with add-file ", null },
67                         { "add-file", 0, 0, OptionArg.STRING, ref opt_compile_add, "Add this file to compile list", null },
68                         { "output", 0, 0, OptionArg.STRING, ref opt_compile_output, "output binary file path", null },
69                         { "debug", 0, 0, OptionArg.NONE, ref opt_debug, "Show debug messages", null },
70                         { "pull-resources", 0, 0, OptionArg.NONE, ref opt_pull_resources, "Fetch the online resources", null },                 
71             
72             // some testing code.
73             { "list-projects", 0, 0,  OptionArg.NONE, ref opt_list_projects, "List Projects", null },
74             { "list-files", 0, 0,  OptionArg.NONE, ref  opt_list_files, "List Files (in a project", null},
75             { "bjs", 0, 0, OptionArg.STRING, ref opt_bjs_compile, "convert bjs file (use all to convert all of them and compare output)", null },
76             { "bjs-glade", 0, 0, OptionArg.NONE, ref opt_bjs_compile_glade, "output glade", null },
77             { "bjs-test-all", 0, 0, OptionArg.NONE, ref opt_bjs_test, "Test all the BJS files to see if the new parser/writer would change anything", null },            
78             { "bjs-target", 0, 0, OptionArg.STRING, ref opt_bjs_compile_target, "convert bjs file to tareet  : vala / js", null },
79             { "test", 0, 0, OptionArg.STRING, ref opt_test, "run a test use 'help' to list the available tests", null },
80             
81             { "drop-list", 0, 0, OptionArg.STRING, ref opt_drop_list, "show droplist / children for a Gtk type (eg. Gtk.Widget)", null },
82             
83             
84                         { null }
85                 };
86                 public static string opt_compile_project;
87                 public static string opt_compile_target;
88                 public static string opt_compile_skip;
89                 public static string opt_compile_add;
90                 public static string opt_compile_output;
91         public static string opt_bjs_compile;
92         public static string opt_bjs_compile_target;
93         public static string opt_test;  
94         public static string opt_drop_list;
95         
96         
97         public static bool opt_skip_linking = false;
98                 public static bool opt_debug = false;
99                 public static bool opt_list_projects = false;
100                 public static bool opt_list_files = false;
101                 public static bool opt_pull_resources = false;
102                 public static bool opt_bjs_compile_glade = false;
103         public static bool opt_bjs_test = false;                
104                 public static string _self;
105                 
106                 public enum Target {
107                     INT32,
108                     STRING,
109                     ROOTWIN
110                 }
111
112 /*
113                 public const Gtk.TargetEntry[] targetList = {
114                     { "INTEGER",    0, Target.INT32 },
115                     { "STRING",     0, Target.STRING },
116                     { "application/json",     0, Target.STRING },                       
117                     { "text/plain", 0, Target.STRING },
118                     { "application/x-rootwindow-drop", 0, Target.ROOTWIN }
119                 };
120                 */
121                 public AppSettings settings = null;
122
123
124
125                 public static Palete.ValaCompileQueue valacompilequeue;
126
127         
128                 public BuilderApplication (  string[] args)
129                 {
130                         
131                         try {
132                                 _self = FileUtils.read_link("/proc/self/exe");
133                         } catch (Error e) {
134                                 // this should nto happen!!?
135                                 GLib.error("could not read /proc/self/exe");
136                         }
137                         GLib.debug("SELF = %s", _self);
138                         var f =  File.new_for_path(_self);
139                         var dt = "0000";
140                         try {
141                                 var fi = f.query_info("*",0);
142                                 dt = fi.get_creation_date_time().to_unix().to_string();
143                         } catch (GLib.Error e) {
144                                 // skip.
145                         }
146                         
147                         Object(
148                                 application_id: "org.roojs.%s.ver%s".printf( GLib.Path.get_basename(_self),dt),
149                                 flags: ApplicationFlags.FLAGS_NONE
150                         );
151                         BuilderApplication.windows = new        Gee.ArrayList<Xcls_MainWindow>();
152                         BuilderApplication.valacompilequeue = new Palete.ValaCompileQueue();
153                         
154                         
155                         configDirectory();
156                         this.settings = AppSettings.factory();  
157                         var opt_context = new OptionContext ("Application Builder");
158                         
159                         try {
160                                 opt_context.set_help_enabled (true);
161                                 opt_context.add_main_entries (options, null);
162                                 opt_context.parse (ref args);
163                                  
164                                 
165                         } catch (OptionError e) {
166                                 stdout.printf ("error: %s\n", e.message);
167                                 stdout.printf ("Run '%s --help' to see a full list of available command line options.\n %s", 
168                                                          args[0], opt_context.get_help(true,null));
169                                 GLib.Process.exit(Posix.EXIT_FAILURE);
170                                  
171                         }
172                         this.initDebug();
173                         this.runTests();                        
174                         this.pullResources();
175                         
176                 Project.Project.loadAll();
177                         this.listProjects();
178                         var cur_project = this.compileProject();
179                         this.dropList(cur_project);
180                         this.listFiles(cur_project);
181                         this.testBjs(cur_project);
182                         this.compileBjs(cur_project);
183                         this.compileVala();
184
185                 }
186
187
188                 
189                 public static BuilderApplication  singleton(  string[]? args)
190                 {
191                         if (application==null && args != null) {
192                                 application = new BuilderApplication(  args);
193  
194                         
195                         }
196                         return application;
197                 }
198
199                 
200                 public static string configDirectory()
201                 {
202                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
203                 
204                         if (!FileUtils.test(dirname,FileTest.IS_DIR)) {
205                                 var dir = File.new_for_path(dirname);
206                                 try {
207                                         dir.make_directory();   
208                                 } catch (Error e) {
209                                         GLib.error("Failed to make directory %s", dirname);
210                                 } 
211                         }
212                         if (!FileUtils.test(dirname + "/resources",FileTest.IS_DIR)) {
213                                 var dir = File.new_for_path(dirname + "/resources");
214                                 try {
215                                         dir.make_directory();   
216                                 } catch (Error e) {
217                                         GLib.error("Failed to make directory %s", dirname + "/resources");
218                                 } 
219                         }
220
221                 
222                         return dirname;
223                 }
224                 
225                 
226                 // --------------- non static...
227                 
228                 void initDebug() 
229                 {
230                 
231                         if (BuilderApplication.opt_debug  || BuilderApplication.opt_compile_project == null) {
232                                 GLib.Log.set_handler(null, 
233                                         GLib.LogLevelFlags.LEVEL_DEBUG | GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_CRITICAL, 
234                                         (dom, lvl, msg) => {
235                                         print("%s: %s\n", (new DateTime.now_local()).format("%H:%M:%S.%f"), msg);
236                                 });
237                         }
238                         
239                 
240                 }
241                 void listProjects()
242                 {
243                         if (!BuilderApplication.opt_list_projects) {
244                                 return;
245                         }
246                         print("Projects\n %s\n", Project.Project.listAllToString());
247                         GLib.Process.exit(Posix.EXIT_SUCCESS);
248                 
249                 }
250                 Project.Project? compileProject()
251                 {
252                         
253                         if (BuilderApplication.opt_compile_project == null) {
254                                 return null;
255                          }
256                         Project.Project cur_project = null;
257                         cur_project = Project.Project.getProjectByPath( BuilderApplication.opt_compile_project);
258                         
259
260                         
261                         if (cur_project == null) {
262                                 GLib.error("invalid project %s, use --list-projects to show project ids",BuilderApplication.opt_compile_project);
263                         }
264                         cur_project.load();
265
266                         
267
268                         return cur_project;
269                 
270                 }
271                 
272                 void dropList(Project.Project? cur_project) {
273
274
275                         if (cur_project== null || BuilderApplication.opt_drop_list == null) {
276                                 return;
277                         }
278                         
279                         if (BuilderApplication.opt_compile_project == null) {
280                                 GLib.error("need a project %s, to use --drop-list",BuilderApplication.opt_compile_project);
281                          }
282                           if (cur_project.xtype != "Gtk") {
283                                 GLib.error("need a Gtk project %s, to use --drop-list",BuilderApplication.opt_compile_project);
284                          }
285                          var p = (Palete.Gtk) cur_project.palete;
286                         
287                          print("\n\nDropList:\n%s", geeArrayToString(p.getDropList(BuilderApplication.opt_drop_list)));
288                          print("\n\nChildList:\n%s", geeArrayToString(p.getChildList(BuilderApplication.opt_drop_list, false)));
289                          print("\n\nChildList \n(with props): %s", geeArrayToString(p.getChildList(BuilderApplication.opt_drop_list, true)));   
290                          
291                          
292                          print("\n\nPropsList: %s", this.girArrayToString(p.getPropertiesFor( BuilderApplication.opt_drop_list, JsRender.NodePropType.PROP)));
293                          print("\n\nSignalList: %s", this.girArrayToString(p.getPropertiesFor( BuilderApplication.opt_drop_list, JsRender.NodePropType.LISTENER)));
294                          
295                          // ctor.
296                           print("\n\nCtor Values: %s", p.fqnToNode(BuilderApplication.opt_drop_list).toJsonString());
297                          
298                           GLib.Process.exit(Posix.EXIT_SUCCESS);
299                         
300                 }
301                 string geeArrayToString(Gee.ArrayList<string> ar) 
302                 {
303                         var ret = "";
304                         foreach(var n in ar) {
305                                 ret +=   n + "\n";
306                          }
307                          return ret;
308                 }
309                 string girArrayToString(Gee.HashMap<string,Palete.GirObject> map) 
310                 {
311                         var ret = "";
312                         foreach(var gi in map.values) {
313                                  ret += "%s %s (%s)\n".printf(gi.type, gi.name, gi.propertyof);
314                         
315                         }
316                         return ret;
317                 
318                 }
319                  
320                 
321                 void listFiles(Project.Project? cur_project)
322                 {
323                         if (!BuilderApplication.opt_list_files) {
324                                 return;
325                         }
326                         if (cur_project == null) {
327                                 GLib.error("missing project, use --project to select which project");
328                         }
329                         print("Files for %s\n %s\n", cur_project.name, cur_project.listAllFilesToString());
330                         GLib.Process.exit(Posix.EXIT_SUCCESS);
331                         
332                 }
333                 
334                 /**
335                  Test to see if the internal BJS reader/writer still outputs the same files.
336                  -- probably need this for the generator as well.
337                 */
338                 
339                 void testBjs(Project.Project? cur_project)
340                 {
341                         if (!BuilderApplication.opt_bjs_test) {
342                                 return;
343                         }
344                         if (cur_project == null) {
345                                 GLib.error("missing project, use --project to select which project");
346                         }
347                         print("Checking files\n");
348                         try { 
349                                 var ar = cur_project.sortedFiles();
350                                 foreach(var file in ar) {
351                                         string oldstr;
352
353                                         file.loadItems();
354                                         GLib.FileUtils.get_contents(file.path, out oldstr);                             
355                                         var outstr = file.toJsonString();
356                                         if (outstr != oldstr) { 
357                                                 
358                                                 GLib.FileUtils.set_contents("/tmp/" + file.name ,   outstr);
359                                                 print("meld  %s /tmp/%s\n", file.path,  file.name);
360                                                 //GLib.Process.exit(Posix.EXIT_SUCCESS);                
361                                         }
362                                         print("# Files match %s\n", file.name);
363                                         
364                                 }
365                         } catch (FileError e) {
366                                 GLib.debug("Got error %s", e.message);
367                         } catch (Error e) {
368                                 GLib.debug("Got error %s", e.message);
369                         }
370                                 
371                         print("All files pass");
372                         GLib.Process.exit(Posix.EXIT_SUCCESS);
373                 }
374                 
375                 void compileBjs(Project.Project? cur_project)
376                 {
377                         if (BuilderApplication.opt_bjs_compile == null) {
378                                 return;
379                         }
380                         if (cur_project == null) {
381                                 GLib.error("missing project, use --project to select which project");
382                         }
383                         
384                         if (BuilderApplication.opt_bjs_compile == "all") {
385                                 try { 
386                                         var ar = cur_project.sortedFiles();
387                                         
388                                         foreach(var file in ar) {
389                                                 string oldstr;
390
391                                                 file.loadItems();
392                                                 var oldfn = file.targetName();
393                                                 GLib.FileUtils.get_contents(oldfn, out oldstr);
394                                                                                 
395                                                 var outstr = file.toSourceCode();
396                                                 if (outstr != oldstr) { 
397                                                         
398                                                         GLib.FileUtils.set_contents("/tmp/" + file.name   + ".out",   outstr);
399                                                         print("meld   %s /tmp/%s\n", oldfn,  file.name + ".out");
400                                                         //GLib.Process.exit(Posix.EXIT_SUCCESS);                
401                                                 }
402                                                 print("# Files match %s\n", file.name);
403                                         }               
404                                 } catch (FileError e) {
405                                         GLib.debug("Got error %s", e.message);
406                                 } catch (Error e) {
407                                         GLib.debug("got error %s", e.message);
408                                 }
409                                 
410                                 GLib.Process.exit(Posix.EXIT_SUCCESS);
411                         
412                         }
413                         
414                         
415                         
416                         var file = cur_project.getByName(BuilderApplication.opt_bjs_compile);
417                         if (file == null) {
418                                 // then compile them all, and compare them...
419                                 
420                         
421                         
422                         
423                         
424                         
425                                 GLib.error("missing file %s in project %s", BuilderApplication.opt_bjs_compile, cur_project.name);
426                         }
427                         try {
428                                 file.loadItems();
429                         } catch(Error e) {
430                                 GLib.debug("Load items failed");
431                         }
432                                         
433                         if (BuilderApplication.opt_bjs_compile_glade) {
434                                 var str = file.toGlade();
435                                 print("%s", str);
436                                 GLib.Process.exit(Posix.EXIT_SUCCESS);
437                         }
438                         
439                         //BuilderApplication.compileBjs();
440
441                         var str = file.toSourceCode();
442                           
443                           
444                         if (!BuilderApplication.opt_debug) {
445                                 print("%s", str);
446                                 GLib.Process.exit(Posix.EXIT_SUCCESS);
447                         }
448                         
449                         // dump the node tree
450                         file.tree.dumpProps();
451                         
452                         
453                         
454                         
455                         
456                         var str_ar = str.split("\n");
457                         for(var i =0;i<str_ar.length;i++) {
458                                 var node = file.tree.lineToNode(i+1);
459                                 var prop = node == null ? null : node.lineToProp(i+1);
460                                 print("%d: %s   :  %s\n", 
461                                         i+1, 
462                                         node == null ? "......"  : (prop == null ? "????????" : prop.name),
463                                         str_ar[i]
464                                 );
465                         }
466                         
467                         GLib.Process.exit(Posix.EXIT_SUCCESS);
468                 }
469                 
470                 void compileVala()
471                 {
472                         if (BuilderApplication.opt_compile_target == null) {
473                                 return;
474                         }
475                         Palete.ValaSourceCompiler.buildApplication();
476                 
477                         GLib.Process.exit(Posix.EXIT_SUCCESS);
478         
479                 }
480                 void pullResources()
481                 {
482                         if (!opt_pull_resources) {
483                                 return;
484                         }
485                         var loop = new MainLoop();
486                         Resources.singleton().updateProgress.connect((p,t) => {
487                                 print("Got %d/%d", (int) p,(int)t);
488                                 if (p == t) {
489                                         loop.quit();
490                                 }
491                         });
492                         Resources.singleton().fetchStart();     
493                         loop.run();
494                         GLib.Process.exit(Posix.EXIT_SUCCESS);
495                 }
496                 
497                 
498                 void runTests()
499                 {
500                         if (opt_test == null) {
501                                 return;
502                         }
503                         switch(opt_test) {
504                                 case "help":
505                                         print("""
506 help             - list available tests
507 flutter-project  - create a flutter project in /tmp/test-flutter
508 """);           
509                                         break;
510                                 case "flutter-project":
511                                 Project.Project.loadAll();
512                                         //var p =   Project.Project.factory("Flutter", "/tmp/test-flutter");
513                                         /*var pa = p.palete as Palete.Flutter;
514                                         pa.dumpusage();
515                                          var ar = pa.getChildList("material.Scaffold");
516                                         GLib.debug("childlist for material.Scaffold is %s", 
517                                                 string.joinv( "\n-- ", ar)
518                                         );
519                                         ar = pa.getDropList("material.MaterialApp");
520                                         GLib.debug("droplist for material.MaterialApp is %s", 
521                                                 string.joinv( "\n-- ", ar)
522                                         );
523                                         */
524                                         break;
525                                         
526                                 default:
527                                         print("Invalid test\n");
528                                         break;
529
530
531                         }
532                         GLib.Process.exit(Posix.EXIT_SUCCESS);          
533                 }
534                 
535                 
536                 // move to 'window colletction?
537                 public static Gee.ArrayList<Xcls_MainWindow> windows;
538                 
539                 public static void addWindow(Xcls_MainWindow w)
540                 {
541                          
542                         BuilderApplication.windows.add(w);
543                         BuilderApplication.updateWindows();
544   
545                         
546                 }
547                 
548                 public static void removeWindow(Xcls_MainWindow w)
549                 {
550                         //GLib.debug("remove window before = %d", BuilderApplication.windows.size);
551                         BuilderApplication.windows.remove(w);
552                         BuilderApplication.updateWindows();
553                                 
554                         w.el.hide();
555                         w.el.close();
556                         w.el.destroy();
557                         //GLib.debug("remove window after = %d", BuilderApplication.windows.size);
558                         
559                         
560                 }
561                 public static void updateWindows()
562                 {
563                         foreach(var ww in BuilderApplication.windows) {
564                                 ww.windowbtn.updateMenu();
565                         }
566                 }
567                 public static Xcls_MainWindow? getWindow(JsRender.JsRender file)
568                 {
569                         foreach(var ww in BuilderApplication.windows) {
570                                 if (ww.windowstate != null && ww.windowstate.file != null &&  ww.windowstate.file.path == file.path) {
571                                         return ww;
572                                 }
573                         }
574                         return null;
575                 
576                 }
577                 
578                 public static void newWindow(JsRender.JsRender file, int line)
579                 {
580                     var w = new Xcls_MainWindow();
581                         w.ref();
582                         BuilderApplication.addWindow(w);
583                         w.initChildren();
584                         w.windowstate.fileViewOpen(file, false, line);
585                         w.el.present();
586                          
587                 
588                 }
589                 
590                 public static void updateCompileResults( )
591                 {
592                         foreach(var ww in BuilderApplication.windows) {
593                                 if (ww == null || ww.windowstate == null || ww.windowstate.project ==null) {
594                                         continue;
595                                 }
596                                 if (ww.windowstate.project.last_request == null) {
597                                         ww.updateErrors(null);                                  
598                                         return;
599                                 }
600                                 var req = ww.windowstate.project.last_request;
601                                 GLib.debug("checking errors editor for %s", ww.windowstate.file.targetName());
602                                 
603                                 if (req.errorByFile.has_key(ww.windowstate.file.targetName())) {
604                                         GLib.debug("calling update Error margs for  %s", ww.windowstate.file.targetName());             
605                                         ww.windowstate.code_editor_tab.updateErrorMarks(req.errorByFile.get(ww.windowstate.file.targetName()));
606                                 } else {
607                                         ww.windowstate.code_editor_tab.updateErrorMarks(null);
608                                  
609                                         GLib.debug("no errors in errrobyfile for  %s", ww.windowstate.file.targetName());               
610                                 }
611                                 
612                                 GLib.debug("calling udate Errors of window %s", ww.windowstate.file.targetName());
613                                 ww.updateErrors(req);
614                                 
615                                 
616                         }
617                 
618                 }
619                 
620                 
621          
622         }
623         
624         
625                 
626
627  
628
629