Fix #8039 - library support and add back roopacker dependancy
[roobuilder] / src / Project / Gtk.vala
1 //<Script type="text/javascript">
2 /**
3  * Gtk projects - normally vala based now..
4  * 
5  * should have a few extra features..
6  * 
7  * like:
8  *   compile flags etc..
9  *   different versions (eg. different files can compile different versions - eg. for testing.
10  *   
11  * If we model this like adjuta - then we would need a 'project' file that is actually in 
12  * the directory somewhere... - and is revision controlled etc..
13  * 
14  * builder.config ??
15  * 
16  * 
17  * 
18  * 
19  */
20  
21
22 namespace Project 
23 {
24  
25         
26
27         public class Gtk : Project
28         {
29                 /**
30                 * Gir cache - it's local as we might want clear it if we modify the packages...
31                 *
32                 */
33                 // public Gee.HashMap<string,Palete.GirObject> gir_cache = null; ?? 
34                 
35                 public bool gir_cache_loaded = false;  /// set this to false to force a relaod of vapi's?
36                 
37                 // these are loaded / created by the palete.. but are project specific.
38                 public Gee.HashMap<string,Gee.ArrayList<string>>? dropList = null;  
39             public Gee.HashMap<string,Gee.ArrayList<string>> child_list_cache;   // what child can on on what node
40                 public Gee.HashMap<string,Gee.ArrayList<string>> child_list_cache_props; // what child can go on what node (with properties included)
41                 
42              public string compile_flags = ""; // generic to all.       
43                 public Gee.ArrayList<string> packages; // list of vapi's that are used by this project. 
44                  
45                 //pblic Gee.ArrayList<string> hidden; // list of dirs to be hidden from display...
46                 
47                 public GtkValaSettings? active_cg = null;
48                 public Gee.HashMap<string,GtkValaSettings> compilegroups;
49                 public Meson meson;
50                 
51                 
52                 public Palete.Gtk gpalete {
53                         get {
54                                 return (Palete.Gtk) this.palete;
55                         }
56                         set {}
57                 }
58                  
59                 
60                 public Gtk(string path) {
61                   
62                   
63                         base(path);
64                         
65                         this.initChildCache();
66                    
67                         this.palete = new Palete.Gtk(this);
68                         
69                         this.gir_cache = new Gee.HashMap<string,Palete.GirObject>();
70                         this.xtype = "Gtk";
71                         //var gid = "project-gtk-%d".printf(gtk_id++);
72                         //this.id = gid;
73                         this.packages = new Gee.ArrayList<string>();
74                         //this.hidden = new Gee.ArrayList<string>();
75                         this.compilegroups = new  Gee.HashMap<string,GtkValaSettings>();
76                         this.meson = new Meson(this);
77                 
78                 }
79                 
80                 public  void initChildCache()
81                 {
82                         this.child_list_cache = new Gee.HashMap<string,Gee.ArrayList<string>>();
83                         this.child_list_cache_props = new Gee.HashMap<string,Gee.ArrayList<string>>();
84                         this.dropList = null;
85                 }
86                 
87                 
88                 
89                 public override void loadJson(Json.Object obj)  
90                 {
91                         // load a builder.config JSON file.
92                         // 
93                         this.compilegroups = new  Gee.HashMap<string,GtkValaSettings>();
94                         
95                         if (obj.has_member("packages")) {
96                                 this.packages = this.readArray(obj.get_array_member("packages"));
97                         }
98                         if (obj.has_member("compiler_flags")) {
99                                 this.compile_flags = obj.get_string_member("compile_flags");
100                         }
101                         if (obj.has_member("version")) {
102                                 this.version = obj.get_string_member("version");
103                         }
104                         if (obj.has_member("licence")) {
105                                 this.licence = obj.get_string_member("licence");
106                         }
107                          if (!obj.has_member("compilegroups") || obj.get_member("compilegroups").get_node_type () != Json.NodeType.ARRAY) {
108                                 // make _default_ ?
109                                  return;
110                          }
111                         
112                         //this.hidden = this.readArray(obj.get_array_member("hidden"));
113                         var ar = obj.get_array_member("compilegroups");
114                         for(var i= 0;i<ar.get_length();i++) {
115                                 var el = ar.get_object_element(i);
116                                 var vs = new GtkValaSettings.from_json(this,el);
117                 if (vs == null) {
118                     print("problem loading json file");
119                     continue;
120                 }
121                                  
122                                 this.compilegroups.set(vs.name,vs);
123                         }
124                                                 
125                          
126                         //GLib.debug("%s\n",this.configToString ());
127                         
128                 }
129                 public override void saveJson(Json.Object obj)
130                 {
131                         var ar = new Json.Array();
132                         foreach(var cg in this.compilegroups.values) {
133                                  ar.add_object_element(cg.toJson());
134                         }
135                         obj.set_array_member("compilegroups", ar);
136                         
137                         obj.set_string_member("compile_flags", this.compile_flags);
138                         obj.set_string_member("version", this.version);
139                         obj.set_string_member("licence", this.licence);
140                         
141                         var par = new Json.Array();
142                         foreach(var p in this.packages) {
143                                 par.add_string_element(p);
144                         }
145                         obj.set_array_member("packages", par);
146                         //var hi = new Json.Array();
147                         //foreach(var p in this.hidden) {
148                         //      hi.add_string_element(p);
149                         //}
150                         //obj.set_array_member("hidden", hi);
151                         
152                         this.gir_cache_loaded = false; // force reload of the cache if we change the packages.
153                         this.gpalete.loaded = false;
154                         this.initChildCache();
155                         this.gir_cache = null;
156                 }
157                 
158                 public override void onSave()
159                 {
160                         this.meson.save();
161                         var vl = this.language_servers.get("vala");
162                         if (vl != null) {
163                                 vl.initialize_server(); // hopefully better than exit?
164                         }
165                 }
166          
167                 /**
168                  *  perhaps we should select the default in the window somewhere...
169                  */ 
170                 public string firstBuildModule()
171                 {
172                         
173                         foreach(var cg in this.compilegroups.values) {
174                                 return cg.name;
175                                 
176                         }
177                         return "";
178                          
179                 }
180                 public string firstBuildModuleWith(JsRender.JsRender file)
181                 {
182                         foreach(var cg in this.compilegroups.values) {
183                                  if (cg.has_file(file)) {
184                                         return cg.name;
185                                  }
186                                  
187                                  
188                         }
189                         return this.firstBuildModule();
190                          
191                 }
192                 
193                 public void loadVapiIntoStore(GLib.ListStore ls) 
194                 {
195                         ls.remove_all();
196     
197                          
198                         var pal = (Palete.Gtk) this.palete;
199                         var pkgs = pal.packages(this);
200                         foreach (var p in pkgs) {
201                                 ls.append(new VapiSelection(this.packages, p));
202                         }
203                         
204                 }
205                 
206                 public void loadTargetsIntoStore(GLib.ListStore ls) 
207                 {
208                         ls.remove_all();
209                         foreach(var cg in this.compilegroups.values) {
210                                 ls.append(cg);
211                         }
212                 }
213                 
214                  
215                 
216                  
217                 
218                 public string[] vapidirs()
219                 {
220                         return this.pathsMatching("vapi", false);
221                 }
222                 
223                 
224                  
225                 public override Palete.LanguageClient getLanguageServer(string lang)
226                 {
227                         if (this.language_servers.has_key(lang)) {
228                                 return this.language_servers.get(lang);
229                         }
230                         switch( lang ) {
231                                 case "vala":
232                                         var ls = new Palete.LanguageClientVala(this);
233                                         ls.log.connect((act, msg) => {
234                                                 //GLib.debug("log %s: %s", act.to_string(), msg);
235                                                 BuilderApplication.showSpinnerLspLog(act,msg);
236                                         });
237                                         this.language_servers.set(lang, ls);
238                                         break;
239                                 default :
240                                          return this.language_servers.get("dummy");
241                                          
242                                 }
243                                 return this.language_servers.get(lang);
244                 
245                 }
246                  
247                  
248                  
249                  
250                  
251                  
252                  // ------------------  new project stufff
253                 public override void initialize()
254                 {
255                         string[] dirs = {
256                                 "src",
257                                 "src/ui"
258                                 // ?? docs ?
259                                 //   
260                         };
261                         
262                         
263                         string[] vapis = {
264                                 "gtk4",
265                                 "gee-0.8",
266                                 "gio-2.0",
267                                  
268                                 "glib-2.0",
269                                 "gobject-2.0",
270                                  
271                                 // "json-glib-1.0",
272                                  
273                                 //"libadwaita-1",
274                                 //"libxml-2.0",
275                                 "posix"
276                                  
277  
278                         };
279                         for(var i = 0;  i < dirs.length; i++) {
280                                 this.makeProjectSubdir( dirs[i]);
281                         }
282                         for(var i = 0;  i < vapis.length; i++) {
283                                 this.packages.add(vapis[i]);
284                         
285                         }
286                         // create/// some dummy files?
287                         // application
288                         
289                         this.makeMain();
290                         this.makeApplication();
291                         this.makeWindow();
292                         this.makeGitIgnore();
293
294                         var cg =  new GtkValaSettings(this, this.name);
295                         this.compilegroups.set(this.name, cg);
296                         cg.sources.add("src/Main.vala");
297                         cg.sources.add("src/%sApplication.vala".printf(this.name));
298                         cg.sources.add("src/ui/ui.Window.bjs");
299                         // rescan... not needed as it get's selected after initialization.
300                         this.load();
301                         var fn = this.getByPath(this.path + "/src/ui/ui.Window.bjs");
302                         try {
303                                 fn.loadItems();
304                         } catch (GLib.Error e) { } // do nothing?
305                         
306                         fn.save();
307                         
308                         
309                         
310                 }
311                 
312                 
313                 void makeTemplatedFile(string name, string[] str, string replace) 
314                 {
315                         var o = "";
316                         for(var i=0;i< str.length;i++) {
317                                 o += str[i].replace("%s", replace) + "\n";
318                         }
319                         this.writeFile(name, o);
320                 }
321                 public void writeFile(string name, string o) 
322                 {
323                         var f = GLib.File.new_for_path(this.path + "/" + name);
324                         try {
325                                 var data_out = new GLib.DataOutputStream( f.replace(null, false, GLib.FileCreateFlags.NONE, null) );
326                                 data_out.put_string(o, null);
327                                 data_out.close(null);
328                         } catch (GLib.Error e) {
329                                 GLib.debug("Error writing file %s", e.message);
330                         }
331                         
332                 } 
333                 
334                 void makeMain()
335                 {
336                         string[] str = {
337                                 "int main (string[] args)",
338                                 "{",
339                                 "       var app = new  %sApplication(  args);",
340                                 "       Gtk.init ();",
341                                 "       GLib.Log.set_always_fatal(LogLevelFlags.LEVEL_ERROR ); ",
342                                 "       app.activate.connect(() => {",
343                                 "               var w = new ui.Window();",   // ?? main window as UI window?
344                                 "               w.el.application  = app;",
345                                 "               w.ref();",
346                                 "               w.show();",
347                                 "       });",
348                                 "       var ret = app.run(args);",
349                                 "       return ret; ",
350                                 "}"
351                         };
352                         this.makeTemplatedFile("src/Main.vala", str, this.name); // fixme name needs to be code friendly!
353                 }
354                 void makeApplication()
355                 {
356                         string[] str = {
357                         
358                         
359                                 "public class %sApplication : Gtk.Application",
360                                 "{",
361                                 "       public %sApplication (string[] args) ",
362                                 "       {",
363                                 "               Object(",
364                                 "                       application_id: \"org.roojs.%s\",",
365                                 "                       flags: ApplicationFlags.FLAGS_NONE",
366                                 "               );",
367                                 "       }",
368                                 "}"
369                         };
370                                 
371                         
372                         this.makeTemplatedFile("src/%sApplication.vala".printf(this.name), str, this.name); // fixme name needs to be code friendly!
373                 }
374
375                 
376                 void makeWindow()
377                 {
378                         this.writeFile("src/ui/ui.Window.bjs", """{
379  "build_module" : "",
380  "items" : [
381   {
382    "$ xns" : "Gtk",
383    "| void show" : "() { this.el.show(); }",
384    "items" : [
385     {
386      "$ xns" : "Gtk",
387      "* prop" : "child",
388      "Gtk.Orientation orientation" : "Gtk.Orientation.HORIZONTAL",
389      "int spacing" : 0,
390      "items" : [
391       {
392        "$ xns" : "Gtk",
393        "string label" : "Hello World",
394        "xtype" : "Label"
395       }
396      ],
397      "xtype" : "Box"
398     }
399    ],
400    "xtype" : "Window"
401   }
402  ],
403  "name" : "ui.Window",
404  "gen_extended" : false
405 }
406 """);
407         }
408         void makeGitIgnore()
409         {
410                         this.writeFile(".gitignore", """
411 build/
412 """);
413         }
414                         
415                 
416                  public override void   initDatabase()
417                 {
418                      // nOOP
419                 }
420         }
421          
422    
423 }