001: package com.xoetrope.svg;
002:
003: import com.kitfox.svg.SVGDiagram;
004: import com.kitfox.svg.SVGRoot;
005: import com.kitfox.svg.animation.AnimationElement;
006: import com.xoetrope.carousel.build.BuildProperties;
007: import java.awt.Component;
008: import java.awt.Cursor;
009: import java.awt.Graphics2D;
010: import java.awt.Image;
011: import java.awt.Point;
012: import java.awt.RenderingHints;
013: import java.awt.Toolkit;
014: import java.awt.event.MouseEvent;
015: import java.awt.event.MouseListener;
016: import java.awt.event.MouseMotionListener;
017: import java.awt.image.BufferedImage;
018: import java.beans.PropertyChangeEvent;
019: import java.beans.PropertyChangeListener;
020: import java.text.DecimalFormat;
021: import java.text.NumberFormat;
022: import javax.imageio.ImageIO;
023: import javax.swing.SwingUtilities;
024:
025: /**
026: *
027: *
028: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
029: * the GNU Public License (GPL), please see license.txt for more details. If
030: * you make commercial use of this software you must purchase a commercial
031: * license from Xoetrope.</p>
032: * <p> $Revision: 1.2 $</p>
033: */
034: public class XGrabMap implements MouseListener, MouseMotionListener {
035: protected XSvgImageMap imageMap;
036: protected BufferedImage buffer;
037: protected double x, y, dragX, dragY, startX, startY, offsetX,
038: offsetY, previousWidth, previousHeight;
039: protected int previousW, previousH;
040: protected String previousId;
041: protected XPointSystem pointSystem;
042: protected Cursor handOpen, handClosed;
043: protected Component glassPane;
044: protected boolean first, running, enabled, tilingEnabled,
045: hideComponents;
046: protected NumberFormat formatter;
047:
048: protected BufferedImage[] images;
049: protected XRenderingSemaphore semaphore;
050:
051: /**
052: * Creates a new instance of XGrabMap
053: */
054: public XGrabMap(XSvgImageMap iMap) {
055: imageMap = iMap;
056: imageMap.addMouseListener(this );
057: imageMap.addMouseMotionListener(this );
058: pointSystem = new XPointSystem(imageMap);
059: formatter = new DecimalFormat(".00000");
060: images = new BufferedImage[8];
061: semaphore = imageMap.getSemaphore();
062: tilingEnabled = false;
063:
064: Toolkit toolkit = Toolkit.getDefaultToolkit();
065: try {
066: Image image1 = ImageIO.read(XGrabMap.class
067: .getResource("images/handOpen.gif"));
068: Image image2 = ImageIO.read(XGrabMap.class
069: .getResource("images/handClosed.gif"));
070:
071: handOpen = toolkit.createCustomCursor(image1, new Point(15,
072: 15), "handOpen");
073: handClosed = toolkit.createCustomCursor(image2, new Point(
074: 15, 15), "handOpen");
075: } catch (Exception ex) {
076: if (BuildProperties.DEBUG)
077: ex.printStackTrace();
078: }
079:
080: first = true;
081: enabled = true;
082:
083: imageMap
084: .addPropertyChangeListener(new PropertyChangeListener() {
085: public void propertyChange(PropertyChangeEvent evt) {
086: if (imageMap != null) {
087: SVGDiagram diagram = imageMap
088: .getSvgDiagram();
089: if (diagram != null) {
090: SVGRoot root = diagram.getRoot();
091: double[] attr = root.getPresAbsolute(
092: "viewBox").getDoubleList();
093:
094: previousWidth = attr[2];
095: previousHeight = attr[3];
096: previousId = root.getId();
097:
098: buffer = imageMap.getBufferedImage();
099: offsetX = attr[0];
100: offsetY = attr[1];
101:
102: x = 0;
103: y = 0;
104:
105: if (tilingEnabled) {
106: createAuxilaryImages();
107: }
108: }
109: }
110: }
111: });
112: }
113:
114: /**
115: * Sets the glass pane component so that the cursor can be changed on the glasspane.
116: * @param glassPane the passed glass pane <CODE>Component</CODE>
117: */
118: public void setGlassPane(Component glassPane) {
119: this .glassPane = glassPane;
120: }
121:
122: /**
123: * Fired when the mouse enters the imageMap.
124: * @param e the passed <CODE>MouseEvent</CODE>.
125: */
126: public void mouseEntered(MouseEvent e) {
127: if (enabled) {
128: setCursor(handOpen);
129: }
130: }
131:
132: /**
133: * Fired when the mouse exits the imageMap.
134: * @param e the passed <CODE>MouseEvent</CODE>.
135: */
136: public void mouseExited(MouseEvent e) {
137: if (enabled) {
138: setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
139: }
140: }
141:
142: /**
143: * Fired when the mouse is dragged on the imageMap.
144: * @param e the passed <CODE>MouseEvent</CODE>.
145: */
146: public void mouseDragged(MouseEvent e) {
147: if (enabled && ((e.getModifiers() & e.CTRL_MASK) == 0)) {
148: if (glassPane != null && hideComponents) {
149: glassPane.setVisible(false);
150: }
151:
152: x = ((double) e.getX() - dragX) + startX;
153: y = ((double) e.getY() - dragY) + startY;
154:
155: imageMap.setImageLocation((int) x, (int) y);
156: imageMap.repaint(500);
157:
158: setCursor(handClosed);
159: }
160: }
161:
162: /**
163: * Fired when the mouse is pressed on the imageMap.
164: * @param e the passed <CODE>MouseEvent</CODE>.
165: */
166: public void mousePressed(MouseEvent e) {
167: if (enabled && ((e.getModifiers() & e.CTRL_MASK) == 0)) {
168: running = true;
169: startX = x;
170: startY = y;
171:
172: imageMap.setImage(buffer);
173: dragX = (double) e.getX();
174: dragY = (double) e.getY();
175:
176: setCursor(handClosed);
177: imageMap.setDrawAuxImages(true);
178: }
179: }
180:
181: /**
182: * Fired when the mouse is released on the imageMap.
183: * @param e the passed <CODE>MouseEvent</CODE>.
184: */
185: public void mouseReleased(MouseEvent e) {
186: if (enabled && ((e.getModifiers() & e.CTRL_MASK) == 0)) {
187: SVGRoot root = imageMap.getSvgDiagram().getRoot();
188: double[] attr = root.getPresAbsolute("viewBox")
189: .getDoubleList();
190:
191: double scaleX = (x * (attr[2] / (double) root
192: .getDeviceWidth()))
193: - offsetX;
194: double scaleY = (y * (attr[3] / (double) root
195: .getDeviceHeight()))
196: - offsetY;
197:
198: try {
199: String viewBox = formatter.format(-scaleX) + " "
200: + formatter.format(-scaleY) + " "
201: + formatter.format(attr[2]) + " "
202: + formatter.format(attr[3]);
203:
204: root.setAttribute("viewBox", AnimationElement.AT_XML,
205: viewBox);
206: root.build();
207: imageMap.resetBuffer();
208: imageMap.repaint();
209: imageMap.notifyListeners();
210:
211: imageMap.setPanCoords(-scaleX, -scaleY);
212: imageMap.setDrawAuxImages(false);
213: } catch (Exception ex) {
214: if (BuildProperties.DEBUG)
215: ex.printStackTrace();
216: }
217:
218: if (glassPane != null && hideComponents) {
219: glassPane.setVisible(true);
220: }
221:
222: setCursor(handOpen);
223: }
224: }
225:
226: public void mouseClicked(MouseEvent e) {
227: }
228:
229: /**
230: * Fired when the mouse is moved on the imageMap.
231: * @param e the passed <CODE>MouseEvent</CODE>.
232: */
233: public void mouseMoved(MouseEvent e) {
234: if (enabled) {
235: if (first) {
236: mouseEntered(e);
237: first = false;
238: }
239: }
240: }
241:
242: /**
243: * returns true if a drag event is in progress.
244: * @return the returned <CODE>boolean</CODE>.
245: */
246: public boolean isRunning() {
247: return running;
248: }
249:
250: public void disable() {
251: enabled = false;
252:
253: imageMap.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
254: if (glassPane != null) {
255: glassPane.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
256: }
257: }
258:
259: /**
260: * Enable usage of the grab map;
261: */
262: public void enable() {
263: enabled = true;
264: }
265:
266: public void hideComponents(boolean b) {
267: hideComponents = b;
268: }
269:
270: /**
271: * Set the mouse cursor type.
272: * @param cursor <CODE>Cursor</CODE> object representing the cursor to be used.
273: */
274: private void setCursor(Cursor cursor) {
275: try {
276: if (cursor != null) {
277: if (glassPane == null || !glassPane.isVisible()) {
278: imageMap.setCursor(cursor);
279: } else {
280: glassPane.setCursor(cursor);
281: imageMap.setCursor(cursor);
282: }
283: }
284: } catch (Exception ex) {
285: if (BuildProperties.DEBUG)
286: ex.printStackTrace();
287: }
288: }
289:
290: /**
291: * Enable usage of tiling, i.e drawing of the off-screen sections of the image while dragging.
292: * @param b <CODE>boolean</CODE> specifying whether tiling is to be used or not
293: */
294: public void setTilingEnabled(boolean b) {
295: tilingEnabled = b;
296: }
297:
298: /**
299: * Method used within this class to render the off-screen regions of the svg image.
300: * These off-screen regions are displayed if tiling is enabled.
301: */
302: private void createAuxilaryImages() {
303: try {
304: SVGRoot root = imageMap.getSvgDiagram().getRoot();
305: double[] attr = root.getPresAbsolute("viewBox")
306: .getDoubleList();
307:
308: int width = imageMap.getWidth();
309: int height = imageMap.getHeight();
310: int halfWidth = imageMap.getWidth() / 2;
311: int halfHeight = imageMap.getHeight() / 2;
312:
313: for (int i = 0; i < images.length; i++) {
314: // images[ i ] = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB );
315:
316: if (i == 1 || i == 6) {
317: images[i] = new BufferedImage(width, halfHeight,
318: BufferedImage.TYPE_INT_ARGB);
319: } else if (i == 3 || i == 4) {
320: images[i] = new BufferedImage(halfWidth, height,
321: BufferedImage.TYPE_INT_ARGB);
322: } else {
323: images[i] = new BufferedImage(halfWidth,
324: halfHeight, BufferedImage.TYPE_INT_ARGB);
325: }
326:
327: Graphics2D buffer = images[i].createGraphics();
328: imageMap.getSvgDiagram().setIgnoringClipHeuristic(true);
329: // buffer.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
330:
331: if (i == 0) // top left
332: buffer.translate(halfWidth, halfHeight);
333: else if (i == 1) // top centre
334: buffer.translate(0, halfHeight);
335: else if (i == 2) // top right
336: buffer.translate(-width, halfHeight);
337: else if (i == 3) // centre left
338: buffer.translate(halfWidth, 0);
339: else if (i == 4) // centre right
340: buffer.translate(-width, 0);
341: else if (i == 5) // bottom left
342: buffer.translate(halfWidth, -height);
343: else if (i == 6) // bottom centre
344: buffer.translate(0, -height);
345: else if (i == 7) // bottom right
346: buffer.translate(-width, -height);
347:
348: root.render(buffer);
349: buffer.dispose();
350: }
351:
352: previousW = imageMap.getWidth();
353: previousH = imageMap.getHeight();
354:
355: imageMap.setAuxilaryImages(images);
356: } catch (Exception ex) {
357: if (BuildProperties.DEBUG)
358: ex.printStackTrace();
359: }
360: }
361: }
|