Reflect View#zoom through matrix decomposition, and implement additional decomposed properties.

Closes #1107
This commit is contained in:
Jürg Lehni 2016-07-20 00:04:24 +02:00
parent 4d9c0c9f05
commit f874b927bf
2 changed files with 112 additions and 62 deletions

View file

@ -779,13 +779,11 @@ new function() { // Injection scope for various item event handlers
* @type Point * @type Point
* @default null * @default null
*/ */
getPivot: function(_dontLink) { getPivot: function() {
var pivot = this._pivot; var pivot = this._pivot;
if (pivot) { return pivot
var ctor = _dontLink ? Point : LinkedPoint; ? new LinkedPoint(pivot.x, pivot.y, this, 'setPivot')
pivot = new ctor(pivot.x, pivot.y, this, 'setPivot'); : null;
}
return pivot;
}, },
setPivot: function(/* point */) { setPivot: function(/* point */) {
@ -1088,11 +1086,12 @@ new function() { // Injection scope for various item event handlers
* @bean * @bean
* @type Point * @type Point
*/ */
getScaling: function(_dontLink) { getScaling: function() {
var decomposed = this._decompose(), var decomposed = this._decompose(),
scaling = decomposed && decomposed.scaling, scaling = decomposed && decomposed.scaling;
ctor = _dontLink ? Point : LinkedPoint; return scaling
return scaling && new ctor(scaling.x, scaling.y, this, 'setScaling'); ? new LinkedPoint(scaling.x, scaling.y, this, 'setScaling')
: undefined;
}, },
setScaling: function(/* scaling */) { setScaling: function(/* scaling */) {

View file

@ -107,7 +107,6 @@ var View = Base.extend(Emitter, /** @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._matrix = new Matrix())._owner = this; (this._matrix = new Matrix())._owner = this;
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)
View._focused = this; View._focused = this;
@ -331,7 +330,7 @@ var View = Base.extend(Emitter, /** @lends View# */{
// one thing: // one thing:
this._project._changed(/*#=*/Change.VIEW); this._project._changed(/*#=*/Change.VIEW);
// Force recalculation of these values next time they are requested. // Force recalculation of these values next time they are requested.
this._bounds = null; this._bounds = this._decomposed = undefined;
}, },
/** /**
@ -436,56 +435,6 @@ var View = Base.extend(Emitter, /** @lends View# */{
return this.getBounds().getSize(); return this.getBounds().getSize();
}, },
/**
* The center of the visible area in project coordinates.
*
* @bean
* @type Point
*/
getCenter: function() {
return this.getBounds().getCenter();
},
setCenter: function(/* center */) {
var center = Point.read(arguments);
this.translate(this.getCenter().subtract(center));
},
/**
* The zoom factor by which the project coordinates are magnified.
*
* @bean
* @type Number
*/
getZoom: function() {
return this._zoom;
},
setZoom: function(zoom) {
this.transform(new Matrix().scale(zoom / this._zoom,
this.getCenter()));
this._zoom = zoom;
},
/**
* The view's transformation matrix, defining the view onto the project's
* contents (position, zoom level, rotation, etc).
*
* @bean
* @type Matrix
*/
getMatrix: function() {
return this._matrix;
},
setMatrix: function() {
// Use Matrix#initialize to easily copy over values.
// NOTE: calling initialize() also calls #_changed() for us, through its
// call to #set() / #reset(), and this also handles _applyMatrix for us.
var matrix = this._matrix;
matrix.initialize.apply(matrix, arguments);
},
/** /**
* Checks whether the view is currently visible within the current browser * Checks whether the view is currently visible within the current browser
* viewport. * viewport.
@ -539,6 +488,10 @@ var View = Base.extend(Emitter, /** @lends View# */{
center || this.getCenter(true))); center || this.getCenter(true)));
}; };
}, /** @lends View# */{ }, /** @lends View# */{
_decompose: function() {
return this._decomposed || (this._decomposed = this._matrix.decompose());
},
/** /**
* {@grouptitle Transform Functions} * {@grouptitle Transform Functions}
* *
@ -551,6 +504,104 @@ var View = Base.extend(Emitter, /** @lends View# */{
return this.transform(mx.translate.apply(mx, arguments)); return this.transform(mx.translate.apply(mx, arguments));
}, },
/**
* The center of the visible area in project coordinates.
*
* @bean
* @type Point
*/
getCenter: function() {
return this.getBounds().getCenter();
},
setCenter: function(/* center */) {
var center = Point.read(arguments);
this.translate(this.getCenter().subtract(center));
},
/**
* The view's zoom factor by which the project coordinates are magnified.
*
* @bean
* @type Number
* @see #getScaling()
*/
getZoom: function() {
var decomposed = this._decompose(),
scaling = decomposed && decomposed.scaling;
// Use average since it can be non-uniform, and return 0 when it can't
// be decomposed.
return scaling ? (scaling.x + scaling.y) / 2 : 0;
},
setZoom: function(zoom) {
this.transform(new Matrix().scale(zoom / this.getZoom(),
this.getCenter()));
},
/**
* The current rotation angle of the view, as described by its
* {@link #matrix}.
*
* @bean
* @type Number
*/
getRotation: function() {
var decomposed = this._decompose();
return decomposed && decomposed.rotation;
},
setRotation: function(rotation) {
var current = this.getRotation();
if (current != null && rotation != null) {
this.rotate(rotation - current);
}
},
/**
* The current scale factor of the view, as described by its
* {@link #matrix}.
*
* @bean
* @type Point
* @see #getZoom()
*/
getScaling: function() {
var decomposed = this._decompose(),
scaling = decomposed && decomposed.scaling;
return scaling
? new LinkedPoint(scaling.x, scaling.y, this, 'setScaling')
: undefined;
},
setScaling: function(/* scaling */) {
var current = this.getScaling(),
// Clone existing points since we're caching internally.
scaling = Point.read(arguments, 0, { clone: true, readNull: true });
if (current && scaling) {
this.scale(scaling.x / current.x, scaling.y / current.y);
}
},
/**
* The view's transformation matrix, defining the view onto the project's
* contents (position, zoom level, rotation, etc).
*
* @bean
* @type Matrix
*/
getMatrix: function() {
return this._matrix;
},
setMatrix: function() {
// Use Matrix#initialize to easily copy over values.
// NOTE: calling initialize() also calls #_changed() for us, through its
// call to #set() / #reset(), and this also handles _applyMatrix for us.
var matrix = this._matrix;
matrix.initialize.apply(matrix, arguments);
},
/** /**
* Rotates the view by a given angle around the given center point. * Rotates the view by a given angle around the given center point.
* *