View Javadoc

1   /**********************************************
2    * Copyright (C) 2010 Lukas Laag
3    * This file is part of vectomatic2.
4    * 
5    * vectomatic2 is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    * 
10   * vectomatic2 is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License
16   * along with vectomatic2.  If not, see http://www.gnu.org/licenses/
17   **********************************************/
18  package org.vectomatic.svg.edit.client.widget;
19  
20  import org.vectomatic.dom.svg.OMSVGGElement;
21  import org.vectomatic.dom.svg.OMSVGMatrix;
22  import org.vectomatic.dom.svg.OMSVGPoint;
23  import org.vectomatic.dom.svg.OMSVGSVGElement;
24  import org.vectomatic.dom.svg.OMSVGTransform;
25  import org.vectomatic.dom.svg.utils.DOMHelper;
26  import org.vectomatic.dom.svg.utils.SVGPrefixResolver;
27  import org.vectomatic.svg.edit.client.AppBundle;
28  import org.vectomatic.svg.edit.client.engine.SVGProcessor;
29  import org.vectomatic.svg.edit.client.event.HasRotationHandlers;
30  import org.vectomatic.svg.edit.client.event.RotationEvent;
31  import org.vectomatic.svg.edit.client.event.RotationHandler;
32  
33  import com.google.gwt.core.client.GWT;
34  import com.google.gwt.event.dom.client.MouseDownEvent;
35  import com.google.gwt.event.dom.client.MouseDownHandler;
36  import com.google.gwt.event.dom.client.MouseEvent;
37  import com.google.gwt.event.dom.client.MouseMoveEvent;
38  import com.google.gwt.event.dom.client.MouseMoveHandler;
39  import com.google.gwt.event.dom.client.MouseUpEvent;
40  import com.google.gwt.event.dom.client.MouseUpHandler;
41  import com.google.gwt.event.shared.EventHandler;
42  import com.google.gwt.event.shared.GwtEvent;
43  import com.google.gwt.event.shared.HandlerManager;
44  import com.google.gwt.event.shared.HandlerRegistration;
45  
46  /**
47   * An compass widget implemented using an SVG image.
48   * @author laaglu
49   */
50  public class Compass implements HasRotationHandlers {
51  	protected OMSVGTransform rotation;
52  	protected boolean rotate;
53  	protected int angle;
54  	protected OMSVGSVGElement compass;
55  	protected HandlerManager handlerManager;
56  	protected OMSVGGElement textGroup;
57  	
58  	/**
59  	 * Constructor.
60  	 */
61  	public Compass() {
62  		compass = AppBundle.INSTANCE.compass().getSvg();
63  		textGroup = (OMSVGGElement)DOMHelper.evaluateXPath(compass, ".//svg:g[@id='textGroup']", new SVGPrefixResolver()).next();
64  		SVGProcessor.normalizeIds(compass);
65  		rotation = textGroup.getTransform().getBaseVal().getItem(0);
66  		compass.addMouseDownHandler(new MouseDownHandler()  {
67  			@Override
68  			public void onMouseDown(MouseDownEvent event) {
69  				rotate = true;
70  				DOMHelper.setCaptureElement(compass, null);
71  				event.preventDefault();
72  				event.stopPropagation();
73  			}
74  		});
75  		compass.addMouseMoveHandler(new MouseMoveHandler() {
76  			@Override
77  			public void onMouseMove(MouseMoveEvent event) {
78  				if (rotate) {
79  					OMSVGPoint p = getLocalCoordinates(event).substract(compass.createSVGPoint(50,50));
80  					GWT.log(p.getDescription() + " " + Float.toString(-p.getY() / p.length()));
81  					double a = Math.acos(-p.getY() / p.length());
82  					if (p.getX() < 0) {
83  						a = 2 * Math.PI - a;
84  					}
85  					setRotation((((int)toDeg(a)) / 6) * 6);
86  					event.preventDefault();
87  					event.stopPropagation();
88  				}
89  			}
90  		});
91  		compass.addMouseUpHandler(new MouseUpHandler() {
92  			@Override
93  			public void onMouseUp(MouseUpEvent event) {
94  				if (rotate) {
95  					rotate = false;
96  					DOMHelper.releaseCaptureElement();
97  					event.preventDefault();
98  					event.stopPropagation();
99  				}
100 			}
101 		});
102 	}
103 	
104 	public void setRotation(int angle) {
105 		this.angle = angle;
106 		rotation.setRotate(angle, 50, 50);
107 		fireEvent(new RotationEvent(angle)); 
108 	}
109 	
110 	public OMSVGSVGElement getSvgElement() {
111 		return compass;
112 	}
113 
114 	private static final float toDeg(double rad) {
115 		return (float)(rad * 180 / Math.PI);
116 	}
117 
118     /**
119      * Returns the coordinates of a mouse event, converted
120      * to the compass coordinate system
121      * @param e
122      * A mouse event
123      * @return
124      * The coordinates of the mouse event, converted
125      * to the compass coordinate system
126      */
127     public OMSVGPoint getLocalCoordinates(MouseEvent<? extends EventHandler> e) {
128         OMSVGPoint p = compass.createSVGPoint(e.getClientX(), e.getClientY());
129         OMSVGMatrix m = compass.getScreenCTM().inverse();
130         return p.matrixTransform(m);
131     }
132     
133 
134 
135 
136 	@Override
137 	public void fireEvent(GwtEvent<?> event) {
138 		if (handlerManager != null) {
139 			handlerManager.fireEvent(event);
140 		}
141 	}
142 
143 	@Override
144 	public HandlerRegistration addRotationHandler(RotationHandler handler) {
145 		return ensureHandlers().addHandler(RotationEvent.getType(), handler);
146 	}
147 	
148 	private HandlerManager ensureHandlers() {
149 		if (handlerManager == null) {
150 			handlerManager = new HandlerManager(this);
151 		}
152 		return handlerManager;
153 	}
154 
155 }