/**********************************************
* Copyright (C) 2009 Lukas Laag
* This file is part of lib-gwt-svg-samples.
*
* libgwtsvg-samples 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.
*
* libgwtsvg-samples 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 libgwtsvg-samples. If not, see http://www.gnu.org/licenses/
**********************************************/
package org.vectomatic.svg.samples.client.events;
import org.vectomatic.dom.svg.OMSVGCircleElement;
import org.vectomatic.dom.svg.OMSVGDocument;
import org.vectomatic.dom.svg.OMSVGMatrix;
import org.vectomatic.dom.svg.OMSVGPoint;
import org.vectomatic.dom.svg.OMSVGRectElement;
import org.vectomatic.dom.svg.OMSVGSVGElement;
import org.vectomatic.dom.svg.utils.DOMHelper;
import org.vectomatic.dom.svg.utils.OMSVGParser;
import org.vectomatic.dom.svg.utils.SVGConstants;
import org.vectomatic.svg.samples.client.Main;
import org.vectomatic.svg.samples.client.Main.MainBundle;
import org.vectomatic.svg.samples.client.SampleBase;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
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.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.TabLayoutPanel;
/**
* Class to demonstrate the SVG event handling
* @author laaglu
*/
public class EventSample extends SampleBase implements MouseUpHandler, MouseMoveHandler, MouseDownHandler {
interface EventSampleBinder extends UiBinder<TabLayoutPanel, EventSample> {
}
private static EventSampleBinder binder = GWT.create(EventSampleBinder.class);
@UiField(provided=true)
public static MainBundle mainBundle = Main.mainBundle;
@UiField
HTML svgContainer;
private boolean dragging;
private OMSVGPoint p0;
private OMSVGSVGElement svg;
private OMSVGRectElement square;
@Override
public TabLayoutPanel getPanel() {
if (tabPanel == null) {
tabPanel = binder.createAndBindUi(this);
tabPanel.setTabText(0, "Events");
createCodeTabs("EventSample");
// Cast the document into a SVG document
Element div = svgContainer.getElement();
OMSVGDocument doc = OMSVGParser.currentDocument();
// Create the root svg element
svg = doc.createSVGSVGElement();
svg.setViewBox(0f, 0f, 400f, 200f);
svg.getWidth().getBaseVal().newValueSpecifiedUnits(Unit.PCT, 100);
svg.getHeight().getBaseVal().newValueSpecifiedUnits(Unit.PCT, 100);
// Create a circle
final OMSVGCircleElement circle = doc.createSVGCircleElement(80f, 80f, 40f);
circle.getStyle().setSVGProperty(SVGConstants.CSS_STROKE_PROPERTY, SVGConstants.CSS_BLACK_VALUE);
setCircleColor(circle, SVGConstants.CSS_RED_VALUE);
svg.appendChild(circle);
// Set a mousedown event handler
circle.addMouseDownHandler(new MouseDownHandler() {
final String[] colors = new String[] {
SVGConstants.CSS_RED_VALUE,
SVGConstants.CSS_BLUE_VALUE,
SVGConstants.CSS_GREEN_VALUE,
SVGConstants.CSS_YELLOW_VALUE,
SVGConstants.CSS_PINK_VALUE };
@Override
public void onMouseDown(MouseDownEvent event) {
String color = getCircleColor(circle);
while (color.equals(getCircleColor(circle))) {
setCircleColor(circle, colors[Random.nextInt(colors.length)]);
}
event.stopPropagation();
event.preventDefault();
}
});
// Create a square
square = doc.createSVGRectElement(140f, 40f, 80f, 80f, 0f, 0f);
square.getStyle().setSVGProperty(SVGConstants.CSS_STROKE_PROPERTY, SVGConstants.CSS_BLACK_VALUE);
square.getStyle().setSVGProperty(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_GREEN_VALUE);
square.addMouseDownHandler(this);
square.addMouseUpHandler(this);
square.addMouseMoveHandler(this);
svg.appendChild(square);
// Insert the SVG root element into the HTML UI
div.appendChild(svg.getElement());
}
return tabPanel;
}
private static final String getCircleColor(OMSVGCircleElement circle) {
return circle.getStyle().getSVGProperty(SVGConstants.CSS_FILL_PROPERTY);
}
private static final void setCircleColor(OMSVGCircleElement circle, String color) {
circle.getStyle().setSVGProperty(SVGConstants.CSS_FILL_PROPERTY, color);
}
@Override
public void onMouseUp(MouseUpEvent event) {
dragging = false;
DOMHelper.releaseCaptureElement();
event.stopPropagation();
event.preventDefault();
}
@Override
public void onMouseMove(MouseMoveEvent event) {
if (dragging) {
OMSVGPoint p = getLocalCoordinates(event);
float dx = p.getX() - p0.getX();
float dy = p.getY() - p0.getY();
float x = square.getX().getBaseVal().getValue();
float y = square.getY().getBaseVal().getValue();
square.getX().getBaseVal().setValue(x + dx);
square.getY().getBaseVal().setValue(y + dy);
p0 = p;
}
event.stopPropagation();
event.preventDefault();
}
/**
* Returns the coordinates of a mouse event, converted
* to the SVG coordinate system
* @param e
* A mouse event
* @return
* The coordinates of the mouse event, converted
* to the SVG coordinate system
*/
public OMSVGPoint getLocalCoordinates(MouseEvent<? extends EventHandler> e) {
OMSVGPoint p = svg.createSVGPoint(e.getClientX(), e.getClientY());
OMSVGMatrix m = square.getScreenCTM().inverse();
return p.matrixTransform(m);
}
@Override
public void onMouseDown(MouseDownEvent event) {
dragging = true;
p0 = getLocalCoordinates(event);
DOMHelper.setCaptureElement(square, null);
event.stopPropagation();
event.preventDefault();
}
}