/********************************************** * Copyright (C) 2010 Lukas Laag * This file is part of svgreal. * * svgreal is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * svgreal 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 for more details. * * You should have received a copy of the GNU General Public License * along with svgreal. If not, see http://www.gnu.org/licenses/ **********************************************/ package org.vectomatic.svg.edit.client.gxt.widget; import org.vectomatic.dom.svg.OMSVGGElement; import org.vectomatic.dom.svg.OMSVGMatrix; import org.vectomatic.dom.svg.OMSVGPoint; import org.vectomatic.dom.svg.OMSVGSVGElement; import org.vectomatic.dom.svg.utils.DOMHelper; import org.vectomatic.dom.svg.utils.SVGPrefixResolver; import org.vectomatic.svg.edit.client.AppBundle; import org.vectomatic.svg.edit.client.SvgrealApp; import org.vectomatic.svg.edit.client.engine.SVGProcessor; import org.vectomatic.svg.edit.client.event.HasRotationHandlers; import org.vectomatic.svg.edit.client.event.RotationEvent; import org.vectomatic.svg.edit.client.event.RotationHandler; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.MouseDownEvent; import com.google.gwt.event.dom.client.MouseDownHandler; import com.google.gwt.event.dom.client.MouseEvent; import com.google.gwt.event.dom.client.MouseMoveEvent; import com.google.gwt.event.dom.client.MouseMoveHandler; import com.google.gwt.event.dom.client.MouseUpEvent; import com.google.gwt.event.dom.client.MouseUpHandler; import com.google.gwt.event.shared.EventHandler; import com.google.gwt.event.shared.GwtEvent; import com.google.gwt.event.shared.HandlerRegistration; /** * An compass widget implemented using an SVG image. * @author laaglu */ public class Compass implements HasRotationHandlers { private static final String COMPASS_PREFIX="compass"; protected boolean rotate; protected int angle; protected OMSVGSVGElement compass; protected OMSVGGElement textGroup; /** * Constructor. */ public Compass() { compass = AppBundle.INSTANCE.compass().getSvg(); textGroup = (OMSVGGElement)DOMHelper.evaluateXPath(compass, ".//svg:g[@id='textGroup']", new SVGPrefixResolver()).next(); SVGProcessor.normalizeIds(compass, COMPASS_PREFIX); compass.addMouseDownHandler(new MouseDownHandler() { @Override public void onMouseDown(MouseDownEvent event) { rotate = true; DOMHelper.setCaptureElement(compass, null); event.preventDefault(); event.stopPropagation(); } }); compass.addMouseMoveHandler(new MouseMoveHandler() { @Override public void onMouseMove(MouseMoveEvent event) { if (rotate) { OMSVGPoint p = getLocalCoordinates(event).substract(compass.createSVGPoint(50,50)); GWT.log(p.getDescription() + " " + Float.toString(-p.getY() / p.length())); double a = Math.acos(-p.getY() / p.length()); if (p.getX() < 0) { a = 2 * Math.PI - a; } setRotation((((int)toDeg(a)) / 6) * 6); event.preventDefault(); event.stopPropagation(); } } }); compass.addMouseUpHandler(new MouseUpHandler() { @Override public void onMouseUp(MouseUpEvent event) { if (rotate) { rotate = false; DOMHelper.releaseCaptureElement(); event.preventDefault(); event.stopPropagation(); } } }); } public void setRotation(int angle) { this.angle = angle; textGroup.getTransform().getBaseVal().getItem(0).setRotate(angle, 50, 50); fireEvent(new RotationEvent(angle)); } public OMSVGSVGElement getSvgElement() { return compass; } private static final float toDeg(double rad) { return (float)(rad * 180 / Math.PI); } /** * Returns the coordinates of a mouse event, converted * to the compass coordinate system * @param e * A mouse event * @return * The coordinates of the mouse event, converted * to the compass coordinate system */ public OMSVGPoint getLocalCoordinates(MouseEvent<? extends EventHandler> e) { OMSVGPoint p = compass.createSVGPoint(e.getClientX(), e.getClientY()); OMSVGMatrix m = compass.getScreenCTM().inverse(); return p.matrixTransform(m); } @Override public void fireEvent(GwtEvent<?> event) { SvgrealApp.getApp().getEventBus().fireEventFromSource(event, this); } @Override public HandlerRegistration addRotationHandler(RotationHandler handler) { return SvgrealApp.getApp().getEventBus().addHandlerToSource(RotationEvent.getType(), this, handler); } }