Java tutorial
/******************************************************************************* * Copyright (c) 2011 itemis AG and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Matthias Wienand (itemis AG) - initial API and implementation * *******************************************************************************/ package examples.geometry.containment; import java.util.ArrayList; import org.eclipse.gef4.geometry.planar.Ellipse; import org.eclipse.gef4.geometry.planar.IGeometry; import org.eclipse.gef4.geometry.planar.Point; import com.google.gwt.canvas.client.Canvas; import com.google.gwt.canvas.dom.client.Context2d; import com.google.gwt.canvas.dom.client.CssColor; import com.google.gwt.core.shared.GWT; import com.google.gwt.event.dom.client.MouseDownEvent; import com.google.gwt.event.dom.client.MouseDownHandler; 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.EventBus; import examples.geometry.CanvasDrawer; import examples.geometry.GWTExample; public abstract class AbstractContainmentExample implements GWTExample { abstract public class AbstractControllableShape { private final CssColor CONTROL_POINT_COLOR = CssColor.make("blue"); private static final int CONTROL_POINT_RADIUS = 5; private Canvas canvas; ArrayList<ControlPoint> points; public AbstractControllableShape(Canvas canvas) { this.canvas = canvas; points = new ArrayList<ControlPoint>(); createControlPoints(); } public ControlPoint addControlPoint(Point p) { return addControlPoint(p, CONTROL_POINT_COLOR); } public ControlPoint addControlPoint(Point p, CssColor color) { return addControlPoint(p, color, CONTROL_POINT_RADIUS); } public ControlPoint addControlPoint(Point p, CssColor color, double radius) { ControlPoint cp = new ControlPoint(canvas, p, radius, color); for (ControlPoint ocp : points) { ocp.addForbiddenArea(cp); cp.addForbiddenArea(ocp); } points.add(cp); return cp; } abstract public void createControlPoints(); abstract public IGeometry createGeometry(); public void drawControlPoints() { for (ControlPoint cp : points) { cp.draw(canvas); } } abstract public void drawShape(); public void fillShape(CssColor color) { drawShape(); } public Canvas getCanvas() { return canvas; } public Point[] getControlPoints() { Point[] points = new Point[this.points.size()]; int i = 0; for (ControlPoint cp : this.points) { points[i++] = cp.getPoint(); } return points; } } /** * A draggable point. On the screen it is represented as an ellipse. * * @author wienand * */ class ControlPoint { private Canvas canvas; private CssColor color = CssColor.make("blue"); private Ellipse ellipse; private ArrayList<ControlPoint> forbidden; private ArrayList<ControlPoint> updateLinks; private ControlPoint xLink, yLink; private double relX, relY; private Point p; private double radius = 5; /** * Creates a new ControlPoint object. Adds event listeners to the given * Canvas object, so that the user can drag the control point with the * mouse. * * @param canvas * Drawing area * @param color2 * @param radius2 * @param p2 * @param control */ public ControlPoint(Canvas canvas) { this.canvas = canvas; p = new Point(0, 0); updateLinks = new ArrayList<ControlPoint>(); forbidden = new ArrayList<ControlPoint>(); update(); } /** * Creates a new ControlPoint object. Adds event listeners to the given * Canvas object, so that the user can drag the control point with the * mouse. * * @param canvas * Drawing area * @param p * Exact point * @param radius * Of the ellipse that represents the point * @param color * Of the ellipse that represents the point */ public ControlPoint(Canvas canvas, Point p, double radius, CssColor color) { this(canvas); this.p = p; this.radius = radius; this.color = color; update(); } public void addForbiddenArea(ControlPoint cp) { forbidden.add(cp); } /** * Draws an ellipse with the given GC at the control points location. * * @param gc */ public void draw(Canvas canvas) { Context2d context2d = canvas.getContext2d(); context2d.setFillStyle(color.value()); CanvasDrawer.drawOval(ellipse, context2d); context2d.fill(); } /** * Returns the exact Point of this ControlPoint object. * * @return The exact Point of this ControlPoint object. */ public Point getPoint() { return p; } private double inRange(double low, double value, double high) { if (value < low) { return low; } else if (value > high) { return high; } return value; } public void setXLink(ControlPoint cp) { xLink = cp; cp.updateLinks.add(this); } public void setYLink(ControlPoint cp) { yLink = cp; cp.updateLinks.add(this); } private void update() { double oldX = p.x, oldY = p.y; // check canvas pane: p.x = inRange(radius, p.x, canvas.getCoordinateSpaceWidth() - radius); p.y = inRange(radius, p.y, canvas.getCoordinateSpaceHeight() - radius); // check links: if (xLink != null) { p.x = xLink.p.x; p.y += xLink.relY; } else if (yLink != null) { // no need to link both x and y p.x += yLink.relX; p.y = yLink.p.y; } // check forbidden areas: for (ControlPoint cp : forbidden) { double minDistance = radius + cp.radius; if (p.getDistance(cp.p) < minDistance) { if (relX > 0) { p.x = cp.p.x - minDistance; } else if (relX < 0) { p.x = cp.p.x + minDistance; } else if (relY > 0) { p.y = cp.p.y - minDistance; } else { p.y = cp.p.y + minDistance; } } } relX += p.x - oldX; relY += p.y - oldY; for (ControlPoint cp : updateLinks) { cp.update(); } ellipse = new Ellipse(p.x - radius, p.y - radius, radius * 2, radius * 2); } } private static final CssColor INTERSECTS_COLOR = CssColor.make("yellow"); private static final CssColor CONTAINS_COLOR = CssColor.make("green"); private AbstractControllableShape controllableShape1, controllableShape2; private Canvas canvas; private EventBus eventBus; private ControlPoint currentControl = null; /** * */ public AbstractContainmentExample(EventBus eventBus, Canvas canvas) { this.canvas = canvas; this.eventBus = eventBus; controllableShape1 = createControllableShape1(canvas); controllableShape2 = createControllableShape2(canvas); init(); } protected abstract boolean computeContains(IGeometry g1, IGeometry g2); protected abstract boolean computeIntersects(IGeometry g1, IGeometry g2); protected abstract AbstractControllableShape createControllableShape1(Canvas canvas); protected abstract AbstractControllableShape createControllableShape2(Canvas canvas); private void init() { // eventBus.addHandler(DrawEvent.TYPE, new DrawEventHandler() { // @Override // public void onDraw() { // draw(); // } // }); canvas.addMouseDownHandler(new MouseDownHandler() { @Override public void onMouseDown(MouseDownEvent event) { int x = event.getX(); int y = event.getY(); for (ControlPoint cp : controllableShape1.points) { if (cp.ellipse.contains(new Point(x, y))) { currentControl = cp; return; } } if (currentControl == null) { for (ControlPoint cp : controllableShape2.points) { if (cp.ellipse.contains(new Point(x, y))) { currentControl = cp; return; } } } } }); canvas.addMouseMoveHandler(new MouseMoveHandler() { @Override public void onMouseMove(MouseMoveEvent event) { int x = event.getX(); int y = event.getY(); if (currentControl != null) { currentControl.relX = x - currentControl.p.x; currentControl.relY = y - currentControl.p.y; currentControl.p.x = x; currentControl.p.y = y; currentControl.update(); GWT.log("call draw"); draw(); } } }); canvas.addMouseUpHandler(new MouseUpHandler() { @Override public void onMouseUp(MouseUpEvent event) { currentControl = null; } }); } @Override public void draw() { Context2d context2d = canvas.getContext2d(); context2d.clearRect(0, 0, canvas.getCoordinateSpaceWidth(), canvas.getCoordinateSpaceWidth()); IGeometry cs1geometry = controllableShape1.createGeometry(); IGeometry cs2geometry = controllableShape2.createGeometry(); if (computeIntersects(cs1geometry, cs2geometry)) { controllableShape2.fillShape(INTERSECTS_COLOR); } if (computeContains(cs1geometry, cs2geometry)) { controllableShape2.fillShape(CONTAINS_COLOR); } controllableShape1.drawShape(); controllableShape2.drawShape(); controllableShape1.drawControlPoints(); controllableShape2.drawControlPoints(); } }