Merge branch 'master' of http://git.roojs.com/roobuilder
[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                         FileUtils.get_contents(setting_file, out data);
28                         return Json.gobject_from_data (typeof (AppSettings), data) as AppSettings;
29                 }
30                 public void save()
31                 {
32                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
33                         var setting_file = dirname + "/builder.settings";
34                         string data = Json.gobject_to_data (this, null);
35                         print("saving application settings\n");
36                         FileUtils.set_contents(setting_file,   data);
37                 }
38
39                 
40         }
41         
42         
43         public static BuilderApplication application = null;
44         
45         public class BuilderApplication : Gtk.Application
46         {
47                 
48                 // options - used when builder is run as a compiler
49                 // we have to spawn ourself as a compiler as just running libvala
50                 // as a task to check syntax causes memory leakage..
51                 // 
52                 const OptionEntry[] options = {
53                 
54                         
55                         { "project", 0, 0, OptionArg.STRING, ref opt_compile_project, "Compile a project", null },
56                         { "target", 0, 0, OptionArg.STRING, ref opt_compile_target, "Target to build", null },
57                         { "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 },
58                         { "add-file", 0, 0, OptionArg.STRING, ref opt_compile_add, "Add this file to compile list", null },
59                         { "output", 0, 0, OptionArg.STRING, ref opt_compile_output, "output binary file path", null },
60                         { "debug", 0, 0, OptionArg.NONE, ref opt_debug, "Show debug messages", null },
61                         { "pull-resources", 0, 0, OptionArg.NONE, ref opt_pull_resources, "Fetch the online resources", null },                 
62             
63             // some testing code.
64             { "list-projects", 0, 0,  OptionArg.NONE, ref opt_list_projects, "List Projects", null },
65             { "list-files", 0, 0,  OptionArg.NONE, ref  opt_list_files, "List Files (in a project", null},
66             { "bjs", 0, 0, OptionArg.STRING, ref opt_bjs_compile, "convert bjs file (use all to convert all of them and compare output)", null },
67             { "bjs-glade", 0, 0, OptionArg.NONE, ref opt_bjs_compile_glade, "output glade", null },
68             { "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 },            
69             { "bjs-target", 0, 0, OptionArg.STRING, ref opt_bjs_compile_target, "convert bjs file to tareet  : vala / js", null },
70             { "test", 0, 0, OptionArg.STRING, ref opt_test, "run a test use 'help' to list the available tests", null },
71             
72                         { null }
73                 };
74                 public static string opt_compile_project;
75                 public static string opt_compile_target;
76                 public static string opt_compile_skip;
77                 public static string opt_compile_add;
78                 public static string opt_compile_output;
79         public static string opt_bjs_compile;
80
81         public static string opt_bjs_compile_target;
82         public static string opt_test;        
83                 public static bool opt_debug = false;
84                 public static bool opt_list_projects = false;
85                 public static bool opt_list_files = false;
86                 public static bool opt_pull_resources = false;
87                 public static bool opt_bjs_compile_glade = false;
88         public static bool opt_bjs_test = false;                
89                 public static string _self;
90                 
91                 public enum Target {
92                     INT32,
93                     STRING,
94                     ROOTWIN
95                 }
96
97
98                 public const Gtk.TargetEntry[] targetList = {
99                     { "INTEGER",    0, Target.INT32 },
100                     { "STRING",     0, Target.STRING },
101                     { "application/json",     0, Target.STRING },                       
102                     { "text/plain", 0, Target.STRING },
103                     { "application/x-rootwindow-drop", 0, Target.ROOTWIN }
104                 };
105                 public AppSettings settings = null;
106
107
108
109                 public static Palete.ValaSource valasource;
110
111         
112                 public BuilderApplication (  string[] args)
113                 {
114                         
115                         
116                         _self = FileUtils.read_link("/proc/self/exe");
117                         GLib.debug("SELF = %s", _self);
118                         
119                         Object(
120                                application_id: "org.roojs.app-builder",
121                                 flags: ApplicationFlags.FLAGS_NONE
122                         );
123                         BuilderApplication.windows = new        Gee.ArrayList<Xcls_MainWindow>();
124                         BuilderApplication.valasource = new Palete.ValaSource();
125                         
126                         
127                         configDirectory();
128                         this.settings = AppSettings.factory();  
129                         var opt_context = new OptionContext ("Application Builder");
130                         
131                         try {
132                                 opt_context.set_help_enabled (true);
133                                 opt_context.add_main_entries (options, null);
134                                 opt_context.parse (ref args);
135                                  
136                                 
137                         } catch (OptionError e) {
138                                 stdout.printf ("error: %s\n", e.message);
139                                 stdout.printf ("Run '%s --help' to see a full list of available command line options.\n %s", 
140                                                          args[0], opt_context.get_help(true,null));
141                                 GLib.Process.exit(Posix.EXIT_FAILURE);
142                                  
143                         }
144                         this.initDebug();
145                         this.runTests();                        
146                         this.pullResources();
147                         
148                 Project.Project.loadAll();
149                         this.listProjects();
150                         var cur_project = this.compileProject();
151                         this.listFiles(cur_project);
152                         this.testBjs(cur_project);
153                         this.compileBjs(cur_project);
154                         this.compileVala();
155
156                 }
157
158
159                 
160                 public static BuilderApplication  singleton(  string[] args)
161                 {
162                         if (application==null) {
163                                 application = new BuilderApplication(  args);
164  
165                         
166                         }
167                         return application;
168                 }
169
170                 
171                 public static string configDirectory()
172                 {
173                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
174                 
175                         if (!FileUtils.test(dirname,FileTest.IS_DIR)) {
176                                 var dir = File.new_for_path(dirname);
177                                 dir.make_directory();    
178                         }
179                         if (!FileUtils.test(dirname + "/resources",FileTest.IS_DIR)) {
180                                 var dir = File.new_for_path(dirname + "/resources");
181                                 dir.make_directory();    
182                         }
183
184                 
185                         return dirname;
186                 }
187                 
188                 
189                 // --------------- non static...
190                 
191                 void initDebug() 
192                 {
193                 
194                         if (BuilderApplication.opt_debug  || BuilderApplication.opt_compile_project == null) {
195                                 GLib.Log.set_handler(null, 
196                                         GLib.LogLevelFlags.LEVEL_DEBUG | GLib.LogLevelFlags.LEVEL_WARNING, 
197                                         (dom, lvl, msg) => {
198                                         print("%s: %s\n", dom, msg);
199                                 });
200                         }
201                         
202                 
203                 }
204                 void listProjects()
205                 {
206                         if (!BuilderApplication.opt_list_projects) {
207                                 return;
208                         }
209                         print("Projects\n %s\n", Project.Project.listAllToString());
210                         GLib.Process.exit(Posix.EXIT_SUCCESS);
211                 
212                 }
213                 Project.Project? compileProject()
214                 {
215                         
216                         if (BuilderApplication.opt_compile_project == null) {
217                                 return null;
218                          }
219                         Project.Project cur_project = null;
220                         cur_project = Project.Project.getProjectByHash( BuilderApplication.opt_compile_project);
221                         
222                         if (cur_project == null) {
223                                 GLib.error("invalid project %s, use --list-projects to show project ids",BuilderApplication.opt_compile_project);
224                         }
225                         cur_project.scanDirs();
226                                 
227                         return cur_project;
228                 
229                 }
230                 void listFiles(Project.Project? cur_project)
231                 {
232                         if (!BuilderApplication.opt_list_files) {
233                                 return;
234                         }
235                         if (cur_project == null) {
236                                 GLib.error("missing project, use --project to select which project");
237                         }
238                         print("Files for %s\n %s\n", cur_project.name, cur_project.listAllFilesToString());
239                         GLib.Process.exit(Posix.EXIT_SUCCESS);
240                         
241                 }
242                 
243                 /**
244                  Test to see if the internal BJS reader/writer still outputs the same files.
245                  -- probably need this for the generator as well.
246                 */
247                 
248                 void testBjs(Project.Project? cur_project)
249                 {
250                         if (!BuilderApplication.opt_bjs_test) {
251                                 return;
252                         }
253                         if (cur_project == null) {
254                                 GLib.error("missing project, use --project to select which project");
255                         }
256                         print("Checking files\n");
257                         var ar = cur_project.sortedFiles();
258                         foreach(var file in ar) {
259                                 string oldstr;
260
261                                 file.loadItems();
262                                 GLib.FileUtils.get_contents(file.path, out oldstr);                             
263                                 var outstr = file.toJsonString();
264                                 if (outstr != oldstr) { 
265                                         
266                                         GLib.FileUtils.set_contents("/tmp/" + file.name ,   outstr);
267                                         print("meld  %s /tmp/%s\n", file.path,  file.name);
268                                         //GLib.Process.exit(Posix.EXIT_SUCCESS);                
269                                 }
270                                 print("# Files match %s\n", file.name);
271                                 
272                         }
273                         
274                         print("All files pass");
275                         GLib.Process.exit(Posix.EXIT_SUCCESS);
276                 }
277                 
278                 void compileBjs(Project.Project? cur_project)
279                 {
280                         if (BuilderApplication.opt_bjs_compile == null) {
281                                 return;
282                         }
283                         if (cur_project == null) {
284                                 GLib.error("missing project, use --project to select which project");
285                         }
286                         
287                         if (BuilderApplication.opt_bjs_compile == "all") {
288                                 var ar = cur_project.sortedFiles();
289                                 foreach(var file in ar) {
290                                         string oldstr;
291
292                                         file.loadItems();
293                                         var oldfn = file.targetName();
294                                         GLib.FileUtils.get_contents(oldfn, out oldstr);
295                                                                         
296                                         var outstr = file.toSourceCode();
297                                         if (outstr != oldstr) { 
298                                                 
299                                                 GLib.FileUtils.set_contents("/tmp/" + file.name   + ".out",   outstr);
300                                                 print("meld   %s /tmp/%s\n", oldfn,  file.name + ".out");
301                                                 //GLib.Process.exit(Posix.EXIT_SUCCESS);                
302                                         }
303                                         print("# Files match %s\n", file.name);
304                                         
305                                 }
306                                 GLib.Process.exit(Posix.EXIT_SUCCESS);
307                         
308                         }
309                         
310                         
311                         
312                         var file = cur_project.getByName(BuilderApplication.opt_bjs_compile);
313                         if (file == null) {
314                                 // then compile them all, and compare them...
315                                 
316                         
317                         
318                         
319                         
320                         
321                                 GLib.error("missing file %s in project %s", BuilderApplication.opt_bjs_compile, cur_project.name);
322                         }
323                         file.loadItems();
324                                                 
325                         if (BuilderApplication.opt_bjs_compile_glade) {
326                                 var str = file.toGlade();
327                                 print("%s", str);
328                                 GLib.Process.exit(Posix.EXIT_SUCCESS);
329                         }
330                         
331                         //BuilderApplication.compileBjs();
332
333                         var str = file.toSourceCode();
334                           
335                           
336                         if (!BuilderApplication.opt_debug) {
337                                 print("%s", str);
338                                 GLib.Process.exit(Posix.EXIT_SUCCESS);
339                         }
340                         
341                         // dump the node tree
342                         file.tree.dumpProps();
343                         
344                         
345                         
346                         
347                         
348                         var str_ar = str.split("\n");
349                         for(var i =0;i<str_ar.length;i++) {
350                                 var node = file.tree.lineToNode(i+1);
351                                 var prop = node == null ? null : node.lineToProp(i+1);
352                                 print("%d: %s   :  %s\n", 
353                                         i+1, 
354                                         node == null ? "......"  : (prop == null ? "????????" : prop),
355                                         str_ar[i]
356                                 );
357                         }
358                         
359                         GLib.Process.exit(Posix.EXIT_SUCCESS);
360                 }
361                 
362                 void compileVala()
363                 {
364                         if (BuilderApplication.opt_compile_target == null) {
365                                 return;
366                         }
367                         Palete.ValaSourceCompiler.buildApplication();
368                 
369                         GLib.Process.exit(Posix.EXIT_SUCCESS);
370         
371                 }
372                 void pullResources()
373                 {
374                         if (!opt_pull_resources) {
375                                 return;
376                         }
377                         var loop = new MainLoop();
378                         Resources.singleton().updateProgress.connect((p,t) => {
379                                 print("Got %d/%d", (int) p,(int)t);
380                                 if (p == t) {
381                                         loop.quit();
382                                 }
383                         });
384                         Resources.singleton().fetchStart();     
385                         loop.run();
386                         GLib.Process.exit(Posix.EXIT_SUCCESS);
387                 }
388                 
389                 
390                 void runTests()
391                 {
392                         if (opt_test == null) {
393                                 return;
394                         }
395                         switch(opt_test) {
396                                 case "help":
397                                         print("""
398 help             - list available tests
399 flutter-project  - create a flutter project in /tmp/test-flutter
400 """);           
401                                         break;
402                                 case "flutter-project":
403                                 Project.Project.loadAll();
404                                         var p =   Project.Project.factory("Flutter", "/tmp/test-flutter");
405                                         /*var pa = p.palete as Palete.Flutter;
406                                         pa.dumpusage();
407                                          var ar = pa.getChildList("material.Scaffold");
408                                         GLib.debug("childlist for material.Scaffold is %s", 
409                                                 string.joinv( "\n-- ", ar)
410                                         );
411                                         ar = pa.getDropList("material.MaterialApp");
412                                         GLib.debug("droplist for material.MaterialApp is %s", 
413                                                 string.joinv( "\n-- ", ar)
414                                         );
415                                         */
416                                         break;
417                                         
418                                 default:
419                                         print("Invalid test\n");
420                                         break;
421
422
423                         }
424                         GLib.Process.exit(Posix.EXIT_SUCCESS);          
425                 }
426                 
427                 public static Gee.ArrayList<Xcls_MainWindow> windows;
428                 
429                 public static void addWindow(Xcls_MainWindow w)
430                 {
431                          
432                         BuilderApplication.windows.add(w);
433                         BuilderApplication.updateWindows();
434   
435                         
436                 }
437                 
438                 public static void removeWindow(Xcls_MainWindow w)
439                 {
440                 
441                         BuilderApplication.windows.remove(w);
442                         BuilderApplication.updateWindows();
443                         BuilderApplication.valasource.compiled.disconnect(w.windowstate.showCompileResult);
444                         BuilderApplication.valasource.compile_output.disconnect(w.windowstate.compile_results.addLine);                 
445                         
446                         
447                 }
448                 public static void updateWindows()
449                 {
450                         foreach(var ww in BuilderApplication.windows) {
451                                 ww.windowbtn.updateMenu();
452                         }
453                 }
454                 public static Xcls_MainWindow? getWindow(JsRender.JsRender file)
455                 {
456                         foreach(var ww in BuilderApplication.windows) {
457                                 if (ww.windowstate != null && ww.windowstate.file != null &&  ww.windowstate.file.path == file.path) {
458                                         return ww;
459                                 }
460                         }
461                         return null;
462                 
463                 }
464                 
465                 public static void newWindow(JsRender.JsRender file, int line)
466                 {
467                     var w = new Xcls_MainWindow();
468                         w.ref();
469                         BuilderApplication.addWindow(w);
470                         w.el.show_all();
471                         w.initChildren();
472                         w.windowstate. fileViewOpen(file, false, line);
473                          
474                 
475                 }
476                 
477                 
478          
479         }
480         
481         
482                 
483
484  
485
486