1 // ==========================================================================
  2 // Project:   SproutCore Costello - Property Observing Library
  3 // Copyright: ©2006-2011 Strobe Inc. and contributors.
  4 //            Portions ©2008-2011 Apple Inc. All rights reserved.
  5 // License:   Licensed under MIT license (see license.js)
  6 // ==========================================================================
  7 
  8 /**
  9   @class
 10 
 11   Implements some standard methods for copying an object.  Add this mixin to
 12   any object you create that can create a copy of itself.  This mixin is
 13   added automatically to the built-in array.
 14 
 15   You should generally implement the copy() method to return a copy of the
 16   receiver.
 17 
 18   Note that frozenCopy() will only work if you also implement SC.Freezable.
 19 
 20   @since SproutCore 1.0
 21 */
 22 SC.Copyable = /** @scope SC.Copyable.prototype */{
 23 
 24   /**
 25     Walk like a duck.  Indicates that the object can be copied.
 26 
 27     @type Boolean
 28   */
 29   isCopyable: YES,
 30 
 31   /**
 32     Override to return a copy of the receiver.  Default implementation raises
 33     an exception.
 34 
 35     @param deep {Boolean} if true, a deep copy of the object should be made
 36     @returns {Object} copy of receiver
 37   */
 38   copy: function(deep) {
 39     var className = SC._object_className(this.constructor);
 40     throw new Error("%@.copy() is not implemented".fmt(className));
 41   },
 42 
 43   /**
 44     If the object implements SC.Freezable, then this will return a new copy
 45     if the object is not frozen and the receiver if the object is frozen.
 46 
 47     Raises an exception if you try to call this method on a object that does
 48     not support freezing.
 49 
 50     You should use this method whenever you want a copy of a freezable object
 51     since a freezable object can simply return itself without actually
 52     consuming more memory.
 53 
 54     @returns {Object} copy of receiver or receiver
 55   */
 56   frozenCopy: function() {
 57     var isFrozen = this.get ? this.get('isFrozen') : this.isFrozen;
 58     if (isFrozen === YES) return this;
 59     else if (isFrozen === undefined) throw new Error("%@ does not support freezing".fmt(this));
 60     else return this.copy().freeze();
 61   }
 62 };
 63 
 64 // Make Array copyable
 65 SC.mixin(Array.prototype, SC.Copyable);
 66 /**
 67   Override to return a copy of the receiver.  Default implementation raises
 68   an exception.
 69 
 70   @param deep {Boolean} if true, a deep copy of the object should be made
 71   @returns {Object} copy of receiver
 72 */
 73 Array.prototype.copy = function(deep) {
 74 	var ret = this.slice(), idx;
 75 	if (deep) {
 76       idx = ret.length;
 77 	  while (idx--) ret[idx] = SC.copy(ret[idx], true);
 78 	}
 79 	return ret;
 80 };
 81