From 3ac039bd6612ca95e73994dcfab325b14136acda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Tue, 25 Dec 2012 22:12:25 +0100 Subject: [PATCH] Implement properties object literal initialization for all Item constructors. --- src/core/Base.js | 8 ++++---- src/item/Group.js | 5 +++-- src/item/Item.js | 9 +++++++++ src/item/PlacedSymbol.js | 12 +++++++++--- src/item/Raster.js | 23 +++++++++++++++-------- src/path/Path.js | 39 +++++++++++++++++++++++---------------- src/text/TextItem.js | 12 ++++++++++-- 7 files changed, 73 insertions(+), 35 deletions(-) diff --git a/src/core/Base.js b/src/core/Base.js index 9a6527fb..d09538cc 100644 --- a/src/core/Base.js +++ b/src/core/Base.js @@ -105,7 +105,7 @@ this.Base = Base.inject(/** @lends Base# */{ * @param {Boolean} clone controls wether passed objects should be * cloned if they are already provided in the required type */ - read: function(list, start, length, clone) { + read: function(list, start, length, clone, readNull) { var proto = this.prototype, readIndex = proto._readIndex, index = start || readIndex && list._index || 0; @@ -113,9 +113,9 @@ this.Base = Base.inject(/** @lends Base# */{ length = list.length - index; var obj = list[index]; if (obj instanceof this - // If the class defines _readNull, return null when nothing - // was provided - || proto._readNull && obj == null && length <= 1) { + // If the class defines _readNull, return null when nothing + // was provided + || (proto._readNull || readNull) && obj == null && length <= 1) { if (readIndex) list._index = index + 1; return obj && clone ? obj.clone() : obj; diff --git a/src/item/Group.js b/src/item/Group.js index fa7fc747..44559140 100644 --- a/src/item/Group.js +++ b/src/item/Group.js @@ -68,12 +68,13 @@ var Group = this.Group = Item.extend(/** @lends Group# */{ * group.rotate(1, view.center); * } */ - initialize: function(items) { + initialize: function(arg) { this.base(); // Allow Group to have children and named children this._children = []; this._namedChildren = {}; - this.addChildren(Array.isArray(items) ? items : arguments); + if (!this.setProperties(arg)) + this.addChildren(Array.isArray(arg) ? arg : arguments); }, _changed: function(flags) { diff --git a/src/item/Item.js b/src/item/Item.js index f58a259a..bae42543 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -111,6 +111,15 @@ var Item = this.Item = Base.extend(Callback, /** @lends Item# */{ this._matrix.translate(point); }, + setProperties: function(props) { + if (Base.isObject(props)) { + for (var key in props) + if (props.hasOwnProperty(key)) + this[key] = props[key]; + return true; + } + }, + /** * Private notifier that is called whenever a change occurs in this item or * its sub-elements, such as Segments, Curves, PathStyles, etc. diff --git a/src/item/PlacedSymbol.js b/src/item/PlacedSymbol.js index f9b3f7aa..a6086a6a 100644 --- a/src/item/PlacedSymbol.js +++ b/src/item/PlacedSymbol.js @@ -60,9 +60,15 @@ var PlacedSymbol = this.PlacedSymbol = PlacedItem.extend(/** @lends PlacedSymbol * instance.scale(0.25 + Math.random() * 0.75); * } */ - initialize: function(symbol, point) { - this.base(Point.read(arguments, 1)); - this.setSymbol(symbol instanceof Symbol ? symbol : new Symbol(symbol)); + initialize: function(arg0, arg1) { + // Support two forms of item initialization: Passing one object literal + // describing all the different properties to be set, or a symbol (arg0) + // and a point where it should be placed (arg1). + this.base(arg1 !== undefined && Point.read(arguments, 1)); + // If we can handle setting properties through object literal, we're all + // set. Otherwise we need to set symbol. + if (!this.setProperties(arg0)) + this.setSymbol(arg0 instanceof Symbol ? arg0 : new Symbol(arg0)); }, /** diff --git a/src/item/Raster.js b/src/item/Raster.js index e5f6c7a8..b366c57c 100644 --- a/src/item/Raster.js +++ b/src/item/Raster.js @@ -35,14 +35,21 @@ var Raster = this.Raster = PlacedItem.extend(/** @lends Raster# */{ * * @param {HTMLImageElement|Canvas|string} [object] */ - initialize: function(object, point) { - this.base(Point.read(arguments, 1)); - if (object.getContext) { - this.setCanvas(object); - } else if (typeof object === 'string') { - this.setSource(object); - } else { - this.setImage(object); + initialize: function(arg0, arg1) { + // Support two forms of item initialization: Passing one object literal + // describing all the different properties to be set, or an image (arg0) + // and a point where it should be placed (arg1). + this.base(arg1 !== undefined && Point.read(arguments, 1)); + // If we can handle setting properties through object literal, we're all + // set. Otherwise we need to check the type of arg0: + if (!this.setProperties(arg0)) { + if (arg0.getContext) { + this.setCanvas(arg0); + } else if (typeof arg0 === 'string') { + this.setSource(arg0); + } else { + this.setImage(arg0); + } } }, diff --git a/src/path/Path.js b/src/path/Path.js index 62a11f18..1198d350 100644 --- a/src/path/Path.js +++ b/src/path/Path.js @@ -44,15 +44,27 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{ * var path = new Path(segments); * path.strokeColor = 'black'; */ - initialize: function(segments) { - this.base(); + initialize: function(arg) { this._closed = false; - this._selectedSegmentState = 0; - // Support both passing of segments as array or arguments + this._segments = []; + this.base(); + // arg can either be an object literal describing properties to be set + // on the path, a list of segments to be set, or the first of multiple + // arguments describing separate segments. // If it is an array, it can also be a description of a point, so - // check its first entry for object as well - this.setSegments(Array.isArray(segments) - && typeof segments[0] === 'object' ? segments : arguments); + // check its first entry for object as well. + // But first see if segments are directly passed at all. If not, try + // #setProperties(arg). + var segments = Array.isArray(arg) + ? typeof arg[0] === 'object' + ? arg + : arguments + : arg && (arg.point !== undefined || arg.x !== undefined) + ? arguments + : null; + this.setSegments(segments || []); + if (!segments) + this.setProperties(arg); }, clone: function() { @@ -94,15 +106,10 @@ var Path = this.Path = PathItem.extend(/** @lends Path# */{ }, setSegments: function(segments) { - if (!this._segments) { - this._segments = []; - } else { - this._selectedSegmentState = 0; - this._segments.length = 0; - // Make sure new curves are calculated next time we call getCurves() - if (this._curves) - delete this._curves; - } + this._selectedSegmentState = 0; + this._segments.length = 0; + // Make sure new curves are calculated next time we call getCurves() + delete this._curves; this._add(Segment.readAll(segments)); }, diff --git a/src/text/TextItem.js b/src/text/TextItem.js index 60164650..04136386 100644 --- a/src/text/TextItem.js +++ b/src/text/TextItem.js @@ -30,18 +30,26 @@ var TextItem = this.TextItem = Item.extend(/** @lends TextItem# */{ // so use the same name for all of them _boundsGetter: 'getBounds', - initialize: function(point) { + initialize: function(arg) { + // Support two forms of item initialization: Passing one object literal + // describing all the different properties to be set, or a point where + // it should be placed (arg). // Note that internally #characterStyle is the same as #style, but // defined as an instance of CharacterStyle. We need to define it before // calling this.base(), to override the default PathStyle instance. this._style = CharacterStyle.create(this); this._paragraphStyle = ParagraphStyle.create(this); - this.base(Point.read(arguments)); + // See if a point is passed, and if so, pass it on to base(). If not, it + // might be a properties object literal for #setPropeties() at the end. + var point = Point.read(arguments, 0, 0, false, true); // readNull + this.base(point); // No need to call setStyle(), since base() handles this already. // Call with no parameter to initalize defaults now. this.setParagraphStyle(); this._content = ''; this._lines = []; + if (!point) + this.setProperties(arg); }, /**