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