All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nakedobjects.nos.client.dnd.drawing.Bounds Maven / Gradle / Ivy

package org.nakedobjects.nos.client.dnd.drawing;


import org.apache.log4j.Logger;


/**
 * Bounds represent a rectangular area on the screen. The top-left corner is represented by the location
 * (available using getLocation(), and getX() and getY()). The extent of the bounds is specified by its height
 * and width (available using getHeight() and getWidth()). The bottom-right point is the offset from the
 * top-left point by width -1 and hieght - 1 pixels.
 * 
 * For example a bounds created as follows
 * 
 * new Bounds(5, 10, 10, 20)
 * 
 * Would represent a rectangle at location (5, 10), with a width of 10 pixels and a height of 20. Note, hower
 * that the lower-right corner would be at (14, 29), as there are 10 pixels between pixel 5 and pixel 14, and
 * 20 between 10 and 29.
 */
public class Bounds {
    int height;

    Logger LOG = Logger.getLogger("Bounds");
    int width;
    int x;
    int y;

    public Bounds() {
        x = 0;
        y = 0;
        width = 0;
        height = 0;
    }

    public Bounds(final Bounds bounds) {
        this(bounds.x, bounds.y, bounds.width, bounds.height);
    }

    public Bounds(final int x, final int y, final int width, final int height) {
        super();
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    public Bounds(final Location location, final Size size) {
        this(location.x, location.y, size.width, size.height);
    }

    public Bounds(final Size size) {
        this(0, 0, size.width, size.height);
    }

    public boolean contains(final Location location) {
        int xp = location.getX();
        int yp = location.getY();
        int xMax = x + width - 1;
        int yMax = y + height - 1;

        return xp >= x && xp <= xMax && yp >= y && yp <= yMax;
    }

    public void contract(final int width, final int height) {
        this.width -= width;
        this.height -= height;
    }

    public void contract(final Padding padding) {
        height -= padding.top + padding.bottom;
        width -= padding.left + padding.right;
        x += padding.left;
        y += padding.top;
    }

    public void contract(final Size size) {
        this.width -= size.width;
        this.height -= size.height;
    }

    public void contractHeight(final int height) {
        this.height -= height;
    }

    public void contractWidth(final int width) {
        this.width -= width;
    }

    public void ensureHeight(final int height) {
        this.height = Math.max(this.height, height);
    }

    public void ensureWidth(final int width) {
        this.width = Math.max(this.width, width);
    }

    public boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }

        if (obj instanceof Bounds) {
            Bounds b = (Bounds) obj;

            return b.x == x && b.y == y && b.width == width && b.height == height;
        }

        return false;
    }

    public void extend(final int width, final int height) {
        this.width += width;
        this.height += height;
    }

    public void extend(final Padding padding) {
        this.width += padding.getLeftRight();
        this.height += padding.getTopBottom();
    }

    public void extend(final Size size) {
        this.width += size.width;
        this.height += size.height;
    }

    public void extendHeight(final int height) {
        this.height += height;
    }

    public void extendWidth(final int width) {
        this.width += width;
    }

    public int getHeight() {
        return height;
    }

    public Location getLocation() {
        return new Location(x, y);
    }

    public Size getSize() {
        return new Size(width, height);
    }

    public int getWidth() {
        return width;
    }

    public int getX() {
        return x;
    }

    public int getX2() {
        return x + width - 1;
    }

    public int getY() {
        return y;
    }

    public int getY2() {
        return y + height - 1;
    }

    /**
     * Determines whether this bounds overlaps the specified bounds. If any area is shared by the two bounds
     * then this will return true. As the edges of the bounds are of a finite size the bounds overlap if any
     * of the edges overlap.
     */
    public boolean intersects(final Bounds bounds) {
        int tx1 = this.x;
        int tx2 = this.x + this.width - 1;
        int ox1 = bounds.x;
        int ox2 = bounds.x + bounds.width - 1;

        // tx1 < ox1 < tx2 || tx1 < ox2 < tx2
        boolean xOverlap = (tx1 <= ox1 && ox1 <= tx2) || (tx1 <= ox2 && ox1 <= tx2) || (ox1 <= tx1 && tx1 <= ox2)
                || (ox1 <= tx2 && tx1 <= ox2);

        int ty1 = this.y;
        int ty2 = this.y + this.height - 1;
        int oy1 = bounds.y;
        int oy2 = bounds.y + bounds.height - 1;
        boolean yOverlap = (ty1 <= oy1 && oy1 <= ty2) || (ty1 <= oy2 && oy1 <= ty2) || (oy1 <= ty1 && ty1 <= oy2)
                || (oy1 <= ty2 && ty1 <= oy2);
        return xOverlap && yOverlap;

    }

    public void limitLocation(final Size bounds) {
        if (x + width > bounds.width) {
            x = bounds.width - width;
        }
        if (y + height > bounds.height) {
            y = bounds.height - height;
        }
    }

    /**
     * Limits the specified bounds so that it fits within this bounds.
     */
    public boolean limitBounds(final Bounds toLimit) {
        boolean limited = false;
        Location location = toLimit.getLocation();
        Size size = toLimit.getSize();

        int viewLeft = location.getX();
        int viewTop = location.getY();
        int viewRight = viewLeft + size.getWidth();
        int viewBottom = viewTop + size.getHeight();

        Size wd = getSize();

        int limitLeft = x;
        int limitTop = y;
        int limitRight = x + width;
        int limitBottom = y + height;

        if (viewRight > limitRight) {
            viewLeft = limitRight - size.getWidth();
            limited = true;
            LOG.info("right side oustide limits, moving left to " + viewLeft);
        }

        if (viewLeft < limitLeft) {
            viewLeft = limitLeft;
            limited = true;
            LOG.info("left side outside limit, moving left to " + viewLeft);
        }

        if (viewBottom > limitBottom) {
            viewTop = limitBottom - size.getHeight();
            limited = true;
            LOG.info("bottom outside limit, moving top to " + viewTop);
        }

        if (viewTop < limitTop) {
            viewTop = limitTop;
            limited = true;
            LOG.info("top outside limit, moving top to " + viewTop);
        }

        toLimit.setX(viewLeft);
        toLimit.setY(viewTop);

        viewBottom = viewTop + size.getHeight();
        viewRight = viewLeft + size.getWidth();

        if (viewRight > limitRight) {
            toLimit.width = wd.width;
            limited = true;
            LOG.info("width outside limit, reducing width to " + viewTop);
        }

        if (viewBottom > limitBottom) {
            toLimit.height = wd.height;
            limited = true;
            LOG.info("height outside limit, reducing height to " + viewTop);
        }

        if (limited) {
            LOG.info("limited " + toLimit);
        }
        return limited;
    }

    public void setBounds(final Bounds bounds) {
        x = bounds.x;
        y = bounds.y;
        width = bounds.width;
        height = bounds.height;

    }

    public void setHeight(final int height) {
        this.height = height;
    }

    public void setWidth(final int width) {
        this.width = width;
    }

    public void setX(final int x) {
        this.x = x;
    }

    public void setY(final int y) {
        this.y = y;
    }

    public String toString() {
        return x + "," + y + " " + width + "x" + height;
    }

    public void translate(final int x, final int y) {
        this.x += x;
        this.y += y;
    }

    public void union(final Bounds bounds) {
        int newX = Math.min(x, bounds.x);
        int newY = Math.min(y, bounds.y);
        width = Math.max(x + width, bounds.x + bounds.width) - newX;
        height = Math.max(y + height, bounds.y + bounds.height) - newY;
        x = newX;
        y = newY;
    }

}
// Copyright (c) Naked Objects Group Ltd.




© 2015 - 2025 Weber Informatics LLC | Privacy Policy