/******************************************************************************* * MontiCore Language Workbench * Copyright (c) 2015, 2016, MontiCore, All rights reserved. * * This project is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this project. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ package de.monticore.genericgraphics.view.figures.connections.locators; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.Locator; import org.eclipse.draw2d.PolylineConnection; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PointList; import org.eclipse.draw2d.geometry.Rectangle; /** * A {@link Locator} implementation that can handle * <ul> * <li>a position given as {@link ConnectionLocatorPosition}</li> * <li>a offset given as a {@link Point}</li> * </ul> * for a given {@link PolylineConnection} on which a {@link IFigure} should be * placed at the position, with the offset. * * @author Tim Enger */ public class ConnectionLabelLocator implements Locator { private ConnectionLocatorPosition position; private Point offset; private PolylineConnection connection; private IFigure figure; /** * Constructor * * @param connection The {@link PolylineConnection} * @param position The {@link ConnectionLocatorPosition} where the figure * should be located * @param figure The {@link IFigure} that should be placed at this location * @param offset The offset as {@link Point} */ public ConnectionLabelLocator(PolylineConnection connection, ConnectionLocatorPosition position, Point offset, IFigure figure) { this.connection = connection; this.position = position; this.offset = offset; this.figure = figure; } /** * Constructor without setting the offset * * @param connection The {@link PolylineConnection} * @param position The {@link ConnectionLocatorPosition} where the figure * should be located * @param figure The {@link IFigure} that should be placed at this location */ public ConnectionLabelLocator(PolylineConnection connection, ConnectionLocatorPosition position, IFigure figure) { this.connection = connection; this.position = position; this.figure = figure; } @Override public void relocate(IFigure target) { target.setSize(target.getPreferredSize()); Point location = getLocation(); if (offset != null) { location.translate(offset); } target.setLocation(location); target.repaint(); } /** * Set new offset. * * @param offset The offset to set */ public void setOffset(Point offset) { this.offset = offset; } /** * Set new offset. * * @param x The x position * @param y The y position */ public void setOffset(int x, int y) { setOffset(new Point(x, y)); } /** * Set new offset by computing the distance to the from the connection * location and this point. * * @param point The {@link Point} from which the new offset has to be computed */ public void setOffsetFromPoint(Point point) { Point location = getLocation(); if (location != null) { Dimension diff; diff = point.getDifference(location); offset = new Point(diff.width, diff.height); } } /** * Set new offset by computing the distance to the from the connection * location and this point, given by x and y. * * @param x The x position * @param y The y position */ public void setOffsetFromPoint(int x, int y) { setOffsetFromPoint(new Point(x, y)); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("ConnectionLabelLocator> "); sb.append("position: "); sb.append(position); sb.append(" offset: "); sb.append(offset); return sb.toString(); } private Point getLocation() { return getLocation(position, connection, figure); } /** * Helper method for returning a {@link Point} that corresponds to the given * {@link ConnectionLocatorPosition} on the given {@link PolylineConnection}. * * @param position The {@link ConnectionLocatorPosition} * @param connection The {@link PolylineConnection} * @param figure The {@link IFigure} that should be placed at this location * @return The {@link Point} corresponding to the position and connection */ public static Point getLocation(ConnectionLocatorPosition position, PolylineConnection connection, IFigure figure) { Point location = null; PointList points = connection.getPoints(); Rectangle bounds = figure.getBounds(); switch (position) { case SOURCE: location = connection.getStart().getCopy(); break; case BEFORE_SOURCE_UP: // choose the middle between mid & target Point startu = connection.getStart().getCopy(); Point midsu = points.getPoint(1); location = startu.getTranslated(midsu).scale(0.5f); location.x -= bounds.width / 2; location.y -= bounds.height / 2; break; case BEFORE_SOURCE_DOWN: // choose the middle between mid & target Point startd = connection.getStart().getCopy(); Point midsd = points.getPoint(1); location = startd.getTranslated(midsd).scale(0.5f); location.x -= bounds.width / 2; location.y -= bounds.height / 2; break; case MIDDLE_DOWN: location = connection.getPoints().getMidpoint().getCopy(); location.x -= bounds.width / 2; location.y += bounds.height / 2; break; case MIDDLE_UP: location = connection.getPoints().getMidpoint().getCopy(); location.x -= bounds.width / 2; location.y -= bounds.height / 2; break; case BEFORE_TARGET_UP: // choose the middle between mid & target Point endu = connection.getEnd().getCopy(); Point mideu = points.getPoint(points.size() - 2); location = mideu.getTranslated(endu).scale(0.5f); location.x -= bounds.width / 2; location.y -= bounds.height / 2; break; case BEFORE_TARGET_DOWN: // choose the middle between mid & target Point endd = connection.getEnd().getCopy(); Point mided = points.getPoint(points.size() - 2); location = mided.getTranslated(endd).scale(0.5f); location.x -= bounds.width / 2; location.y -= bounds.height / 2; break; case TARGET: location = connection.getEnd().getCopy(); break; default: break; } return location; } }