1 /*
   2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.scene.layout;
  27 
  28 import javafx.geometry.Insets;
  29 import javafx.scene.paint.Color;
  30 import javafx.scene.shape.Circle;
  31 import org.junit.Before;
  32 import org.junit.Test;
  33 
  34 import static org.junit.Assert.*;
  35 
  36 /**
  37  * Tests for Region picking. By default, Region has pickOnBounds set to true, so picking
  38  * anything within the bounds of the region will return true, anything outside the bounds
  39  * false. However, due to RT-25066, the bounds of a region defined by a shape will be 0x0,
  40  * in which case it will never be picked.
  41  *
  42  * If pickOnBounds is false, then an entire different code path is executed. We don't care
  43  * whether a fill is transparent or not (transparent fills can still cause the region to
  44  * pick), but we do care about picking within the "shape" and picking within the rounded
  45  * rectangle which is created as a result of background fills / background images.
  46  *
  47  * In the case of background images, we don't care about whether we are picking a transparent
  48  * pixel or not, but just based on the insets etc (since we don't have a good means for testing
  49  * the image pixel value).
  50  */
  51 public class RegionPickTest {
  52     private static final double X = 0;
  53     private static final double Y = 0;
  54     private static final double WIDTH = 100;
  55     private static final double HEIGHT = 100;
  56     private static final double CENTER_X = X + (WIDTH / 2.0);
  57     private static final double CENTER_Y = Y + (HEIGHT / 2.0);
  58     private static final double LEFT_OF = X - 10;
  59     private static final double ABOVE = Y - 10;
  60     private static final double RIGHT_OF = X + WIDTH + 10;
  61     private static final double BELOW = Y + HEIGHT + 10;
  62 
  63     private Region region;
  64 
  65     @Before public void setup() {
  66         region = new Region();
  67         region.resizeRelocate(X, Y, WIDTH, HEIGHT);
  68         region.setPickOnBounds(false);
  69     }
  70 
  71     /**************************************************************************
  72      *                                                                        *
  73      * Set of tests to ensure that picking within / without a region with     *
  74      * pickOnBounds set to true (the normal default) results in expected      *
  75      * behavior (pick when within bounds, not when without bounds)            *
  76      *                                                                        *
  77      *************************************************************************/
  78 
  79     @Test public void pickingNormalRegion() {
  80         region.setPickOnBounds(true);
  81         assertFalse(region.contains(LEFT_OF, CENTER_Y));
  82         assertFalse(region.contains(CENTER_X, ABOVE));
  83         assertFalse(region.contains(RIGHT_OF, CENTER_Y));
  84         assertFalse(region.contains(CENTER_X, BELOW));
  85         assertTrue(region.contains(CENTER_X, CENTER_Y));
  86     }
  87 
  88     /**************************************************************************
  89      *                                                                        *
  90      * Test for a Region which has no fills of any kind, but has              *
  91      * pickOnBounds set to false. Such a Region should never pick.            *
  92      *                                                                        *
  93      *************************************************************************/
  94 
  95     @Test public void pickingEmptyRegionDoesNotWork() {
  96         assertFalse(region.contains(LEFT_OF, CENTER_Y));
  97         assertFalse(region.contains(CENTER_X, ABOVE));
  98         assertFalse(region.contains(RIGHT_OF, CENTER_Y));
  99         assertFalse(region.contains(CENTER_X, BELOW));
 100         assertFalse(region.contains(CENTER_X, CENTER_Y));
 101     }
 102 
 103     /**************************************************************************
 104      *                                                                        *
 105      * Test behavior when picking a region with fills, but no shape or border *
 106      * or images.                                                             *
 107      *                                                                        *
 108      *************************************************************************/
 109 
 110     @Test public void pickingRectangularFillWorks() {
 111         region.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
 112         assertFalse(region.contains(LEFT_OF, CENTER_Y));
 113         assertFalse(region.contains(CENTER_X, ABOVE));
 114         assertFalse(region.contains(RIGHT_OF, CENTER_Y));
 115         assertFalse(region.contains(CENTER_X, BELOW));
 116         assertTrue(region.contains(CENTER_X, CENTER_Y));
 117     }
 118 
 119     @Test public void pickingRectangularFillWithInsetsWorks() {
 120         // With insets of 10, we ought to not pick inside the region until we get to position 10
 121         region.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, new Insets(10))));
 122         assertFalse(region.contains(X + 9, CENTER_Y));
 123         assertFalse(region.contains(CENTER_X, Y + 9));
 124         assertFalse(region.contains(X + WIDTH - 9, CENTER_Y));
 125         assertFalse(region.contains(CENTER_X, Y + HEIGHT - 9));
 126         assertTrue(region.contains(X + 10, CENTER_Y));
 127         assertTrue(region.contains(CENTER_X, Y + 10));
 128         assertTrue(region.contains(X + WIDTH - 10, CENTER_Y));
 129         assertTrue(region.contains(CENTER_X, Y + HEIGHT - 10));
 130         assertTrue(region.contains(CENTER_X, CENTER_Y));
 131     }
 132 
 133     @Test public void pickingRectangularFillWithUniformRadiusWorks() {
 134         region.setBackground(new Background(new BackgroundFill(Color.RED, new CornerRadii(10), Insets.EMPTY)));
 135         // Check points in the top-left corner area
 136         assertTrue(region.contains(X, Y + 10));
 137         assertTrue(region.contains(X + 10, Y));
 138         assertTrue(region.contains(X + 10 - (10 * Math.cos(45)), Y + 10 - (10 * Math.sin(45))));
 139         assertTrue(region.contains(X + 10 - (9 * Math.cos(45)), Y + 10 - (9 * Math.sin(45))));
 140         assertFalse(region.contains(X + 10 - (11 * Math.cos(45)), Y + 10 - (11 * Math.sin(45))));
 141         // Check points in the top-right corner area
 142         assertTrue(region.contains(X + WIDTH, Y + 10));
 143         assertTrue(region.contains(X + WIDTH - 10, Y));
 144         assertTrue(region.contains(X + WIDTH - 10 + (10 * Math.cos(45)), Y + 10 - (10 * Math.sin(45))));
 145         assertTrue(region.contains(X + WIDTH - 10 + (9 * Math.cos(45)), Y + 10 - (9 * Math.sin(45))));
 146         assertFalse(region.contains(X + WIDTH - 10 + (11 * Math.cos(45)), Y + 10 - (11 * Math.sin(45))));
 147         // Check points in the bottom-right corner area
 148         assertTrue(region.contains(X + WIDTH, Y + HEIGHT - 10));
 149         assertTrue(region.contains(X + WIDTH - 10, Y + HEIGHT));
 150         assertTrue(region.contains(X + WIDTH - 10 + (10 * Math.cos(45)), Y + HEIGHT - 10 + (10 * Math.sin(45))));
 151         assertTrue(region.contains(X + WIDTH - 10 + (9 * Math.cos(45)), Y + HEIGHT - 10 + (9 * Math.sin(45))));
 152         assertFalse(region.contains(X + WIDTH - 10 + (11 * Math.cos(45)), Y + HEIGHT - 10 + (11 * Math.sin(45))));
 153         // Check points in the bottom-left corner area
 154         assertTrue(region.contains(X, Y + HEIGHT - 10));
 155         assertTrue(region.contains(X + 10, Y + HEIGHT));
 156         assertTrue(region.contains(X + 10 - (10 * Math.cos(45)), Y + HEIGHT - 10 + (10 * Math.sin(45))));
 157         assertTrue(region.contains(X + 10 - (9 * Math.cos(45)), Y + HEIGHT - 10 + (9 * Math.sin(45))));
 158         assertFalse(region.contains(X + 10 - (11 * Math.cos(45)), Y + HEIGHT - 10 + (11 * Math.sin(45))));
 159         // Check the center
 160         assertTrue(region.contains(CENTER_X, CENTER_Y));
 161     }
 162 
 163     @Test public void pickingRectangularFillWithUniformRadiusWithInsetsWorks() {
 164         region.setBackground(new Background(new BackgroundFill(Color.RED, new CornerRadii(10), new Insets(10))));
 165         // Check points in the top-left corner area
 166         assertTrue(region.contains(X + 10, Y + 20));
 167         assertTrue(region.contains(X + 20, Y + 10));
 168         assertTrue(region.contains(X + 20 - (10 * Math.cos(45)), Y + 20 - (10 * Math.sin(45))));
 169         assertTrue(region.contains(X + 20 - (9 * Math.cos(45)), Y + 20 - (9 * Math.sin(45))));
 170         assertFalse(region.contains(X + 20 - (11 * Math.cos(45)), Y + 20 - (11 * Math.sin(45))));
 171         // Check points in the top-right corner area
 172         assertTrue(region.contains(X + WIDTH - 10, Y + 20));
 173         assertTrue(region.contains(X + WIDTH - 20, Y + 10));
 174         assertTrue(region.contains(X + WIDTH - 20 + (10 * Math.cos(45)), Y + 20 - (10 * Math.sin(45))));
 175         assertTrue(region.contains(X + WIDTH - 20 + (9 * Math.cos(45)), Y + 20 - (9 * Math.sin(45))));
 176         assertFalse(region.contains(X + WIDTH - 20 + (11 * Math.cos(45)), Y + 20 - (11 * Math.sin(45))));
 177         // Check points in the bottom-right corner area
 178         assertTrue(region.contains(X + WIDTH - 10, Y + HEIGHT - 20));
 179         assertTrue(region.contains(X + WIDTH - 20, Y + HEIGHT - 10));
 180         assertTrue(region.contains(X + WIDTH - 20 + (10 * Math.cos(45)), Y + HEIGHT - 20 + (10 * Math.sin(45))));
 181         assertTrue(region.contains(X + WIDTH - 20 + (9 * Math.cos(45)), Y + HEIGHT - 20 + (9 * Math.sin(45))));
 182         assertFalse(region.contains(X + WIDTH - 20 + (11 * Math.cos(45)), Y + HEIGHT - 20 + (11 * Math.sin(45))));
 183         // Check points in the bottom-left corner area
 184         assertTrue(region.contains(X + 10, Y + HEIGHT - 20));
 185         assertTrue(region.contains(X + 20, Y + HEIGHT - 10));
 186         assertTrue(region.contains(X + 20 - (10 * Math.cos(45)), Y + HEIGHT - 20 + (10 * Math.sin(45))));
 187         assertTrue(region.contains(X + 20 - (9 * Math.cos(45)), Y + HEIGHT - 20 + (9 * Math.sin(45))));
 188         assertFalse(region.contains(X + 20 - (11 * Math.cos(45)), Y + HEIGHT - 20 + (11 * Math.sin(45))));
 189         // Check the center
 190         assertTrue(region.contains(CENTER_X, CENTER_Y));
 191     }
 192 
 193     // test with really really large corner radius
 194     @Test public void pickingRectangularFillWithUniformVERYLARGERadiusWorks() {
 195         region.setBackground(new Background(new BackgroundFill(Color.RED, new CornerRadii(10000000), Insets.EMPTY)));
 196         // This produces an effective radius of 50 due to my width/height being 100x100
 197         // Check points in the top-left corner area
 198         assertTrue(region.contains(X, Y + 50));
 199         assertTrue(region.contains(X + 50, Y));
 200         assertTrue(region.contains(X + 50 - (50 * Math.cos(45)), Y + 50 - (50 * Math.sin(45))));
 201         assertTrue(region.contains(X + 50 - (49 * Math.cos(45)), Y + 50 - (49 * Math.sin(45))));
 202         assertFalse(region.contains(X + 50 - (51 * Math.cos(45)), Y + 50 - (51 * Math.sin(45))));
 203         // Check points in the top-right corner area
 204         assertTrue(region.contains(X + WIDTH, Y + 50));
 205         assertTrue(region.contains(X + WIDTH - 50, Y));
 206         assertTrue(region.contains(X + WIDTH - 50 + (50 * Math.cos(45)), Y + 50 - (50 * Math.sin(45))));
 207         assertTrue(region.contains(X + WIDTH - 50 + (49 * Math.cos(45)), Y + 50 - (49 * Math.sin(45))));
 208         assertFalse(region.contains(X + WIDTH - 50 + (51 * Math.cos(45)), Y + 50 - (51 * Math.sin(45))));
 209         // Check points in the bottom-right corner area
 210         assertTrue(region.contains(X + WIDTH, Y + HEIGHT - 50));
 211         assertTrue(region.contains(X + WIDTH - 50, Y + HEIGHT));
 212         assertTrue(region.contains(X + WIDTH - 50 + (50 * Math.cos(45)), Y + HEIGHT - 50 + (50 * Math.sin(45))));
 213         assertTrue(region.contains(X + WIDTH - 50 + (49 * Math.cos(45)), Y + HEIGHT - 50 + (49 * Math.sin(45))));
 214         assertFalse(region.contains(X + WIDTH - 50 + (51 * Math.cos(45)), Y + HEIGHT - 50 + (51 * Math.sin(45))));
 215         // Check points in the bottom-left corner area
 216         assertTrue(region.contains(X, Y + HEIGHT - 50));
 217         assertTrue(region.contains(X + 50, Y + HEIGHT));
 218         assertTrue(region.contains(X + 50 - (50 * Math.cos(45)), Y + HEIGHT - 50 + (50 * Math.sin(45))));
 219         assertTrue(region.contains(X + 50 - (49 * Math.cos(45)), Y + HEIGHT - 50 + (49 * Math.sin(45))));
 220         assertFalse(region.contains(X + 50 - (51 * Math.cos(45)), Y + HEIGHT - 50 + (51 * Math.sin(45))));
 221         // Check the center
 222         assertTrue(region.contains(CENTER_X, CENTER_Y));
 223     }
 224 
 225     @Test public void pickingRectangularFillWithIndependentRadiusWorks() {
 226         region.setBackground(new Background(new BackgroundFill(Color.RED, new CornerRadii(1, 2, 3, 4, false),
 227                                                                Insets.EMPTY)));
 228         // Check points in the top-left corner area
 229         assertTrue(region.contains(X, Y + 1));
 230         assertTrue(region.contains(X + 1, Y));
 231         assertTrue(region.contains(X + 1 - (1 * Math.cos(45)), Y + 1 - (1 * Math.sin(45))));
 232         assertTrue(region.contains(X + 1 - (.5 * Math.cos(45)), Y + 1 - (.5 * Math.sin(45))));
 233         assertFalse(region.contains(X + 1 - (2 * Math.cos(45)), Y + 1 - (2 * Math.sin(45))));
 234         // Check points in the top-right corner area
 235         assertTrue(region.contains(X + WIDTH, Y + 2));
 236         assertTrue(region.contains(X + WIDTH - 2, Y));
 237         assertTrue(region.contains(X + WIDTH - 2 + (2 * Math.cos(45)), Y + 2 - (2 * Math.sin(45))));
 238         assertTrue(region.contains(X + WIDTH - 2 + (1 * Math.cos(45)), Y + 2 - (1 * Math.sin(45))));
 239         assertFalse(region.contains(X + WIDTH - 2 + (3 * Math.cos(45)), Y + 2 - (3 * Math.sin(45))));
 240         // Check points in the bottom-right corner area
 241         assertTrue(region.contains(X + WIDTH, Y + HEIGHT - 3));
 242         assertTrue(region.contains(X + WIDTH - 3, Y + HEIGHT));
 243         assertTrue(region.contains(X + WIDTH - 3 + (3 * Math.cos(45)), Y + HEIGHT - 3 + (3 * Math.sin(45))));
 244         assertTrue(region.contains(X + WIDTH - 3 + (2 * Math.cos(45)), Y + HEIGHT - 3 + (2 * Math.sin(45))));
 245         assertFalse(region.contains(X + WIDTH - 3 + (4 * Math.cos(45)), Y + HEIGHT - 3 + (4 * Math.sin(45))));
 246         // Check points in the bottom-left corner area
 247         assertTrue(region.contains(X, Y + HEIGHT - 4));
 248         assertTrue(region.contains(X + 4, Y + HEIGHT));
 249         assertTrue(region.contains(X + 4 - (4 * Math.cos(45)), Y + HEIGHT - 4 + (4 * Math.sin(45))));
 250         assertTrue(region.contains(X + 4 - (3 * Math.cos(45)), Y + HEIGHT - 4 + (3 * Math.sin(45))));
 251         assertFalse(region.contains(X + 4 - (5 * Math.cos(45)), Y + HEIGHT - 4 + (5 * Math.sin(45))));
 252         // Check the center
 253         assertTrue(region.contains(CENTER_X, CENTER_Y));
 254     }
 255 
 256     @Test public void pickingRectangularFillWithIndependentRadiusWorks2() {
 257         region.setBackground(new Background(new BackgroundFill(Color.RED,
 258             new CornerRadii(1, 2, 3, 4, 5, 6, 7, 8, false, false, false, false, false, false, false, false),
 259             Insets.EMPTY)));
 260         // Check points in the top-left corner area
 261         assertTrue(region.contains(X, Y + 2));
 262         assertTrue(region.contains(X + 1, Y));
 263         assertTrue(region.contains(X + 1 - (1 * Math.cos(45)), Y + 2 - (2 * Math.sin(45))));
 264         assertTrue(region.contains(X + 1 - (.5 * Math.cos(45)), Y + 2 - (1 * Math.sin(45))));
 265         assertFalse(region.contains(X + 1 - (2 * Math.cos(45)), Y + 2 - (3 * Math.sin(45))));
 266         // Check points in the top-right corner area
 267         assertTrue(region.contains(X + WIDTH, Y + 3));
 268         assertTrue(region.contains(X + WIDTH - 4, Y));
 269         assertTrue(region.contains(X + WIDTH - 4 + (4 * Math.cos(45)), Y + 3 - (3 * Math.sin(45))));
 270         assertTrue(region.contains(X + WIDTH - 4 + (3 * Math.cos(45)), Y + 3 - (2 * Math.sin(45))));
 271         assertFalse(region.contains(X + WIDTH - 4 + (5 * Math.cos(45)), Y + 3 - (4 * Math.sin(45))));
 272         // Check points in the bottom-right corner area
 273         assertTrue(region.contains(X + WIDTH, Y + HEIGHT - 6));
 274         assertTrue(region.contains(X + WIDTH - 5, Y + HEIGHT));
 275         assertTrue(region.contains(X + WIDTH - 5 + (5 * Math.cos(45)), Y + HEIGHT - 6 + (6 * Math.sin(45))));
 276         assertTrue(region.contains(X + WIDTH - 5 + (4 * Math.cos(45)), Y + HEIGHT - 6 + (5 * Math.sin(45))));
 277         assertFalse(region.contains(X + WIDTH - 5 + (6 * Math.cos(45)), Y + HEIGHT - 6 + (7 * Math.sin(45))));
 278         // Check points in the bottom-left corner area
 279         assertTrue(region.contains(X, Y + HEIGHT - 7));
 280         assertTrue(region.contains(X + 8, Y + HEIGHT));
 281         assertTrue(region.contains(X + 8 - (8 * Math.cos(45)), Y + HEIGHT - 7 + (7 * Math.sin(45))));
 282         assertTrue(region.contains(X + 8 - (7 * Math.cos(45)), Y + HEIGHT - 7 + (6 * Math.sin(45))));
 283         assertFalse(region.contains(X + 8 - (9 * Math.cos(45)), Y + HEIGHT - 7 + (8 * Math.sin(45))));
 284         // Check the center
 285         assertTrue(region.contains(CENTER_X, CENTER_Y));
 286     }
 287 
 288     @Test public void pickingRectangularFillWithIndependentRadiusWithInsetsWorks() {
 289         region.setBackground(new Background(new BackgroundFill(Color.RED,
 290             new CornerRadii(1, 2, 3, 4, 5, 6, 7, 8, false, false, false, false, false, false, false, false),
 291             new Insets(4, 3, 2, 1))));
 292         // Check points in the top-left corner area
 293         assertTrue(region.contains(X + 1, Y + 2 + 4));
 294         assertTrue(region.contains(X + 1 + 1, Y + 4));
 295         assertTrue(region.contains(X + 1 + 1 - (1 * Math.cos(45)), Y + 2 + 4 - (2 * Math.sin(45))));
 296         assertTrue(region.contains(X + 1 + 1 - (.5 * Math.cos(45)), Y + 2 + 4 - (1 * Math.sin(45))));
 297         assertFalse(region.contains(X + 1 + 1 - (2 * Math.cos(45)), Y + 2 + 4 - (3 * Math.sin(45))));
 298         // Check points in the top-right corner area
 299         assertTrue(region.contains(X + WIDTH - 3, Y + 3 + 4));
 300         assertTrue(region.contains(X + WIDTH - 4 - 3, Y + 4));
 301         assertTrue(region.contains(X + WIDTH - 4 - 3 + (4 * Math.cos(45)), Y + 4 + 3 - (3 * Math.sin(45))));
 302         assertTrue(region.contains(X + WIDTH - 4 - 3 + (3 * Math.cos(45)), Y + 4 + 3 - (2 * Math.sin(45))));
 303         assertFalse(region.contains(X + WIDTH - 4 - 3 + (5 * Math.cos(45)), Y + 4 + 3 - (4 * Math.sin(45))));
 304         // Check points in the bottom-right corner area
 305         assertTrue(region.contains(X + WIDTH - 3, Y + HEIGHT - 2 - 6));
 306         assertTrue(region.contains(X + WIDTH - 3 - 5, Y + HEIGHT - 2));
 307         assertTrue(region.contains(X + WIDTH - 3 - 5 + (5 * Math.cos(45)), Y + HEIGHT - 2 - 6 + (6 * Math.sin(45))));
 308         assertTrue(region.contains(X + WIDTH - 3 - 5 + (4 * Math.cos(45)), Y + HEIGHT - 2 - 6 + (5 * Math.sin(45))));
 309         assertFalse(region.contains(X + WIDTH - 3 - 5 + (6 * Math.cos(45)), Y + HEIGHT - 2 - 6 + (7 * Math.sin(45))));
 310         // Check points in the bottom-left corner area
 311         assertTrue(region.contains(X + 1, Y + HEIGHT - 2 - 7));
 312         assertTrue(region.contains(X + 1 + 8, Y + HEIGHT - 2));
 313         assertTrue(region.contains(X + 1 + 8 - (8 * Math.cos(45)), Y + HEIGHT - 2 - 7 + (7 * Math.sin(45))));
 314         assertTrue(region.contains(X + 1 + 8 - (7 * Math.cos(45)), Y + HEIGHT - 2 - 7 + (6 * Math.sin(45))));
 315         assertFalse(region.contains(X + 1 + 8 - (9 * Math.cos(45)), Y + HEIGHT - 2 - 7 + (8 * Math.sin(45))));
 316         // Check the center
 317         assertTrue(region.contains(CENTER_X, CENTER_Y));
 318     }
 319 
 320     // TODO test with really really large corner radius
 321 
 322     /**************************************************************************
 323      *                                                                        *
 324      * Test behavior when picking a region with borders, but no shape or      *
 325      * or images.                                                             *
 326      *                                                                        *
 327      *************************************************************************/
 328 
 329     @Test public void pickingRectangularBorderWorks() {
 330         region.setBorder(new Border(new BorderStroke(Color.GREEN, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,
 331                                                      new BorderWidths(1))));
 332         assertFalse(region.contains(LEFT_OF, CENTER_Y));
 333         assertFalse(region.contains(CENTER_X, ABOVE));
 334         assertFalse(region.contains(RIGHT_OF, CENTER_Y));
 335         assertFalse(region.contains(CENTER_X, BELOW));
 336         // Note that the center is empty and should not be picked
 337         assertFalse(region.contains(CENTER_X, CENTER_Y));
 338     }
 339 
 340     @Test public void pickingRectangularBorderWithThickBorder() {
 341         region.setBorder(new Border(new BorderStroke(Color.GREEN, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,
 342                                                      new BorderWidths(10))));
 343         assertFalse(region.contains(LEFT_OF, CENTER_Y));
 344         assertFalse(region.contains(CENTER_X, ABOVE));
 345         assertFalse(region.contains(RIGHT_OF, CENTER_Y));
 346         assertFalse(region.contains(CENTER_X, BELOW));
 347         assertFalse(region.contains(CENTER_X, CENTER_Y));
 348 
 349         assertTrue(region.contains(X, Y));
 350         assertTrue(region.contains(X+5, Y+5));
 351         assertFalse(region.contains(X+10, Y+10));
 352     }
 353 
 354     @Test public void pickingRectangularBorderWithIndependentBorderWidths() {
 355         region.setBorder(new Border(new BorderStroke(Color.GREEN, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,
 356                                                      new BorderWidths(5, 10, 15, 20))));
 357         assertFalse(region.contains(LEFT_OF, CENTER_Y));
 358         assertFalse(region.contains(CENTER_X, ABOVE));
 359         assertFalse(region.contains(RIGHT_OF, CENTER_Y));
 360         assertFalse(region.contains(CENTER_X, BELOW));
 361         assertFalse(region.contains(CENTER_X, CENTER_Y));
 362 
 363         // Top. Test first and last pixels, and one-past
 364         assertTrue(region.contains(CENTER_X, Y));
 365         assertTrue(region.contains(CENTER_X, Y + 4));
 366         assertFalse(region.contains(CENTER_X, Y + 5));
 367 
 368         // Right. Test first and last pixels, and one-past
 369         assertTrue(region.contains(WIDTH, CENTER_Y));
 370         assertTrue(region.contains(WIDTH - 9, CENTER_Y));
 371         assertFalse(region.contains(WIDTH - 10, CENTER_Y));
 372 
 373         // Bottom. Test first and last pixels, and one-past
 374         assertTrue(region.contains(CENTER_X, HEIGHT));
 375         assertTrue(region.contains(CENTER_X, HEIGHT - 14));
 376         assertFalse(region.contains(CENTER_X, HEIGHT - 15));
 377 
 378         // Left. Test first and last pixels, and one-past
 379         assertTrue(region.contains(X, CENTER_Y));
 380         assertTrue(region.contains(X + 19, CENTER_Y));
 381         assertFalse(region.contains(X + 20, CENTER_Y));
 382     }
 383 
 384     @Test public void pickingRectangularBorderWithIndependentPercentageBorderWidths() {
 385         region.setBorder(new Border(new BorderStroke(Color.GREEN, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,
 386                                                      new BorderWidths(.05, .10, .15, .20, true, true, true, true))));
 387         assertFalse(region.contains(LEFT_OF, CENTER_Y));
 388         assertFalse(region.contains(CENTER_X, ABOVE));
 389         assertFalse(region.contains(RIGHT_OF, CENTER_Y));
 390         assertFalse(region.contains(CENTER_X, BELOW));
 391         assertFalse(region.contains(CENTER_X, CENTER_Y));
 392 
 393         // Top. Test first and last pixels, and one-past
 394         assertTrue(region.contains(CENTER_X, Y));
 395         assertTrue(region.contains(CENTER_X, Y + 4));
 396         assertFalse(region.contains(CENTER_X, Y + 5));
 397 
 398         // Right. Test first and last pixels, and one-past
 399         assertTrue(region.contains(WIDTH, CENTER_Y));
 400         assertTrue(region.contains(WIDTH - 9, CENTER_Y));
 401         assertFalse(region.contains(WIDTH - 10, CENTER_Y));
 402 
 403         // Bottom. Test first and last pixels, and one-past
 404         assertTrue(region.contains(CENTER_X, HEIGHT));
 405         assertTrue(region.contains(CENTER_X, HEIGHT - 14));
 406         assertFalse(region.contains(CENTER_X, HEIGHT - 15));
 407 
 408         // Left. Test first and last pixels, and one-past
 409         assertTrue(region.contains(X, CENTER_Y));
 410         assertTrue(region.contains(X + 19, CENTER_Y));
 411         assertFalse(region.contains(X + 20, CENTER_Y));
 412     }
 413 
 414     @Test public void pickingRectangularBorderWithIndependentBorderWidthsAndInsets() {
 415         region.setBorder(new Border(new BorderStroke(Color.GREEN, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,
 416                                                      new BorderWidths(5, 10, 15, 20), new Insets(1, 2, 3, 4))));
 417         // Top. Test first and last pixels, and one-past
 418         assertFalse(region.contains(CENTER_X, Y));
 419         assertTrue(region.contains(CENTER_X, Y+1));
 420         assertTrue(region.contains(CENTER_X, Y+1 + 4));
 421         assertFalse(region.contains(CENTER_X, Y+1 + 5));
 422 
 423         // Right. Test first and last pixels, and one-past
 424         assertFalse(region.contains(WIDTH-1, CENTER_Y));
 425         assertTrue(region.contains(WIDTH-2, CENTER_Y));
 426         assertTrue(region.contains(WIDTH-2 - 9, CENTER_Y));
 427         assertFalse(region.contains(WIDTH-2 - 10, CENTER_Y));
 428 
 429         // Bottom. Test first and last pixels, and one-past
 430         assertFalse(region.contains(CENTER_X, HEIGHT-2));
 431         assertTrue(region.contains(CENTER_X, HEIGHT-3));
 432         assertTrue(region.contains(CENTER_X, HEIGHT-3 - 14));
 433         assertFalse(region.contains(CENTER_X, HEIGHT-3 - 15));
 434 
 435         // Left. Test first and last pixels, and one-past
 436         assertFalse(region.contains(X+3, CENTER_Y));
 437         assertTrue(region.contains(X+4, CENTER_Y));
 438         assertTrue(region.contains(X+4 + 19, CENTER_Y));
 439         assertFalse(region.contains(X+4 + 20, CENTER_Y));
 440     }
 441 
 442     @Test public void pickingRectangularBorderWithIndependentRadiusWithInsetsWorks() {
 443         region.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID,
 444             new CornerRadii(1, 2, 3, 4, 5, 6, 7, 8, false, false, false, false, false, false, false, false),
 445             new BorderWidths(5, 10, 15, 20), new Insets(4, 3, 2, 1))));
 446         // Check points in the top-left corner area
 447         assertTrue(region.contains(X + 1, Y + 2 + 4));
 448         assertTrue(region.contains(X + 1 + 1, Y + 4));
 449         assertTrue(region.contains(X + 1 + 1 - (1 * Math.cos(45)), Y + 2 + 4 - (2 * Math.sin(45))));
 450         assertTrue(region.contains(X + 1 + 1 - (.5 * Math.cos(45)), Y + 2 + 4 - (1 * Math.sin(45))));
 451         assertFalse(region.contains(X + 1 + 1 - (2 * Math.cos(45)), Y + 2 + 4 - (3 * Math.sin(45))));
 452         // Check points in the top-right corner area
 453         assertTrue(region.contains(X + WIDTH - 3, Y + 3 + 4));
 454         assertTrue(region.contains(X + WIDTH - 4 - 3, Y + 4));
 455         assertTrue(region.contains(X + WIDTH - 4 - 3 + (4 * Math.cos(45)), Y + 4 + 3 - (3 * Math.sin(45))));
 456         assertTrue(region.contains(X + WIDTH - 4 - 3 + (3 * Math.cos(45)), Y + 4 + 3 - (2 * Math.sin(45))));
 457         assertFalse(region.contains(X + WIDTH - 4 - 3 + (5 * Math.cos(45)), Y + 4 + 3 - (4 * Math.sin(45))));
 458         // Check points in the bottom-right corner area
 459         assertTrue(region.contains(X + WIDTH - 3, Y + HEIGHT - 2 - 6));
 460         assertTrue(region.contains(X + WIDTH - 3 - 5, Y + HEIGHT - 2));
 461         assertTrue(region.contains(X + WIDTH - 3 - 5 + (5 * Math.cos(45)), Y + HEIGHT - 2 - 6 + (6 * Math.sin(45))));
 462         assertTrue(region.contains(X + WIDTH - 3 - 5 + (4 * Math.cos(45)), Y + HEIGHT - 2 - 6 + (5 * Math.sin(45))));
 463         assertFalse(region.contains(X + WIDTH - 3 - 5 + (6 * Math.cos(45)), Y + HEIGHT - 2 - 6 + (7 * Math.sin(45))));
 464         // Check points in the bottom-left corner area
 465         assertTrue(region.contains(X + 1, Y + HEIGHT - 2 - 7));
 466         assertTrue(region.contains(X + 1 + 8, Y + HEIGHT - 2));
 467         assertTrue(region.contains(X + 1 + 8 - (8 * Math.cos(45)), Y + HEIGHT - 2 - 7 + (7 * Math.sin(45))));
 468         assertTrue(region.contains(X + 1 + 8 - (7 * Math.cos(45)), Y + HEIGHT - 2 - 7 + (6 * Math.sin(45))));
 469         assertFalse(region.contains(X + 1 + 8 - (9 * Math.cos(45)), Y + HEIGHT - 2 - 7 + (8 * Math.sin(45))));
 470         // Check the center
 471         assertFalse(region.contains(CENTER_X, CENTER_Y));
 472         // TODO Could stand to have more tests testing the inside hit edge
 473     }
 474 
 475     @Test public void pickingRectangularBorderWithIndependentPercentageRadiusWithInsetsWorks() {
 476         region.setBorder(new Border(new BorderStroke(Color.RED, BorderStrokeStyle.SOLID,
 477             new CornerRadii(.01, .02, .03, .04, .05, .06, .07, .08, true, true, true, true, true, true, true, true),
 478             new BorderWidths(5, 10, 15, 20), new Insets(4, 3, 2, 1))));
 479         // Check points in the top-left corner area
 480         assertTrue(region.contains(X + 1, Y + 2 + 4));
 481         assertTrue(region.contains(X + 1 + 1, Y + 4));
 482         assertTrue(region.contains(X + 1 + 1 - (1 * Math.cos(45)), Y + 2 + 4 - (2 * Math.sin(45))));
 483         assertTrue(region.contains(X + 1 + 1 - (.5 * Math.cos(45)), Y + 2 + 4 - (1 * Math.sin(45))));
 484         assertFalse(region.contains(X + 1 + 1 - (2 * Math.cos(45)), Y + 2 + 4 - (3 * Math.sin(45))));
 485         // Check points in the top-right corner area
 486         assertTrue(region.contains(X + WIDTH - 3, Y + 3 + 4));
 487         assertTrue(region.contains(X + WIDTH - 4 - 3, Y + 4));
 488         assertTrue(region.contains(X + WIDTH - 4 - 3 + (4 * Math.cos(45)), Y + 4 + 3 - (3 * Math.sin(45))));
 489         assertTrue(region.contains(X + WIDTH - 4 - 3 + (3 * Math.cos(45)), Y + 4 + 3 - (2 * Math.sin(45))));
 490         assertFalse(region.contains(X + WIDTH - 4 - 3 + (5 * Math.cos(45)), Y + 4 + 3 - (4 * Math.sin(45))));
 491         // Check points in the bottom-right corner area
 492         assertTrue(region.contains(X + WIDTH - 3, Y + HEIGHT - 2 - 6));
 493         assertTrue(region.contains(X + WIDTH - 3 - 5, Y + HEIGHT - 2));
 494         assertTrue(region.contains(X + WIDTH - 3 - 5 + (5 * Math.cos(45)), Y + HEIGHT - 2 - 6 + (6 * Math.sin(45))));
 495         assertTrue(region.contains(X + WIDTH - 3 - 5 + (4 * Math.cos(45)), Y + HEIGHT - 2 - 6 + (5 * Math.sin(45))));
 496         assertFalse(region.contains(X + WIDTH - 3 - 5 + (6 * Math.cos(45)), Y + HEIGHT - 2 - 6 + (7 * Math.sin(45))));
 497         // Check points in the bottom-left corner area
 498         assertTrue(region.contains(X + 1, Y + HEIGHT - 2 - 7));
 499         assertTrue(region.contains(X + 1 + 8, Y + HEIGHT - 2));
 500         assertTrue(region.contains(X + 1 + 8 - (8 * Math.cos(45)), Y + HEIGHT - 2 - 7 + (7 * Math.sin(45))));
 501         assertTrue(region.contains(X + 1 + 8 - (7 * Math.cos(45)), Y + HEIGHT - 2 - 7 + (6 * Math.sin(45))));
 502         assertFalse(region.contains(X + 1 + 8 - (9 * Math.cos(45)), Y + HEIGHT - 2 - 7 + (8 * Math.sin(45))));
 503         // Check the center
 504         assertFalse(region.contains(CENTER_X, CENTER_Y));
 505         // TODO Could stand to have more tests testing the inside hit edge
 506     }
 507 
 508     /**************************************************************************
 509      *                                                                        *
 510      * Test behavior when picking a shaped region. We have to test all the    *
 511      * positionShape / scaleShape variants to make sure we are always picking *
 512      * based on the perceived (rendered) shape                                *
 513      *                                                                        *
 514      *************************************************************************/
 515 
 516     @Test public void pickingSimpleShape() {
 517         region.setPickOnBounds(false);
 518         region.setScaleShape(false);
 519         region.setCenterShape(false);
 520         region.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
 521         
 522         region.setShape(new Circle(50, 50, 30));
 523         
 524         assertFalse(region.contains(X + 50, Y + 81));
 525         assertFalse(region.contains(X + 50, Y + 19));
 526         assertFalse(region.contains(X + 81, Y + 50));
 527         assertFalse(region.contains(X + 19, Y + 50));
 528         assertTrue(region.contains(X + 50, Y + 79));
 529         assertTrue(region.contains(X + 50, Y + 21));
 530         assertTrue(region.contains(X + 79, Y + 50));
 531         assertTrue(region.contains(X + 21, Y + 50));
 532         
 533     }
 534     
 535     @Test public void pickingCenteredShape() {
 536         region.setPickOnBounds(false);
 537         region.setScaleShape(false);
 538         region.setCenterShape(true);
 539         region.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
 540 
 541         region.setShape(new Circle(0, 0, 30));
 542 
 543         assertFalse(region.contains(X + 50, Y + 81));
 544         assertFalse(region.contains(X + 50, Y + 19));
 545         assertFalse(region.contains(X + 81, Y + 50));
 546         assertFalse(region.contains(X + 19, Y + 50));
 547         assertTrue(region.contains(X + 50, Y + 79));
 548         assertTrue(region.contains(X + 50, Y + 21));
 549         assertTrue(region.contains(X + 79, Y + 50));
 550         assertTrue(region.contains(X + 21, Y + 50));
 551         
 552     }
 553     
 554     @Test public void pickingScaledShape() {
 555         region.setPickOnBounds(false);
 556         region.setScaleShape(true);
 557         region.setCenterShape(false);
 558         region.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
 559 
 560         region.setShape(new Circle(0, 0, 30));
 561 
 562         assertFalse(region.contains(X, Y + HEIGHT / 2  + 1));
 563         assertFalse(region.contains(X, Y - HEIGHT / 2  - 1));
 564         assertFalse(region.contains(X + WIDTH / 2 + 1, Y));
 565         assertFalse(region.contains(X - WIDTH / 2 - 1, Y));
 566         
 567         assertTrue(region.contains(X + 1, Y + HEIGHT / 2 - 1));
 568         assertTrue(region.contains(X + WIDTH / 2 - 1, Y));
 569         
 570         // Even though the shape is there, these points are outside of region's bounds, so it wouldn't be really picked.
 571         assertFalse(region.contains(X + 1, Y - HEIGHT / 2 + 1));
 572         assertFalse(region.contains(X - WIDTH / 2 + 1, Y));
 573         
 574     }
 575     
 576     @Test public void pickingScaledAndCenteredShape() {
 577         region.setPickOnBounds(false);
 578         region.setScaleShape(true);
 579         region.setCenterShape(true);
 580         region.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)));
 581 
 582         region.setShape(new Circle(0, 0, 30));
 583 
 584         assertFalse(region.contains(X + WIDTH / 2, Y + HEIGHT + 1));
 585         assertFalse(region.contains(X + WIDTH / 2, Y - 1));
 586         assertFalse(region.contains(X + WIDTH + 1, Y + HEIGHT / 2));
 587         assertFalse(region.contains(X - 1, Y + HEIGHT / 2));
 588         
 589         assertTrue(region.contains(X + WIDTH / 2, Y + HEIGHT - 1));
 590         assertTrue(region.contains(X + WIDTH / 2, Y + 1));
 591         assertTrue(region.contains(X + WIDTH - 1, Y + HEIGHT / 2));
 592         assertTrue(region.contains(X + 1, Y + HEIGHT / 2));
 593         
 594     }
 595     
 596 }