mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2024-12-28 17:02:24 -05:00
Implement Base.readSupported() and improve argument reading in Shape
This commit is contained in:
parent
2b62eb5cfa
commit
dacfce0498
3 changed files with 82 additions and 34 deletions
|
@ -98,11 +98,13 @@ var Rectangle = Base.extend(/** @lends Rectangle# */{
|
|||
arg0.width || 0, arg0.height || 0);
|
||||
read = 1;
|
||||
} else if (arg0.from === undefined && arg0.to === undefined) {
|
||||
// Use Base.filter() to support whatever property the rectangle
|
||||
// can take, but handle from/to separately below.
|
||||
// Use `Base.readSupported()` to read and consume whatever
|
||||
// property the rectangle can receive, but handle `from` / `to`
|
||||
// separately below.
|
||||
this._set(0, 0, 0, 0);
|
||||
Base.filter(this, arg0);
|
||||
read = 1;
|
||||
if (Base.readSupported(arguments, this)) {
|
||||
read = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (read === undefined) {
|
||||
|
@ -141,13 +143,13 @@ var Rectangle = Base.extend(/** @lends Rectangle# */{
|
|||
}
|
||||
this._set(x, y, width, height);
|
||||
read = arguments.__index;
|
||||
// arguments.__filtered wouldn't survive the function call even if a
|
||||
// previous arguments list was passed through Function#apply().
|
||||
// Return it on the object instead, see Base.read()
|
||||
var filtered = arguments.__filtered;
|
||||
if (filtered)
|
||||
this.__filtered = filtered;
|
||||
}
|
||||
// arguments.__filtered wouldn't survive the function call even if a
|
||||
// previous arguments list was passed through Function#apply().
|
||||
// Return it on the object instead, see Base.read()
|
||||
var filtered = arguments.__filtered;
|
||||
if (filtered)
|
||||
this.__filtered = filtered;
|
||||
if (this.__read)
|
||||
this.__read = read;
|
||||
return this;
|
||||
|
|
|
@ -269,11 +269,11 @@ statics: /** @lends Base */{
|
|||
},
|
||||
|
||||
/**
|
||||
* Allows using of Base.read() mechanism in combination with reading named
|
||||
* arguments form a passed property object literal. Calling Base.readNamed()
|
||||
* can read both from such named properties and normal unnamed arguments
|
||||
* through Base.read(). In use for example for the various
|
||||
* Path.Constructors.
|
||||
* Allows using of `Base.read()` mechanism in combination with reading named
|
||||
* arguments form a passed property object literal. Calling
|
||||
* `Base.readNamed()` can read both from such named properties and normal
|
||||
* unnamed arguments through `Base.read()`. In use for example for
|
||||
* the various `Path` constructors in `Path.Constructors.js`.
|
||||
*
|
||||
* @param {Array} list the list to read from, either an arguments object or
|
||||
* a normal array
|
||||
|
@ -287,24 +287,68 @@ statics: /** @lends Base */{
|
|||
*/
|
||||
readNamed: function(list, name, start, options, amount) {
|
||||
var value = this.getNamed(list, name),
|
||||
hasObject = value !== undefined;
|
||||
if (hasObject) {
|
||||
// Create a _filtered object that inherits from list[0], and
|
||||
hasValue = value !== undefined;
|
||||
if (hasValue) {
|
||||
// Create a _filtered object that inherits from `source`, and
|
||||
// override all fields that were already read with undefined.
|
||||
var filtered = list.__filtered;
|
||||
if (!filtered) {
|
||||
filtered = list.__filtered = Base.create(list[0]);
|
||||
// Point _unfiltered to the original so Base#_set() can
|
||||
// execute hasOwnProperty on it.
|
||||
filtered.__unfiltered = list[0];
|
||||
var source = this.getSource(list);
|
||||
filtered = list.__filtered = Base.create(source);
|
||||
// Point __unfiltered to the original, so `Base.filter()` can
|
||||
// use it to get all keys to iterate over.
|
||||
filtered.__unfiltered = source;
|
||||
}
|
||||
// delete wouldn't work since the masked parent's value would
|
||||
// shine through.
|
||||
filtered[name] = undefined;
|
||||
}
|
||||
var l = hasObject ? [value] : list,
|
||||
res = this.read(l, start, options, amount);
|
||||
return res;
|
||||
return this.read(hasValue ? [value] : list, start, options, amount);
|
||||
},
|
||||
|
||||
/**
|
||||
* If `list[0]` is a source object, calls `Base.readNamed()` for each key in
|
||||
* it that is supported on `dest`, consuming these values.
|
||||
*
|
||||
* @param {Array} list the list to read from, either an arguments object or
|
||||
* a normal array
|
||||
* @param {Object} dest the object on which to set the supported properties
|
||||
* @return {Boolean} {@true if any property was read from the source object}
|
||||
*/
|
||||
readSupported: function(list, dest) {
|
||||
var source = this.getSource(list),
|
||||
that = this,
|
||||
read = false;
|
||||
if (source) {
|
||||
// If `source` is a filtered object, we get the keys from the the
|
||||
// original object (it's parent / prototype). See _filtered
|
||||
// inheritance trick in the argument reading code.
|
||||
Object.keys(source).forEach(function(key) {
|
||||
if (key in dest) {
|
||||
var value = that.readNamed(list, key);
|
||||
// Due to the _filtered inheritance trick, undefined is used
|
||||
// to mask already consumed named arguments.
|
||||
if (value !== undefined) {
|
||||
dest[key] = value;
|
||||
}
|
||||
read = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return read;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return the arguments object if the list provides one at `list[0]`
|
||||
*/
|
||||
getSource: function(list) {
|
||||
var source = list.__source;
|
||||
if (source === undefined) {
|
||||
var arg = list.length === 1 && list[0];
|
||||
source = list.__source = arg && Base.isPlainObject(arg)
|
||||
? arg : null;
|
||||
}
|
||||
return source;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -314,12 +358,11 @@ statics: /** @lends Base */{
|
|||
* provided, it returns the whole arguments object
|
||||
*/
|
||||
getNamed: function(list, name) {
|
||||
var arg = list[0];
|
||||
if (list._hasObject === undefined)
|
||||
list._hasObject = list.length === 1 && Base.isPlainObject(arg);
|
||||
if (list._hasObject)
|
||||
var source = this.getSource(list);
|
||||
if (source) {
|
||||
// Return the whole arguments object if no name is provided.
|
||||
return name ? arg[name] : list.__filtered || arg;
|
||||
return name ? source[name] : list.__filtered || source;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,7 +82,7 @@ var Shape = Item.extend(/** @lends Shape# */{
|
|||
setSize: function(/* size */) {
|
||||
var size = Size.read(arguments);
|
||||
if (!this._size) {
|
||||
// First time, e.g. whean reading from JSON...
|
||||
// First time, e.g. when reading from JSON...
|
||||
this._size = size.clone();
|
||||
} else if (!this._size.equals(size)) {
|
||||
var type = this._type,
|
||||
|
@ -101,8 +101,8 @@ var Shape = Item.extend(/** @lends Shape# */{
|
|||
this._radius._set(width / 2, height / 2);
|
||||
}
|
||||
this._size._set(width, height);
|
||||
this._changed(/*#=*/Change.GEOMETRY);
|
||||
}
|
||||
this._changed(/*#=*/Change.GEOMETRY);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -130,7 +130,7 @@ var Shape = Item.extend(/** @lends Shape# */{
|
|||
} else {
|
||||
radius = Size.read(arguments);
|
||||
if (!this._radius) {
|
||||
// First time, e.g. whean reading from JSON...
|
||||
// First time, e.g. when reading from JSON...
|
||||
this._radius = radius.clone();
|
||||
} else {
|
||||
if (this._radius.equals(radius))
|
||||
|
@ -390,10 +390,13 @@ new function() { // Scope for _contains() and _hitTestSelf() code.
|
|||
// Mess with indentation in order to get more line-space below:
|
||||
statics: new function() {
|
||||
function createShape(type, point, size, radius, args) {
|
||||
var item = new Shape(Base.getNamed(args), point);
|
||||
// Use `Base.create()` to avoid calling `initialize()` until after the
|
||||
// internal fields are set here, then call `_initialize()` directly:
|
||||
var item = Base.create(Shape.prototype);
|
||||
item._type = type;
|
||||
item._size = size;
|
||||
item._radius = radius;
|
||||
item._initialize(Base.getNamed(args), point);
|
||||
return item;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue