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

com.dlsc.gemsfx.util.Utils Maven / Gradle / Ivy

There is a newer version: 2.67.0
Show newest version
/*
 * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.dlsc.gemsfx.util;

import javafx.geometry.BoundingBox;
import javafx.geometry.Bounds;
import javafx.geometry.HPos;
import javafx.geometry.NodeOrientation;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.paint.Stop;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.Window;

import java.util.List;

/**
 * Some basic utilities which need to be in java (for shifting operations or
 * other reasons), which are not toolkit dependent.
 */
public class Utils {

    /***************************************************************************
     *                                                                         *
     * Math-related utilities                                                  *
     *                                                                         *
     **************************************************************************/

    /**
     * Simple utility function which clamps the given value to be strictly
     * between the min and max values.
     */
    public static float clamp(float min, float value, float max) {
        if (value < min) return min;
        if (value > max) return max;
        return value;
    }

    /**
     * Simple utility function which clamps the given value to be strictly
     * between the min and max values.
     */
    public static int clamp(int min, int value, int max) {
        if (value < min) return min;
        if (value > max) return max;
        return value;
    }

    /**
     * Simple utility function which clamps the given value to be strictly
     * between the min and max values.
     */
    public static double clamp(double min, double value, double max) {
        if (value < min) return min;
        if (value > max) return max;
        return value;
    }

    /**
     * Simple utility function which clamps the given value to be strictly
     * between the min and max values.
     */
    public static long clamp(long min, long value, long max) {
        if (value < min) return min;
        if (value > max) return max;
        return value;
    }

    /**
     * Simple utility function which clamps the given value to be strictly
     * above the min value.
     */
    public static double clampMin(double value, double min) {
        if (value < min) return min;
        return value;
    }

    /**
     * Simple utility function which clamps the given value to be strictly
     * under the max value.
     */
    public static int clampMax(int value, int max) {
        if (value > max) return max;
        return value;
    }

    /**
     * Utility function which returns either {@code less} or {@code more}
     * depending on which {@code value} is closer to. If {@code value}
     * is perfectly between them, then either may be returned.
     */
    public static double nearest(double less, double value, double more) {
        double lessDiff = value - less;
        double moreDiff = more - value;
        if (lessDiff < moreDiff) return less;
        return more;
    }

    /***************************************************************************
     *                                                                         *
     * String-related utilities                                                *
     *                                                                         *
     **************************************************************************/

    /**
     * Helper to remove leading and trailing quotes from a string.
     * Works with single or double quotes.
     */
    public static String stripQuotes(String str) {
        if (str == null) return str;
        if (str.isEmpty()) return str;

        int beginIndex = 0;
        char openQuote = str.charAt(beginIndex);
        if (openQuote == '\"' || openQuote == '\'') beginIndex += 1;

        int endIndex = str.length();
        char closeQuote = str.charAt(endIndex - 1);
        if (closeQuote == '\"' || closeQuote == '\'') endIndex -= 1;

        if ((endIndex - beginIndex) < 0) return str;

        // note that String.substring returns "this" if beginIndex == 0 && endIndex == count
        // or a new string that shares the character buffer with the original string.
        return str.substring(beginIndex, endIndex);
    }

    /**
     * Because mobile doesn't have string.split(s) function, this function
     * was written.
     */
    public static String[] split(String str, String separator) {
        if (str == null || str.length() == 0) return new String[]{};
        if (separator == null || separator.length() == 0) return new String[]{};
        if (separator.length() > str.length()) return new String[]{};

        List result = new java.util.ArrayList();

        int index = str.indexOf(separator);
        while (index >= 0) {
            String newStr = str.substring(0, index);
            if (!newStr.isEmpty()) {
                result.add(newStr);
            }
            str = str.substring(index + separator.length());
            index = str.indexOf(separator);
        }

        if (!str.isEmpty()) {
            result.add(str);
        }

        return result.toArray(new String[]{});
    }

    /**
     * Because mobile doesn't have string.contains(s) function, this function
     * was written.
     */
    public static boolean contains(String src, String s) {
        if (src == null || src.length() == 0) return false;
        if (s == null || s.length() == 0) return false;
        if (s.length() > src.length()) return false;

        return src.indexOf(s) > -1;
    }

    /***************************************************************************
     *                                                                         *
     * Color-related utilities                                                 *
     *                                                                         *
     **************************************************************************/

    /**
     * Calculates a perceptual brightness for a color between 0.0 black and 1.0 while
     */
    public static double calculateBrightness(Color color) {
        return (0.3 * color.getRed()) + (0.59 * color.getGreen()) + (0.11 * color.getBlue());
    }

    /**
     * Derives a lighter or darker of a given color.
     *
     * @param c          The color to derive from
     * @param brightness The brightness difference for the new color -1.0 being 100% dark which is always black, 0.0 being
     *                   no change and 1.0 being 100% lighter which is always white
     */
    public static Color deriveColor(Color c, double brightness) {
        double baseBrightness = calculateBrightness(c);
        double calcBrightness = brightness;
        // Fine adjustments to colors in ranges of brightness to adjust the contrast for them
        if (brightness > 0) {
            if (baseBrightness > 0.85) {
                calcBrightness = calcBrightness * 1.6;
            } else if (baseBrightness > 0.6) {
                // no change
            } else if (baseBrightness > 0.5) {
                calcBrightness = calcBrightness * 0.9;
            } else if (baseBrightness > 0.4) {
                calcBrightness = calcBrightness * 0.8;
            } else if (baseBrightness > 0.3) {
                calcBrightness = calcBrightness * 0.7;
            } else {
                calcBrightness = calcBrightness * 0.6;
            }
        } else {
            if (baseBrightness < 0.2) {
                calcBrightness = calcBrightness * 0.6;
            }
        }
        // clamp brightness
        if (calcBrightness < -1) {
            calcBrightness = -1;
        } else if (calcBrightness > 1) {
            calcBrightness = 1;
        }
        // window two take the calculated brightness multiplyer and derive color based on source color
        double[] hsb = RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue());
        // change brightness
        if (calcBrightness > 0) { // brighter
            hsb[1] *= 1 - calcBrightness;
            hsb[2] += (1 - hsb[2]) * calcBrightness;
        } else { // darker
            hsb[2] *= calcBrightness + 1;
        }
        // clip saturation and brightness
        if (hsb[1] < 0) {
            hsb[1] = 0;
        } else if (hsb[1] > 1) {
            hsb[1] = 1;
        }
        if (hsb[2] < 0) {
            hsb[2] = 0;
        } else if (hsb[2] > 1) {
            hsb[2] = 1;
        }
        // convert back to color
        Color c2 = Color.hsb((int) hsb[0], hsb[1], hsb[2], c.getOpacity());
        return Color.hsb((int) hsb[0], hsb[1], hsb[2], c.getOpacity());

     /*   var hsb:Number[] = RGBtoHSB(c.red,c.green,c.blue);
        // change brightness
        if (brightness > 0) {
            //var bright:Number = brightness * (1-calculateBrightness(c));
            var bright:Number = if (calculateBrightness(c)<0.65 and brightness > 0.5) {
                    if (calculateBrightness(c)<0.2) then brightness * 0.55 else brightness * 0.7
            } else brightness;
            // brighter
            hsb[1] *= 1 - bright;
            hsb[2] += (1 - hsb[2]) * bright;
        } else {
            // darker
            hsb[2] *= brightness+1;
        }
        // clip saturation and brightness
        if (hsb[1] < 0) { hsb[1] = 0;} else if (hsb[1] > 1) {hsb[1] = 1}
        if (hsb[2] < 0) { hsb[2] = 0;} else if (hsb[2] > 1) {hsb[2] = 1}
        // convert back to color
        return Color.hsb(hsb[0],hsb[1],hsb[2]) */
    }

    /**
     * interpolate at a set {@code position} between two colors {@code color1} and {@code color2}.
     * The interpolation is done is linear RGB color space not the default sRGB color space.
     */
    private static Color interpolateLinear(double position, Color color1, Color color2) {
        Color c1Linear = convertSRGBtoLinearRGB(color1);
        Color c2Linear = convertSRGBtoLinearRGB(color2);
        return convertLinearRGBtoSRGB(Color.color(
                c1Linear.getRed() + (c2Linear.getRed() - c1Linear.getRed()) * position,
                c1Linear.getGreen() + (c2Linear.getGreen() - c1Linear.getGreen()) * position,
                c1Linear.getBlue() + (c2Linear.getBlue() - c1Linear.getBlue()) * position,
                c1Linear.getOpacity() + (c2Linear.getOpacity() - c1Linear.getOpacity()) * position
        ));
    }

    /**
     * Get the color at the give {@code position} in the ladder of color stops
     */
    private static Color ladder(double position, Stop[] stops) {
        Stop prevStop = null;
        for (int i = 0; i < stops.length; i++) {
            Stop stop = stops[i];
            if (position <= stop.getOffset()) {
                if (prevStop == null) {
                    return stop.getColor();
                } else {
                    return interpolateLinear((position - prevStop.getOffset()) / (stop.getOffset() - prevStop.getOffset()), prevStop.getColor(), stop.getColor());
                }
            }
            prevStop = stop;
        }

        // position is greater than biggest stop, so will we biggest stop's color
        if (prevStop != null) {
            return prevStop.getColor();
        }

        return null;
    }

    /**
     * Get the color at the give {@code position} in the ladder of color stops
     */
    public static Color ladder(Color color, Stop[] stops) {
        return ladder(calculateBrightness(color), stops);
    }

    public static double[] HSBtoRGB(double hue, double saturation, double brightness) {
        // normalize the hue
        double normalizedHue = ((hue % 360) + 360) % 360;
        hue = normalizedHue / 360;

        double r = 0, g = 0, b = 0;
        if (saturation == 0) {
            r = g = b = brightness;
        } else {
            double h = (hue - Math.floor(hue)) * 6.0;
            double f = h - Math.floor(h);
            double p = brightness * (1.0 - saturation);
            double q = brightness * (1.0 - saturation * f);
            double t = brightness * (1.0 - (saturation * (1.0 - f)));
            switch ((int) h) {
                case 0:
                    r = brightness;
                    g = t;
                    b = p;
                    break;
                case 1:
                    r = q;
                    g = brightness;
                    b = p;
                    break;
                case 2:
                    r = p;
                    g = brightness;
                    b = t;
                    break;
                case 3:
                    r = p;
                    g = q;
                    b = brightness;
                    break;
                case 4:
                    r = t;
                    g = p;
                    b = brightness;
                    break;
                case 5:
                    r = brightness;
                    g = p;
                    b = q;
                    break;
            }
        }
        double[] f = new double[3];
        f[0] = r;
        f[1] = g;
        f[2] = b;
        return f;
    }

    public static double[] RGBtoHSB(double r, double g, double b) {
        double hue, saturation, brightness;
        double[] hsbvals = new double[3];
        double cmax = (r > g) ? r : g;
        if (b > cmax) cmax = b;
        double cmin = (r < g) ? r : g;
        if (b < cmin) cmin = b;

        brightness = cmax;
        if (cmax != 0)
            saturation = (cmax - cmin) / cmax;
        else
            saturation = 0;

        if (saturation == 0) {
            hue = 0;
        } else {
            double redc = (cmax - r) / (cmax - cmin);
            double greenc = (cmax - g) / (cmax - cmin);
            double bluec = (cmax - b) / (cmax - cmin);
            if (r == cmax)
                hue = bluec - greenc;
            else if (g == cmax)
                hue = 2.0 + redc - bluec;
            else
                hue = 4.0 + greenc - redc;
            hue = hue / 6.0;
            if (hue < 0)
                hue = hue + 1.0;
        }
        hsbvals[0] = hue * 360;
        hsbvals[1] = saturation;
        hsbvals[2] = brightness;
        return hsbvals;
    }

    /**
     * Helper function to convert a color in sRGB space to linear RGB space.
     */
    public static Color convertSRGBtoLinearRGB(Color color) {
        double[] colors = new double[]{color.getRed(), color.getGreen(), color.getBlue()};
        for (int i = 0; i < colors.length; i++) {
            if (colors[i] <= 0.04045) {
                colors[i] = colors[i] / 12.92;
            } else {
                colors[i] = Math.pow((colors[i] + 0.055) / 1.055, 2.4);
            }
        }
        return Color.color(colors[0], colors[1], colors[2], color.getOpacity());
    }

    /**
     * Helper function to convert a color in linear RGB space to SRGB space.
     */
    public static Color convertLinearRGBtoSRGB(Color color) {
        double[] colors = new double[]{color.getRed(), color.getGreen(), color.getBlue()};
        for (int i = 0; i < colors.length; i++) {
            if (colors[i] <= 0.0031308) {
                colors[i] = colors[i] * 12.92;
            } else {
                colors[i] = (1.055 * Math.pow(colors[i], (1.0 / 2.4))) - 0.055;
            }
        }
        return Color.color(colors[0], colors[1], colors[2], color.getOpacity());
    }

    /**
     * helper function for calculating the sum of a series of numbers
     */
    public static double sum(double[] values) {
        double sum = 0;
        for (double v : values) sum = sum + v;
        return sum / values.length;
    }

    public static Point2D pointRelativeTo(Node parent, Node node, HPos hpos,
                                          VPos vpos, double dx, double dy, boolean reposition) {
        double nodeWidth = node.getLayoutBounds().getWidth();
        double nodeHeight = node.getLayoutBounds().getHeight();
        return pointRelativeTo(parent, nodeWidth, nodeHeight, hpos, vpos, dx, dy, reposition);
    }

    public static Point2D pointRelativeTo(Node parent, double anchorWidth,
                                          double anchorHeight, HPos hpos, VPos vpos, double dx, double dy,
                                          boolean reposition) {
        Bounds parentBounds = getBounds(parent);
        Scene scene = parent.getScene();
        NodeOrientation orientation = parent.getEffectiveNodeOrientation();

        if (orientation == NodeOrientation.RIGHT_TO_LEFT) {
            if (hpos == HPos.LEFT) {
                hpos = HPos.RIGHT;
            } else if (hpos == HPos.RIGHT) {
                hpos = HPos.LEFT;
            }
            dx *= -1;
        }

        double layoutX = positionX(parentBounds, anchorWidth, hpos) + dx;
        double layoutY = positionY(parentBounds, anchorHeight, vpos) + dy;

        if (orientation == NodeOrientation.RIGHT_TO_LEFT && hpos == HPos.CENTER) {
            //TODO - testing for an instance of Stage seems wrong but works for menus
            if (scene.getWindow() instanceof Stage) {
                layoutX = layoutX + parentBounds.getWidth() - anchorWidth;
            } else {
                layoutX = layoutX - parentBounds.getWidth() - anchorWidth;
            }
        }

        if (reposition) {
            return pointRelativeTo(parent, anchorWidth, anchorHeight, layoutX, layoutY, hpos, vpos);
        } else {
            return new Point2D(layoutX, layoutY);
        }
    }

    /**
     * This is the fallthrough function that most other functions fall into. It takes
     * care specifically of the repositioning of the item such that it remains onscreen
     * as best it can, given it's unique qualities.
     * 

* As will all other functions, this one returns a Point2D that represents an x,y * location that should safely position the item onscreen as best as possible. *

* Note that width and refer to the width and height of the * node/popup that is needing to be repositioned, not of the parent. *

* Don't use the BASELINE vpos, it doesn't make sense and would produce wrong result. */ public static Point2D pointRelativeTo(Object parent, double width, double height, double screenX, double screenY, HPos hpos, VPos vpos) { double finalScreenX = screenX; double finalScreenY = screenY; Bounds parentBounds = getBounds(parent); // ...and then we get the bounds of this screen Screen currentScreen = getScreen(parent); Rectangle2D screenBounds = hasFullScreenStage(currentScreen) ? currentScreen.getBounds() : currentScreen.getVisualBounds(); // test if this layout will force the node to appear outside // of the screens bounds. If so, we must reposition the item to a better position. // We firstly try to do this intelligently, so as to not overlap the parent if // at all possible. if (hpos != null) { // Firstly we consider going off the right hand side if ((finalScreenX + width) > screenBounds.getMaxX()) { finalScreenX = positionX(parentBounds, width, getHPosOpposite(hpos, vpos)); } // don't let the node go off to the left of the current screen if (finalScreenX < screenBounds.getMinX()) { finalScreenX = positionX(parentBounds, width, getHPosOpposite(hpos, vpos)); } } if (vpos != null) { // don't let the node go off the bottom of the current screen if ((finalScreenY + height) > screenBounds.getMaxY()) { finalScreenY = positionY(parentBounds, height, getVPosOpposite(hpos, vpos)); } // don't let the node out of the top of the current screen if (finalScreenY < screenBounds.getMinY()) { finalScreenY = positionY(parentBounds, height, getVPosOpposite(hpos, vpos)); } } // --- after all the moving around, we do one last check / rearrange. // Unlike the check above, this time we are just fully committed to keeping // the item on screen at all costs, regardless of whether or not that results /// in overlapping the parent object. if ((finalScreenX + width) > screenBounds.getMaxX()) { finalScreenX -= (finalScreenX + width - screenBounds.getMaxX()); } if (finalScreenX < screenBounds.getMinX()) { finalScreenX = screenBounds.getMinX(); } if ((finalScreenY + height) > screenBounds.getMaxY()) { finalScreenY -= (finalScreenY + height - screenBounds.getMaxY()); } if (finalScreenY < screenBounds.getMinY()) { finalScreenY = screenBounds.getMinY(); } return new Point2D(finalScreenX, finalScreenY); } /** * Utility function that returns the x-axis position that an object should be positioned at, * given the parents screen bounds, the width of the object, and * the required HPos. */ private static double positionX(Bounds parentBounds, double width, HPos hpos) { if (hpos == HPos.CENTER) { // this isn't right, but it is needed for root menus to show properly return parentBounds.getMinX(); } else if (hpos == HPos.RIGHT) { return parentBounds.getMaxX(); } else if (hpos == HPos.LEFT) { return parentBounds.getMinX() - width; } else { return 0; } } /** * Utility function that returns the y-axis position that an object should be positioned at, * given the parents screen bounds, the height of the object, and * the required VPos. *

* The BASELINE vpos doesn't make sense here, 0 is returned for it. */ private static double positionY(Bounds parentBounds, double height, VPos vpos) { if (vpos == VPos.BOTTOM) { return parentBounds.getMaxY(); } else if (vpos == VPos.CENTER) { return parentBounds.getMinY(); } else if (vpos == VPos.TOP) { return parentBounds.getMinY() - height; } else { return 0; } } /** * To facilitate multiple types of parent object, we unfortunately must allow for * Objects to be passed in. This method handles determining the bounds of the * given Object. If the Object type is not supported, a default Bounds will be returned. */ private static Bounds getBounds(Object obj) { if (obj instanceof Node) { Node n = (Node) obj; Bounds b = n.localToScreen(n.getLayoutBounds()); return b != null ? b : new BoundingBox(0, 0, 0, 0); } else if (obj instanceof Window) { Window window = (Window) obj; return new BoundingBox(window.getX(), window.getY(), window.getWidth(), window.getHeight()); } else { return new BoundingBox(0, 0, 0, 0); } } /* * Simple utitilty function to return the 'opposite' value of a given HPos, taking * into account the current VPos value. This is used to try and avoid overlapping. */ private static HPos getHPosOpposite(HPos hpos, VPos vpos) { if (vpos == VPos.CENTER) { if (hpos == HPos.LEFT) { return HPos.RIGHT; } else if (hpos == HPos.RIGHT) { return HPos.LEFT; } else if (hpos == HPos.CENTER) { return HPos.CENTER; } else { // by default center for now return HPos.CENTER; } } else { return HPos.CENTER; } } /* * Simple utitilty function to return the 'opposite' value of a given VPos, taking * into account the current HPos value. This is used to try and avoid overlapping. */ private static VPos getVPosOpposite(HPos hpos, VPos vpos) { if (hpos == HPos.CENTER) { if (vpos == VPos.BASELINE) { return VPos.BASELINE; } else if (vpos == VPos.BOTTOM) { return VPos.TOP; } else if (vpos == VPos.CENTER) { return VPos.CENTER; } else if (vpos == VPos.TOP) { return VPos.BOTTOM; } else { // by default center for now return VPos.CENTER; } } else { return VPos.CENTER; } } public static boolean hasFullScreenStage(Screen screen) { List allWindows = Window.getWindows(); for (Window window : allWindows) { if (window instanceof Stage) { Stage stage = (Stage) window; if (stage.isFullScreen() && (getScreen(stage) == screen)) { return true; } } } return false; } /* * Returns true if the primary Screen has QVGA dimensions, in landscape or portrait mode. */ public static boolean isQVGAScreen() { Rectangle2D bounds = Screen.getPrimary().getBounds(); return ((bounds.getWidth() == 320 && bounds.getHeight() == 240) || (bounds.getWidth() == 240 && bounds.getHeight() == 320)); } /** * This function attempts to determine the best screen given the parent object * from which we are wanting to position another item relative to. This is particularly * important when we want to keep items from going off screen, and for handling * multiple monitor support. */ public static Screen getScreen(Object obj) { Bounds parentBounds = getBounds(obj); Rectangle2D rect = new Rectangle2D( parentBounds.getMinX(), parentBounds.getMinY(), parentBounds.getWidth(), parentBounds.getHeight()); return getScreenForRectangle(rect); } public static Screen getScreenForRectangle(Rectangle2D rect) { List screens = Screen.getScreens(); double rectX0 = rect.getMinX(); double rectX1 = rect.getMaxX(); double rectY0 = rect.getMinY(); double rectY1 = rect.getMaxY(); Screen selectedScreen; selectedScreen = null; double maxIntersection = 0; for (Screen screen : screens) { Rectangle2D screenBounds = screen.getBounds(); double intersection = getIntersectionLength(rectX0, rectX1, screenBounds.getMinX(), screenBounds.getMaxX()) * getIntersectionLength(rectY0, rectY1, screenBounds.getMinY(), screenBounds.getMaxY()); if (maxIntersection < intersection) { maxIntersection = intersection; selectedScreen = screen; } } if (selectedScreen != null) { return selectedScreen; } selectedScreen = Screen.getPrimary(); double minDistance = Double.MAX_VALUE; for (Screen screen : screens) { Rectangle2D screenBounds = screen.getBounds(); double dx = getOuterDistance(rectX0, rectX1, screenBounds.getMinX(), screenBounds.getMaxX()); double dy = getOuterDistance(rectY0, rectY1, screenBounds.getMinY(), screenBounds.getMaxY()); double distance = dx * dx + dy * dy; if (minDistance > distance) { minDistance = distance; selectedScreen = screen; } } return selectedScreen; } public static Screen getScreenForPoint(double x, double y) { List screens = Screen.getScreens(); // first check whether the point is inside some screen for (Screen screen : screens) { // can't use screen.bounds.contains, because it returns true for // the min + width point Rectangle2D screenBounds = screen.getBounds(); if ((x >= screenBounds.getMinX()) && (x < screenBounds.getMaxX()) && (y >= screenBounds.getMinY()) && (y < screenBounds.getMaxY())) { return screen; } } // the point is not inside any screen, find the closest screen now Screen selectedScreen = Screen.getPrimary(); double minDistance = Double.MAX_VALUE; for (Screen screen : screens) { Rectangle2D screenBounds = screen.getBounds(); double dx = getOuterDistance(screenBounds.getMinX(), screenBounds.getMaxX(), x); double dy = getOuterDistance(screenBounds.getMinY(), screenBounds.getMaxY(), y); double distance = dx * dx + dy * dy; if (minDistance >= distance) { minDistance = distance; selectedScreen = screen; } } return selectedScreen; } private static double getIntersectionLength( double a0, double a1, double b0, double b1) { // (a0 <= a1) && (b0 <= b1) return (a0 <= b0) ? getIntersectionLengthImpl(b0, b1, a1) : getIntersectionLengthImpl(a0, a1, b1); } private static double getIntersectionLengthImpl( double v0, double v1, double v) { // (v0 <= v1) if (v <= v0) { return 0; } return (v <= v1) ? v - v0 : v1 - v0; } private static double getOuterDistance( double a0, double a1, double b0, double b1) { // (a0 <= a1) && (b0 <= b1) if (a1 <= b0) { return b0 - a1; } if (b1 <= a0) { return b1 - a0; } return 0; } private static double getOuterDistance(double v0, double v1, double v) { // (v0 <= v1) if (v <= v0) { return v0 - v; } if (v >= v1) { return v - v1; } return 0; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy