Implement change propagation in matrices.

This commit is contained in:
Jürg Lehni 2013-11-26 19:03:58 +01:00
parent ade2a2f456
commit 56f25e8742
6 changed files with 45 additions and 18 deletions

View file

@ -83,13 +83,15 @@ var Matrix = Base.extend(/** @lends Matrix# */{
* @param {Number} ty the translateY coordinate of the transform * @param {Number} ty the translateY coordinate of the transform
* @return {Matrix} this affine transform * @return {Matrix} this affine transform
*/ */
set: function(a, c, b, d, tx, ty) { set: function(a, c, b, d, tx, ty, _dontNotify) {
this._a = a; this._a = a;
this._c = c; this._c = c;
this._b = b; this._b = b;
this._d = d; this._d = d;
this._tx = tx; this._tx = tx;
this._ty = ty; this._ty = ty;
if (!_dontNotify)
this._changed();
return this; return this;
}, },
@ -97,6 +99,11 @@ var Matrix = Base.extend(/** @lends Matrix# */{
return Base.serialize(this.getValues(), options); return Base.serialize(this.getValues(), options);
}, },
_changed: function() {
if (this._owner)
this._owner._changed(/*#=*/ Change.GEOMETRY);
},
/** /**
* @return {Matrix} a copy of this transform * @return {Matrix} a copy of this transform
*/ */
@ -136,6 +143,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
reset: function() { reset: function() {
this._a = this._d = 1; this._a = this._d = 1;
this._c = this._b = this._tx = this._ty = 0; this._c = this._b = this._tx = this._ty = 0;
this._changed();
return this; return this;
}, },
@ -171,6 +179,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
this._d *= scale.y; this._d *= scale.y;
if (center) if (center)
this.translate(center.negate()); this.translate(center.negate());
this._changed();
return this; return this;
}, },
@ -197,6 +206,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
y = point.y; y = point.y;
this._tx += x * this._a + y * this._b; this._tx += x * this._a + y * this._b;
this._ty += x * this._c + y * this._d; this._ty += x * this._c + y * this._d;
this._changed();
return this; return this;
}, },
@ -241,6 +251,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
this._d = -sin * c + cos * d; this._d = -sin * c + cos * d;
this._tx += tx * a + ty * b; this._tx += tx * a + ty * b;
this._ty += tx * c + ty * d; this._ty += tx * c + ty * d;
this._changed();
return this; return this;
}, },
@ -278,6 +289,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
this._d += point.x * c; this._d += point.x * c;
if (center) if (center)
this.translate(center.negate()); this.translate(center.negate());
this._changed();
return this; return this;
}, },
@ -298,6 +310,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
this._d = mx._b * c + mx._d * d; this._d = mx._b * c + mx._d * d;
this._tx += mx._tx * a + mx._ty * b; this._tx += mx._tx * a + mx._ty * b;
this._ty += mx._tx * c + mx._ty * d; this._ty += mx._tx * c + mx._ty * d;
this._changed();
return this; return this;
}, },
@ -320,6 +333,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
this._d = mx._c * b + mx._d * d; this._d = mx._c * b + mx._d * d;
this._tx = mx._a * tx + mx._b * ty + mx._tx; this._tx = mx._a * tx + mx._b * ty + mx._tx;
this._ty = mx._c * tx + mx._d * ty + mx._ty; this._ty = mx._c * tx + mx._d * ty + mx._ty;
this._changed();
return this; return this;
}, },
@ -327,8 +341,8 @@ var Matrix = Base.extend(/** @lends Matrix# */{
* @return {Boolean} whether this transform is the identity transform * @return {Boolean} whether this transform is the identity transform
*/ */
isIdentity: function() { isIdentity: function() {
return this._a == 1 && this._c == 0 && this._b == 0 && this._d == 1 return this._a === 1 && this._c === 0 && this._b === 0 && this._d === 1
&& this._tx == 0 && this._ty == 0; && this._tx === 0 && this._ty === 0;
}, },
/** /**
@ -386,7 +400,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
* A faster version of transform that only takes one point and does not * A faster version of transform that only takes one point and does not
* attempt to convert it. * attempt to convert it.
*/ */
_transformPoint: function(point, dest, dontNotify) { _transformPoint: function(point, dest, _dontNotify) {
var x = point.x, var x = point.x,
y = point.y; y = point.y;
if (!dest) if (!dest)
@ -394,7 +408,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
return dest.set( return dest.set(
x * this._a + y * this._b + this._tx, x * this._a + y * this._b + this._tx,
x * this._c + y * this._d + this._ty, x * this._c + y * this._d + this._ty,
dontNotify _dontNotify
); );
}, },
@ -425,7 +439,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
* point and finding the new bounding box to these points. This is not * point and finding the new bounding box to these points. This is not
* really the transformed reactangle! * really the transformed reactangle!
*/ */
_transformBounds: function(bounds, dest, dontNotify) { _transformBounds: function(bounds, dest, _dontNotify) {
var coords = this._transformCorners(bounds), var coords = this._transformCorners(bounds),
min = coords.slice(0, 2), min = coords.slice(0, 2),
max = coords.slice(); max = coords.slice();
@ -440,7 +454,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
if (!dest) if (!dest)
dest = new Rectangle(); dest = new Rectangle();
return dest.set(min[0], min[1], max[0] - min[0], max[1] - min[1], return dest.set(min[0], min[1], max[0] - min[0], max[1] - min[1],
dontNotify); _dontNotify);
}, },
/** /**
@ -463,7 +477,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
? det : null; ? det : null;
}, },
_inverseTransform: function(point, dest, dontNotify) { _inverseTransform: function(point, dest, _dontNotify) {
var det = this._getDeterminant(); var det = this._getDeterminant();
if (!det) if (!det)
return null; return null;
@ -474,7 +488,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
return dest.set( return dest.set(
(x * this._d - y * this._b) / det, (x * this._d - y * this._b) / det,
(y * this._a - x * this._c) / det, (y * this._a - x * this._c) / det,
dontNotify _dontNotify
); );
}, },
@ -659,6 +673,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{
}; };
this['set' + name] = function(value) { this['set' + name] = function(value) {
this[prop] = value; this[prop] = value;
this._changed();
}; };
}, {}); }, {});
}); });

View file

@ -932,10 +932,10 @@ var LinkedPoint = Point.extend({
this._setter = setter; this._setter = setter;
}, },
set: function(x, y, dontNotify) { set: function(x, y, _dontNotify) {
this._x = x; this._x = x;
this._y = y; this._y = y;
if (!dontNotify) if (!_dontNotify)
this._owner[this._setter](this); this._owner[this._setter](this);
return this; return this;
}, },

View file

@ -829,12 +829,12 @@ var LinkedRectangle = Rectangle.extend({
this._setter = setter; this._setter = setter;
}, },
set: function(x, y, width, height, dontNotify) { set: function(x, y, width, height, _dontNotify) {
this._x = x; this._x = x;
this._y = y; this._y = y;
this._width = width; this._width = width;
this._height = height; this._height = height;
if (!dontNotify) if (!_dontNotify)
this._owner[this._setter](this); this._owner[this._setter](this);
return this; return this;
} }

View file

@ -537,10 +537,10 @@ var LinkedSize = Size.extend({
this._setter = setter; this._setter = setter;
}, },
set: function(width, height, dontNotify) { set: function(width, height, _dontNotify) {
this._width = width; this._width = width;
this._height = height; this._height = height;
if (!dontNotify) if (!_dontNotify)
this._owner[this._setter](this); this._owner[this._setter](this);
return this; return this;
}, },

View file

@ -83,9 +83,10 @@ var Item = Base.extend(Callback, /** @lends Item# */{
} }
} }
this._style = new Style(this._project._currentStyle, this); this._style = new Style(this._project._currentStyle, this);
this._matrix = new Matrix(); var matrix = this._matrix = new Matrix();
if (point) if (point)
this._matrix.translate(point); matrix.translate(point);
matrix._owner = this;
return props ? this._set(props, { insert: true }) : true; return props ? this._set(props, { insert: true }) : true;
}, },

View file

@ -97,7 +97,7 @@ var View = Base.extend(Callback, /** @lends View# */{
// Link this id to our view // Link this id to our view
View._viewsById[this._id] = this; View._viewsById[this._id] = this;
this._viewSize = size; this._viewSize = size;
this._matrix = new Matrix(); (this._matrix = new Matrix())._owner = this;
this._zoom = 1; this._zoom = 1;
// Make sure the first view is focused for keyboard input straight away // Make sure the first view is focused for keyboard input straight away
if (!View._focused) if (!View._focused)
@ -256,6 +256,17 @@ var View = Base.extend(Callback, /** @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) {
if (flags & /*#=*/ ChangeFlag.APPEARANCE)
this._project._needsRedraw = true;
},
_transform: function(matrix) { _transform: function(matrix) {
this._matrix.concatenate(matrix); this._matrix.concatenate(matrix);
// Force recalculation of these values next time they are requested. // Force recalculation of these values next time they are requested.