examples.geometry.containment.AbstractContainmentExample.java Source code

Java tutorial

Introduction

Here is the source code for examples.geometry.containment.AbstractContainmentExample.java

Source

/*******************************************************************************
 * 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();
    }

}