1 // ==========================================================================
  2 // Project:   Greenhouse
  3 // Copyright: ©2010 Mike Ball
  4 // ==========================================================================
  5 /*globals Greenhouse */
  6 /**
  7   @extends Greenhouse
  8   @author Mike Ball
  9   @author Evin Grano
 10   @version RC1
 11   @since RC1
 12 */
 13 Greenhouse.mixin(SC.StatechartManager, {
 14   /** @scope Greenhouse */
 15 
 16   rootState: SC.State.design({
 17     substatesAreConcurrent: YES,
 18 
 19     mainStates: SC.State.plugin('Greenhouse.mainStates'),
 20 
 21     modalStates: SC.State.plugin('Greenhouse.modalStates'),
 22 
 23     libraryStates: SC.State.plugin('Greenhouse.libraryStates'),
 24 
 25     inspectorStates: SC.State.plugin('Greenhouse.inspectorStates')
 26   }),
 27 
 28   mainStates: SC.State.design({
 29 
 30     initialSubstate: 'loading',
 31 
 32     loading: SC.State.design({
 33 
 34       enterState: function(){
 35         console.log('greenhouse is loading');
 36         var c = Greenhouse.getPath('mainPage.mainPane.container');
 37         c.set('nowShowing', Greenhouse.getPath('mainPage.loading'));
 38       },
 39       exitState: function(){
 40 
 41       },
 42 
 43       // ..........................................................
 44       // Events
 45       //
 46       /*
 47         called when the file list call completes
 48       */
 49       fileListCallDidComplete: function(){
 50         //eval all the appropriate files
 51         this.gotoState('iframeLoading');
 52       },
 53 
 54       /*
 55         called when the file choose call completes
 56       */
 57       fetchTargetsDidComplete: function(){
 58         //eval all the appropriate files
 59         this.gotoState('chooseApp');
 60       }
 61 
 62     }),
 63 
 64     chooseApp: SC.State.design({
 65 
 66       enterState: function(){
 67         var c = Greenhouse.getPath('mainPage.mainPane.container');
 68         c.set('nowShowing', Greenhouse.getPath('mainPage.appPicker'));
 69       },
 70       exitState: function(){
 71 
 72       },
 73 
 74       // ..........................................................
 75       // Events
 76       //
 77       loadApplication: function(){
 78         Greenhouse.filesController.reload();
 79         Greenhouse.viewConfigsController.reload();
 80         this.gotoState('loading');
 81       }
 82     }),
 83 
 84     // ..........................................................
 85     // sub states
 86     //
 87     ready: SC.State.plugin('Greenhouse.readyStates'),
 88 
 89 
 90     iframeLoading: SC.State.design({
 91 
 92       enterState: function(){
 93         var c = Greenhouse.getPath('mainPage.mainPane.container');
 94         c.set('nowShowing', Greenhouse.getPath('appPage.mainView'));
 95         //TODO disable views and display a loading spinner
 96       },
 97       exitState: function(){
 98 
 99       },
100 
101       // ..........................................................
102       // Events
103       //
104       iframeLoaded: function(){
105         this.gotoState('syncRunLoops');
106       }
107     }),
108 
109     syncRunLoops: SC.State.design({
110 
111       enterState: function(){
112         this._setupRunLoops();
113         this._grabDropTargets();
114         this._setupGreenhouse();
115         this._setupEventBlocker();
116         this.gotoState('readyWaiting');
117         //this.invokeLater(function(){this.gotoState('readyWaiting');}); //totally cheating!!
118       },
119       exitState: function(){
120 
121       },
122 
123       // ..........................................................
124       // Monkey-Patch Run Loop
125       //
126       _setupRunLoops: function(){
127         var iframe = Greenhouse.get('iframe'), innerBegin, outerBegin, innerEnd, outerEnd, outerSC = SC;
128 
129         // ..........................................................
130         // run loop patches...
131         //
132         outerBegin = function() {
133           var runLoop = outerSC.RunLoop.currentRunLoop;
134           if (!runLoop) runLoop = outerSC.RunLoop.currentRunLoop = outerSC.RunLoop.runLoopClass.create();
135           runLoop.beginRunLoop();
136           return outerSC.RunLoop ;
137         };
138         outerEnd = function() {
139           var runLoop = outerSC.RunLoop.currentRunLoop;
140           if (!runLoop) {
141             throw "SC.RunLoop.end() called outside of a runloop!";
142           }
143           runLoop.endRunLoop();
144           return outerSC.RunLoop ;
145         };
146 
147         innerBegin = function() {
148           var runLoop = iframe.SC.RunLoop.currentRunLoop;
149           if (!runLoop) runLoop = iframe.SC.RunLoop.currentRunLoop = iframe.SC.RunLoop.runLoopClass.create();
150           runLoop.beginRunLoop();
151           return iframe.SC.RunLoop ;
152         };
153 
154         innerEnd = function() {
155           var runLoop = iframe.SC.RunLoop.currentRunLoop;
156           if (!runLoop) {
157             throw "SC.RunLoop.end() called outside of a runloop!";
158           }
159           runLoop.endRunLoop();
160           return iframe.SC.RunLoop ;
161         };
162 
163         //outer begin
164         outerSC.RunLoop.begin = function() {
165           //console.log('outer begin');
166           var outer = outerBegin();
167           innerBegin();
168           return outer;
169         };
170 
171         //inner begin
172         iframe.SC.RunLoop.begin = function() {
173           //console.log('inner begin');
174           var inner = innerBegin();
175           outerBegin();
176           return inner;
177         };
178 
179         //inner end
180         iframe.SC.RunLoop.end = function() {
181           //console.log('inner end');
182           outerEnd();
183           return innerEnd();
184         };
185 
186         //Outer End
187         outerSC.RunLoop.end = function() {
188           //console.log('outer end');
189           innerEnd();
190           return outerEnd();
191         };
192        },
193 
194       _grabDropTargets: function(){
195         var iframe = Greenhouse.get('iframe'),
196             innerTargets,
197             webViewFrame,
198             dropContainerLayout,
199             webView = Greenhouse.appPage.get('webView');
200 
201         var pv = webView.get('parentView');
202           webViewFrame = webView.get('frame');
203         webViewFrame = pv.convertFrameToView(webViewFrame, null);
204         //add the drop container to the adjusted layout
205         dropContainerLayout = iframe.SC.designPage.getPath('designMainPane.container').layout;
206 
207         if(dropContainerLayout){
208           webViewFrame.x += dropContainerLayout.left;
209           webViewFrame.y += dropContainerLayout.top;
210         }
211         //assign this to
212         Greenhouse._webViewFrame = webViewFrame;
213 
214         //add existing targets
215         innerTargets = iframe.SC.Drag._dropTargets;
216 
217         for(var dt in innerTargets){
218           if(innerTargets.hasOwnProperty(dt)){
219             SC.Drag.addDropTarget(innerTargets[dt]);
220           }
221         }
222 
223         //make sure we get any new ones
224         iframe.SC.Drag.addDropTarget = function(target) {
225           iframe.SC.Drag._dropTargets[iframe.SC.guidFor(target)] = target ;
226           SC.Drag._dropTargets[iframe.SC.guidFor(target)] = target ;
227         };
228 
229 
230         iframe.SC.Drag.removeDropTarget = function(target) {
231           delete iframe.SC.Drag._dropTargets[iframe.SC.guidFor(target)] ;
232           delete SC.Drag._dropTargets[iframe.SC.guidFor(target)];
233         };
234 
235         //make sure all drags have an iframeTargetOffset...
236         SC.Drag.start = function(ops) {
237           var ret = this.create(ops);
238           ret.globalTargetOffset = Greenhouse._webViewFrame;
239           ret.startDrag();
240           return ret;
241         };
242 
243         //all inner drags are actually outer drags
244         iframe.SC.Drag.start = SC.Drag.start;
245 
246 
247         SC.Drag.prototype._findDropTarget = function(evt) {
248           var loc = { x: evt.pageX, y: evt.pageY }, globalOffset = this.globalTargetOffset ;
249           var target, frame ;
250           var ary = this._dropTargets() ;
251           for (var idx=0, len=ary.length; idx<len; idx++) {
252             target = ary[idx] ;
253             // If the target is not visible, it is not valid.
254             if (!target.get('isVisibleInWindow')) continue ;
255 
256             // get clippingFrame, converted to the pane.
257             frame = target.convertFrameToView(target.get('clippingFrame'), null) ;
258             //convert to iframe pane if it is in the winodw
259             if(globalOffset && target.inGlobalOffset){
260               frame.x += globalOffset.x;
261               frame.y += globalOffset.y;
262             }
263             // check to see if loc is inside.  If so, then make this the drop target
264             // unless there is a drop target and the current one is not deeper.
265             if(SC.pointInRect(loc, frame)) return target;
266 
267           }
268           return null ;        };
269         //all inner drags are actually outer drags
270         iframe.SC.Drag.start = SC.Drag.start;
271       },
272 
273       _setupGreenhouse: function(){
274         var iframe = Greenhouse.get('iframe');
275         iframe.SC._Greenhouse = Greenhouse;
276       },
277 
278       _setupEventBlocker: function(){
279         var eventBlocker = Greenhouse.appPage.get('eventBlocker');
280         Greenhouse.set('eventBlocker', eventBlocker);
281       }
282     })
283   })
284 });
285