/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.gef;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
/**
* @author Brian Sun
*/
public class ZoomManager extends ZoomObject {
private double max;
private double min;
private double scale = 1;
public ZoomManager() {
this(0.5d, 2.0d);
}
public ZoomManager(double min, double max) {
this.min = min;
this.max = max;
}
public void setConstraints(double min, double max) {
this.min = min;
this.max = max;
setScale(getScale());
}
public double getScale() {
return scale;
}
public void setScale(double scale) {
scale = Math.min(getMax(), Math.max(getMin(), scale));
internalSetScale(scale);
}
private void internalSetScale(double scale) {
double oldScale = getScale();
if (scale == oldScale)
return;
this.scale = scale;
fireScaleChanged(oldScale, getScale());
}
public void zoomIn() {
double scale = getScale();
if (scale >= 1 && scale < 1.2) {
scale = forceMultiple(scale + 0.2, 0.2);
} else if (scale < 1) {
scale = Math.min(1.0, forceMultiple(scale + 0.1, 0.1));
} else {
scale = forceMultiple(scale + 0.5, 0.5);
}
setScale(scale);
}
public void zoomOut() {
double scale = getScale();
if (scale <= 1) {
scale = forceMultiple(scale + 0.09, 0.1) - 0.1;
} else if (scale > 1 && scale <= 1.2) {
scale = forceMultiple(scale + 0.19, 0.2) - 0.2;
} else {
scale = Math.max(1.2, forceMultiple(scale + 0.49, 0.5) - 0.5);
}
setScale(scale);
}
private static double forceMultiple(double a, double m) {
int x = (int) Math.round(a * 100);
int y = (int) Math.round(m * 100);
int d = x / y;
double tmp = d * m;
tmp = ((int) (tmp * 100)) / 100.0;
return tmp;
}
public void actualSize() {
setScale(1.0);
}
public double getMax() {
return max;
}
public double getMin() {
return min;
}
public void fitScale(Dimension box, Dimension client) {
fitScale(box, client, -1, -1);
}
private double calculateFitScale(Dimension box, Dimension client) {
return Math.min(box.width * 1.0 / client.width, box.height * 1.0
/ client.height);
}
public void fitScale(Dimension box, Dimension client, double min, double max) {
double scale = calculateFitScale(box, client);
if (min > max) {
double t = max;
max = min;
min = t;
}
if (min > 0 && scale < min) {
if (getScale() > min)
scale = getScale();
else
scale = min;
}
if (max > 0 && scale > max) {
if (getScale() < max)
scale = getScale();
else
scale = max;
}
setScale(scale);
}
public Dimension getScaled(Dimension d) {
return d.getScaled(getScale());
}
public Point getScaled(Point p) {
return p.getScaled(getScale());
}
public Rectangle getScaled(Rectangle r) {
return r.getCopy().scale(getScale());
}
public Dimension getAntiScaled(Dimension d) {
return d.getScaled(1 / getScale());
}
public Point getAntiScaled(Point p) {
return p.getScaled(1 / getScale());
}
public Rectangle getAntiScaled(Rectangle r) {
return r.getCopy().scale(1 / getScale());
}
}