BoundedZoomAction.java revision 1472:c18cbe5936b8
1/* 2 * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24package com.sun.hotspot.igv.util; 25 26import java.awt.Container; 27import java.awt.Dimension; 28import java.awt.Point; 29import java.awt.Rectangle; 30import javax.swing.JComponent; 31import javax.swing.JScrollPane; 32import org.netbeans.api.visual.action.WidgetAction; 33import org.netbeans.api.visual.action.WidgetAction.State; 34import org.netbeans.api.visual.action.WidgetAction.WidgetMouseWheelEvent; 35import org.netbeans.api.visual.animator.SceneAnimator; 36import org.netbeans.api.visual.widget.Scene; 37import org.netbeans.api.visual.widget.Widget; 38 39/** 40 * 41 * @author Thomas Wuerthinger 42 */ 43public class BoundedZoomAction extends WidgetAction.Adapter { 44 45 private double minFactor = 0.0; 46 private double maxFactor = Double.MAX_VALUE; 47 private double zoomMultiplier; 48 private boolean useAnimator; 49 50 public BoundedZoomAction(double zoomMultiplier, boolean useAnimator) { 51 this.zoomMultiplier = zoomMultiplier; 52 this.useAnimator = useAnimator; 53 } 54 55 public double getMinFactor() { 56 return minFactor; 57 } 58 59 public void setMinFactor(double d) { 60 minFactor = d; 61 } 62 63 public double getMaxFactor() { 64 return maxFactor; 65 } 66 67 public void setMaxFactor(double d) { 68 maxFactor = d; 69 } 70 71 private JScrollPane findScrollPane(JComponent component) { 72 for (;;) { 73 if (component == null) { 74 return null; 75 } 76 if (component instanceof JScrollPane) { 77 return ((JScrollPane) component); 78 } 79 Container parent = component.getParent(); 80 if (!(parent instanceof JComponent)) { 81 return null; 82 } 83 component = (JComponent) parent; 84 } 85 } 86 87 @Override 88 public State mouseWheelMoved(Widget widget, WidgetMouseWheelEvent event) { 89 final Scene scene = widget.getScene(); 90 int amount = event.getWheelRotation(); 91 JScrollPane scrollPane = findScrollPane(scene.getView()); 92 Point viewPosition = null; 93 Point mouseLocation = scene.convertSceneToView(event.getPoint()); 94 int xOffset = 0; 95 int yOffset = 0; 96 Point oldViewPosition = null; 97 Rectangle bounds = new Rectangle(scene.getBounds()); 98 Dimension componentSize = new Dimension(scene.getView().getPreferredSize()); 99 100 if (scrollPane != null) { 101 viewPosition = new Point(scrollPane.getViewport().getViewPosition()); 102 oldViewPosition = new Point(viewPosition); 103 xOffset = (mouseLocation.x - viewPosition.x); 104 yOffset = (mouseLocation.y - viewPosition.y); 105 viewPosition.x += xOffset; 106 viewPosition.y += yOffset; 107 } 108 109 if (useAnimator) { 110 SceneAnimator sceneAnimator = scene.getSceneAnimator(); 111 synchronized (sceneAnimator) { 112 double zoom = sceneAnimator.isAnimatingZoomFactor() ? sceneAnimator.getTargetZoomFactor() : scene.getZoomFactor(); 113 while (amount > 0 && zoom / zoomMultiplier >= minFactor && zoom / zoomMultiplier <= maxFactor) { 114 zoom /= zoomMultiplier; 115 if (viewPosition != null) { 116 viewPosition.x /= zoomMultiplier; 117 viewPosition.y /= zoomMultiplier; 118 bounds.width /= zoomMultiplier; 119 bounds.height /= zoomMultiplier; 120 componentSize.width /= zoomMultiplier; 121 componentSize.height /= zoomMultiplier; 122 } 123 amount--; 124 } 125 while (amount < 0 && zoom * zoomMultiplier >= minFactor && zoom * zoomMultiplier <= maxFactor) { 126 zoom *= zoomMultiplier; 127 if (viewPosition != null) { 128 viewPosition.x *= zoomMultiplier; 129 viewPosition.y *= zoomMultiplier; 130 bounds.width *= zoomMultiplier; 131 bounds.height *= zoomMultiplier; 132 componentSize.width *= zoomMultiplier; 133 componentSize.height *= zoomMultiplier; 134 } 135 amount++; 136 } 137 sceneAnimator.animateZoomFactor(zoom); 138 } 139 } else { 140 double zoom = scene.getZoomFactor(); 141 while (amount > 0 && zoom / zoomMultiplier >= minFactor && zoom / zoomMultiplier <= maxFactor) { 142 zoom /= zoomMultiplier; 143 if (viewPosition != null) { 144 viewPosition.x /= zoomMultiplier; 145 viewPosition.y /= zoomMultiplier; 146 bounds.width /= zoomMultiplier; 147 bounds.height /= zoomMultiplier; 148 componentSize.width /= zoomMultiplier; 149 componentSize.height /= zoomMultiplier; 150 } 151 amount--; 152 } 153 while (amount < 0 && zoom * zoomMultiplier >= minFactor && zoom * zoomMultiplier <= maxFactor) { 154 zoom *= zoomMultiplier; 155 if (viewPosition != null) { 156 viewPosition.x *= zoomMultiplier; 157 viewPosition.y *= zoomMultiplier; 158 bounds.width *= zoomMultiplier; 159 bounds.height *= zoomMultiplier; 160 componentSize.width *= zoomMultiplier; 161 componentSize.height *= zoomMultiplier; 162 } 163 amount++; 164 } 165 scene.setZoomFactor(zoom); 166 } 167 168 if (scrollPane != null) { 169 scene.validate(); // Call validate to update size of scene 170 Dimension size = scrollPane.getViewport().getExtentSize(); 171 viewPosition.x -= xOffset; 172 viewPosition.y -= yOffset; 173 scene.resolveBounds(scene.getLocation(), bounds); 174 scene.getView().setPreferredSize(componentSize); 175 scene.getView().revalidate(); 176 scene.getView().addNotify(); 177 scrollPane.getViewport().setViewPosition(viewPosition); 178 } 179 180 return WidgetAction.State.CONSUMED; 181 } 182} 183