diff dwtx/jface/util/Geometry.d @ 4:c87617952847

some JFace modules
author Frank Benoit <benoit@tionex.de>
date Fri, 28 Mar 2008 17:08:33 +0100
parents
children da5ad8eedf5d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/util/Geometry.d	Fri Mar 28 17:08:33 2008 +0100
@@ -0,0 +1,812 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation 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:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module dwtx.jface.util.Geometry;
+
+import dwt.DWT;
+import dwt.graphics.Point;
+import dwt.graphics.Rectangle;
+import dwt.widgets.Control;
+
+import dwt.dwthelper.utils;
+import dwt.dwthelper.Integer;
+
+/**
+ * Contains static methods for performing simple geometric operations
+ * on the DWT geometry classes.
+ *
+ * @since 3.0
+ */
+public class Geometry {
+
+    /**
+     * Prevent this class from being instantiated.
+     *
+     * @since 3.0
+     */
+    private this() {
+        //This is not instantiated
+    }
+
+    /**
+     * Returns the square of the distance between two points.
+     * <p>This is preferred over the real distance when searching
+     * for the closest point, since it avoids square roots.</p>
+     *
+     * @param p1 first endpoint
+     * @param p2 second endpoint
+     * @return the square of the distance between the two points
+     *
+     * @since 3.0
+     */
+    public static int distanceSquared(Point p1, Point p2) {
+        int term1 = p1.x - p2.x;
+        int term2 = p1.y - p2.y;
+        return term1 * term1 + term2 * term2;
+    }
+
+    /**
+     * Returns the magnitude of the given 2d vector (represented as a Point)
+     *
+     * @param p point representing the 2d vector whose magnitude is being computed
+     * @return the magnitude of the given 2d vector
+     * @since 3.0
+     */
+    public static double magnitude(Point p) {
+        return Math.sqrt( cast(real) magnitudeSquared(p));
+    }
+
+    /**
+     * Returns the square of the magnitude of the given 2-space vector (represented
+     * using a point)
+     *
+     * @param p the point whose magnitude is being computed
+     * @return the square of the magnitude of the given vector
+     * @since 3.0
+     */
+    public static int magnitudeSquared(Point p) {
+        return p.x * p.x + p.y * p.y;
+    }
+
+    /**
+     * Returns the dot product of the given vectors (expressed as Points)
+     *
+     * @param p1 the first vector
+     * @param p2 the second vector
+     * @return the dot product of the two vectors
+     * @since 3.0
+     */
+    public static int dotProduct(Point p1, Point p2) {
+        return p1.x * p2.x + p1.y * p2.y;
+    }
+
+    /**
+     * Returns a new point whose coordinates are the minimum of the coordinates of the
+     * given points
+     *
+     * @param p1 a Point
+     * @param p2 a Point
+     * @return a new point whose coordinates are the minimum of the coordinates of the
+     * given points
+     * @since 3.0
+     */
+    public static Point min(Point p1, Point p2) {
+        return new Point(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y));
+    }
+
+    /**
+     * Returns a new point whose coordinates are the maximum of the coordinates
+     * of the given points
+     * @param p1 a Point
+     * @param p2 a Point
+     * @return point a new point whose coordinates are the maximum of the coordinates
+     * @since 3.0
+     */
+    public static Point max(Point p1, Point p2) {
+        return new Point(Math.max(p1.x, p2.x), Math.max(p1.y, p2.y));
+    }
+
+    /**
+     * Returns a vector in the given direction with the given
+     * magnitude. Directions are given using DWT direction constants, and
+     * the resulting vector is in the screen's coordinate system. That is,
+     * the vector (0, 1) is down and the vector (1, 0) is right.
+     *
+     * @param distance magnitude of the vector
+     * @param direction one of DWT.TOP, DWT.BOTTOM, DWT.LEFT, or DWT.RIGHT
+     * @return a point representing a vector in the given direction with the given magnitude
+     * @since 3.0
+     */
+    public static Point getDirectionVector(int distance, int direction) {
+        switch (direction) {
+        case DWT.TOP:
+            return new Point(0, -distance);
+        case DWT.BOTTOM:
+            return new Point(0, distance);
+        case DWT.LEFT:
+            return new Point(-distance, 0);
+        case DWT.RIGHT:
+            return new Point(distance, 0);
+        }
+
+        return new Point(0, 0);
+    }
+
+    /**
+     * Returns the point in the center of the given rectangle.
+     *
+     * @param rect rectangle being computed
+     * @return a Point at the center of the given rectangle.
+     * @since 3.0
+     */
+    public static Point centerPoint(Rectangle rect) {
+        return new Point(rect.x + rect.width / 2, rect.y + rect.height / 2);
+    }
+
+    /**
+     * Returns a copy of the given point
+     *
+     * @param toCopy point to copy
+     * @return a copy of the given point
+     */
+    public static Point copy(Point toCopy) {
+        return new Point(toCopy.x, toCopy.y);
+    }
+
+    /**
+     * Sets result equal to toCopy
+     *
+     * @param result object that will be modified
+     * @param toCopy object that will be copied
+     * @since 3.1
+     */
+    public static void set(Point result, Point toCopy) {
+        result.x = toCopy.x;
+        result.y = toCopy.y;
+    }
+
+    /**
+     * Sets result equal to toCopy
+     *
+     * @param result object that will be modified
+     * @param toCopy object that will be copied
+     * @since 3.1
+     */
+    public static void set(Rectangle result, Rectangle toCopy) {
+        result.x = toCopy.x;
+        result.y = toCopy.y;
+        result.width = toCopy.width;
+        result.height = toCopy.height;
+    }
+
+    /**
+     * <p>Returns a new difference Rectangle whose x, y, width, and height are equal to the difference of the corresponding
+     * attributes from the given rectangles</p>
+     *
+     * <p></p>
+     * <b>Example: Compute the margins for a given Composite, and apply those same margins to a new GridLayout</b>
+     *
+     * <code><pre>
+     *      // Compute the client area, in the coordinate system of the input composite's parent
+     *      Rectangle clientArea = Display.getCurrent().map(inputComposite,
+     *          inputComposite.getParent(), inputComposite.getClientArea());
+     *
+     *      // Compute the margins for a given Composite by subtracting the client area from the composite's bounds
+     *      Rectangle margins = Geometry.subtract(inputComposite.getBounds(), clientArea);
+     *
+     *      // Now apply these margins to a new GridLayout
+     *      GridLayout layout = GridLayoutFactory.fillDefaults().margins(margins).create();
+     * </pre></code>
+     *
+     * @param rect1 first rectangle
+     * @param rect2 rectangle to subtract
+     * @return the difference between the two rectangles (computed as rect1 - rect2)
+     * @since 3.3
+     */
+    public static Rectangle subtract(Rectangle rect1, Rectangle rect2) {
+        return new Rectangle(rect1.x - rect2.x, rect1.y - rect2.y, rect1.width - rect2.width, rect1.height - rect2.height);
+    }
+
+    /**
+     * <p>Returns a new Rectangle whose x, y, width, and height is the sum of the x, y, width, and height values of
+     * both rectangles respectively.</p>
+     *
+     * @param rect1 first rectangle to add
+     * @param rect2 second rectangle to add
+     * @return a new rectangle whose x, y, height, and width attributes are the sum of the corresponding attributes from
+     *         the arguments.
+     * @since 3.3
+     */
+    public static Rectangle add(Rectangle rect1, Rectangle rect2) {
+        return new Rectangle(rect1.x + rect2.x, rect1.y + rect2.y,
+                rect1.width + rect2.width, rect1.height + rect2.height);
+    }
+
+    /**
+     * Adds two points as 2d vectors. Returns a new point whose coordinates are
+     * the sum of the original two points.
+     *
+     * @param point1 the first point (not null)
+     * @param point2 the second point (not null)
+     * @return a new point whose coordinates are the sum of the given points
+     * @since 3.0
+     */
+    public static Point add(Point point1, Point point2) {
+        return new Point(point1.x + point2.x, point1.y + point2.y);
+    }
+
+    /**
+     * Divides both coordinates of the given point by the given scalar.
+     *
+     * @since 3.1
+     *
+     * @param toDivide point to divide
+     * @param scalar denominator
+     * @return a new Point whose coordinates are equal to the original point divided by the scalar
+     */
+    public static Point divide(Point toDivide, int scalar) {
+        return new Point(toDivide.x / scalar, toDivide.y / scalar);
+    }
+
+
+    /**
+     * Performs vector subtraction on two points. Returns a new point equal to
+     * (point1 - point2).
+     *
+     * @param point1 initial point
+     * @param point2 vector to subtract
+     * @return the difference (point1 - point2)
+     * @since 3.0
+     */
+    public static Point subtract(Point point1, Point point2) {
+        return new Point(point1.x - point2.x, point1.y - point2.y);
+    }
+
+    /**
+     * Swaps the X and Y coordinates of the given point.
+     *
+     * @param toFlip modifies this point
+     * @since 3.1
+     */
+    public static void flipXY(Point toFlip) {
+        int temp = toFlip.x;
+        toFlip.x = toFlip.y;
+        toFlip.y = temp;
+    }
+
+    /**
+     * Swaps the X and Y coordinates of the given rectangle, along with the height and width.
+     *
+     * @param toFlip modifies this rectangle
+     * @since 3.1
+     */
+    public static void flipXY(Rectangle toFlip) {
+        int temp = toFlip.x;
+        toFlip.x = toFlip.y;
+        toFlip.y = temp;
+
+        temp = toFlip.width;
+        toFlip.width = toFlip.height;
+        toFlip.height = temp;
+    }
+
+    /**
+     * Returns the height or width of the given rectangle.
+     *
+     * @param toMeasure rectangle to measure
+     * @param width returns the width if true, and the height if false
+     * @return the width or height of the given rectangle
+     * @since 3.0
+     */
+    public static int getDimension(Rectangle toMeasure, bool width) {
+        if (width) {
+            return toMeasure.width;
+        }
+        return toMeasure.height;
+    }
+
+    /**
+     * Returns the x or y coordinates of the given point.
+     *
+     * @param toMeasure point being measured
+     * @param width if true, returns x. Otherwise, returns y.
+     * @return the x or y coordinate
+     * @since 3.1
+     */
+    public static int getCoordinate(Point toMeasure, bool width) {
+        return width ? toMeasure.x : toMeasure.y;
+    }
+
+    /**
+     * Returns the x or y coordinates of the given rectangle.
+     *
+     * @param toMeasure rectangle being measured
+     * @param width if true, returns x. Otherwise, returns y.
+     * @return the x or y coordinate
+     * @since 3.1
+     */
+    public static int getCoordinate(Rectangle toMeasure, bool width) {
+        return width ? toMeasure.x : toMeasure.y;
+    }
+
+    /**
+     * Sets one dimension of the given rectangle. Modifies the given rectangle.
+     *
+     * @param toSet rectangle to modify
+     * @param width if true, the width is modified. If false, the height is modified.
+     * @param newCoordinate new value of the width or height
+     * @since 3.1
+     */
+    public static void setDimension(Rectangle toSet, bool width, int newCoordinate) {
+        if (width) {
+            toSet.width = newCoordinate;
+        } else {
+            toSet.height = newCoordinate;
+        }
+    }
+
+    /**
+     * Sets one coordinate of the given rectangle. Modifies the given rectangle.
+     *
+     * @param toSet rectangle to modify
+     * @param width if true, the x coordinate is modified. If false, the y coordinate is modified.
+     * @param newCoordinate new value of the x or y coordinates
+     * @since 3.1
+     */
+    public static void setCoordinate(Rectangle toSet, bool width, int newCoordinate) {
+        if (width) {
+            toSet.x = newCoordinate;
+        } else {
+            toSet.y = newCoordinate;
+        }
+    }
+
+    /**
+     * Sets one coordinate of the given point. Modifies the given point.
+     *
+     * @param toSet point to modify
+     * @param width if true, the x coordinate is modified. If false, the y coordinate is modified.
+     * @param newCoordinate new value of the x or y coordinates
+     * @since 3.1
+     */
+    public static void setCoordinate(Point toSet, bool width, int newCoordinate) {
+        if (width) {
+            toSet.x = newCoordinate;
+        } else {
+            toSet.y = newCoordinate;
+        }
+    }
+
+    /**
+     * Returns the distance of the given point from a particular side of the given rectangle.
+     * Returns negative values for points outside the rectangle.
+     *
+     * @param rectangle a bounding rectangle
+     * @param testPoint a point to test
+     * @param edgeOfInterest side of the rectangle to test against
+     * @return the distance of the given point from the given edge of the rectangle
+     * @since 3.0
+     */
+    public static int getDistanceFromEdge(Rectangle rectangle, Point testPoint,
+            int edgeOfInterest) {
+        switch (edgeOfInterest) {
+        case DWT.TOP:
+            return testPoint.y - rectangle.y;
+        case DWT.BOTTOM:
+            return rectangle.y + rectangle.height - testPoint.y;
+        case DWT.LEFT:
+            return testPoint.x - rectangle.x;
+        case DWT.RIGHT:
+            return rectangle.x + rectangle.width - testPoint.x;
+        }
+
+        return 0;
+    }
+
+    /**
+     * Extrudes the given edge inward by the given distance. That is, if one side of the rectangle
+     * was sliced off with a given thickness, this returns the rectangle that forms the slice. Note
+     * that the returned rectangle will be inside the given rectangle if size > 0.
+     *
+     * @param toExtrude the rectangle to extrude. The resulting rectangle will share three sides
+     * with this rectangle.
+     * @param size distance to extrude. A negative size will extrude outwards (that is, the resulting
+     * rectangle will overlap the original iff this is positive).
+     * @param orientation the side to extrude.  One of DWT.LEFT, DWT.RIGHT, DWT.TOP, or DWT.BOTTOM. The
+     * resulting rectangle will always share this side with the original rectangle.
+     * @return a rectangle formed by extruding the given side of the rectangle by the given distance.
+     * @since 3.0
+     */
+    public static Rectangle getExtrudedEdge(Rectangle toExtrude, int size,
+            int orientation) {
+        Rectangle bounds = new Rectangle(toExtrude.x, toExtrude.y,
+                toExtrude.width, toExtrude.height);
+
+        if (!isHorizontal(orientation)) {
+            bounds.width = size;
+        } else {
+            bounds.height = size;
+        }
+
+        switch (orientation) {
+        case DWT.RIGHT:
+            bounds.x = toExtrude.x + toExtrude.width - bounds.width;
+            break;
+        case DWT.BOTTOM:
+            bounds.y = toExtrude.y + toExtrude.height - bounds.height;
+            break;
+        }
+
+        normalize(bounds);
+
+        return bounds;
+    }
+
+    /**
+     * Returns the opposite of the given direction. That is, returns DWT.LEFT if
+     * given DWT.RIGHT and visa-versa.
+     *
+     * @param swtDirectionConstant one of DWT.LEFT, DWT.RIGHT, DWT.TOP, or DWT.BOTTOM
+     * @return one of DWT.LEFT, DWT.RIGHT, DWT.TOP, or DWT.BOTTOM
+     * @since 3.0
+     */
+    public static int getOppositeSide(int swtDirectionConstant) {
+        switch (swtDirectionConstant) {
+        case DWT.TOP:
+            return DWT.BOTTOM;
+        case DWT.BOTTOM:
+            return DWT.TOP;
+        case DWT.LEFT:
+            return DWT.RIGHT;
+        case DWT.RIGHT:
+            return DWT.LEFT;
+        }
+
+        return swtDirectionConstant;
+    }
+
+    /**
+     * Converts the given bool into an DWT orientation constant.
+     *
+     * @param horizontal if true, returns DWT.HORIZONTAL. If false, returns DWT.VERTICAL
+     * @return DWT.HORIZONTAL or DWT.VERTICAL.
+     * @since 3.0
+     */
+    public static int getSwtHorizontalOrVerticalConstant(bool horizontal) {
+        if (horizontal) {
+            return DWT.HORIZONTAL;
+        }
+        return DWT.VERTICAL;
+    }
+
+    /**
+     * Returns true iff the given DWT side constant corresponds to a horizontal side
+     * of a rectangle. That is, returns true for the top and bottom but false for the
+     * left and right.
+     *
+     * @param swtSideConstant one of DWT.TOP, DWT.BOTTOM, DWT.LEFT, or DWT.RIGHT
+     * @return true iff the given side is horizontal.
+     * @since 3.0
+     */
+    public static bool isHorizontal(int swtSideConstant) {
+        return !(swtSideConstant is DWT.LEFT || swtSideConstant is DWT.RIGHT);
+    }
+
+    /**
+     * Moves the given rectangle by the given delta.
+     *
+     * @param rect rectangle to move (will be modified)
+     * @param delta direction vector to move the rectangle by
+     * @since 3.0
+     */
+    public static void moveRectangle(Rectangle rect, Point delta) {
+        rect.x += delta.x;
+        rect.y += delta.y;
+    }
+
+    /**
+     * Moves each edge of the given rectangle outward by the given amount. Negative values
+     * cause the rectangle to contract. Does not allow the rectangle's width or height to be
+     * reduced below zero.
+     *
+     * @param rect normalized rectangle to modify
+     * @param differenceRect difference rectangle to be added to rect
+     * @since 3.3
+     */
+    public static void expand(Rectangle rect, Rectangle differenceRect) {
+        rect.x += differenceRect.x;
+        rect.y += differenceRect.y;
+        rect.height = Math.max(0, rect.height + differenceRect.height);
+        rect.width = Math.max(0, rect.width + differenceRect.width);
+    }
+
+    /**
+     * <p>Returns a rectangle which, when added to another rectangle, will expand each side
+     * by the given number of units.</p>
+     *
+     * <p>This is commonly used to store margin sizes. For example:</p>
+     *
+     * <code><pre>
+     *     // Expands the left, right, top, and bottom
+     *     // of the given control by 10, 5, 1, and 15 units respectively
+     *
+     *     Rectangle margins = Geometry.createDifferenceRect(10,5,1,15);
+     *     Rectangle bounds = someControl.getBounds();
+     *     someControl.setBounds(Geometry.add(bounds, margins));
+     * </pre></code>
+     *
+     * @param left distance to expand the left side (negative values move the edge inward)
+     * @param right distance to expand the right side (negative values move the edge inward)
+     * @param top distance to expand the top (negative values move the edge inward)
+     * @param bottom distance to expand the bottom (negative values move the edge inward)
+     *
+     * @return a difference rectangle that, when added to another rectangle, will cause each
+     * side to expand by the given number of units
+     * @since 3.3
+     */
+    public static Rectangle createDiffRectangle(int left, int right, int top, int bottom) {
+        return new Rectangle(-left, -top, left + right, top + bottom);
+    }
+
+    /**
+     * Moves each edge of the given rectangle outward by the given amount. Negative values
+     * cause the rectangle to contract. Does not allow the rectangle's width or height to be
+     * reduced below zero.
+     *
+     * @param rect normalized rectangle to modify
+     * @param left distance to move the left edge outward (negative values move the edge inward)
+     * @param right distance to move the right edge outward (negative values move the edge inward)
+     * @param top distance to move the top edge outward (negative values move the edge inward)
+     * @param bottom distance to move the bottom edge outward (negative values move the edge inward)
+     * @since 3.1
+     */
+    public static void expand(Rectangle rect, int left, int right, int top, int bottom) {
+        rect.x -= left;
+        rect.width = Math.max(0, rect.width + left + right);
+        rect.y -= top;
+        rect.height = Math.max(0, rect.height + top + bottom);
+    }
+
+    /**
+     * Normalizes the given rectangle. That is, any rectangle with
+     * negative width or height becomes a rectangle with positive
+     * width or height that extends to the upper-left of the original
+     * rectangle.
+     *
+     * @param rect rectangle to modify
+     * @since 3.0
+     */
+    public static void normalize(Rectangle rect) {
+        if (rect.width < 0) {
+            rect.width = -rect.width;
+            rect.x -= rect.width;
+        }
+
+        if (rect.height < 0) {
+            rect.height = -rect.height;
+            rect.y -= rect.height;
+        }
+    }
+
+    /**
+     * Converts the given rectangle from display coordinates to the local coordinate system
+     * of the given object into display coordinates.
+     *
+     * @param coordinateSystem local coordinate system being converted to
+     * @param toConvert rectangle to convert
+     * @return a rectangle in control coordinates
+     * @since 3.0
+     */
+    public static Rectangle toControl(Control coordinateSystem,
+            Rectangle toConvert) {
+        return(coordinateSystem.getDisplay().map
+                (null,coordinateSystem,toConvert));
+    }
+
+    /**
+     * Converts the given rectangle from the local coordinate system of the given object
+     * into display coordinates.
+     *
+     * @param coordinateSystem local coordinate system being converted from
+     * @param toConvert rectangle to convert
+     * @return a rectangle in display coordinates
+     * @since 3.0
+     */
+    public static Rectangle toDisplay(Control coordinateSystem,
+            Rectangle toConvert) {
+        return(coordinateSystem.getDisplay().map
+                (coordinateSystem,null,toConvert));
+
+    }
+
+    /**
+     * Determines where the given point lies with respect to the given rectangle.
+     * Returns a combination of DWT.LEFT, DWT.RIGHT, DWT.TOP, and DWT.BOTTOM, combined
+     * with bitwise or (for example, returns DWT.TOP | DWT.LEFT if the point is to the
+     * upper-left of the rectangle). Returns 0 if the point lies within the rectangle.
+     * Positions are in screen coordinates (ie: a point is to the upper-left of the
+     * rectangle if its x and y coordinates are smaller than any point in the rectangle)
+     *
+     * @param boundary normalized boundary rectangle
+     * @param toTest point whose relative position to the rectangle is being computed
+     * @return one of DWT.LEFT | DWT.TOP, DWT.TOP, DWT.RIGHT | DWT.TOP, DWT.LEFT, 0,
+     * DWT.RIGHT, DWT.LEFT | DWT.BOTTOM, DWT.BOTTOM, DWT.RIGHT | DWT.BOTTOM
+     * @since 3.0
+     */
+    public static int getRelativePosition(Rectangle boundary, Point toTest) {
+        int result = 0;
+
+        if (toTest.x < boundary.x) {
+            result |= DWT.LEFT;
+        } else if (toTest.x >= boundary.x + boundary.width) {
+            result |= DWT.RIGHT;
+        }
+
+        if (toTest.y < boundary.y) {
+            result |= DWT.TOP;
+        } else if (toTest.y >= boundary.y + boundary.height) {
+            result |= DWT.BOTTOM;
+        }
+
+        return result;
+    }
+
+    /**
+     * Returns the distance from the point to the nearest edge of the given
+     * rectangle. Returns negative values if the point lies outside the rectangle.
+     *
+     * @param boundary rectangle to test
+     * @param toTest point to test
+     * @return the distance between the given point and the nearest edge of the rectangle.
+     * Returns positive values for points inside the rectangle and negative values for points
+     * outside the rectangle.
+     * @since 3.1
+     */
+    public static int getDistanceFrom(Rectangle boundary, Point toTest) {
+        int side = getClosestSide(boundary, toTest);
+        return getDistanceFromEdge(boundary, toTest, side);
+    }
+
+    /**
+     * Returns the edge of the given rectangle is closest to the given
+     * point.
+     *
+     * @param boundary rectangle to test
+     * @param toTest point to compare
+     * @return one of DWT.LEFT, DWT.RIGHT, DWT.TOP, or DWT.BOTTOM
+     *
+     * @since 3.0
+     */
+    public static int getClosestSide(Rectangle boundary, Point toTest) {
+        int[] sides = [ DWT.LEFT, DWT.RIGHT, DWT.TOP, DWT.BOTTOM ];
+
+        int closestSide = DWT.LEFT;
+        int closestDistance = Integer.MAX_VALUE;
+
+        for (int idx = 0; idx < sides.length; idx++) {
+            int side = sides[idx];
+
+            int distance = getDistanceFromEdge(boundary, toTest, side);
+
+            if (distance < closestDistance) {
+                closestDistance = distance;
+                closestSide = side;
+            }
+        }
+
+        return closestSide;
+    }
+
+    /**
+     * Returns a copy of the given rectangle
+     *
+     * @param toCopy rectangle to copy
+     * @return a copy of the given rectangle
+     * @since 3.0
+     */
+    public static Rectangle copy(Rectangle toCopy) {
+        return new Rectangle(toCopy.x, toCopy.y, toCopy.width, toCopy.height);
+    }
+
+    /**
+     * Returns the size of the rectangle, as a Point
+     *
+     * @param rectangle rectangle whose size is being computed
+     * @return the size of the given rectangle
+     * @since 3.0
+     */
+    public static Point getSize(Rectangle rectangle) {
+        return new Point(rectangle.width, rectangle.height);
+    }
+
+    /**
+     * Sets the size of the given rectangle to the given size
+     *
+     * @param rectangle rectangle to modify
+     * @param newSize new size of the rectangle
+     * @since 3.0
+     */
+    public static void setSize(Rectangle rectangle, Point newSize) {
+        rectangle.width = newSize.x;
+        rectangle.height = newSize.y;
+    }
+
+    /**
+     * Sets the x,y position of the given rectangle. For a normalized
+     * rectangle (a rectangle with positive width and height), this will
+     * be the upper-left corner of the rectangle.
+     *
+     * @param rectangle rectangle to modify
+     * @param newSize new size of the rectangle
+     *
+     * @since 3.0
+     */
+    public static void setLocation(Rectangle rectangle, Point newSize) {
+        rectangle.width = newSize.x;
+        rectangle.height = newSize.y;
+    }
+
+    /**
+     * Returns the x,y position of the given rectangle. For normalized rectangles
+     * (rectangles with positive width and height), this is the upper-left
+     * corner of the rectangle.
+     *
+     * @param toQuery rectangle to query
+     * @return a Point containing the x,y position of the rectangle
+     *
+     * @since 3.0
+     */
+    public static Point getLocation(Rectangle toQuery) {
+        return new Point(toQuery.x, toQuery.y);
+    }
+
+    /**
+     * Returns a new rectangle with the given position and dimensions, expressed
+     * as points.
+     *
+     * @param position the (x,y) position of the rectangle
+     * @param size the size of the new rectangle, where (x,y) -> (width, height)
+     * @return a new Rectangle with the given position and size
+     *
+     * @since 3.0
+     */
+    public static Rectangle createRectangle(Point position, Point size) {
+        return new Rectangle(position.x, position.y, size.x, size.y);
+    }
+
+    /**
+     * Repositions the 'inner' rectangle to lie completely within the bounds of the 'outer'
+     * rectangle if possible. One use for this is to ensure that, when setting a control's bounds,
+     * that they will always lie within its parent's client area (to avoid clipping).
+     *
+     * @param inner The 'inner' rectangle to be repositioned (should be smaller than the 'outer' rectangle)
+     * @param outer The 'outer' rectangle
+     */
+    public static void moveInside(Rectangle inner, Rectangle outer) {
+        // adjust X
+        if (inner.x < outer.x) {
+            inner.x = outer.x;
+        }
+        if ((inner.x + inner.width) > (outer.x + outer.width)) {
+            inner.x -= (inner.x + inner.width) - (outer.x + outer.width);
+        }
+
+        // Adjust Y
+        if (inner.y < outer.y) {
+            inner.y = outer.y;
+        }
+        if ((inner.y + inner.height) > (outer.y + outer.height)) {
+            inner.y -= (inner.y + inner.height) - (outer.y + outer.height);
+        }
+    }
+
+}