diff --git a/src/basic/Matrix.js b/src/basic/Matrix.js index f89892c7..a70e61ee 100644 --- a/src/basic/Matrix.js +++ b/src/basic/Matrix.js @@ -220,8 +220,6 @@ var Matrix = Base.extend(/** @lends Matrix# */{ * @return {Matrix} this affine transform */ scale: function(/* scale, center */) { - // Do not modify scale, center, since that would arguments of which - // we're reading from! var scale = Point.read(arguments), center = Point.read(arguments, 0, { readNull: true }); if (center) @@ -761,10 +759,10 @@ var Matrix = Base.extend(/** @lends Matrix# */{ this._tx, this._ty); } } -}, Base.each(['a', 'c', 'b', 'd', 'tx', 'ty'], function(name) { +}, Base.each(['a', 'c', 'b', 'd', 'tx', 'ty'], function(key) { // Create getters and setters for all internal attributes. - var part = Base.capitalize(name), - prop = '_' + name; + var part = Base.capitalize(key), + prop = '_' + key; this['get' + part] = function() { return this[prop]; }; diff --git a/src/basic/Point.js b/src/basic/Point.js index bafb1a90..d597fe8e 100644 --- a/src/basic/Point.js +++ b/src/basic/Point.js @@ -947,10 +947,10 @@ var Point = Base.extend(/** @lends Point# */{ * /*#=*/Numerical.TRIGONOMETRIC_EPSILON; } } -}, Base.each(['round', 'ceil', 'floor', 'abs'], function(name) { +}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) { // Inject round, ceil, floor, abs: - var op = Math[name]; - this[name] = function() { + var op = Math[key]; + this[key] = function() { return new Point(op(this.x), op(this.y)); }; }, {})); diff --git a/src/basic/Size.js b/src/basic/Size.js index fd43d088..da1a3781 100644 --- a/src/basic/Size.js +++ b/src/basic/Size.js @@ -524,10 +524,10 @@ var Size = Base.extend(/** @lends Size# */{ return new Size(Math.random(), Math.random()); } } -}, Base.each(['round', 'ceil', 'floor', 'abs'], function(name) { +}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) { // Inject round, ceil, floor, abs: - var op = Math[name]; - this[name] = function() { + var op = Math[key]; + this[key] = function() { return new Size(op(this.width), op(this.height)); }; }, {})); diff --git a/src/item/ChangeFlag.js b/src/item/ChangeFlag.js index 3fe36442..a6f79383 100644 --- a/src/item/ChangeFlag.js +++ b/src/item/ChangeFlag.js @@ -35,7 +35,9 @@ var ChangeFlag = { // Raster pixels PIXELS: 0x200, // Clipping in one of the child items - CLIPPING: 0x400 + CLIPPING: 0x400, + // The view has been transformed + VIEW: 0x800 }; // Shortcuts to often used ChangeFlag values including APPEARANCE @@ -51,5 +53,6 @@ var Change = { STYLE: ChangeFlag.STYLE | ChangeFlag.APPEARANCE, ATTRIBUTE: ChangeFlag.ATTRIBUTE | ChangeFlag.APPEARANCE, CONTENT: ChangeFlag.CONTENT | ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE, - PIXELS: ChangeFlag.PIXELS | ChangeFlag.APPEARANCE + PIXELS: ChangeFlag.PIXELS | ChangeFlag.APPEARANCE, + VIEW: ChangeFlag.VIEW | ChangeFlag.APPEARANCE }; diff --git a/src/item/Item.js b/src/item/Item.js index 23dd66de..103d8e7c 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -2936,11 +2936,19 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ * @property * @type Color */ - +}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) { + var rotate = key === 'rotate'; + this[key] = function(/* value, center */) { + var value = (rotate ? Base : Point).read(arguments), + center = Point.read(arguments, 0, { readNull: true }); + return this.transform(new Matrix()[key](value, + center || this.getPosition(true))); + }; +}, /** @lends Item# */{ /** * {@grouptitle Transform Functions} * - * Translates (moves) the item by the given offset point. + * Translates (moves) the item by the given offset views. * * @param {Point} delta the offset to translate the item by */ @@ -2950,13 +2958,15 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ }, /** - * Rotates the item by a given angle around the given point. + * Rotates the item by a given angle around the given center point. * * Angles are oriented clockwise and measured in degrees. * + * @name Item#rotate + * @function * @param {Number} angle the rotation angle * @param {Point} [center={@link Item#position}] - * @see Matrix#rotate + * @see Matrix#rotate(angle[, center]) * * @example {@paperscript} * // Rotating an item: @@ -2993,20 +3003,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ * path.rotate(3, view.center); * } */ - rotate: function(angle /*, center */) { - return this.transform(new Matrix().rotate(angle, - Point.read(arguments, 1, { readNull: true }) - || this.getPosition(true))); - } -}, Base.each(['scale', 'shear', 'skew'], function(name) { - this[name] = function() { - // See Matrix#scale for explanation of this: - var point = Point.read(arguments), - center = Point.read(arguments, 0, { readNull: true }); - return this.transform(new Matrix()[name](point, - center || this.getPosition(true))); - }; -}, /** @lends Item# */{ + /** * Scales the item by the given value from its center point, or optionally * from a supplied point. @@ -3078,7 +3075,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ * @function * @param {Point} shear the horziontal and vertical shear factors as a point * @param {Point} [center={@link Item#position}] - * @see Matrix#shear + * @see Matrix#shear(shear[, center]) */ /** * Shears the item by the given values from its center point, or optionally @@ -3089,7 +3086,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ * @param {Number} hor the horizontal shear factor * @param {Number} ver the vertical shear factor * @param {Point} [center={@link Item#position}] - * @see Matrix#shear + * @see Matrix#shear(hor, ver[, center]) */ /** @@ -3100,7 +3097,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ * @function * @param {Point} skew the horziontal and vertical skew angles in degrees * @param {Point} [center={@link Item#position}] - * @see Matrix#shear + * @see Matrix#shear(skew[, center]) */ /** * Skews the item by the given angles from its center point, or optionally @@ -3111,9 +3108,9 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ * @param {Number} hor the horizontal skew angle in degrees * @param {Number} ver the vertical sskew angle in degrees * @param {Point} [center={@link Item#position}] - * @see Matrix#shear + * @see Matrix#shear(hor, ver[, center]) */ -}), /** @lends Item# */{ + /** * Transform the item. * @@ -3331,7 +3328,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ */ fitBounds: function(rectangle, fill) { // TODO: Think about passing options with various ways of defining - // fitting. + // fitting. Compare with InDesign fitting to see possible options. rectangle = Rectangle.read(arguments); var bounds = this.getBounds(), itemRatio = bounds.height / bounds.width, @@ -3343,8 +3340,8 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ new Size(bounds.width * scale, bounds.height * scale)); newBounds.setCenter(rectangle.getCenter()); this.setBounds(newBounds); - }, - + } +}), /** @lends Item# */{ /** * {@grouptitle Event Handlers} * @@ -4070,10 +4067,10 @@ var Item = Base.extend(Emitter, /** @lends Item# */{ _canComposite: function() { return false; } -}, Base.each(['down', 'drag', 'up', 'move'], function(name) { - this['removeOn' + Base.capitalize(name)] = function() { +}, Base.each(['down', 'drag', 'up', 'move'], function(key) { + this['removeOn' + Base.capitalize(key)] = function() { var hash = {}; - hash[name] = true; + hash[key] = true; return this.removeOn(hash); }; }, /** @lends Item# */{ diff --git a/src/view/View.js b/src/view/View.js index 152e5b65..c1100f6d 100644 --- a/src/view/View.js +++ b/src/view/View.js @@ -261,18 +261,13 @@ var View = Base.extend(Emitter, /** @lends View# */{ /** * Private notifier that is called whenever a change occurs in this view. * Used only by Matrix for now. - * - * @param {ChangeFlag} flags describes what exactly has changed */ - _changed: function(flags) { - this._project._changed(flags); - }, - - _transform: function(matrix) { - this._matrix.concatenate(matrix); + _changed: function() { + // The only one calling View._changed() is Matrix, so it can only mean + // one thing: + this._project._changed(/*#=*/Change.VIEW); // Force recalculation of these values next time they are requested. this._bounds = null; - this._update(); }, /** @@ -329,13 +324,13 @@ var View = Base.extend(Emitter, /** @lends View# */{ return; this._viewSize.set(size.width, size.height); this._setViewSize(size); - this._bounds = null; // Force recalculation // Call onResize handler on any size change this.emit('resize', { size: size, delta: delta }); - this._update(); + this._changed(); + this.update(); }, /** @@ -382,7 +377,7 @@ var View = Base.extend(Emitter, /** @lends View# */{ setCenter: function(/* center */) { var center = Point.read(arguments); - this.scrollBy(center.subtract(this.getCenter())); + this.translate(this.getCenter().subtract(center)); }, /** @@ -396,8 +391,7 @@ var View = Base.extend(Emitter, /** @lends View# */{ }, setZoom: function(zoom) { - // TODO: Clamp the view between 1/32 and 64, just like Illustrator? - this._transform(new Matrix().scale(zoom / this._zoom, + this.transform(new Matrix().scale(zoom / this._zoom, this.getCenter())); this._zoom = zoom; }, @@ -438,17 +432,124 @@ var View = Base.extend(Emitter, /** @lends View# */{ */ isInserted: function() { return DomElement.isInserted(this._element); + } +}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) { + var rotate = key === 'rotate'; + this[key] = function(/* value, center */) { + var value = (rotate ? Base : Point).read(arguments), + center = Point.read(arguments, 0, { readNull: true }); + return this.transform(new Matrix()[key](value, + center || this.getCenter(true))); + }; +}, /** @lends View# */{ + /** + * {@grouptitle Transform Functions} + * + * Translates (scrolls) the view by the given offset vector. + * + * @param {Point} delta the offset to translate the view by + */ + translate: function(/* delta */) { + var mx = new Matrix(); + return this.transform(mx.translate.apply(mx, arguments)); + }, + + /** + * Rotates the view by a given angle around the given center point. + * + * Angles are oriented clockwise and measured in degrees. + * + * @name View#rotate + * @function + * @param {Number} angle the rotation angle + * @param {Point} [center={@link View#getCenter()}] + * @see Matrix#rotate(angle[, center]) + */ + + /** + * Scales the view by the given value from its center point, or optionally + * from a supplied point. + * + * @name View#scale + * @function + * @param {Number} scale the scale factor + * @param {Point} [center={@link View#getCenter()}] + */ + /** + * Scales the view by the given values from its center point, or optionally + * from a supplied point. + * + * @name View#scale + * @function + * @param {Number} hor the horizontal scale factor + * @param {Number} ver the vertical scale factor + * @param {Point} [center={@link View#getCenter()}] + */ + + /** + * Shears the view by the given value from its center point, or optionally + * by a supplied point. + * + * @name View#shear + * @function + * @param {Point} shear the horziontal and vertical shear factors as a point + * @param {Point} [center={@link View#getCenter()}] + * @see Matrix#shear(shear[, center]) + */ + /** + * Shears the view by the given values from its center point, or optionally + * by a supplied point. + * + * @name View#shear + * @function + * @param {Number} hor the horizontal shear factor + * @param {Number} ver the vertical shear factor + * @param {Point} [center={@link View#getCenter()}] + * @see Matrix#shear(hor, ver[, center]) + */ + + /** + * Skews the view by the given angles from its center point, or optionally + * by a supplied point. + * + * @name View#skew + * @function + * @param {Point} skew the horziontal and vertical skew angles in degrees + * @param {Point} [center={@link View#getCenter()}] + * @see Matrix#shear(skew[, center]) + */ + /** + * Skews the view by the given angles from its center point, or optionally + * by a supplied point. + * + * @name View#skew + * @function + * @param {Number} hor the horizontal skew angle in degrees + * @param {Number} ver the vertical sskew angle in degrees + * @param {Point} [center={@link View#getCenter()}] + * @see Matrix#shear(hor, ver[, center]) + */ + + /** + * Transform the view. + * + * @param {Matrix} matrix the matrix by which the view shall be transformed + */ + transform: function(matrix) { + this._matrix.concatenate(matrix); }, /** * Scrolls the view by the given vector. * * @param {Point} point + * @deprecated use {@link #translate(delta)} instead (using opposite + * direction). */ scrollBy: function(/* point */) { - this._transform(new Matrix().translate(Point.read(arguments).negate())); - }, - + this.translate(Point.read(arguments).negate()); + } +}), /** @lends View# */{ /** * Makes all animation play by adding the view to the request animation * loop.