blob: 667a09f85fe41dfe74ba6d4816503cd933ec56af [file] [log] [blame]
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package com.sun.hotspot.igv.view;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.action.WidgetAction.State;
import org.netbeans.api.visual.action.WidgetAction.WidgetMouseWheelEvent;
import org.netbeans.api.visual.animator.SceneAnimator;
import org.netbeans.api.visual.widget.Scene;
import org.netbeans.api.visual.widget.Widget;
/**
*
* @author Thomas Wuerthinger
*/
public class BoundedZoomAction extends WidgetAction.Adapter {
private double minFactor = 0.0;
private double maxFactor = Double.MAX_VALUE;
private double zoomMultiplier;
private boolean useAnimator;
public BoundedZoomAction(double zoomMultiplier, boolean useAnimator) {
assert zoomMultiplier > 1.0;
this.zoomMultiplier = zoomMultiplier;
this.useAnimator = useAnimator;
}
public double getMinFactor() {
return minFactor;
}
public void setMinFactor(double d) {
minFactor = d;
}
public double getMaxFactor() {
return maxFactor;
}
public void setMaxFactor(double d) {
maxFactor = d;
}
private JScrollPane findScrollPane(JComponent component) {
for (;;) {
if (component == null) {
return null;
}
if (component instanceof JScrollPane) {
return ((JScrollPane) component);
}
Container parent = component.getParent();
if (!(parent instanceof JComponent)) {
return null;
}
component = (JComponent) parent;
}
}
@Override
public State mouseWheelMoved(Widget widget, WidgetMouseWheelEvent event) {
final Scene scene = widget.getScene();
int amount = event.getWheelRotation();
JScrollPane scrollPane = findScrollPane(scene.getView());
Point viewPosition = null;
Point mouseLocation = scene.convertSceneToView(event.getPoint());
int xOffset = 0;
int yOffset = 0;
Rectangle bounds = new Rectangle(scene.getBounds());
Dimension componentSize = new Dimension(scene.getView().getPreferredSize());
if (scrollPane != null) {
viewPosition = new Point(scrollPane.getViewport().getViewPosition());
xOffset = (mouseLocation.x - viewPosition.x);
yOffset = (mouseLocation.y - viewPosition.y);
viewPosition.x += xOffset;
viewPosition.y += yOffset;
}
if (useAnimator) {
SceneAnimator sceneAnimator = scene.getSceneAnimator();
synchronized (sceneAnimator) {
double zoom = sceneAnimator.isAnimatingZoomFactor() ? sceneAnimator.getTargetZoomFactor() : scene.getZoomFactor();
while (amount > 0 && zoom / zoomMultiplier >= minFactor) {
zoom /= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x /= zoomMultiplier;
viewPosition.y /= zoomMultiplier;
bounds.width /= zoomMultiplier;
bounds.height /= zoomMultiplier;
componentSize.width /= zoomMultiplier;
componentSize.height /= zoomMultiplier;
}
amount--;
}
while (amount < 0 && zoom * zoomMultiplier <= maxFactor) {
zoom *= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x *= zoomMultiplier;
viewPosition.y *= zoomMultiplier;
bounds.width *= zoomMultiplier;
bounds.height *= zoomMultiplier;
componentSize.width *= zoomMultiplier;
componentSize.height *= zoomMultiplier;
}
amount++;
}
sceneAnimator.animateZoomFactor(zoom);
}
} else {
double zoom = scene.getZoomFactor();
while (amount > 0 && zoom / zoomMultiplier >= minFactor) {
zoom /= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x /= zoomMultiplier;
viewPosition.y /= zoomMultiplier;
bounds.width /= zoomMultiplier;
bounds.height /= zoomMultiplier;
componentSize.width /= zoomMultiplier;
componentSize.height /= zoomMultiplier;
}
amount--;
}
while (amount < 0 && zoom * zoomMultiplier <= maxFactor) {
zoom *= zoomMultiplier;
if (viewPosition != null) {
viewPosition.x *= zoomMultiplier;
viewPosition.y *= zoomMultiplier;
bounds.width *= zoomMultiplier;
bounds.height *= zoomMultiplier;
componentSize.width *= zoomMultiplier;
componentSize.height *= zoomMultiplier;
}
amount++;
}
scene.setZoomFactor(zoom);
}
if (scrollPane != null) {
viewPosition.x -= xOffset;
viewPosition.y -= yOffset;
scrollPane.getViewport().setViewPosition(viewPosition);
}
return WidgetAction.State.CONSUMED;
}
}