Java tutorial
/********************************************** * Copyright (C) 2010 Lukas Laag * This file is part of lib-gwt-svg-edu. * * libgwtsvg-edu 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-edu 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-edu. If not, see http://www.gnu.org/licenses/ **********************************************/ package org.vectomatic.svg.edu.client.dots; import java.util.ArrayList; import java.util.List; import org.vectomatic.dom.svg.OMNode; import org.vectomatic.dom.svg.OMNodeList; import org.vectomatic.dom.svg.OMSVGCircleElement; import org.vectomatic.dom.svg.OMSVGDefsElement; import org.vectomatic.dom.svg.OMSVGDocument; import org.vectomatic.dom.svg.OMSVGFEColorMatrixElement; import org.vectomatic.dom.svg.OMSVGFEGaussianBlurElement; import org.vectomatic.dom.svg.OMSVGFilterElement; import org.vectomatic.dom.svg.OMSVGGElement; import org.vectomatic.dom.svg.OMSVGLength; import org.vectomatic.dom.svg.OMSVGMatrix; import org.vectomatic.dom.svg.OMSVGNumber; import org.vectomatic.dom.svg.OMSVGPoint; import org.vectomatic.dom.svg.OMSVGPointList; import org.vectomatic.dom.svg.OMSVGPolylineElement; import org.vectomatic.dom.svg.OMSVGRect; import org.vectomatic.dom.svg.OMSVGSVGElement; import org.vectomatic.dom.svg.OMSVGTextElement; import org.vectomatic.dom.svg.OMSVGTransform; import org.vectomatic.dom.svg.OMText; import org.vectomatic.dom.svg.ui.SVGPushButton; import org.vectomatic.dom.svg.utils.AsyncXmlLoader; import org.vectomatic.dom.svg.utils.AsyncXmlLoaderCallback; 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.edu.client.commons.CommonBundle; import org.vectomatic.svg.edu.client.commons.CommonConstants; import org.vectomatic.svg.edu.client.commons.LicenseBox; import com.google.gwt.animation.client.Animation; import com.google.gwt.core.client.Duration; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.Style.Visibility; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ClickEvent; 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.logical.shared.ResizeEvent; import com.google.gwt.event.logical.shared.ResizeHandler; import com.google.gwt.event.shared.EventHandler; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiFactory; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.DecoratorPanel; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.PushButton; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextArea; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.widgetideas.client.HSliderBar; import com.google.gwt.widgetideas.client.SliderBar; import com.google.gwt.widgetideas.client.SliderListenerAdapter; /** * Main game class * @author laaglu */ public class DotsMain implements MouseDownHandler, MouseMoveHandler, MouseUpHandler, EntryPoint { interface DotsMainBinder extends UiBinder<FlowPanel, DotsMain> { } private static DotsMainBinder mainBinder = GWT.create(DotsMainBinder.class); private static String[] pictures; enum Mode { GAME, DESIGN }; private static final String DIR = "dots"; private static final String ID_ALPHA1_FILTER = "pictureAlpha"; private static final String ID_TRANSITION_FILTER = "pictureTransition"; private static final String ID_ALPHA2_FILTER = "dotAlpha"; private DotsCss css = DotsResources.INSTANCE.css(); @UiField(provided = true) CommonBundle common = CommonBundle.INSTANCE; @UiField HTML svgContainer; @UiField SVGPushButton prevButton; @UiField SVGPushButton nextButton; @UiField FlowPanel navigationPanel; Widget menuWidget; @UiField DecoratorPanel designPanel; @UiField Button addButton; @UiField Button removeButton; @UiField Button saveButton; @UiField Button testButton; @UiField CheckBox showLineCheck; @UiField HSliderBar pictureAlphaSlider; @UiField Label fileLabel; @UiField ListBox dotList; @UiField TextArea textArea; private FlowPanel panel; /** * Index of the currently displayed image in the pictures array */ private int level; /** * The SVG document. The document has the following structure * <tt> * <svg> // rootSvg * <defs> * <g/> // pictureGroup * <g> // lineGroup * <polyline> // polyline * </g> * <g> // dotGroup * <g/> // first dot * <g/> // N-th dot * </g> * </svg> * </tt> */ private OMSVGDocument doc; private OMSVGSVGElement rootSvg; private OMSVGDefsElement defs; private OMSVGGElement pictureGroup; private OMSVGGElement lineGroup; private OMSVGPolylineElement polyline; private OMSVGGElement dotGroup; /** * The vertices of the polyline */ OMSVGPointList points; /** * The dots in dotGroup */ private List<OMSVGGElement> dots; /** * The dot currently being moved */ private OMSVGGElement currentDot; /** * The index in dotGroup of dot currently being moved */ private int currentDotIndex; /** * The alpha channel in the filter applied to pictureSvg in edit mode */ private OMSVGNumber pictureAlpha1; /** * The alpha channel in the filter applied to pictureSvg in game mode */ private OMSVGNumber pictureAlpha2; /** * The Gaussian blur filter applied to pictureSvg */ private OMSVGFEGaussianBlurElement gaussianBlur; /** * The alpha channel in the filter applied to dotSvg */ private OMSVGNumber dotAlpha; /** * The mousedown point */ private OMSVGPoint mouseDownPoint; /** * The position of the current dot at the time of mousedown */ private OMSVGPoint p0; /** * The index of the last dot found by the player */ private int maxIndex; /** * To load game levels */ AsyncXmlLoader loader; /** * Constructor for standalone game */ public DotsMain() { } /** * Constructor for integration in a menu */ public DotsMain(Widget menuWidget) { this.menuWidget = menuWidget; } /** * Entry point */ @Override public void onModuleLoad() { css.ensureInjected(); common.css().ensureInjected(); // Initialize the UI with UiBinder panel = mainBinder.createAndBindUi(this); if (menuWidget == null) { menuWidget = LicenseBox.createAboutButton(); } navigationPanel.insert(menuWidget, 0); designPanel.setVisible(false); RootPanel.get(CommonConstants.ID_UIROOT).add(panel); Element div = svgContainer.getElement(); // Handle resizing issues. ResizeHandler resizeHandler = new ResizeHandler() { @Override public void onResize(ResizeEvent event) { updatePictureSize(); } }; Window.addResizeHandler(resizeHandler); pictureAlphaSlider.addSliderListener(new SliderListenerAdapter() { @Override public void onValueChanged(SliderBar slider, double curValue) { setPictureAlpha((float) curValue); } }); dots = new ArrayList<OMSVGGElement>(); // Create the root SVG structure elements doc = OMSVGParser.currentDocument(); rootSvg = doc.createSVGSVGElement(); // Create the SVG filters defs = doc.createSVGDefsElement(); OMSVGFilterElement alpha1Filter = doc.createSVGFilterElement(); alpha1Filter.setId(ID_ALPHA1_FILTER); OMSVGFEColorMatrixElement feColorMatrix1 = doc.createSVGFEColorMatrixElement(); feColorMatrix1.getIn1().setBaseVal(OMSVGFilterElement.IN_SOURCE_GRAPHIC); feColorMatrix1.getType().setBaseVal(OMSVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX); pictureAlpha1 = feColorMatrix1.getValues().getBaseVal().appendItems(rootSvg, new float[] { 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, })[18]; OMSVGFilterElement transitionFilter = doc.createSVGFilterElement(); transitionFilter.setId(ID_TRANSITION_FILTER); gaussianBlur = doc.createSVGFEGaussianBlurElement(); gaussianBlur.setStdDeviation(0, 0); gaussianBlur.getIn1().setBaseVal(OMSVGFilterElement.IN_SOURCE_GRAPHIC); gaussianBlur.getResult().setBaseVal("blur"); gaussianBlur = doc.createSVGFEGaussianBlurElement(); gaussianBlur.setStdDeviation(0, 0); gaussianBlur.getIn1().setBaseVal(OMSVGFilterElement.IN_SOURCE_GRAPHIC); gaussianBlur.getResult().setBaseVal("blur"); OMSVGFEColorMatrixElement feColorMatrix2 = doc.createSVGFEColorMatrixElement(); feColorMatrix2.getIn1().setBaseVal("blur"); feColorMatrix2.getType().setBaseVal(OMSVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX); pictureAlpha2 = feColorMatrix2.getValues().getBaseVal().appendItems(rootSvg, new float[] { 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, })[18]; OMSVGFilterElement alpha3Filter = doc.createSVGFilterElement(); alpha3Filter.setId(ID_ALPHA2_FILTER); OMSVGFEColorMatrixElement feColorMatrix3 = doc.createSVGFEColorMatrixElement(); feColorMatrix3.getIn1().setBaseVal(OMSVGFilterElement.IN_SOURCE_GRAPHIC); feColorMatrix3.getType().setBaseVal(OMSVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX); dotAlpha = feColorMatrix3.getValues().getBaseVal().appendItems(rootSvg, new float[] { 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, })[18]; // Compose the root SVG structure rootSvg.appendChild(defs); pictureGroup = doc.createSVGGElement(); dotGroup = doc.createSVGGElement(); dotGroup.setAttribute("id", "dots"); lineGroup = doc.createSVGGElement(); polyline = doc.createSVGPolylineElement(); polyline.setClassNameBaseVal(css.lineInvisible()); polyline.getStyle().setSVGProperty(SVGConstants.SVG_FILTER_ATTRIBUTE, DOMHelper.toUrl(ID_ALPHA2_FILTER)); points = polyline.getPoints(); lineGroup.appendChild(polyline); rootSvg.appendChild(pictureGroup); defs.appendChild(alpha1Filter); alpha1Filter.appendChild(feColorMatrix1); defs.appendChild(transitionFilter); transitionFilter.appendChild(gaussianBlur); transitionFilter.appendChild(feColorMatrix2); defs.appendChild(alpha3Filter); alpha3Filter.appendChild(feColorMatrix3); rootSvg.appendChild(lineGroup); rootSvg.appendChild(dotGroup); // Add the SVG to the HTML page div.appendChild(rootSvg.getElement()); // Read the picture list pictures = DotsResources.INSTANCE.pictureList().getText().split("\\s"); String levelParam = Window.Location.getParameter("level"); if (levelParam != null) { try { int value = Integer.parseInt(levelParam); if (value >= 0 && value < pictures.length) { level = value; } } catch (NumberFormatException e) { } } loader = GWT.create(AsyncXmlLoader.class); updateLevel(); } /** * UiBinder factory method to instantiate HSliderBar * @return */ @UiFactory HSliderBar makeHSliderBar() { HSliderBar sliderBar = new HSliderBar(0, 1); sliderBar.setStepSize(0.1); sliderBar.setCurrentValue(0); return sliderBar; } private void updatePictureSize() { if (rootSvg != null) { OMSVGMatrix m = dotGroup.getCTM().inverse(); updateScales(m.getA(), m.getD()); } } private void updateLevel() { fileLabel.setText(pictures[level]); // The data come in two files: a picture file and a dot file // In design mode, both must be read // In game mode, the dot file is read first and the picture file // is read later if the player succeeds if (getMode() == Mode.DESIGN) { readPicture(true); } else { readDots(); } } private String getPictureUrl() { return GWT.getModuleBaseURL() + DIR + "/" + pictures[level]; } private String getDotsUrl() { String url = GWT.getModuleBaseURL() + DIR + "/" + pictures[level] + ".dots"; // Add a bogus query to bypass the browser cache as advised by: // https://developer.mozilla.org/En/Using_XMLHttpRequest#Bypassing_the_cache url += (url.indexOf("?") == -1) ? ("?ts=" + System.currentTimeMillis()) : ("&ts=" + +System.currentTimeMillis()); return url; } private Mode getMode() { return "design".equals(Window.Location.getParameter("mode")) ? Mode.DESIGN : Mode.GAME; } public void readPicture(final boolean readDots) { loader.loadResource(getPictureUrl(), new AsyncXmlLoaderCallback() { @Override public void onError(String resourceName, Throwable error) { svgContainer.setHTML("Cannot find resource"); } @Override public void onSuccess(String resourceName, com.google.gwt.dom.client.Element root) { OMSVGSVGElement svg = OMNode.convert(root); // Position the filter on the picture OMSVGGElement g = reparent(svg); pictureAlpha2.setValue(0f); OMSVGRect viewBox = svg.getViewBox().getBaseVal(); rootSvg.setViewBox(viewBox.inset(svg.createSVGRect(), viewBox.getWidth() * -0.025f, viewBox.getHeight() * -0.025f)); // Insert the picture into the SVG structure rootSvg.replaceChild(g, pictureGroup); pictureGroup = g; pictureGroup.getStyle().setSVGProperty(SVGConstants.SVG_FILTER_ATTRIBUTE, DOMHelper.toUrl(ID_TRANSITION_FILTER)); // Send the dots request if (readDots) { readDots(); } else { transition(null); } } }); } public void readDots() { maxIndex = -1; dots.clear(); dotList.clear(); points.clear(); loader.loadResource(getDotsUrl(), new AsyncXmlLoaderCallback() { private void finish() { if (getMode() == Mode.DESIGN) { pictureGroup.getStyle().setSVGProperty(SVGConstants.SVG_FILTER_ATTRIBUTE, DOMHelper.toUrl(ID_ALPHA1_FILTER)); setPictureAlpha(1f); showLineCheck.setValue(false); pictureAlphaSlider.setCurrentValue(1); } else { pictureGroup.getStyle().setVisibility(Visibility.HIDDEN); polyline.setClassNameBaseVal(css.lineVisible()); } dotAlpha.setValue(1f); dotGroup.getStyle().setSVGProperty(SVGConstants.SVG_FILTER_ATTRIBUTE, DOMHelper.toUrl(ID_ALPHA2_FILTER)); designPanel.setVisible(getMode() == Mode.DESIGN); // Resize to the size of the window updatePictureSize(); updateUI(); } @Override public void onError(String resourceName, Throwable error) { if (getMode() == Mode.GAME) { svgContainer.setHTML("Cannot find resource"); return; } OMSVGGElement g = doc.createSVGGElement(); rootSvg.replaceChild(g, dotGroup); dotGroup = g; finish(); } @Override public void onSuccess(String resourceName, com.google.gwt.dom.client.Element root) { OMSVGSVGElement svg = OMNode.convert(root); OMSVGGElement g = (OMSVGGElement) svg.getFirstChild(); rootSvg.replaceChild(g, dotGroup); dotGroup = g; OMSVGRect viewBox = svg.getViewBox().getBaseVal(); rootSvg.setViewBox(viewBox.inset(svg.createSVGRect(), viewBox.getWidth() * -0.025f, viewBox.getHeight() * -0.025f)); // Parse the dots to recreate the polyline OMNodeList<OMSVGGElement> childNodes = dotGroup.getChildNodes(); for (int i = 0, size = childNodes.getLength(); i < size; i++) { OMSVGGElement g1 = childNodes.getItem(i); g1.addMouseDownHandler(DotsMain.this); dots.add(g1); if (getMode() == Mode.DESIGN) { g1.addMouseMoveHandler(DotsMain.this); g1.addMouseUpHandler(DotsMain.this); dotList.addItem(toDotName(i)); OMSVGMatrix m = g1.getTransform().getBaseVal().getItem(0).getMatrix(); points.appendItem(rootSvg.createSVGPoint(m.getE(), m.getF())); } } finish(); } }); } @UiHandler("prevButton") public void previousPicture(ClickEvent event) { level--; if (level < 0) { level = pictures.length - 1; } updateLevel(); } @UiHandler("nextButton") public void nextPicture(ClickEvent event) { level++; if (level >= pictures.length) { level = 0; } updateLevel(); } private OMSVGPoint getLocalCoordinates(MouseEvent<? extends EventHandler> e) { OMSVGPoint p = rootSvg.createSVGPoint(e.getClientX(), e.getClientY()); OMSVGMatrix m = rootSvg.getScreenCTM().inverse(); return p.matrixTransform(m); } @UiHandler("addButton") public void addDot(ClickEvent event) { int pIndex = dots.size(); OMSVGRect viewBox = rootSvg.getViewBox().getBaseVal(); // Position the new points in a circle centered at the view box // with a radius of 20% float r = Math.min(viewBox.getWidth(), viewBox.getHeight()) * 0.2f; float x = ((float) Math.cos(pIndex / 16d * 2d * Math.PI)) * r + viewBox.getCenterX(); float y = ((float) Math.sin(pIndex / 16d * 2d * Math.PI)) * r + viewBox.getCenterY(); OMSVGGElement g1 = createDot(pIndex + 1, x, y); dots.add(g1); points.appendItem(rootSvg.createSVGPoint(x, y)); dotGroup.appendChild(g1); dotList.addItem(toDotName(pIndex)); // Autoselect the new point dotList.setSelectedIndex(dotList.getItemCount() - 1); updateUI(); } @UiHandler("removeButton") public void removeDot(ClickEvent event) { int index = dotList.getSelectedIndex(); OMSVGGElement g1 = dots.remove(index); dotGroup.removeChild(g1); dotList.removeItem(index); points.removeItem(index); updateUI(); renumber(); } @UiHandler("saveButton") public void save(ClickEvent event) { rootSvg.removeChild(defs); rootSvg.removeChild(pictureGroup); rootSvg.removeChild(lineGroup); dotGroup.removeAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE); textArea.setText(rootSvg.getMarkup()); rootSvg.insertBefore(lineGroup, dotGroup); rootSvg.insertBefore(pictureGroup, lineGroup); rootSvg.insertBefore(defs, pictureGroup); dotGroup.getStyle().setSVGProperty(SVGConstants.SVG_FILTER_ATTRIBUTE, DOMHelper.toUrl(ID_ALPHA2_FILTER)); } @UiHandler("showLineCheck") public void toggleShowLine(ClickEvent event) { polyline.setClassNameBaseVal(showLineCheck.getValue() ? css.lineVisible() : css.lineInvisible()); } @UiHandler("dotList") void onChange(ChangeEvent event) { updateUI(); } @UiHandler("testButton") public void transition(ClickEvent event) { pictureAlpha2.setValue(0f); gaussianBlur.setStdDeviation(10f, 10f); polyline.setClassNameBaseVal(css.lineVisible()); pictureGroup.getStyle().setSVGProperty(SVGConstants.SVG_FILTER_ATTRIBUTE, DOMHelper.toUrl(ID_TRANSITION_FILTER)); if (points.getNumberOfItems() > 0) { points.appendItem(points.getItem(0).assignTo(rootSvg.createSVGPoint())); } Animation transition = new Animation() { @Override protected void onUpdate(double progress) { pictureAlpha2.setValue((float) progress); float stdDev = 10f * (1f - (float) progress); gaussianBlur.setStdDeviation(stdDev, stdDev); dotAlpha.setValue(1f - (float) progress); } @Override protected void onComplete() { if (getMode() == Mode.DESIGN) { polyline.setClassNameBaseVal( showLineCheck.getValue() ? css.lineVisible() : css.lineInvisible()); pictureGroup.getStyle().setSVGProperty(SVGConstants.SVG_FILTER_ATTRIBUTE, DOMHelper.toUrl(ID_ALPHA1_FILTER)); dotAlpha.setValue(1f); if (points.getNumberOfItems() > 0) { points.removeItem(points.getNumberOfItems() - 1); } } else { pictureAlpha2.setValue(1f); gaussianBlur.setStdDeviation(0.00001f, 0.00001f); dotAlpha.setValue(0f); } } }; pictureGroup.getStyle().setVisibility(Visibility.VISIBLE); transition.run(2000, Duration.currentTimeMillis() + 1000); } private void updateUI() { textArea.setText(""); removeButton.setEnabled(dotList.getSelectedIndex() != -1); } private OMSVGGElement createDot(int pIndex, float x, float y) { OMSVGGElement g1 = doc.createSVGGElement(); OMSVGTransform translation = rootSvg.createSVGTransform(); translation.setTranslate(x, y); g1.getTransform().getBaseVal().appendItem(translation); OMSVGGElement g2 = doc.createSVGGElement(); OMSVGTransform scaling = rootSvg.createSVGTransform(); OMSVGMatrix m = rootSvg.getScreenCTM().inverse(); scaling.setScale(m.getA(), m.getD()); g2.getTransform().getBaseVal().appendItem(scaling); OMSVGCircleElement circle1 = doc.createSVGCircleElement(0f, 0f, 5f); OMSVGCircleElement circle2 = doc.createSVGCircleElement(0f, 0f, 3f); OMSVGTextElement text = doc.createSVGTextElement(0f, 16f, OMSVGLength.SVG_LENGTHTYPE_PX, Integer.toString(pIndex)); g1.appendChild(g2); g2.appendChild(circle1); g2.appendChild(circle2); g2.appendChild(text); g1.addMouseDownHandler(this); g1.addMouseMoveHandler(this); g1.addMouseUpHandler(this); return g1; } private void updateScales(float sx, float sy) { for (OMSVGGElement g1 : dots) { OMSVGGElement g2 = (OMSVGGElement) g1.getFirstChild(); OMSVGTransform scaling = g2.getTransform().getBaseVal().getItem(0); scaling.setScale(sx, sy); } polyline.getStyle().setSVGProperty(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, Float.toString(sx)); } private void setPictureAlpha(float value) { pictureAlpha1.setValue(value); } private void renumber() { for (int i = 0, size = dots.size(); i < size; i++) { OMText data = (OMText) dots.get(i).getFirstChild().getLastChild().getFirstChild(); data.setData(Integer.toString(i + 1)); dotList.setItemText(i, toDotName(i)); } } @Override public void onMouseDown(MouseDownEvent event) { mouseDownPoint = getLocalCoordinates(event); currentDot = (OMSVGGElement) event.getSource(); currentDotIndex = dots.indexOf(currentDot); if (getMode() == Mode.DESIGN) { OMSVGMatrix m = currentDot.getTransform().getBaseVal().getItem(0).getMatrix(); p0 = rootSvg.createSVGPoint(m.getE(), m.getF()); DOMHelper.setCaptureElement(currentDot, null); event.stopPropagation(); event.preventDefault(); } else { if (currentDotIndex == maxIndex + 1) { maxIndex++; currentDot.setClassNameBaseVal(css.validated()); OMSVGMatrix m = currentDot.getTransform().getBaseVal().getItem(0).getMatrix(); points.appendItem(rootSvg.createSVGPoint(m.getE(), m.getF())); if (maxIndex + 1 == dots.size()) { // Level is succcessfully completed readPicture(false); } } currentDot = null; } } @Override public void onMouseMove(MouseMoveEvent event) { if (currentDot != null) { OMSVGPoint p1 = getLocalCoordinates(event).substract(mouseDownPoint).add(p0); // Update the dot position OMSVGMatrix m = currentDot.getTransform().getBaseVal().getItem(0).getMatrix(); m.setE(p1.getX()); m.setF(p1.getY()); // Update the polyline p1.assignTo(points.getItem(currentDotIndex)); } event.stopPropagation(); event.preventDefault(); } @Override public void onMouseUp(MouseUpEvent event) { if (currentDot != null) { DOMHelper.releaseCaptureElement(); currentDot = null; currentDotIndex = -1; } event.stopPropagation(); event.preventDefault(); } private static String toDotName(int pIndex) { return DotsConstants.INSTANCE.dot() + " #" + (pIndex + 1); } @UiFactory PushButton createPushButton(ImageResource image) { return new PushButton(new Image(image)); } /** * Removes all the child nodes of the svg document and * puts them in a group * @param svg the svg document root * @return the new group */ protected OMSVGGElement reparent(OMSVGSVGElement svg) { OMSVGGElement g = OMSVGParser.currentDocument().createSVGGElement(); Element gElement = g.getElement(); Element svgElement = svg.getElement(); Node node; while ((node = svgElement.getFirstChild()) != null) { gElement.appendChild(svgElement.removeChild(node)); } svgElement.appendChild(gElement); return g; } }