Fix #8103 - updating of tree
[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 for non-ui, or crash on warnings for gdb ", 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             { "language-server", 0, 0, OptionArg.STRING, ref opt_language_server, "run language server on this file", null },
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                 public static string opt_language_server;
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.windowlist = new GLib.ListStore(typeof(WindowState));
153                         //BuilderApplication.valacompilequeue = new Palete.ValaCompileQueue();
154                         
155                         
156                         configDirectory();
157                 //      this.settings = AppSettings.factory();  
158                         var opt_context = new OptionContext ("Application Builder");
159                         
160                         try {
161                                 opt_context.set_help_enabled (true);
162                                 opt_context.add_main_entries (options, null);
163                                 opt_context.parse (ref args);
164                                  
165                                 
166                         } catch (OptionError e) {
167                                 stdout.printf ("error: %s\n", e.message);
168                                 stdout.printf ("Run '%s --help' to see a full list of available command line options.\n %s", 
169                                                          args[0], opt_context.get_help(true,null));
170                                 GLib.Process.exit(Posix.EXIT_FAILURE);
171                                  
172                         }
173                         this.initDebug();
174                         this.runTests();                        
175                         this.pullResources();
176                         
177                 Project.Project.loadAll();
178                         this.listProjects();
179                         var cur_project = this.compileProject();
180                         this.dropList(cur_project); // --drop-list
181                         this.languageServer(cur_project); // --language-server                  
182                         this.listFiles(cur_project);
183                         this.testBjs(cur_project);
184                         this.languageServer(cur_project);
185                         this.compileBjs(cur_project);
186                         //this.compileVala();
187
188                 }
189
190                 public static Settings settings;
191
192                 protected override void activate () 
193                 {
194                         var css = new Gtk.CssProvider();
195                         css.load_from_resource("/css/roobuilder.css");
196                         
197                         Gtk.StyleContext.add_provider_for_display(
198                                 Gdk.Display.get_default(),
199                                 css     ,
200                                 Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
201                         );
202                         BuilderApplication.settings = new Settings();
203                 
204                         var w = new Xcls_MainWindow();
205                     w.initChildren();
206                         BuilderApplication.addWindow(w);
207                         
208                         // it looks like showall after children causes segfault on ubuntu 14.4
209                         w.windowstate.init();
210                 //      w.windowstate.showPopoverFiles(w.open_projects_btn.el, null, false);
211                         w.show();
212                 
213                 }
214                 
215                 public static BuilderApplication  singleton(  string[]? args)
216                 {
217                         if (application==null && args != null) {
218                                 application = new BuilderApplication(  args);
219  
220                         
221                         }
222                         return application;
223                 }
224
225                 
226                 public static string configDirectory()
227                 {
228                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
229                 
230                         if (!FileUtils.test(dirname,FileTest.IS_DIR)) {
231                                 var dir = File.new_for_path(dirname);
232                                 try {
233                                         dir.make_directory();   
234                                 } catch (Error e) {
235                                         GLib.error("Failed to make directory %s", dirname);
236                                 } 
237                         }
238                         if (!FileUtils.test(dirname + "/resources",FileTest.IS_DIR)) {
239                                 var dir = File.new_for_path(dirname + "/resources");
240                                 try {
241                                         dir.make_directory();   
242                                 } catch (Error e) {
243                                         GLib.error("Failed to make directory %s", dirname + "/resources");
244                                 } 
245                         }
246
247                 
248                         return dirname;
249                 }
250                 
251                 
252                 // --------------- non static...
253                 
254                 void initDebug() 
255                 {
256                          
257                         
258                         if (BuilderApplication.opt_debug  || BuilderApplication.opt_compile_project == null) {
259                                 GLib.Log.set_default_handler( 
260                                 //      GLib.LogLevelFlags.LEVEL_DEBUG | GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_CRITICAL, 
261                                         (dom, lvl, msg) => {
262
263                                         print("%s: %s : %s\n", (new DateTime.now_local()).format("%H:%M:%S.%f"), lvl.to_string(), msg);
264                                         
265                                         if (dom== "GtkSourceView") { // seems to be some critical wanrings comming from gtksourceview related to insert?
266                                                 return;
267                                         }
268                                         //if (msg.contains("gdk_popup_present")) { // seems to be problems with the popup present on gtksourceview competion.
269                                         //      return;
270                                         //}
271                                         if (BuilderApplication.opt_debug && lvl ==  GLib.LogLevelFlags.LEVEL_CRITICAL) {
272                                                 GLib.error(msg);
273                                         }
274                                 });
275                         }
276                         
277                         
278                 
279                 }
280                 void listProjects()
281                 {
282                         if (!BuilderApplication.opt_list_projects) {
283                                 return;
284                         }
285                         print("Projects\n %s\n", Project.Project.listAllToString());
286                         GLib.Process.exit(Posix.EXIT_SUCCESS);
287                 
288                 }
289                 Project.Project? compileProject()
290                 {
291                         
292                         if (BuilderApplication.opt_compile_project == null) {
293                                 return null;
294                          }
295                         Project.Project cur_project = null;
296                         cur_project = Project.Project.getProjectByPath( BuilderApplication.opt_compile_project);
297                         
298
299                         
300                         if (cur_project == null) {
301                                 GLib.error("invalid project %s, use --list-projects to show project ids",BuilderApplication.opt_compile_project);
302                         }
303                         cur_project.load();
304
305                         
306
307                         return cur_project;
308                 
309                 }
310                 
311                 void dropList(Project.Project? cur_project) {
312
313
314                         if (cur_project== null || BuilderApplication.opt_drop_list == null) {
315                                 return;
316                         }
317                         
318                         if (BuilderApplication.opt_compile_project == null) {
319                                 GLib.error("need a project %s, to use --drop-list",BuilderApplication.opt_compile_project);
320                          }
321                           if (cur_project.xtype != "Gtk") {
322                                  var rp = (Palete.Roo) cur_project.palete;
323                                 print("\n\nDropList:\n%s", geeArrayToString(rp.getDropList(BuilderApplication.opt_drop_list)));
324                                  print("\n\nChildList:\n%s", geeArrayToString(rp.getChildList(BuilderApplication.opt_drop_list, false)));
325                                  print("\n\nChildList \n(with props): %s", geeArrayToString(rp.getChildList(BuilderApplication.opt_drop_list, true)));  
326                                  
327                                  
328                                  print("\n\nPropsList: %s", this.girArrayToString(rp.getPropertiesFor( BuilderApplication.opt_drop_list, JsRender.NodePropType.PROP)));
329                                  print("\n\nSignalList: %s", this.girArrayToString(rp.getPropertiesFor( BuilderApplication.opt_drop_list, JsRender.NodePropType.LISTENER)));
330                                  
331                                  // ctor.
332                                   print("\n\nCtor Values: %s", rp.fqnToNode(BuilderApplication.opt_drop_list).toJsonString());
333                                  GLib.Process.exit(Posix.EXIT_SUCCESS);
334                           
335                           
336                          
337                          }
338                          var p = (Palete.Gtk) cur_project.palete;
339                         
340                          print("\n\nDropList:\n%s", geeArrayToString(p.getDropList(BuilderApplication.opt_drop_list)));
341                          print("\n\nChildList:\n%s", geeArrayToString(p.getChildList(BuilderApplication.opt_drop_list, false)));
342                          print("\n\nChildList \n(with props): %s", geeArrayToString(p.getChildList(BuilderApplication.opt_drop_list, true)));   
343                          
344                          
345                          print("\n\nPropsList: %s", this.girArrayToString(p.getPropertiesFor( BuilderApplication.opt_drop_list, JsRender.NodePropType.PROP)));
346                          print("\n\nSignalList: %s", this.girArrayToString(p.getPropertiesFor( BuilderApplication.opt_drop_list, JsRender.NodePropType.LISTENER)));
347                          
348                          // ctor.
349                           print("\n\nCtor Values: %s", p.fqnToNode(BuilderApplication.opt_drop_list).toJsonString());
350                          
351                           GLib.Process.exit(Posix.EXIT_SUCCESS);
352                         
353                 }
354                 string geeArrayToString(Gee.ArrayList<string> ar) 
355                 {
356                         var ret = "";
357                         foreach(var n in ar) {
358                                 ret +=   n + "\n";
359                          }
360                          return ret;
361                 }
362                 string girArrayToString(Gee.HashMap<string,Palete.GirObject> map) 
363                 {
364                         var ret = "";
365                         foreach(var gi in map.values) {
366                                  ret += "%s %s (%s)\n".printf(gi.type, gi.name, gi.propertyof);
367                         
368                         }
369                         return ret;
370                 
371                 }
372                  
373                 
374                 void listFiles(Project.Project? cur_project)
375                 {
376                         if (!BuilderApplication.opt_list_files) {
377                                 return;
378                         }
379                         if (cur_project == null) {
380                                 GLib.error("missing project, use --project to select which project");
381                         }
382                         print("Files for %s\n %s\n", cur_project.name, cur_project.listAllFilesToString());
383                         GLib.Process.exit(Posix.EXIT_SUCCESS);
384                         
385                 }
386                 
387                 /**
388                  Test to see if the internal BJS reader/writer still outputs the same files.
389                  -- probably need this for the generator as well.
390                 */
391                 
392                 void testBjs(Project.Project? cur_project)
393                 {
394                         if (!BuilderApplication.opt_bjs_test) {
395                                 return;
396                         }
397                         if (cur_project == null) {
398                                 GLib.error("missing project, use --project to select which project");
399                         }
400                         print("Checking files\n");
401                         try { 
402                                 var ar = cur_project.sortedFiles();
403                                 foreach(var file in ar) {
404                                         string oldstr;
405
406                                         file.loadItems();
407                                         GLib.FileUtils.get_contents(file.path, out oldstr);                             
408                                         var outstr = file.toJsonString();
409                                         if (outstr != oldstr) { 
410                                                 
411                                                 GLib.FileUtils.set_contents("/tmp/" + file.name ,   outstr);
412                                                 print("meld  %s /tmp/%s\n", file.path,  file.name);
413                                                 //GLib.Process.exit(Posix.EXIT_SUCCESS);                
414                                         }
415                                         print("# Files match %s\n", file.name);
416                                         
417                                 }
418                         } catch (FileError e) {
419                                 GLib.debug("Got error %s", e.message);
420                         } catch (Error e) {
421                                 GLib.debug("Got error %s", e.message);
422                         }
423                                 
424                         print("All files pass");
425                         GLib.Process.exit(Posix.EXIT_SUCCESS);
426                 }
427                 
428                 void compileBjs(Project.Project? cur_project)
429                 {
430                         if (BuilderApplication.opt_bjs_compile == null) {
431                                 return;
432                         }
433                         if (cur_project == null) {
434                                 GLib.error("missing project, use --project to select which project");
435                         }
436                         
437                         if (BuilderApplication.opt_bjs_compile == "all") {
438                                 try { 
439                                         var ar = cur_project.sortedFiles();
440                                         
441                                         foreach(var file in ar) {
442                                         
443                                                 if (file is JsRender.PlainFile) {
444                                                         continue;
445                                                 }
446                         
447
448                                                 file.loadItems();
449                                                 var oldfn = file.targetName();
450                                                 
451                                                 print("\n\n\n\nFile : %s\n", oldfn);
452                                                 
453                                                                                 
454                                                 var outstr = file.toSourceCode();
455                                                 
456                                                 /* line number checking
457                                                 var bad = false;
458                                                 // check line numbers:
459                                                 var bits = outstr.split("\n");
460                                                 var end = bits.length;
461                                                 for(var i = 0;i < end; i++) {
462                                                         print("%i : %s\n", i+1 , bits[i]);
463                                                         if (!bad && bits[i].has_prefix("/*") && !bits[i].has_prefix(("/*%d*" +"/").printf(i+1))) {
464                                                                 end = i + 5 > bits.length ? bits.length: (i + 5);
465                                                                 print ("^^^^ mismatch\null");
466                                                                 bad = true;
467                                                         }
468
469                                                 
470                                                 }
471                                                 if (bad) {
472                                                         GLib.error("got bad file");
473                                                 }
474                                                 */
475                                                 // compare files. 
476                                                 string oldstr;
477                                                 GLib.FileUtils.get_contents(oldfn, out oldstr);
478                                                 if (outstr != oldstr) { 
479                                                         
480                                                         GLib.FileUtils.set_contents("/tmp/" + file.name   + ".out",   outstr);
481                                                         print("meld   %s /tmp/%s\n", oldfn,  file.name + ".out");
482                                                         //GLib.Process.exit(Posix.EXIT_SUCCESS);                
483                                                 }                                               
484                                                 //print("# Files match %s\n", file.name);
485                                         }               
486                                 } catch (FileError e) {
487                                         GLib.debug("Got error %s", e.message);
488                                 } catch (Error e) {
489                                         GLib.debug("got error %s", e.message);
490                                 }
491                                 
492                                 GLib.Process.exit(Posix.EXIT_SUCCESS);
493                         
494                         }
495                         
496                         
497                         
498                         var file = cur_project.getByRelPath(BuilderApplication.opt_bjs_compile);
499                         if (file == null) {
500                                 // then compile them all, and compare them...
501                                 
502                          
503                         
504                                 GLib.error("missing file %s in project %s", BuilderApplication.opt_bjs_compile, cur_project.name);
505                         }
506                         try {
507                                 file.loadItems();
508                         } catch(Error e) {
509                                 GLib.debug("Load items failed");
510                         }
511                                         
512                         if (BuilderApplication.opt_bjs_compile_glade) {
513                                 var str = file.toGlade();
514                                 print("%s", str);
515                                 GLib.Process.exit(Posix.EXIT_SUCCESS);
516                         }
517                         
518                         //BuilderApplication.compileBjs();
519
520                         var str = file.toSourceCode();
521                           
522                           
523                         if (!BuilderApplication.opt_debug) {
524                                 print("%s", str);
525                                 GLib.Process.exit(Posix.EXIT_SUCCESS);
526                         }
527                         
528                         // dump the node tree
529                         file.tree.dumpProps();
530                         
531                         
532                         
533                         
534                         
535                         var str_ar = str.split("\n");
536                         for(var i =0;i<str_ar.length;i++) {
537                                 var node = file.tree.lineToNode(i+1);
538                                 var prop = node == null ? null : node.lineToProp(i+1);
539                                 print("%d: %s   :  %s\n", 
540                                         i+1, 
541                                         node == null ? "......"  : (prop == null ? "????????" : prop.name),
542                                         str_ar[i]
543                                 );
544                         }
545                         
546                         GLib.Process.exit(Posix.EXIT_SUCCESS);
547                 }
548                 void languageServer(Project.Project? cur_project)
549                 {
550                         if (BuilderApplication.opt_language_server == null) {
551                                 return;
552                         }
553                         if (cur_project == null) {
554                                 GLib.error("missing project, use --project to select which project");
555                         }
556                         var file = cur_project.getByRelPath(BuilderApplication.opt_language_server);
557                         if (file == null) {
558                                 // then compile them all, and compare them...
559                                  GLib.error("missing file %s in project %s", BuilderApplication.opt_language_server, cur_project.name);
560                         }
561                         
562                         var ls = file.getLanguageServer();
563                         if (ls == null) {
564                                 GLib.error("No langauge server returned for file:%s", file.relpath);
565                         }
566                         
567                         //GLib.debug("started server - sleep 30 secs so you can gdb attach");
568                         //Posix.sleep( 30 );
569                         var loop = new MainLoop();
570                         GLib.Timeout.add_seconds(1, () => {
571                          
572                                 GLib.debug("Sending document_open");
573                                 // it's ready..
574                                  
575                                 ls.document_open(file);
576                                 ls.document_save.begin( file, (o,res) => {
577                                         ls.document_save.end(res);
578                                  });
579                                 
580                                 //ls.syntax.begin(file, (obj,res) => {
581                                 //      ls.syntax.end(res);
582                                 
583                                 //});
584                                 
585                                 
586                                 return false;
587                                 
588                         });
589                         
590                          
591                         loop.run();
592                         GLib.Process.exit(Posix.EXIT_SUCCESS);
593                 }
594                         
595         /*      
596                 void compileVala()
597                 {
598                         if (BuilderApplication.opt_compile_target == null) {
599                                 return;
600                         }
601                         Palete.ValaSourceCompiler.buildApplication();
602                 
603                         GLib.Process.exit(Posix.EXIT_SUCCESS);
604         
605                 }
606                 */
607                 void pullResources()
608                 {
609                         if (!opt_pull_resources) {
610                                 return;
611                         }
612                         var loop = new MainLoop();
613                         Resources.singleton().updateProgress.connect((p,t) => {
614                                 print("Got %d/%d", (int) p,(int)t);
615                                 if (p == t) {
616                                         loop.quit();
617                                 }
618                         });
619                         Resources.singleton().fetchStart();     
620                         loop.run();
621                         GLib.Process.exit(Posix.EXIT_SUCCESS);
622                 }
623                 
624                 
625                 void runTests()
626                 {
627                         if (opt_test == null) {
628                                 return;
629                         }
630                         switch(opt_test) {
631                                 case "help":
632                                         print("""
633 help             - list available tests
634 flutter-project  -  was try and read flutter data (but desnt work.)
635 """);           
636                                         break;
637                                 case "flutter-project":
638                                 Project.Project.loadAll();
639                                         //var p =   Project.Project.factory("Flutter", "/tmp/test-flutter");
640                                         /*var pa = p.palete as Palete.Flutter;
641                                         pa.dumpusage();
642                                          var ar = pa.getChildList("material.Scaffold");
643                                         GLib.debug("childlist for material.Scaffold is %s", 
644                                                 string.joinv( "\n-- ", ar)
645                                         );
646                                         ar = pa.getDropList("material.MaterialApp");
647                                         GLib.debug("droplist for material.MaterialApp is %s", 
648                                                 string.joinv( "\n-- ", ar)
649                                         );
650                                         */
651                                         break;
652                                         
653                                  
654                                         
655                                         
656                                 default:
657                                         print("Invalid test\n");
658                                         break;
659
660
661                         }
662                         GLib.Process.exit(Posix.EXIT_SUCCESS);          
663                 }
664                 
665                 
666                 // move to 'window colletction?
667                 public static Gee.ArrayList<Xcls_MainWindow> windows;
668                 public static GLib.ListStore windowlist;
669                 
670                 public static void addWindow(Xcls_MainWindow w)
671                 {
672                          
673                 windowlist.append(w.windowstate);
674                         BuilderApplication.windows.add(w);
675
676   
677                         
678                 }
679                 
680                 public static void removeWindow(Xcls_MainWindow w)
681                 {
682                         //GLib.debug("remove window before = %d", BuilderApplication.windows.size);
683                         BuilderApplication.windows.remove(w);
684                         for(var i = 0 ; i < windowlist.get_n_items(); i++) {
685                                 var ws = windowlist.get_item(i) as WindowState;
686                                 if (ws.file.path == w.windowstate.file.path && ws.project.path == w.windowstate.project.path) {
687                                         windowlist.remove(i);
688                                         break;
689                                 }
690                         }
691                         
692
693                                 
694                         w.el.hide();
695                         w.el.close();
696                         w.el.destroy();
697                         //GLib.debug("remove window after = %d", BuilderApplication.windows.size);
698                         
699                         
700                 }
701          
702                 public static Xcls_MainWindow? getWindow(JsRender.JsRender file)
703                 {
704                         foreach(var ww in BuilderApplication.windows) {
705                                 if (ww.windowstate != null && ww.windowstate.file != null &&  ww.windowstate.file.path == file.path) {
706                                         return ww;
707                                 }
708                         }
709                         return null;
710                 
711                 }
712                 
713                 public static void newWindow(JsRender.JsRender file, int line)
714                 {
715                     var w = new Xcls_MainWindow();
716                         w.ref();
717                         w.initChildren();
718                         BuilderApplication.addWindow(w);
719                         w.windowstate.init();
720                         w.windowstate.fileViewOpen(file, false, line);
721                         w.el.present();
722                          
723                 
724                 }
725                 
726                 static int queue_update_compile_countdown = -1;
727                 static uint queue_update_compile_id = 0;
728                 
729                 public static void updateCompileResults( )
730                 {
731                         queue_update_compile_countdown = 2; // 1 second after last call.
732                         if (queue_update_compile_id == 0) {
733                                 queue_update_compile_id = GLib.Timeout.add(100, () => {
734                                         if (queue_update_compile_countdown < 0) {
735                                                 return true;
736                                         }
737                                         queue_update_compile_countdown--;
738                                         if (queue_update_compile_countdown < 0) {
739                                                 realUpdateCompileResults();
740                                         }
741                                         
742                                         return true;
743                                 });
744                         }
745                 }
746                 
747                 
748                 public static void realUpdateCompileResults( )
749                 {
750                         
751                         
752                         
753                         foreach(var ww in BuilderApplication.windows) {
754                                 if (ww == null || ww.windowstate == null || ww.windowstate.project ==null) {
755                                         continue;
756                                 }
757                                 
758
759                                 ww.windowstate.updateErrorMarksAll();
760                                  
761                                 //GLib.debug("calling udate Errors of window %s", ww.windowstate.file.targetName());
762                                 ww.updateErrors();
763                                 ww.windowstate.left_tree.updateErrors();
764                                 ww.windowstate.left_props.updateErrors();
765                                 
766                         }
767                 
768                 }
769                 
770                 public static void showSpinnerLspLog(Palete.LanguageClientAction action, string message) {
771                         
772                         var msg = action.to_string() + " " + message;
773                         switch(action) {
774                         
775                                         case Palete.LanguageClientAction.INIT:
776                                         case Palete.LanguageClientAction.LAUNCH:
777                                         case Palete.LanguageClientAction.ACCEPT:
778                                                 BuilderApplication.showSpinner( "software-update-available", msg );
779                                                 return;
780                                                 
781                                         case Palete.LanguageClientAction.DIAG:
782                                                 BuilderApplication.showSpinner( "format-justify-fill", msg);                                    
783                                                 return;
784
785                                         case Palete.LanguageClientAction.DIAG_END:
786                                                 BuilderApplication.showSpinner( "", "");
787                                                 return;
788
789                                         case Palete.LanguageClientAction.OPEN:
790                                                 BuilderApplication.showSpinner( "document-open", msg);                                  
791                                                 return;
792                                         case Palete.LanguageClientAction.SAVE:
793                                                 BuilderApplication.showSpinner( "document-save", msg);                                  
794                                                 return;
795                                         case Palete.LanguageClientAction.CLOSE:
796                                                 BuilderApplication.showSpinner( "window.close", msg);                                   
797                                                 return;
798                                         case Palete.LanguageClientAction.CHANGE:
799                                                 BuilderApplication.showSpinner( "format-text-direction-ltr", msg);
800                                                 return;                                         
801                                         case Palete.LanguageClientAction.TERM:
802                                                 BuilderApplication.showSpinner( "media-playback-stop", msg);
803                                                 return;                                         
804                                         case Palete.LanguageClientAction.COMPLETE:
805                                                 BuilderApplication.showSpinner( "mail-send-recieve", msg);
806                                                 return;
807                                         
808                                         case Palete.LanguageClientAction.COMPLETE_REPLY:
809                                                 BuilderApplication.showSpinner( "face-cool", msg);
810                                                 return;
811                                                 
812                                         case Palete.LanguageClientAction.RESTART:
813                                         case Palete.LanguageClientAction.ERROR:
814                                         case Palete.LanguageClientAction.ERROR_START:
815                                         case Palete.LanguageClientAction.ERROR_RPC:
816                                         case Palete.LanguageClientAction.ERROR_REPLY:
817                                                 BuilderApplication.showSpinner( "software-update-urgent", msg );
818                                                 return;
819
820                                         case Palete.LanguageClientAction.EXIT:
821                                                 BuilderApplication.showSpinner( "face-sick", msg);
822                                                 return;
823                                         
824                         
825                         }
826                 }
827                 
828                 public static  void showSpinner(string icon, string tooltip = "")
829                 {
830
831                         // events:
832                         // doc change send: - spinner - 
833                         
834                         
835                         // ?? restart = software-update-urgent - crash?
836
837                         
838                         foreach (var win in BuilderApplication.windows) {
839                                 if (icon != "") {
840                                         win.statusbar_compile_spinner.start(icon, tooltip);
841                                 }  else {
842                                         win.statusbar_compile_spinner.stop();
843                                 }
844                         }
845                 }
846                 
847                 
848                 
849          
850         }
851         
852         
853                 
854
855  
856