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