Fix #7378 - search bar in files brower
[roobuilder] / src / JsRender / JsRender.vala
1 //<Script type="text/javascript">
2
3 namespace JsRender {
4
5
6         public errordomain Error {
7                 INVALID_FORMAT,
8                 RENAME_FILE_EXISTS
9         }
10                 
11         public abstract class JsRender  : Object {
12                 /**
13                  * @cfg {Array} doubleStringProps list of properties that can be double quoted.
14                  */
15                 public Gee.ArrayList<string> doubleStringProps;
16                 
17                 public string id;
18                 public string name;   // is the JS name of the file.
19                 public string fullname;
20                 public string path;  // is the full path to the file.
21                 public string parent;  // JS parent.
22                 public string region;  // RooJS - insert region.
23         
24                 public string title;  // a title.. ?? nickname.. ??? -
25                 public string build_module; // module to build if we compile (or are running tests...)
26                 
27
28                 public string permname;
29                 public string language;
30                 public string content_type;
31                 public string modOrder;
32                 public string xtype;
33                 public uint64 webkit_page_id; // set by webkit view - used to extract extension/etc..
34                     
35                 public Project.Project project;
36                 //Project : false, // link to container project!
37                 
38                 public Node tree; // the tree of nodes.
39                 
40                 public GLib.List<JsRender> cn; // child files.. (used by project ... should move code here..)
41
42                 public bool hasParent; 
43                 
44                 public bool loaded;
45                 
46                 public Gee.HashMap<string,string> transStrings; // map of md5 -> string.
47                 public  Gee.HashMap<string,string> namedStrings;
48
49                 public signal void changed (Node? node, string source); 
50                 
51                  
52                 public signal void compile_notice(string type, string file, int line, string message);
53                 /**
54                  * UI componenets
55                  * 
56                  */
57                 //public Xcls_Editor editor;
58                 
59                 
60                 
61                 //abstract JsRender(Project.Project project, string path); 
62                 
63                 public void aconstruct(Project.Project project, string path)
64                 {
65                     
66                         this.cn = new GLib.List<JsRender>();
67                         this.path = path;
68                         this.project = project;
69                         this.hasParent = false;
70                         this.parent = "";
71                         this.tree = null;
72                         this.title = "";
73                         this.region = "";
74                         this.permname = "";
75                         this.modOrder = "";
76                         this.language = "";
77                         this.content_type = "";
78                         this.build_module = "";
79                         this.loaded = false;
80                         //print("JsRender.cto() - reset transStrings\n");
81                         this.transStrings = new Gee.HashMap<string,string>();
82                         this.namedStrings = new Gee.HashMap<string,string>();
83                         // should use basename reallly...
84                         
85                         var ar = this.path.split("/");
86                         // name is in theory filename without .bjs (or .js eventually...)
87                         try {
88                                 Regex regex = new Regex ("\\.(bjs|js)$");
89
90                                 this.name = ar.length > 0 ? regex.replace(ar[ar.length-1],ar[ar.length-1].length, 0 , "") : "";
91                         } catch (GLib.Error e) {
92                                 this.name = "???";
93                         }
94                         this.fullname = (this.parent.length > 0 ? (this.parent + ".") : "" ) + this.name;
95
96                         this.doubleStringProps = new Gee.ArrayList<string>();
97
98                 }
99                 
100                 public void renameTo(string name) throws  Error
101                 {
102                         if (this.xtype == "PlainFile") {
103                                 return;
104                         }
105                         var bjs = GLib.Path.get_dirname(this.path) +"/" +  name + ".bjs";
106                         if (FileUtils.test(bjs, FileTest.EXISTS)) {
107                                 throw new Error.RENAME_FILE_EXISTS("File exists %s\n",name);
108                         }
109                         GLib.FileUtils.remove(this.path);
110                         this.removeFiles();
111                         // remove other files?
112                         
113                         this.name = name;
114                         this.path = bjs;
115                         
116                 }
117                 
118
119                 
120                 // not sure why xt is needed... -> project contains xtype..
121                 
122                 public static JsRender factory(string xt, Project.Project project, string path) throws Error
123                 {
124          
125                         switch (xt) {
126                                 case "Gtk":
127                                         return new Gtk(project, path);
128                                 case "Roo":
129                                         return new Roo(project, path);
130 //                      case "Flutter":
131 //                                      return new Flutter(project, path);
132                                 case "PlainFile":
133                                         return new PlainFile(project, path);
134                         }
135                         throw new Error.INVALID_FORMAT("JsRender Factory called with xtype=%s", xt);
136                         //return null;    
137                 }
138
139         
140         
141                 public string nickType()
142                 {
143                         var ar = this.name.split(".");
144                         string[] ret = {};
145                         for (var i =0; i < ar.length -1; i++) {
146                                 ret += ar[i];
147                         }
148                         return string.joinv(".", ret);
149                         
150                 }
151                 public string nickName()
152                 {
153                         var ar = this.name.split(".");
154                         return ar[ar.length-1];
155                         
156                 }
157                 
158                 public string nickNameSplit()
159                 {
160                         var n = this.nickName();
161                         var ret = "";
162                         var len = 0;
163                         for (var i = 0; i < n.length; i++) {
164                                 if (i!=0 && n.get(i).isupper() && len > 10) {
165                                         ret +="\n";
166                                         len= 0;
167                                 }
168                                 ret += n.get(i).to_string();
169                                 len++;
170                         }
171                         
172
173                         
174                         return ret;
175                 
176                 }
177                 
178                 Gdk.Pixbuf screenshot = null;
179                 Gdk.Pixbuf screenshot92 = null;
180                 Gdk.Pixbuf screenshot368 = null;
181                 
182                 public Gdk.Pixbuf? getIcon(int size = 0) {
183                     var fname = this.getIconFileName( );                
184                     if (!FileUtils.test(fname, FileTest.EXISTS)) {
185                 GLib.debug("PIXBUF %s:  %s does not exist?", this.name, fname);
186                                 return null;
187                         }
188                         
189                         switch (size) {
190                                 case 0:
191                                         if (this.screenshot == null) {
192                                                 this.screenshot = new Gdk.Pixbuf.from_file(fname);
193                                         }
194                                         return this.screenshot;
195                                 
196                                 case 92:
197                                         
198                                         if (this.screenshot == null) {
199                                                 this.getIcon(0);
200                                                 if (this.screenshot == null) {
201                                                         return null;
202                                                 }
203                                         }
204                                         
205                                         this.screenshot92 = this.screenshot.scale_simple(92, (int) (this.screenshot.height * 92.0 /this.screenshot.width * 1.0 )
206                                                 , Gdk.InterpType.NEAREST) ;
207                                     return this.screenshot92;
208                             
209                             case 368:
210                                         if (this.screenshot == null) {
211                                                 this.getIcon(0);
212                                                 if (this.screenshot == null) {
213                                                         return null;
214                                                 }
215                                         }
216                                         
217                                         this.screenshot368 = this.screenshot.scale_simple(368, (int) (this.screenshot.height * 368.0 /this.screenshot.width * 1.0 )
218                                     , Gdk.InterpType.NEAREST) ;
219                                     return this.screenshot368;
220                     }
221                     return null;
222                 }
223                 
224                 public void writeIcon(Gdk.Pixbuf pixbuf) {
225                         
226                         pixbuf.save(this.getIconFileName( ),"png");
227                         this.screenshot = pixbuf;
228                         this.screenshot92 = null;
229                         this.screenshot368 = null;
230                         
231                 
232                 }
233                 
234
235                 
236                 public string getIconFileName( )
237                 {
238                          
239                         var m5 = GLib.Checksum.compute_for_string(GLib.ChecksumType.MD5,this.path); 
240
241                         var dir = GLib.Environment.get_home_dir() + "/.Builder/icons";
242                         try {
243                                 if (!FileUtils.test(dir, FileTest.IS_DIR)) {
244                                          File.new_for_path(dir).make_directory();
245                                 }
246                         } catch (GLib.Error e) {
247                                 // eakk.. what to do here...
248                         }
249                         var fname = dir + "/" + m5 + ".png";
250                         
251                          
252                         return fname;
253                           
254                 }
255                 
256                 public string toJsonString()
257                 {
258                         if (this.xtype == "PlainFile") {
259                                 return "";
260                         }
261                         var node = new Json.Node(Json.NodeType.OBJECT);
262                         node.set_object(this.toJsonObject());                   
263                         var generator = new JsonGen(node);
264                     generator.indent = 1;
265                     generator.pretty = true;
266                     
267                         
268                         return generator.to_data();
269                 }
270                 
271                 public void saveBJS()
272                 {
273                     if (!this.loaded) {
274                             return;
275                     }
276                     if (this.xtype == "PlainFile") {
277                             return;
278                     }
279                    ;
280                      
281                     
282                     print("WRITE :%s\n " , this.path);// + "\n" + JSON.stringify(write));
283                     try {
284                                 this.writeFile(this.path, this.toJsonString());
285                          
286                     } catch(Error e) {
287                         print("Save failed");
288                     }
289                 }
290                  
291                  
292
293                 public abstract void loadItems() throws GLib.Error;
294                  
295                  
296                  
297                   
298                 public string jsonHasOrEmpty(Json.Object obj, string key) {
299                         return obj.has_member(key) ? 
300                                                 obj.get_string_member(key) : "";
301                 }
302
303                 
304                 public Json.Object toJsonObject ()
305                 {
306                     
307                     
308                         var ret = new Json.Object();
309                         if (this.xtype == "PlainFile") {
310                                 return ret;
311                         }
312                         
313                         //ret.set_string_member("id", this.id); // not relivant..
314                         ret.set_string_member("name", this.name);
315                         ret.set_string_member("parent", this.parent == null ? "" : this.parent);
316                         ret.set_string_member("title", this.title == null ? "" : this.title);
317                         ret.set_string_member("path", this.path);
318                         //ret.set_string_member("items", this.items);
319                         ret.set_string_member("permname", this.permname  == null ? "" : this.permname);
320                         ret.set_string_member("modOrder", this.modOrder  == null ? "" : this.modOrder);
321                         if (this.project.xtype == "Gtk") {
322                                 ret.set_string_member("build_module", this.build_module  == null ? "" : this.build_module);
323                         }
324                         
325                         if (this.transStrings.size > 0) {
326                                 var tr =  new Json.Object();
327                                 var iter = this.transStrings.map_iterator();
328                                 while (iter.next()) {
329                                         tr.set_string_member(iter.get_value(), iter.get_key());
330                                 }
331                                 ret.set_object_member("strings", tr);
332             }
333
334             
335             
336                         if (this.namedStrings.size > 0) {
337                                 var tr =  new Json.Object();
338                                 var iter = this.namedStrings.map_iterator();
339                                 while (iter.next()) {
340                                         tr.set_string_member(iter.get_key(), iter.get_value());
341                                 }
342                                 ret.set_object_member("named_strings", tr);
343             }
344                         
345                         var ar = new Json.Array();
346                         // empty files do not have a tree.
347                         if (this.tree != null) {
348                                 ar.add_object_element(this.tree.toJsonObject());
349                         }
350                         ret.set_array_member("items", ar);
351                 
352                     return ret;
353                 }
354                 
355                 
356
357                 public string getTitle ()
358                 {
359                     if (this.title.length > 0) {
360                         return this.title;
361                     }
362                     var a = this.path.split("/");
363                     return a[a.length-1];
364                 }
365                 public string getTitleTip()
366                 {
367                     if (this.title.length > 0) {
368                         return "<b>" + this.title + "</b> " + this.path;
369                     }
370                     return this.path;
371                 }
372                 /*
373                     sortCn: function()
374                     {
375                         this.cn.sort(function(a,b) {
376                             return a.path > b.path;// ? 1 : -1;
377                         });
378                     },
379                 */
380                     // should be in palete provider really..
381
382
383                 public Palete.Palete palete()
384                 {
385                         // error on plainfile?
386                         return this.project.palete;
387
388                 }
389                 
390                 public string guessName(Node ar) // turns the object into full name.
391                 {
392                      // eg. xns: Roo, xtype: XXX -> Roo.xxx
393                     if (!ar.hasXnsType()) {
394                        return "";
395                     }
396                     
397                     return ar.get("xns") + "." + ar.get("xtype");
398                                       
399                                         
400                 }
401                 /**
402                  *  non-atomic write (replacement for put contents, as it creates temporary files.
403                  */
404                 public void writeFile(string path, string contents) throws GLib.IOError, GLib.Error
405                 {
406
407                                  
408                         var f = GLib.File.new_for_path(path);
409                         var data_out = new GLib.DataOutputStream(
410                                           f.replace(null, false, GLib.FileCreateFlags.NONE, null)
411                        );
412                         data_out.put_string(contents, null);
413                         data_out.close(null);
414                 }
415                  
416                 
417                 
418                 public  Node? lineToNode(int line)
419                 {
420                         if (this.tree == null) {
421                                 return null;
422                         }
423                         return this.tree.lineToNode(line);
424                         
425                         
426                 }
427                 
428                 
429                 public abstract void save();
430                 public abstract void saveHTML(string html);
431                 public abstract string toSource() ;
432                 public abstract string toSourceCode() ; // used by commandline tester..
433                 public abstract void setSource(string str);
434                 public abstract string toSourcePreview() ;
435                 public abstract void removeFiles() ;
436                 public abstract void  findTransStrings(Node? node );
437                 public abstract string toGlade();
438                 public abstract string targetName();
439         } 
440
441 }
442