Move more getter / setter injection functionality from PathStyle to Style, to be shared among all Style classes.

This commit is contained in:
Jürg Lehni 2011-06-20 15:21:42 +01:00
parent a7e57ada88
commit 456bf7f2a9
3 changed files with 260 additions and 271 deletions

View file

@ -38,7 +38,7 @@ var ChangeFlag = {
var Change = { var Change = {
HIERARCHY: ChangeFlag.HIERARCHY | ChangeFlag.APPEARANCE, HIERARCHY: ChangeFlag.HIERARCHY | ChangeFlag.APPEARANCE,
GEOMETRY: ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE, GEOMETRY: ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE,
STROKE: ChangeFlag.STROKE | ChangeFlag.APPEARANCE, STROKE: ChangeFlag.STROKE | ChangeFlag.STYLE | ChangeFlag.APPEARANCE,
STYLE: ChangeFlag.STYLE | ChangeFlag.APPEARANCE, STYLE: ChangeFlag.STYLE | ChangeFlag.APPEARANCE,
ATTRIBUTE: ChangeFlag.ATTRIBUTE | ChangeFlag.APPEARANCE, ATTRIBUTE: ChangeFlag.ATTRIBUTE | ChangeFlag.APPEARANCE,
CONTENT: ChangeFlag.CONTENT | ChangeFlag.APPEARANCE CONTENT: ChangeFlag.CONTENT | ChangeFlag.APPEARANCE

View file

@ -14,13 +14,12 @@
* All rights reserved. * All rights reserved.
*/ */
var PathStyle = this.PathStyle = Style.extend(new function() { var PathStyle = this.PathStyle = Style.extend({
/** @lends PathStyle# */
// windingRule / resolution / fillOverprint / strokeOverprint are currently // windingRule / resolution / fillOverprint / strokeOverprint are currently
// not supported. The full list of properties would be: // not supported.
// ['windingRule', 'resolution', 'strokeColor', 'strokeWidth', _defaults: {
// 'strokeCap', 'strokeJoin', 'miterLimit', 'dashOffset','dashArray',
// 'strokeOverprint', 'fillColor', 'fillOverprint'],
var defaults = {
fillColor: undefined, fillColor: undefined,
strokeColor: undefined, strokeColor: undefined,
strokeWidth: 1, strokeWidth: 1,
@ -29,267 +28,206 @@ var PathStyle = this.PathStyle = Style.extend(new function() {
miterLimit: 10, miterLimit: 10,
dashOffset: 0, dashOffset: 0,
dashArray: [] dashArray: []
}; },
_flags: {
strokeWidth: Change.STROKE,
strokeCap: Change.STROKE,
strokeJoin: Change.STROKE,
miterLimit: Change.STROKE
},
_owner: Item,
_style: '_style'
var strokeFlags = { // DOCS: why isn't the example code showing up?
strokeWidth: true, /**
strokeCap: true, * PathStyle objects don't need to be created directly. Just pass an
strokeJoin: true, * object to {@link Item#style} or {@link Project#currentStyle}, it will
miterLimit: true * be converted to a PathStyle object internally.
}; *
* @constructs PathStyle
* @param {object} style
*
* @class PathStyle is used for changing the visual styles of items
* contained within a Paper.js project and is returned by
* {@link Item#style} and {@link Project#currentStyle}.
*
* All properties of PathStyle are also reflected directly in {@link Item},
* i.e.: {@link Item#fillColor}.
*
* To set multiple style properties in one go, you can pass an object to
* {@link Item#style}. This is a convenient way to define a style once and
* apply it to a series of items:
*
* @classexample {@paperscript}
* var circleStyle = {
* fillColor: new RGBColor(1, 0, 0),
* strokeColor: 'black',
* strokeWidth: 5
* };
*
* var path = new Path.Circle(new Point(80, 50), 30);
* path.style = circleStyle;
*/
/**
* {@grouptitle Stroke Style}
*
* The color of the stroke.
*
* @property
* @name PathStyle#strokeColor
* @type RGBColor|HSBColor|GrayColor
*
* @example {@paperscript}
* // Setting the stroke color of a path:
*
* // Create a circle shaped path at { x: 80, y: 50 }
* // with a radius of 35:
* var circle = new Path.Circle(new Point(80, 50), 35);
*
* // Set its stroke color to RGB red:
* circle.strokeColor = new RGBColor(1, 0, 0);
*/
return Base.each(defaults, function(value, key) { /**
var isColor = !!key.match(/Color$/), * The width of the stroke.
part = Base.capitalize(key), *
set = 'set' + part, * @property
get = 'get' + part; * @name PathStyle#strokeWidth
* @default 1
* @type Number
*
* @example {@paperscript}
* // Setting an item's stroke width:
*
* // Create a circle shaped path at { x: 80, y: 50 }
* // with a radius of 35:
* var circle = new Path.Circle(new Point(80, 50), 35);
*
* // Set its stroke color to black:
* circle.strokeColor = 'black';
*
* // Set its stroke width to 10:
* circle.strokeWidth = 10;
*/
this[set] = function(value) { /**
var children = this._item && this._item._children; * The shape to be used at the end of open {@link Path} items, when they
value = isColor ? Color.read(arguments) : value; * have a stroke.
if (children) { *
for (var i = 0, l = children.length; i < l; i++) * @property
children[i]._style[set](value); * @name Item#strokeCap
} else { * @default 'butt'
var old = this['_' + key]; * @type String('round', 'square', 'butt')
if (old != value && !(old && old.equals && old.equals(value))) { *
this['_' + key] = value; * @example {@paperscript height=200}
if (isColor) { * // A look at the different stroke caps:
if (old) *
old._removeOwner(this._item); * var line = new Path(new Point(80, 50), new Point(420, 50));
if (value) * line.strokeColor = 'black';
value._addOwner(this._item); * line.strokeWidth = 20;
} *
if (this._item) { * // Select the path, so we can see where the stroke is formed:
this._item._changed(Change.STYLE * line.selected = true;
| (strokeFlags[key] ? Change.STROKE : 0)); *
} * // Set the stroke cap of the line to be round:
} * line.strokeCap = 'round';
} *
return this; * // Copy the path and set its stroke cap to be square:
}; * var line2 = line.clone();
* line2.position.y += 50;
* line2.strokeCap = 'square';
*
* // Make another copy and set its stroke cap to be butt:
* var line2 = line.clone();
* line2.position.y += 100;
* line2.strokeCap = 'butt';
*/
this[get] = function() { /**
var children = this._item && this._item._children, * The shape to be used at the corners of paths when they have a stroke.
style; *
// If this item has children, walk through all of them and see if * @property
// they all have the same style. * @name PathStyle#strokeJoin
if (children) { * @default 'miter'
for (var i = 0, l = children.length; i < l; i++) { * @type String ('miter', 'round', 'bevel')
var childStyle = children[i]._style[get](); *
if (!style) { * @example {@paperscript height=120}
style = childStyle; * // A look at the different stroke joins:
} else if (style != childStyle && !(style && style.equals * var path = new Path();
&& style.equals(childStyle))) { * path.add(new Point(80, 100));
// If there is another item with a different style, * path.add(new Point(120, 40));
// the style is not defined: * path.add(new Point(160, 100));
// PORT: Change this in Scriptographer * path.strokeColor = 'black';
// (currently returns null) * path.strokeWidth = 20;
return undefined; *
} * // Select the path, so we can see where the stroke is formed:
} * path.selected = true;
return style; *
} else { * var path2 = path.clone();
return this['_' + key]; * path2.position.x += path2.bounds.width * 1.5;
} * path2.strokeJoin = 'round';
}; *
}, { * var path3 = path2.clone();
_defaults: defaults, * path3.position.x += path3.bounds.width * 1.5;
_owner: Item, * path3.strokeJoin = 'bevel';
_style: '_style' */
});
/**
* The dash offset of the stroke.
*
* @property
* @name PathStyle#dashOffset
* @default 0
* @type Number
*/
/**
* Specifies an array containing the dash and gap lengths of the stroke.
*
* @example {@paperscript}
* var path = new Path.Circle(new Point(80, 50), 40);
* path.strokeWidth = 2;
* path.strokeColor = 'black';
*
* // Set the dashed stroke to [10pt dash, 4pt gap]:
* path.dashArray = [10, 4];
*
* @property
* @name PathStyle#dashArray
* @default []
* @type Array
*/
/**
* The miter limit of the stroke.
* When two line segments meet at a sharp angle and miter joins have been
* specified for {@link #strokeJoin}, it is possible for the miter to extend
* far beyond the {@link #strokeWidth} of the path. The miterLimit imposes a
* limit on the ratio of the miter length to the {@link #strokeWidth}.
*
* @property
* @default 10
* @name PathStyle#miterLimit
* @type Number
*/
/**
* {@grouptitle Fill Style}
*
* The fill color.
*
* @property
* @name PathStyle#fillColor
* @type RGBColor|HSBColor|GrayColor
*
* @example {@paperscript}
* // Setting the fill color of a path to red:
*
* // Create a circle shaped path at { x: 80, y: 50 }
* // with a radius of 35:
* var circle = new Path.Circle(new Point(80, 50), 35);
*
* // Set the fill color of the circle to RGB red:
* circle.fillColor = new RGBColor(1, 0, 0);
*/
}); });
// TODO: See if these still show up?
// DOCS: why isn't the example code showing up?
/**
* PathStyle objects don't need to be created directly. Just pass an
* object to {@link Item#style} or {@link Project#currentStyle}, it will
* be converted to a PathStyle object internally.
*
* @constructs PathStyle
* @param {object} style
*
* @class PathStyle is used for changing the visual styles of items
* contained within a Paper.js project and is returned by
* {@link Item#style} and {@link Project#currentStyle}.
*
* All properties of PathStyle are also reflected directly in {@link Item},
* i.e.: {@link Item#fillColor}.
*
* To set multiple style properties in one go, you can pass an object to
* {@link Item#style}. This is a convenient way to define a style once and
* apply it to a series of items:
*
* @classexample {@paperscript}
* var circleStyle = {
* fillColor: new RGBColor(1, 0, 0),
* strokeColor: 'black',
* strokeWidth: 5
* };
*
* var path = new Path.Circle(new Point(80, 50), 30);
* path.style = circleStyle;
*/
/**
* {@grouptitle Stroke Style}
*
* The color of the stroke.
*
* @property
* @name PathStyle#strokeColor
* @type RGBColor|HSBColor|GrayColor
*
* @example {@paperscript}
* // Setting the stroke color of a path:
*
* // Create a circle shaped path at { x: 80, y: 50 }
* // with a radius of 35:
* var circle = new Path.Circle(new Point(80, 50), 35);
*
* // Set its stroke color to RGB red:
* circle.strokeColor = new RGBColor(1, 0, 0);
*/
/**
* The width of the stroke.
*
* @property
* @name PathStyle#strokeWidth
* @default 1
* @type Number
*
* @example {@paperscript}
* // Setting an item's stroke width:
*
* // Create a circle shaped path at { x: 80, y: 50 }
* // with a radius of 35:
* var circle = new Path.Circle(new Point(80, 50), 35);
*
* // Set its stroke color to black:
* circle.strokeColor = 'black';
*
* // Set its stroke width to 10:
* circle.strokeWidth = 10;
*/
/**
* The shape to be used at the end of open {@link Path} items, when they
* have a stroke.
*
* @property
* @name Item#strokeCap
* @default 'butt'
* @type String('round', 'square', 'butt')
*
* @example {@paperscript height=200}
* // A look at the different stroke caps:
*
* var line = new Path(new Point(80, 50), new Point(420, 50));
* line.strokeColor = 'black';
* line.strokeWidth = 20;
*
* // Select the path, so we can see where the stroke is formed:
* line.selected = true;
*
* // Set the stroke cap of the line to be round:
* line.strokeCap = 'round';
*
* // Copy the path and set its stroke cap to be square:
* var line2 = line.clone();
* line2.position.y += 50;
* line2.strokeCap = 'square';
*
* // Make another copy and set its stroke cap to be butt:
* var line2 = line.clone();
* line2.position.y += 100;
* line2.strokeCap = 'butt';
*/
/**
* The shape to be used at the corners of paths when they have a stroke.
*
* @property
* @name PathStyle#strokeJoin
* @default 'miter'
* @type String ('miter', 'round', 'bevel')
*
* @example {@paperscript height=120}
* // A look at the different stroke joins:
* var path = new Path();
* path.add(new Point(80, 100));
* path.add(new Point(120, 40));
* path.add(new Point(160, 100));
* path.strokeColor = 'black';
* path.strokeWidth = 20;
*
* // Select the path, so we can see where the stroke is formed:
* path.selected = true;
*
* var path2 = path.clone();
* path2.position.x += path2.bounds.width * 1.5;
* path2.strokeJoin = 'round';
*
* var path3 = path2.clone();
* path3.position.x += path3.bounds.width * 1.5;
* path3.strokeJoin = 'bevel';
*/
/**
* The dash offset of the stroke.
*
* @property
* @name PathStyle#dashOffset
* @default 0
* @type Number
*/
/**
* Specifies an array containing the dash and gap lengths of the stroke.
*
* @example {@paperscript}
* var path = new Path.Circle(new Point(80, 50), 40);
* path.strokeWidth = 2;
* path.strokeColor = 'black';
*
* // Set the dashed stroke to [10pt dash, 4pt gap]:
* path.dashArray = [10, 4];
*
* @property
* @name PathStyle#dashArray
* @default []
* @type Array
*/
/**
* The miter limit of the stroke.
* When two line segments meet at a sharp angle and miter joins have been
* specified for {@link #strokeJoin}, it is possible for the miter to extend
* far beyond the {@link #strokeWidth} of the path. The miterLimit imposes a
* limit on the ratio of the miter length to the {@link #strokeWidth}.
*
* @property
* @default 10
* @name PathStyle#miterLimit
* @type Number
*/
/**
* {@grouptitle Fill Style}
*
* The fill color.
*
* @property
* @name PathStyle#fillColor
* @type RGBColor|HSBColor|GrayColor
*
* @example {@paperscript}
* // Setting the fill color of a path to red:
*
* // Create a circle shaped path at { x: 80, y: 50 }
* // with a radius of 35:
* var circle = new Path.Circle(new Point(80, 50), 35);
*
* // Set the fill color of the circle to RGB red:
* circle.fillColor = new RGBColor(1, 0, 0);
*/

View file

@ -19,7 +19,6 @@
* PargraphStyle. * PargraphStyle.
*/ */
var Style = Item.extend({ var Style = Item.extend({
initialize: function(style) { initialize: function(style) {
// If the passed style object is also a Style, clone its clonable // If the passed style object is also a Style, clone its clonable
// fields rather than simply copying them. // fields rather than simply copying them.
@ -44,17 +43,69 @@ var Style = Item.extend({
// Inject style getters and setters into the 'owning' class, which // Inject style getters and setters into the 'owning' class, which
// redirect calls to the linked style objects through their internal // redirect calls to the linked style objects through their internal
// property on the instances of that class, as defined by _style. // property on the instances of that class, as defined by _style.
var style = src._style; var styleKey = src._style,
flags = src._flags || {};
src._owner.inject(Base.each(src._defaults, function(value, key) { src._owner.inject(Base.each(src._defaults, function(value, key) {
var part = Base.capitalize(key), var isColor = !!key.match(/Color$/),
part = Base.capitalize(key),
set = 'set' + part, set = 'set' + part,
get = 'get' + part; get = 'get' + part;
// Simply extend src with these getters and setters, to be
// injected into this class using this.base() further down.
src[set] = function(value) {
var children = this._item && this._item._children;
value = isColor ? Color.read(arguments) : value;
if (children) {
for (var i = 0, l = children.length; i < l; i++)
children[i][styleKey][set](value);
} else {
var old = this['_' + key];
if (old != value && !(old && old.equals
&& old.equals(value))) {
this['_' + key] = value;
if (isColor) {
if (old)
old._removeOwner(this._item);
if (value)
value._addOwner(this._item);
}
if (this._item)
this._item._changed(flags[key] || Change.STYLE);
}
}
return this;
};
src[get] = function() {
var children = this._item && this._item._children,
style;
// If this item has children, walk through all of them and
// see if they all have the same style.
if (!children)
return this['_' + key];
for (var i = 0, l = children.length; i < l; i++) {
var childStyle = children[i][styleKey][get]();
if (!style) {
style = childStyle;
} else if (style != childStyle && !(style
&& style.equals && style.equals(childStyle))) {
// If there is another item with a different
// style, the style is not defined:
// PORT: Change this in Scriptographer
// (currently returns null)
return undefined;
}
}
return style;
};
// Style-getters and setters for owner class:
// 'this' = the Base.each() side-car = the object that is
// returned from Base.each and injected into _owner above:
this[set] = function(value) { this[set] = function(value) {
this[style][set](value); this[styleKey][set](value);
return this; return this;
}; };
this[get] = function() { this[get] = function() {
return this[style][get](); return this[styleKey][get]();
}; };
}, {})); }, {}));
return this.base(src); return this.base(src);