001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.swing.gvt;
020:
021: import java.awt.BasicStroke;
022: import java.awt.Color;
023: import java.awt.Dimension;
024: import java.awt.Graphics;
025: import java.awt.Graphics2D;
026: import java.awt.event.InputEvent;
027: import java.awt.event.MouseEvent;
028: import java.awt.geom.AffineTransform;
029: import java.awt.geom.Line2D;
030:
031: /**
032: * This class represents a zoom interactor.
033: * To use it, just redefine the {@link
034: * InteractorAdapter#startInteraction(InputEvent)} method.
035: *
036: * @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
037: * @version $Id: AbstractZoomInteractor.java 475477 2006-11-15 22:44:28Z cam $
038: */
039: public class AbstractZoomInteractor extends InteractorAdapter {
040:
041: /**
042: * Whether the interactor has finished.
043: */
044: protected boolean finished = true;
045:
046: /**
047: * The mouse x start position.
048: */
049: protected int xStart;
050:
051: /**
052: * The mouse y start position.
053: */
054: protected int yStart;
055:
056: /**
057: * The mouse x current position.
058: */
059: protected int xCurrent;
060:
061: /**
062: * The mouse y current position.
063: */
064: protected int yCurrent;
065:
066: /**
067: * The zoom marker top line.
068: */
069: protected Line2D markerTop;
070:
071: /**
072: * The zoom marker left line.
073: */
074: protected Line2D markerLeft;
075:
076: /**
077: * The zoom marker bottom line.
078: */
079: protected Line2D markerBottom;
080:
081: /**
082: * The zoom marker right line.
083: */
084: protected Line2D markerRight;
085:
086: /**
087: * The overlay.
088: */
089: protected Overlay overlay = new ZoomOverlay();
090:
091: /**
092: * Used to draw marker
093: */
094: protected BasicStroke markerStroke = new BasicStroke(1,
095: BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10,
096: new float[] { 4, 4 }, 0);
097:
098: /**
099: * Tells whether the interactor has finished.
100: */
101: public boolean endInteraction() {
102: return finished;
103: }
104:
105: // MouseListener ///////////////////////////////////////////////////////
106:
107: /**
108: * Invoked when a mouse button has been pressed on a component.
109: */
110: public void mousePressed(MouseEvent e) {
111: if (!finished) {
112: mouseExited(e);
113: return;
114: }
115:
116: finished = false;
117: markerTop = null;
118: markerLeft = null;
119: markerBottom = null;
120: markerRight = null;
121:
122: xStart = e.getX();
123: yStart = e.getY();
124: JGVTComponent c = (JGVTComponent) e.getSource();
125: c.getOverlays().add(overlay);
126: }
127:
128: /**
129: * Invoked when a mouse button has been released on a component.
130: */
131: public void mouseReleased(MouseEvent e) {
132: finished = true;
133: JGVTComponent c = (JGVTComponent) e.getSource();
134: c.getOverlays().remove(overlay);
135: overlay.paint(c.getGraphics());
136:
137: xCurrent = e.getX();
138: yCurrent = e.getY();
139:
140: if ((xCurrent - xStart) != 0 && (yCurrent - yStart) != 0) {
141:
142: int dx = xCurrent - xStart;
143: int dy = yCurrent - yStart;
144:
145: if (dx < 0) {
146: dx = -dx;
147: xStart = xCurrent;
148: }
149: if (dy < 0) {
150: dy = -dy;
151: yStart = yCurrent;
152: }
153:
154: Dimension size = c.getSize();
155:
156: // Zoom factor
157: float scaleX = size.width / (float) dx;
158: float scaleY = size.height / (float) dy;
159: float scale = (scaleX < scaleY) ? scaleX : scaleY;
160:
161: // Zoom translate
162: AffineTransform at = new AffineTransform();
163: at.scale(scale, scale);
164: at.translate(-xStart, -yStart);
165:
166: at.concatenate(c.getRenderingTransform());
167: c.setRenderingTransform(at);
168: }
169: }
170:
171: /**
172: * Invoked when the mouse exits a component.
173: */
174: public void mouseExited(MouseEvent e) {
175: finished = true;
176: JGVTComponent c = (JGVTComponent) e.getSource();
177: c.getOverlays().remove(overlay);
178: overlay.paint(c.getGraphics());
179: }
180:
181: // MouseMotionListener /////////////////////////////////////////////////
182:
183: /**
184: * Invoked when a mouse button is pressed on a component and then
185: * dragged. Mouse drag events will continue to be delivered to
186: * the component where the first originated until the mouse button is
187: * released (regardless of whether the mouse position is within the
188: * bounds of the component).
189: */
190: public void mouseDragged(MouseEvent e) {
191: JGVTComponent c = (JGVTComponent) e.getSource();
192:
193: overlay.paint(c.getGraphics());
194:
195: xCurrent = e.getX();
196: yCurrent = e.getY();
197:
198: // Constrain rectangle to window's Aspect Ratio.
199: float xMin, yMin, width, height;
200: if (xStart < xCurrent) {
201: xMin = xStart;
202: width = xCurrent - xStart;
203: } else {
204: xMin = xCurrent;
205: width = xStart - xCurrent;
206: }
207: if (yStart < yCurrent) {
208: yMin = yStart;
209: height = yCurrent - yStart;
210: } else {
211: yMin = yCurrent;
212: height = yStart - yCurrent;
213: }
214: Dimension d = c.getSize();
215: float compAR = d.width / (float) d.height;
216: if (compAR > width / height) {
217: width = compAR * height;
218: } else {
219: height = width / compAR;
220: }
221:
222: markerTop = new Line2D.Float(xMin, yMin, xMin + width, yMin);
223: markerLeft = new Line2D.Float(xMin, yMin, xMin, yMin + height);
224: markerBottom = new Line2D.Float(xMin, yMin + height, xMin
225: + width, yMin + height);
226: markerRight = new Line2D.Float(xMin + width, yMin,
227: xMin + width, yMin + height);
228:
229: overlay.paint(c.getGraphics());
230: }
231:
232: /**
233: * To paint the interactor.
234: */
235: protected class ZoomOverlay implements Overlay {
236:
237: /**
238: * Paints this overlay.
239: */
240: public void paint(Graphics g) {
241: if (markerTop != null) {
242: Graphics2D g2d = (Graphics2D) g;
243:
244: g2d.setXORMode(Color.white);
245: g2d.setColor(Color.black);
246: g2d.setStroke(markerStroke);
247:
248: g2d.draw(markerTop);
249: g2d.draw(markerLeft);
250: g2d.draw(markerBottom);
251: g2d.draw(markerRight);
252: }
253: }
254: }
255: }
|