/*******************************************************************************
* Copyright (c) 2014, 2015 Cisco Systems, Inc. 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
*
*******************************************************************************/
package com.cisco.yangide.ext.model.editor.util.connection;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
/**
* <pre>
* The position information:
* - point
* - direction
* - assigned obstacle
* </pre>
*/
public class Position {
/**
* Enumeration of the rectilinear directions (UP, RIGHT, DOWN, LEFT)
*/
public enum Direction {
UP, RIGHT, DOWN, LEFT
}
private Point point;
private final Direction direction;
private final Rectangle obstacle;
/**
* Create new {@code Position} using specified {@code point}, {@code direction} and
* {@code obstacle}
*
* @param point - the ray start point
* @param direction - the ray direction
* @param obstacle - the area assigned with figure - source of the ray
*/
private Position(Point point, Direction direction, Rectangle obstacle) {
this.point = point;
this.direction = direction;
this.obstacle = obstacle;
}
/**
* Gets the point
*
* @return the point
*/
public Point getPoint() {
return point;
}
/**
* Gets the direction
*
* @return the direction
*/
public Direction getDirection() {
return direction;
}
/**
* Gets the obstacle: the area assigned with figure - source of the ray
*
* @return the obstacle: the area assigned with figure - source of the ray
*/
public Rectangle getObstacle() {
return obstacle;
}
/**
* Checks, is {@code direction} not specified or horizontal
*
* @return {@code true} in case direction not specified or horizontal and {@code false}
* otherwise
*/
public boolean isHorizontal() {
return direction == null || direction == Direction.RIGHT || direction == Direction.LEFT;
}
/**
* Checks, is {@code direction} not specified or vertical
*
* @return {@code true} in case direction not specified or vertical and {@code false} otherwise
*/
public boolean isVertical() {
return direction == null || direction == Direction.UP || direction == Direction.DOWN;
}
/**
* Factory method for create new instance of the {@code Position} using {@code point} and
* {@code obstacle}. Calculates the rectangle side nearest to a point and sets the ray direction
* to opposite. If {@code obstacle} is {@code null} then Ray with empty direction will created.
*
* @param obstacle the area assigned with figure - source of the ray
* @param point the point of ray
* @return new instance of the {@code Position}
*/
public static Position create(Rectangle obstacle, Point point) {
if (obstacle == null) {
return new Position(point, null, null);
}
int minDistance = Math.abs(obstacle.x() - point.x());
Direction direction = Direction.LEFT;
int distance = Math.abs(obstacle.right() - point.x());
if (distance < minDistance) {
minDistance = distance;
direction = Direction.RIGHT;
}
distance = Math.abs(obstacle.y() - point.y());
if (distance < minDistance) {
minDistance = distance;
direction = Direction.UP;
}
distance = Math.abs(obstacle.bottom() - point.y());
if (distance < minDistance) {
minDistance = distance;
direction = Direction.DOWN;
}
return new Position(point.getCopy(), direction, obstacle);
}
/**
* @return a copy of this Position
*/
public Position getCopy() {
return new Position(point.getCopy(), direction, obstacle);
}
/**
* Shifts the start point by the specified {@code length} using the current direction.
*
* @param length - a length
* @return <code>this</code> for convenience
*/
public Position moveOnDirection(int length) {
if (direction == null) {
return this;
}
switch (direction) {
case LEFT:
point.translate(-length, 0);
break;
case RIGHT:
point.translate(length, 0);
break;
case UP:
point.translate(0, -length);
break;
case DOWN:
point.translate(0, length);
break;
}
return this;
}
/**
* Returns the string in the format: "(<x>,<y>) <direction>"
*/
@Override
public String toString() {
return String.format("(%d,%d) %s", point.x, point.y, direction);
}
}