1 sc_require("views/view");
  2 
  3 SC.View.reopen(
  4   /** @scope SC.View.prototype */{
  5 
  6   /**
  7     Handles changes in the layer id.
  8   */
  9   layerIdDidChange: function() {
 10     var layer  = this.get('layer'),
 11         lid    = this.get('layerId'),
 12         lastId = this._lastLayerId;
 13 
 14     if (lid !== lastId) {
 15       // if we had an earlier one, remove from view hash.
 16       if (lastId && SC.View.views[lastId] === this) {
 17         delete SC.View.views[lastId];
 18       }
 19 
 20       // set the current one as the new old one
 21       this._lastLayerId = lid;
 22 
 23       // and add the new one
 24       SC.View.views[lid] = this;
 25 
 26       // and finally, set the actual layer id.
 27       if (layer) { layer.id = lid; }
 28     }
 29   }.observes("layerId"),
 30 
 31   // ------------------------------------------------------------------------
 32   // LAYER LOCATION
 33   //
 34 
 35   /**
 36     Insert the view into the the receiver's childNodes array.
 37 
 38     The view will be added to the childNodes array before the beforeView.  If
 39     beforeView is null, then the view will be added to the end of the array.
 40     This will also add the view's rootElement DOM node to the receivers
 41     containerElement DOM node as a child.
 42 
 43     If the specified view already belongs to another parent, it will be
 44     removed from that view first.
 45 
 46     @param {SC.View} view
 47     @param {SC.View} beforeView
 48     @returns {SC.View} the receiver
 49   */
 50   insertBefore: function(view, beforeView) {
 51     view.beginPropertyChanges(); // limit notifications
 52 
 53     // Reset any views that are already building in or out.
 54     if (view.resetBuildState) { view.resetBuildState(); }
 55     view._doAdopt(this, beforeView);
 56 
 57     view.endPropertyChanges();
 58 
 59     return this ;
 60   },
 61 
 62   /**
 63     Replace the oldView with the specified view in the receivers childNodes
 64     array. This will also replace the DOM node of the oldView with the DOM
 65     node of the new view in the receivers DOM.
 66 
 67     If the specified view already belongs to another parent, it will be
 68     removed from that view first.
 69 
 70     @param view {SC.View} the view to insert in the DOM
 71     @param view {SC.View} the view to remove from the DOM.
 72     @returns {SC.View} the receiver
 73   */
 74   replaceChild: function(view, oldView) {
 75     // suspend notifications
 76     view.beginPropertyChanges();
 77     oldView.beginPropertyChanges();
 78     this.beginPropertyChanges();
 79 
 80     this.insertBefore(view,oldView).removeChild(oldView) ;
 81 
 82     // resume notifications
 83     this.endPropertyChanges();
 84     oldView.endPropertyChanges();
 85     view.endPropertyChanges();
 86 
 87     return this;
 88   },
 89 
 90   /**
 91     Replaces the current array of child views with the new array of child
 92     views.
 93 
 94     This will remove *and* destroy all of the existing child views and their
 95     layers.
 96 
 97     Warning: The new array must be made of *child* views (i.e. created using
 98     this.createChildView() on the parent).
 99 
100     @param {Array} newChildViews Child views you want to add
101     @returns {SC.View} receiver
102   */
103   replaceAllChildren: function (newChildViews) {
104     this.beginPropertyChanges();
105 
106     // If rendered, destroy our layer so we can re-render.
107     // if (this.get('_isRendered')) {
108     //   var layer = this.get('layer');
109 
110     //   // If attached, detach and track our parent node so we can re-attach.
111     //   if (this.get('isAttached')) {
112     //     // We don't allow for transitioning out at this time.
113     //     // TODO: support transition out of child views.
114     //     this._doDetach(true);
115     //   }
116 
117     //   // Destroy our layer in one move.
118     //   this.destroyLayer();
119     // }
120 
121     // Remove the current child views.
122     // We aren't rendered at this point so it bypasses the optimization in
123     // removeAllChildren that would recreate the layer.  We would rather add the
124     // new childViews before recreating the layer.
125     this.removeAllChildren(true);
126 
127     // Add the new children.
128     for (var i = 0, len = newChildViews.get('length'); i < len; i++) {
129       this.appendChild(newChildViews.objectAt(i));
130     }
131 
132     // We were rendered previously.
133     // if (layer) {
134     //   // Recreate our layer (now empty).
135     //   this.createLayer();
136     // }
137     this.endPropertyChanges();
138 
139     return this ;
140   },
141 
142   /**
143     Appends the specified view to the end of the receivers childViews array.
144     This is equivalent to calling insertBefore(view, null);
145 
146     @param view {SC.View} the view to insert
147     @returns {SC.View} the receiver
148   */
149   appendChild: function(view) {
150     return this.insertBefore(view, null);
151   },
152 
153   // ------------------------------------------------------------------------
154   // BUILDING IN/OUT
155   //
156 
157   /**
158     Call this to append a child while building it in. If the child is not
159     buildable, this is the same as calling appendChild.
160 
161     @deprecated Version 1.10
162   */
163   buildInChild: function(view) {
164     view.willBuildInToView(this);
165     this.appendChild(view);
166     view.buildInToView(this);
167   },
168 
169   /**
170     Call to remove a child after building it out. If the child is not buildable,
171     this will simply call removeChild.
172 
173     @deprecated Version 1.10
174   */
175   buildOutChild: function(view) {
176     view.buildOutFromView(this);
177   },
178 
179   /**
180     Called by child view when build in finishes. By default, does nothing.
181 
182     @deprecated Version 1.10
183   */
184   buildInDidFinishFor: function(child) {
185   },
186 
187   /**
188     @private
189     Called by child view when build out finishes. By default removes the child view.
190   */
191   buildOutDidFinishFor: function(child) {
192     this.removeChild(child);
193   },
194 
195   /**
196     Whether the view is currently building in.
197 
198     @deprecated Version 1.10
199   */
200   isBuildingIn: NO,
201 
202   /**
203     Whether the view is currently building out.
204 
205     @deprecated Version 1.10
206   */
207   isBuildingOut: NO,
208 
209   /**
210     Implement this, and call didFinishBuildIn when you are done.
211 
212     @deprecated Version 1.10
213   */
214   buildIn: function() {
215     //@if(debug)
216     SC.warn("The SC.View build methods have been deprecated in favor of the transition plugins.  To build in a view, please provide a transitionIn plugin (many are pre-built in SproutCore) and to build out a view, please provide a transitionOut plugin.");
217     //@endif
218     this.buildInDidFinish();
219   },
220 
221   /**
222     Implement this, and call didFinishBuildOut when you are done.
223 
224     @deprecated Version 1.10
225   */
226   buildOut: function() {
227     //@if(debug)
228     SC.warn("The SC.View build methods have been deprecated in favor of the transition plugins.  To build in a view, please provide a transitionIn plugin (many are pre-built in SproutCore) and to build out a view, please provide a transitionOut plugin.");
229     //@endif
230     this.buildOutDidFinish();
231   },
232 
233   /**
234     This should reset (without animation) any internal states; sometimes called before.
235 
236     It is usually called before a build in, by the parent view.
237     @deprecated Version 1.10
238   */
239   resetBuild: function() {
240 
241   },
242 
243   /**
244     Implement this if you need to do anything special when cancelling build out;
245     note that buildIn will subsequently be called, so you usually won't need to do
246     anything.
247 
248     This is basically called whenever build in happens.
249 
250     @deprecated Version 1.10
251   */
252   buildOutDidCancel: function() {
253 
254   },
255 
256   /**
257     Implement this if you need to do anything special when cancelling build in.
258     You probably won't be able to do anything. I mean, what are you gonna do?
259 
260     If build in was cancelled, it means build out is probably happening.
261     So, any timers or anything you had going, you can cancel.
262     Then buildOut will happen.
263 
264     @deprecated Version 1.10
265   */
266   buildInDidCancel: function() {
267 
268   },
269 
270   /**
271     Call this when you have built in.
272 
273     @deprecated Version 1.10
274   */
275   buildInDidFinish: function() {
276     this.isBuildingIn = NO;
277     this._buildingInTo.buildInDidFinishFor(this);
278     this._buildingInTo = null;
279   },
280 
281   /**
282     Call this when you have finished building out.
283 
284     @deprecated Version 1.10
285   */
286   buildOutDidFinish: function() {
287     this.isBuildingOut = NO;
288     this._buildingOutFrom.buildOutDidFinishFor(this);
289     this._buildingOutFrom = null;
290   },
291 
292   /**
293     Usually called by parentViewDidChange, this resets the build state (calling resetBuild in the process).
294 
295     @deprecated Version 1.10
296   */
297   resetBuildState: function() {
298     if (this.isBuildingIn) {
299       this.buildInDidCancel();
300       this.isBuildingIn = NO;
301     }
302     if (this.isBuildingOut) {
303       this.buildOutDidCancel();
304       this.isBuildingOut = NO;
305     }
306 
307     // finish cleaning up
308     this.buildingInTo = null;
309     this.buildingOutFrom = null;
310 
311     this.resetBuild();
312   },
313 
314   /**
315     @private (semi)
316     Called by building parent view's buildInChild method. This prepares
317     to build in, but unlike buildInToView, this is called _before_ the child
318     is appended.
319 
320     Mostly, this cancels any build out _before_ the view is removed through parent change.
321   */
322   willBuildInToView: function(view) {
323     // stop any current build outs (and if we need to, we also need to build in again)
324     if (this.isBuildingOut) {
325       this.buildOutDidCancel();
326     }
327   },
328 
329   /**
330     @private (semi)
331     Called by building parent view's buildInChild method.
332   */
333   buildInToView: function(view) {
334     // if we are already building in, do nothing.
335     if (this.isBuildingIn) { return; }
336 
337     this._buildingInTo = view;
338     this.isBuildingOut = NO;
339     this.isBuildingIn = YES;
340     this.buildIn();
341   },
342 
343   /**
344     @private (semi)
345     Called by building parent view's buildOutChild method.
346 
347     The supplied view should always be the parent view.
348   */
349   buildOutFromView: function(view) {
350     // if we are already building out, do nothing.
351     if (this.isBuildingOut) { return; }
352 
353     // cancel any build ins
354     if (this.isBuildingIn) {
355       this.buildInDidCancel();
356     }
357 
358     // in any case, we need to build out
359     this.isBuildingOut = YES;
360     this.isBuildingIn = NO;
361     this._buildingOutFrom = view;
362     this.buildOut();
363   }
364 });
365