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