package app.navigps.gui.svgComponents; import app.navigps.gui.NaviRootWindow; import app.navigps.gui.searchServices.SearchServices; import app.navigps.gui.svgComponents.DisplayObjects.AbstractDisplayManager; import app.navigps.gui.svgComponents.DisplayObjects.ComponentDisplayManager; import app.config.SVGConfiguration; import java.awt.BorderLayout; import java.awt.Cursor; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.InputEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.util.LinkedList; import javax.swing.AbstractAction; import javax.swing.KeyStroke; import org.apache.batik.dom.svg.SVGOMPoint; import org.apache.batik.swing.JSVGCanvas; import org.w3c.dom.Node; import org.w3c.dom.svg.SVGLocatable; import org.w3c.dom.svg.SVGMatrix; import org.w3c.dom.svg.SVGPoint; /** * * @author vara */ /* important "Rendering Process" * * The rendering process can be broken down into five phases. * Not all of those steps are required - depending on the method used to specify * the SVG document to display, but basically the steps in the rendering process are: * * --Building a DOM tree * If the loadSVGDocument(String) method is used, the SVG file is parsed * and an SVG DOM Tree is built. * * --Building a GVT tree * Once an SVGDocument is created (using the step 1 or if the setSVGDocument(SVGDocument) * method has been used) - a GVT tree is constructed. * The GVT tree is the data structure used internally to render an SVG document. * see the org.apache.batik.gvt package. * * --Executing the SVGLoad event handlers * If the document is dynamic, the scripts are initialized and the SVGLoad * event is dispatched before the initial rendering. * * --Rendering the GVT tree * Then the GVT tree is rendered. see the org.apache.batik.gvt.renderer package. * * --Running the document * If the document is dynamic, the update threads are started. */ public class Canvas extends JSVGCanvas{ private SVGConfiguration svgConfig = new SVGConfiguration(); private SVGBridgeComponents listeners = NaviRootWindow. getBridgeInformationPipe(); private MouseGestures mouseIteraction; //not used yet //private SVGUserAgentGUIAdapter agent; private SearchServices search; private AbstractDisplayManager dm; private boolean isFocus = false; private LinkedList<TransformAdapter> tranformListener = new LinkedList<TransformAdapter>(); MouseListener requestFocus = new MouseAdapter() { @Override public void mousePressed(MouseEvent mouseEvent) { if(!isFocus) requestFocusInWindow(); } }; public Canvas(){ super(null,false,false); //setDocumentState(JSVGCanvas.ALWAYS_DYNAMIC); setDocumentState(Canvas.ALWAYS_STATIC); setDoubleBuffered(true); //setDoubleBufferedRendering(true); mouseIteraction = new MouseGestures(); setLayout(new BorderLayout()); search = new SearchServices(this); //add(search,BorderLayout.CENTER); //dm = new XMLDOMDisplayManager(this); dm = new ComponentDisplayManager(this); //setEnableZoomInteractor(false); //setEnableImageZoomInteractor(false); setRequestFocusOnWindow(true); addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { isFocus = true; } @Override public void focusLost(FocusEvent e) { isFocus = false; } }); } public AbstractDisplayManager getDisplayManager(){ return dm; } /** * * @param pt */ public void addTranformListener(TransformAdapter ta){ tranformListener.add(ta); } @Override public void setPaintingTransform(AffineTransform at) { super.setPaintingTransform(at); if(at!=null){ final AffineTransform tmpAt = new AffineTransform(at); new Thread(new Runnable() { @Override public void run() { for (Object o : tranformListener) { ((PaintingTransformIterface)o).setPaintingTransform(tmpAt); } } }).start(); } } @Override public void setRenderingTransform(AffineTransform at) { final AffineTransform tmpAt = new AffineTransform(at); new Thread(new Runnable() { @Override public void run() { for (Object o : tranformListener) { ((RenderingTransformInterface)o).setRenderingTransform(tmpAt); } } }).start(); super.setRenderingTransform(at); } @Override public boolean isFocusable() { return true; } public SVGPoint[] getWindowPoints() { final SVGOMPoint upperLeft = new SVGOMPoint(0, 0); final SVGOMPoint upperRight = new SVGOMPoint(this.getWidth(), 0); final SVGOMPoint lowerLeft = new SVGOMPoint(0, this.getHeight()); return new SVGPoint[] {upperLeft, upperRight, lowerLeft}; } /** * Maps the points of the corners of this JSVGCanvas to SVG document * coordinates. * @return An SVGPoint array of points representing document coordinates. */ public SVGPoint[] getDocumentPoints() { if (this.getSVGDocument() != null) { final Node node = this.getSVGDocument().getDocumentElement(); SVGMatrix matrix = ((SVGLocatable) node).getScreenCTM(); if(matrix!=null){ matrix = matrix.inverse(); SVGPoint[] windowPoints = this.getWindowPoints(); final SVGPoint derivedUpperLeft = windowPoints[0].matrixTransform(matrix); final SVGPoint derivedUpperRight = windowPoints[1].matrixTransform(matrix); final SVGPoint derivedLowerLeft = windowPoints[2].matrixTransform(matrix); /* System.out.println("Upper Left: " + windowPoints[0].getX() + ", " + windowPoints[0].getY()); System.out.println("Upper Right: " + windowPoints[1].getX() + ", " + windowPoints[1].getY()); System.out.println("Lower Left: " + windowPoints[2].getX() + ", " + windowPoints[2].getY()); System.out.println("Document Upper Left: " + derivedUpperLeft.getX() + ", " + derivedUpperLeft.getY()); System.out.println("Document Upper Right: " + derivedUpperRight.getX() + ", " + derivedUpperRight.getY()); System.out.println("Document Lower Left: " + derivedLowerLeft.getX() + ", " + derivedLowerLeft.getY()); */ return new SVGPoint[] {derivedUpperLeft, derivedUpperRight, derivedLowerLeft}; } } return null; } /** * * @param val */ public void setRequestFocusOnWindow(boolean val){ if(val){ addMouseListener(requestFocus); }else{ removeMouseListener(requestFocus); } } public SearchServices getSearchServices(){ return search; } /** * * @return */ public boolean isDocumentSet(){ return (getSVGDocument() != null); } /** * * @param zoomIn */ public void zoomFromCenterDocumnet(boolean zoomIn){ mouseIteraction.zoomFromCenterDocumnet(zoomIn); mouseIteraction.setMode(MouseGestures.ZOOM_ACTION); } /** * * @param setZoom */ public void zoomFromMouseCoordinationEnable(boolean setZoom){ if(setZoom){ addMouseListener(mouseIteraction); addMouseMotionListener(mouseIteraction); setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } else{ setCursor(Cursor.getDefaultCursor()); removeMouseListener(mouseIteraction); removeMouseMotionListener(mouseIteraction); } mouseIteraction.setMode(MouseGestures.ZOOM_ACTION); } private class MouseGestures extends MouseAdapter{ private int xStart; private int yStart; private boolean drag=false; public static final byte ZOOM_ACTION =0; public static final byte PAN_ACTION =1; public static final byte ROTATE_ACTION =2; //none mode private byte mode = -1; @Override public void mouseClicked(MouseEvent evt) { Point2D p2d = new Point2D.Double(evt.getX(),evt.getY()); int button = evt.getButton(); if(button==MouseEvent.BUTTON1){ renderingZoom(p2d,svgConfig.getZoomInRate()); System.out.println("Zoom In\n\tPoint "+p2d+ "\n\tRate ["+svgConfig.getZoomInRateX()+","+svgConfig.getZoomInRateY()+"]"); } else if(button == MouseEvent.BUTTON3){ renderingZoom(p2d,svgConfig.getZoomOutRate()); System.out.println("Zoom Out\n\tPoint "+p2d+ "\n\tRate ["+svgConfig.getZoomOutRateX()+","+svgConfig.getZoomOutRateY()+"]"); } } @Override public void mousePressed(MouseEvent e) { xStart = e.getX(); yStart = e.getY(); if(e.getButton() == MouseEvent.BUTTON1 && !e.isShiftDown()){ drag=true; } } @Override public void mouseReleased(MouseEvent e) { if(drag){ drag=false; AffineTransform pt = getPaintingTransform(); if (pt != null) { AffineTransform rt = (AffineTransform)getRenderingTransform(); pt.concatenate(rt); setRenderingTransform(pt); } } } @Override public void mouseDragged(MouseEvent e) { if(drag && getMode()==MouseGestures.ZOOM_ACTION){ int dy = e.getY() - yStart; double s; if (dy < 0) { dy -= 10; s = (dy > -15) ? 1.0 : -15.0/dy; } else { dy += 10; s = (dy < 15) ? 1.0 : dy/15.0; } paintingZoom(new Point(xStart, yStart), new Point2D.Double(s, s)); } } public void paintingZoom(Point2D translate,Point2D scale){ AffineTransform at = getZoomTransform(translate, scale); setPaintingTransform(at); } public void renderingZoom(Point2D translate,Point2D scale){ AffineTransform rat = getRenderingTransform(); if(rat!=null){ AffineTransform at = getZoomTransform(translate, scale); at.concatenate(rat); setRenderingTransform(at); } } private AffineTransform getZoomTransform(Point2D translate,Point2D scale){ AffineTransform t = AffineTransform.getTranslateInstance(translate.getX(),translate.getY()); t.concatenate(AffineTransform.getScaleInstance(scale.getX(),scale.getY())); t.translate(-translate.getX(),-translate.getY()); return t; } public void zoomFromCenterDocumnet(boolean zoomIn){ Point2D translate = new Point(getSize().width>>1,getSize().height>>1); Point2D scale; if(zoomIn) scale= svgConfig.getZoomInRate(); else scale= svgConfig.getZoomOutRate(); renderingZoom(translate, scale); } /** * @return the mode */ public byte getMode() { return mode; } /** * @param mode the mode to set */ public void setMode(byte mode) { this.mode = mode; } }//class MouseGestures /** * */ protected class ThumbnailAction extends AbstractAction{ /** * * @param mnemonic */ public ThumbnailAction(Integer mnemonic) { super(); putValue(AbstractAction.MNEMONIC_KEY, mnemonic); putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(mnemonic,InputEvent.SHIFT_DOWN_MASK|InputEvent.CTRL_DOWN_MASK)); } @Override public void actionPerformed(ActionEvent e) { } } }