src/Builder4/WindowState.vala
[app.Builder.js] / src / Builder4 / WindowState.vala
1 /**
2  * as state management is a bit too complicated inside the builder
3  * it's better to seperate this into this class
4  * 
5  * This class has references to all the Class instances that make up the window..
6  * 
7  */
8 public class WindowState : Object 
9 {
10     public Xcls_MainWindow win;
11
12     public enum State {
13         PREVIEW,
14         OBJECT,
15         PROP,
16         LISTENER,
17         CODE,
18         FILES,
19         PROJECT // project settings..
20     }
21
22     public State state;
23
24     public bool children_loaded = false;
25
26     
27     public Xcls_WindowLeftTree  left_tree;
28     public Xcls_WindowAddProp   add_props;
29     public Xcls_LeftProps       left_props;
30     public Xcls_ProjectSettings projectsettings;
31     public ValaProjectSettings  vala_projectsettings;
32     public Xcls_RightPalete     rightpalete;
33     public Editor               code_editor;    
34     public Xcls_WindowRooView   window_rooview;
35     public Xcls_GtkView         window_gladeview;
36     public Xcls_DialogNewComponent new_file_dialog;     
37
38     public Xcls_WindowLeftProjects left_projects; // can not see where this is initialized.. 
39     // ctor 
40     public WindowState(Xcls_MainWindow win)
41     {
42         this.win = win;
43         // initialize
44
45         // left elements..
46         this.leftTreeInit();
47         this.propsListInit();
48
49         // on clutter space...
50         this.projectEditInit();
51         this.codeEditInit();
52         this.projectListInit();
53         this.fileViewInit();
54         
55         // adding stuff
56         this.objectAddInit();
57         this.propsAddInit();
58      
59         
60         // previews...
61         this.gtkViewInit();
62         this.webkitViewInit();
63
64         // dialogs
65
66         this.fileNewInit();
67
68         this.children_loaded = true;
69     }
70
71
72     // left tree
73
74     public void leftTreeInit()
75     {
76      
77         this.left_tree = new Xcls_WindowLeftTree();
78         this.left_tree.ref();
79         this.left_tree.main_window = this.win;
80     
81         this.win.tree.el.pack_start(this.left_tree.el,true, true,0);
82         this.left_tree.el.show_all();
83            
84         this.left_tree.before_node_change.connect(() => {
85             return this.leftTreeBeforeChange();
86
87         });
88
89         this.left_tree.node_selected.connect((sel) => {
90             this.leftTreeNodeSelected(sel);
91         });
92      
93         this.left_tree.changed.connect(() => {
94             this.window_rooview.requestRedraw();
95             this.left_tree.model.file.save();
96         });
97          
98     }
99
100     public bool leftTreeBeforeChange()
101     {
102         if (this.state != State.CODE) {
103             this.left_props.finish_editing();
104             return true;
105         }
106         if (!this.code_editor.saveContents()) {
107             return false;
108         }
109         return false;
110     }
111     
112     public void leftTreeNodeSelected(JsRender.Node? sel)
113     {
114
115         print("node_selected called %s\n", (sel == null) ? "NULL" : "a value");
116
117         if (sel == null) {
118             this.left_props.el.hide();
119         } 
120         this.left_props.el.show();
121         this.left_props.load(this.left_tree.getActiveFile(), sel);
122         switch (this.state) {
123             
124             case State.OBJECT: 
125                   
126                  if (sel == null) {
127                     this.rightpalete.clear();
128                     break;
129                 }
130                 this.rightpalete.load(this.left_tree.getActiveFile().palete(), sel.fqn());
131                 break;
132                  
133         
134            case State.PROP:
135                 if (sel == null) {
136                     this.add_props.clear();
137                     break;
138                 }
139                 this.add_props.show(this.left_tree.getActiveFile().palete(), "props", sel.fqn());
140                 break;
141
142             case State.LISTENER:
143                
144                 if (sel == null) {
145                     this.add_props.clear();
146                     break;
147                 }
148                 this.add_props.show(this.left_tree.getActiveFile().palete(), "signals", sel.fqn());
149                 break;
150                 
151             case State.CODE:
152                  this.switchState(State.PREVIEW);
153              
154                 break;
155                
156                             
157         }
158          
159
160     }
161
162
163
164
165     public void propsListInit()
166     {
167     
168         this.left_props =new Xcls_LeftProps();
169         this.left_props.ref();
170         this.left_props.main_window = this.win;
171         this.win.props.el.pack_start(this.left_props.el,true, true,0);
172         this.left_props.el.show_all();
173     
174         this.left_props.show_editor.connect( (file, node, type,  key) => {
175             this.switchState(State.CODE);
176             this.code_editor.show(
177                 file,
178                 node,
179                 type,
180                 key
181             );
182             
183             
184         });
185
186    
187         this.left_props.stop_editor.connect( () => {
188             if (this.state != State.CODE) {
189                 return true;
190             }
191     
192             var ret =  this.code_editor.saveContents();
193             if (!ret) {
194                 return false;
195             }
196             this.switchState(State.PREVIEW);
197             return ret;
198         });
199     
200         this.left_props.changed.connect(() => {
201               if (this.left_tree.getActiveFile().xtype == "Roo" ) {
202                    this.win.window_rooview.requestRedraw();
203                    
204                } else {
205                   this.win.window_gladeview.loadFile(this.left_tree.getActiveFile());
206               }
207               this.left_tree.model.updateSelected();
208               this.left_tree.model.file.save();
209         });
210     
211
212
213     }
214
215     //-------------  projects edit
216
217     public void projectEditInit()
218     {
219         this.projectsettings  =new Xcls_ProjectSettings();
220         this.projectsettings.ref();  /// really?
221     
222         this.vala_projectsettings  =new ValaProjectSettings();
223         this.vala_projectsettings.ref();
224         this.vala_projectsettings.window = this;
225     
226         ((Gtk.Container)(this.win.projecteditview.el.get_widget())).add(this.projectsettings.el);
227         //this.projectsettings.el.show_all();
228
229         var stage = this.win.projecteditview.el.get_stage();
230         stage.set_background_color(  Clutter.Color.from_string("#000"));
231     
232         this.projectsettings.buttonPressed.connect((btn) => {
233              if (this.left_tree.getActiveFile().xtype == "Roo" ) {
234                 if (btn == "save") {
235                     this.window_rooview.view.renderJS(true);
236                 }
237                 if (btn == "apply") {
238                     this.window_rooview.view.renderJS(true);
239                     return;
240                 }
241             } else {
242                 // do nothing for gtk..
243             }
244             if (btn == "save" || btn == "apply") {
245                 this.win.project.save();
246          
247             }
248             this.switchState (State.PREVIEW); 
249              
250          });
251
252     }
253     // ----------- object adding
254     public void objectAddInit()
255     {
256
257         this.rightpalete  = new Xcls_RightPalete();
258         this.rightpalete.ref();  /// really?
259         ((Gtk.Container)(this.win.objectview.el.get_widget())).add(this.rightpalete.el);
260         //this.projectsettings.el.show_all();
261
262         stage = _this.win.objectview.el.get_stage();
263         stage.set_background_color(  Clutter.Color.from_string("#000"));
264            
265     }
266     
267     // -----------  properties adding list...
268     // listener uses the properties 
269     public void propsAddInit()
270     {
271     // Add properties
272         this.add_props  = new Xcls_WindowAddProp();
273         this.add_props.ref();  /// really?
274         ((Gtk.Container)(this.win.addpropsview.el.get_widget())).add(this.add_props.el);
275         //this.projectsettings.el.show_all();
276
277         var  stage = _this.win.addpropsview.el.get_stage();
278         stage.set_background_color(  Clutter.Color.from_string("#000"));
279
280
281         this.add_props.select.connect( (key,type,skel, etype) => {
282             this.left_props.addProp(etype, key, skel, type);
283         });
284
285     }
286     public void propsAddShow()
287     {
288
289     }
290     public void propsAddHide()
291     {
292     
293     }
294
295
296
297     
298     // ----------- Add / Edit listener
299     // listener uses the properties 
300     //public void listenerInit()     { }
301     public void listenerShow()
302     {
303
304     }
305     public void listenerHide()
306     {
307     
308     }
309
310     // -------------- codeEditor
311
312     public void codeEditInit()
313     {
314         this.code_editor  = new  Editor();
315         this.code_editor.ref();  /// really?
316         ((Gtk.Container)(this.win.codeeditview.el.get_widget())).add(this.code_editor.el);
317         //this.projectsettings.el.show_all();
318
319         stage = _this.win.codeeditview.el.get_stage();
320         stage.set_background_color(  Clutter.Color.from_string("#000"));
321         // editor.save...
322
323         this.code_editor.save.connect( () => {
324              this.left_tree.model.file.save();
325              this.left_tree.model.updateSelected();
326         });
327         
328     }
329
330     // ----------- list of projects on left
331     public void  projectListInit() 
332     {
333
334         this.left_projects = new Xcls_WindowLeftProjects();
335          this.left_projects.ref();
336          this.win.leftpane.el.pack_start(this.left_projects.el,true, true,0);
337          this.left_projects.el.show_all();
338          this.left_projects.project_selected.connect((proj) => {
339             proj.scanDirs();
340             this.clutterfiles.loadProject(proj);
341         
342          });
343
344     }
345     // ----------- file view
346
347     public void fileViewInit()
348     {
349         var stage = this.win.rooview.el.get_stage(); // seems odd... 
350         this.clutterfiles = new Xcls_ClutterFiles();
351         this.clutterfiles.ref();
352         stage.add_child(this.clutterfiles.el);
353         this.clutterfiles.el.show_all();
354
355
356         this.clutterfiles.open.connect((file) => { 
357             this.fileViewOpen(file);
358         });
359
360     }
361     public void fileNewInit()
362     {
363         this.new_file_dialog = new Xcls_DialogNewComponent();
364         // force it modal to the main window..
365         this.new_file_dialog.el.set_transient_for(this.el);
366         this.new_file_dialog.el.set_modal(true);
367     
368         this.new_file_dialog.success.connect((project,file) =>
369         {
370             this.fileViewOpen(file);
371         });
372
373     }
374
375     
376     public void fileViewOpen(JsRender.JsRender file)
377     {
378         this.win.project = file.project;
379         this.previewShow();
380             this.left_tree.model.loadFile(file);
381     
382         var ctr= ((Gtk.Container)(this.win.rooview.el.get_widget()));
383         var ctr_p= ((Gtk.Container)(this.win.projecteditview.el.get_widget()));
384     
385         if (file.xtype == "Roo" ) { 
386             ctr.foreach( (w) => { ctr.remove(w); });
387             ctr_p.foreach( (w) => { ctr_p.remove(w); });
388             ctr.add(this.window_rooview.el);
389             ctr_p.add(this.projectsettings.el);            
390             this.window_rooview.loadFile(file);
391             this.window_rooview.el.show_all();
392             this.projectsettings.el.show_all();            
393
394         } else {
395             ctr.foreach( (w) => { ctr.remove(w); });
396             ctr_p.foreach( (w) => { ctr_p.remove(w); });            
397             ctr.add(this.window_gladeview.el);
398             ctr_p.add(this.vala_projectsettings.el);
399             this.window_gladeview.loadFile(file);
400             this.window_gladeview.el.show_all();
401             this.vala_projectsettings.el.show_all();
402         }
403         print("OPEN : " + file.name);
404         this.editpane.el.set_position(_this.editpane.el.max_position);
405         this.win.setTitle(file.project.name + " : " +file.name);
406              
407
408         }
409
410     
411     // ---------  webkit view
412     public void webkitViewInit()
413     {
414         this.window_rooview  =new Xcls_WindowRooView();
415         this.window_rooview.ref();
416         ((Gtk.Container)(this.win.rooview.el.get_widget())).add(this.window_rooview.el);
417         this.window_rooview.el.show_all();
418
419         stage = this.win.rooview.el.get_stage();
420         stage.set_background_color(  Clutter.Color.from_string("#000"));
421     }
422
423     // ------ Gtk  - view
424
425     public void gtkViewInit()
426     {
427         this.window_gladeview  =new Xcls_GtkView();
428         this.window_gladeview.ref();
429     }
430
431     public void switchState(State new_state)
432     {
433         
434
435         
436         switch (this.state) {
437
438             case State.PREVIEW:
439                 if (this.left_tree.getActiveFile() != null) {
440                      if (this.left_tree.getActiveFile().xtype == "Roo" ) {
441                          this.window_rooview.createThumb();
442                      } else {
443                           this.window_gladeview.createThumb();
444                       }
445                 }
446                 // normally we are going from preview to another state.
447                 // and different windows hide the preview in differnt ways..
448                 
449                 break;
450             
451            case State.LISTENER:
452            case State.PROP:
453                 this.win.addpropsview.el.save_easing_state();
454                 this.win.addpropsview.el.set_scale(0.0f,0.0f);
455                 this.win.addpropsview.el.restore_easing_state();   
456                 break;
457                 
458             case State.CODE:
459
460
461                 this.code_editor.saveContents();
462                 this.win.codeeditview.el.save_easing_state();
463                 this.win.codeeditview.el.set_scale(0.0f,0.0f);
464                 this.win.codeeditview.el.restore_easing_state();    
465                 break;
466
467
468              case State.OBJECT:
469                 this.win.objectview.el.save_easing_state();
470                 this.win.objectview.el.set_scale(0.0f,0.0f);
471                 this.win.objectview.el.restore_easing_state();    
472                 break;
473
474            case State.PROJECT:
475                 this.win.projecteditview.el.save_easing_state();
476                 this.win.projecteditview.el.set_scale(0.0f,0.0f);
477                 this.win.projecteditview.el.restore_easing_state();    
478                 break;
479
480           case State.FILES:       
481                 this.win.rooview.el.save_easing_state();
482                 this.win.rooview.el.set_rotation_angle(Clutter.RotateAxis.Y_AXIS, 0.0f);
483                 this.win.rooview.el.set_scale(1.0f,1.0f);
484                 this.win.rooview.el.restore_easing_state();  
485
486                  this.win.clutterfiles.el.hide();
487                 break;
488
489                 
490         }
491         
492         var oldstate  =this.state;
493         this.state = new_state;
494
495                 
496         this.buttonsShowHide();
497         
498         switch (this.state) {
499             
500             case State.PREVIEW:  // this is the default state when working...
501                  this.win.rooview.el.save_easing_state();
502                  this.win.rooview.el.set_scale(1.0f,1.0f);
503                  this.win.rooview.el.restore_easing_state();
504                
505                 break;
506
507
508             case State.LISTENER:
509             case State.PROP:
510                 var ae =      this.left_tree.getActiveElement();
511                 if (ae == null) {
512                     this.state = oldstate;
513                     this.buttonsShowHide();
514                     return;
515                 }
516                 this.add_props.el.show_all();
517                 this.add_props.show(
518                     Palete.factory(this.win.project.xtype), 
519                     this.state == State.LISTENER ? "signals" : "props",
520                     ae.fqn()
521                 );
522  
523                     
524  
525                 this.win.rooview.el.save_easing_state();
526                 // -- FIXME? this needs to be State aware?
527                 this.resizeCanvasElementsA();
528                 this.win.rooview.el.restore_easing_state();
529                 
530               
531                 this.win.addpropsview.el.save_easing_state();
532                 this.win.addpropsview.el.set_scale(1.0f,1.0f);
533                 this.win.addpropsview.el.restore_easing_state();
534                  
535                 
536             case State.CODE:
537
538                 this.code_editor.el.show_all();
539                 
540                 // caller needs to call editor - show....
541                 this.win.rooview.el.save_easing_state();
542                 this.resizeCanvasElementsA();
543                 this.win.rooview.el.restore_easing_state();
544                 
545  
546                 this.win.codeeditview.el.save_easing_state();
547                 this.win.codeeditview.el.set_scale(1.0f,1.0f);
548                 this.win.codeeditview.el.restore_easing_state();    
549                 break;
550
551
552              case State.OBJECT:
553                  var n = this.left_tree.getActiveElement();
554
555                 if (this.left_tree.model.file == null) {
556                     this.state =oldstate;
557                     this.buttonsShowHide();
558                     return;
559                 }
560                 
561                 if (n == null && this.left_tree.model.file.tree != null) {
562                     this.state = oldstate;
563                     this.buttonsShowHide();
564                     return;
565                 }
566
567                 this.rightpalete.el.show_all();
568                 this.rightpalete.load(this.left_tree.getActiveFile().palete(), n == null ? "*top" : n.fqn());
569
570                 this.win.rooview.el.save_easing_state();
571                 this.resizeCanvasElementsA();
572                 this.win.rooview.el.restore_easing_state();
573
574                 
575                 this.win.objectview.el.save_easing_state();
576                 this.win.objectview.el.set_scale(1.0f,1.0f);
577                 this.win.objectview.el.restore_easing_state();    
578                 break;
579
580            case State.PROJECT:
581
582              if (this.win.project.xtype == "Roo") {
583                     this.projectsettings.el.show_all();
584                     this.projectsettings.show(this.win.project);
585                 } else {
586                     this.vala_projectsettings.el.show_all();
587                     this.vala_projectsettings.show((Project.Gtk)this.win.project);
588                 }
589
590                  this.win.rooview.el.save_easing_state();
591                 this.resizeCanvasElementsA();
592                 this.win.rooview.el.restore_easing_state();
593
594                 this.win.projecteditview.el.save_easing_state();
595                 this.win.projecteditview.el.set_scale(0.0f,0.0f);
596                 this.win.projecteditview.el.restore_easing_state();    
597                 break;
598                 
599            case State.FILES:  // can only get here from PREVIEW state.. in theory..
600                 
601    
602                 this.win.editpane.el.hide(); // holder for tree and properties..
603              
604                 this.left_projects.el.show(); 
605             
606                 var el = this.win.rooview.el;
607                 el.save_easing_state();
608                 el.set_easing_duration(1000);
609
610                 el.set_rotation_angle(Clutter.RotateAxis.Y_AXIS, 360.0f);
611                 el.set_scale(0.0f,0.0f);
612
613  
614                 if (this.win.project != null) {
615                     this.left_projects.selectProject(this.win.project);
616                 }
617              
618                 el.restore_easing_state();
619                 
620                 break;
621
622
623         }
624
625             
626     }
627     
628     // -- buttons show hide.....
629
630     public void buttonsShowHide()
631     {
632         // basically hide everything, then show the relivant..
633
634          this.win.backbutton.el.hide();
635     
636         this.win.projectbutton.el.hide(); // show file nav...
637         this.win.editfilebutton.el.hide();
638         this.win.projecteditbutton.el.hide();
639          
640         
641         this.win.objectshowbutton.el.hide(); // add objects
642         this.win.addpropbutton.el.hide();  
643         this.win.addlistenerbutton.el.hide(); 
644
645     
646     
647         this.win.addprojectbutton.el.hide();
648         this.win.addfilebutton.el.hide();
649         this.win.delprojectbutton.el.hide();
650         this.win.new_window.el.hide();
651
652         
653         switch (this.state) {
654             
655             case State.PREVIEW:  // this is the default state when working...
656                
657                 this.win.projectbutton.el.show(); // show file nav...
658                 this.win.editfilebutton.el.show();
659                 this.win.projecteditbutton.el.show();
660                  
661                 
662                 this.win.objectshowbutton.el.show(); // add objects
663                 this.win.addpropbutton.el.show();  
664                 this.win.addlistenerbutton.el.show(); 
665                 break;
666             
667            
668             case State.CODE: 
669             case State.PROP:
670             case State.LISTENER:
671             case State.OBJECT:
672                 
673                 this.win.backbutton.el.show();
674                 this.win.objectshowbutton.el.show(); // add objects
675                 this.win.addpropbutton.el.show();  
676                 this.win.addlistenerbutton.el.show(); 
677                 break;
678                 
679             case State.FILES:
680                 this.win.backbutton.el.show();
681                      
682                 this.win.addprojectbutton.el.show();
683                 this.win.addfilebutton.el.show();
684                 this.win.delprojectbutton.el.show();
685                 this.win.new_window.el.show();
686                 break;
687         }
688
689     }
690     public void resizeCanvasElementsA()
691     {
692         Gtk.Allocation alloc;
693         this.win.clutteremebed.get_allocation(out alloc);
694         this.resizeCanvasElements(alloc);
695     }
696     public void resizeCanvasElements(Gtk.Allocation alloc)
697     {
698         if (!_this.children_loaded) { 
699             return; 
700         }
701      
702         this.win.clutterfiles.set_size(alloc.width-50, alloc.height);
703         
704         // ------- project view appears at top...
705         this.win.projecteditview.el.set_size(alloc.width-50, alloc.height / 2.0f);
706                
707         // ------- add property/object left - max 300px, min 50... (or disapear..)     
708         
709         var avail = alloc.width < 50.0f ? 0 :  alloc.width - 50.0f;
710         var palsize = avail < 300.0f ? avail : 300.0f;
711         //print("set palsize size %f\n", palsize);
712         // palate / props : fixed 300 pix
713                 
714         this.win.objectview.el.set_size(palsize, alloc.height);    
715         this.win.addpropsview.el.set_size(palsize, alloc.height);
716         
717          
718         
719         // -------- code edit min 600
720         
721         var codesize = avail < 800.0f ? avail : 800.0f;
722         //print("set code size %f\n", codesize);
723
724         this.win.codeeditview.el.set_size(codesize, alloc.height);
725         this.win.rooview.el.set_size(alloc.width-50, alloc.height);    
726
727
728         
729         switch ( this.state) {
730             case State.CODE: 
731                 var scale = avail > 0.0f ? (avail - codesize -10 ) / avail : 0.0f;
732                     this.win.rooview.el.set_scale(scale,scale);
733                 break;
734                 
735             case State.PROP:
736             case State.LISTENER:        
737             case State.OBJECT:   
738                     var scale = avail > 0.0f ? (avail - palsize -10 ) / avail : 0.0f;
739                 this.win.rooview.el.set_scale(scale,scale);
740                 break;
741         }
742     }
743
744     
745 }
746
747