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