1 /*
   2  * Copyright (c) 2012, 2014, Oracle and/or its affiliates.
   3  * All rights reserved. Use is subject to license terms.
   4  *
   5  * This file is available and licensed under the following license:
   6  *
   7  * Redistribution and use in source and binary forms, with or without
   8  * modification, are permitted provided that the following conditions
   9  * are met:
  10  *
  11  *  - Redistributions of source code must retain the above copyright
  12  *    notice, this list of conditions and the following disclaimer.
  13  *  - Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in
  15  *    the documentation and/or other materials provided with the distribution.
  16  *  - Neither the name of Oracle Corporation nor the names of its
  17  *    contributors may be used to endorse or promote products derived
  18  *    from this software without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 package com.oracle.javafx.scenebuilder.kit.editor.panel.content.util;
  33 
  34 import javafx.geometry.BoundingBox;
  35 import javafx.geometry.Bounds;
  36 import javafx.geometry.Point2D;
  37 
  38 /**
  39  *
  40  *
  41  */
  42 public enum CardinalPoint {
  43     N, NE, E, SE, S, SW, W, NW;
  44 
  45 
  46     public CardinalPoint getOpposite() {
  47         final CardinalPoint result;
  48 
  49         switch(this) {
  50             case N:
  51                 result = S;
  52                 break;
  53             case NE:
  54                 result = SW;
  55                 break;
  56             case E:
  57                 result = W;
  58                 break;
  59             case SE:
  60                 result = NW;
  61                 break;
  62             case S:
  63                 result = N;
  64                 break;
  65             case SW:
  66                 result = NE;
  67                 break;
  68             case W:
  69                 result = E;
  70                 break;
  71             case NW:
  72                 result = SE;
  73                 break;
  74             default:
  75                 assert false : "unexpected cardinal point:" + this;
  76                 result = N;
  77                 break;
  78         }
  79 
  80         return result;
  81     }
  82 
  83 
  84     public Point2D getPosition(Bounds bounds) {
  85         final double x, y;
  86 
  87         switch(this) {
  88             case N:
  89                 x = (bounds.getMinX() + bounds.getMaxX()) / 2.0;
  90                 y = bounds.getMinY();
  91                 break;
  92             case NE:
  93                 x = bounds.getMaxX();
  94                 y = bounds.getMinY();
  95                 break;
  96             case E:
  97                 x = bounds.getMaxX();
  98                 y = (bounds.getMinY() + bounds.getMaxY()) / 2.0;
  99                 break;
 100             case SE:
 101                 x = bounds.getMaxX();
 102                 y = bounds.getMaxY();
 103                 break;
 104             case S:
 105                 x = (bounds.getMinX() + bounds.getMaxX()) / 2.0;
 106                 y = bounds.getMaxY();
 107                 break;
 108             case SW:
 109                 x = bounds.getMinX();
 110                 y = bounds.getMaxY();
 111                 break;
 112             case W:
 113                 x = bounds.getMinX();
 114                 y = (bounds.getMinY() + bounds.getMaxY()) / 2.0;
 115                 break;
 116             case NW:
 117                 x = bounds.getMinX();
 118                 y = bounds.getMinY();
 119                 break;
 120             default:
 121                 assert false : "unexpected cardinal point:" + this;
 122                 x = bounds.getMinX();
 123                 y = bounds.getMinY();
 124                 break;
 125         }
 126 
 127         return new Point2D(x, y);
 128     }
 129 
 130 
 131     public Bounds getResizedBounds(Bounds currentBounds, double dx, double dy) {
 132         /*
 133          *
 134          *        NW                N                NE
 135          *         *----------------*----------------*
 136          *         |                                 |
 137          *         |                                 |
 138          *         |                                 |
 139          *       W *                                 * E
 140          *         |                                 |
 141          *         |                                 |
 142          *         |                                 |
 143          *         *----------------*----------------*
 144          *        SW                S                SE
 145          *
 146          *
 147          */
 148 
 149         // x axis
 150         final double minX = currentBounds.getMinX();
 151         final double maxX = currentBounds.getMaxX();
 152         final double newMinX, newMaxX;
 153         switch(this) {
 154             case NW:
 155             case  W:
 156             case SW:
 157                 newMinX = Math.min(minX + dx, maxX);
 158                 newMaxX = maxX;
 159                 break;
 160             case NE:
 161             case  E:
 162             case SE:
 163                 newMinX = minX;
 164                 newMaxX = Math.max(maxX + dx, minX);
 165                 break;
 166             case N:
 167             case S:
 168                 newMinX = minX;
 169                 newMaxX = maxX;
 170                 break;
 171             default:
 172                 // Emergency code
 173                 assert false : "unexpected value=" + this;
 174                 newMinX = minX;
 175                 newMaxX = maxX;
 176                 break;
 177         }
 178 
 179         // y axis
 180         final double minY = currentBounds.getMinY();
 181         final double maxY = currentBounds.getMaxY();
 182         final double newMinY, newMaxY;
 183         switch(this) {
 184             case NW:
 185             case N:
 186             case NE:
 187                 newMinY = Math.min(minY + dy, maxY);
 188                 newMaxY = maxY;
 189                 break;
 190             case SE:
 191             case S:
 192             case SW:
 193                 newMinY = minY;
 194                 newMaxY = Math.max(maxY + dy, minY);
 195                 break;
 196             case  E:
 197             case  W:
 198                 newMinY = minY;
 199                 newMaxY = maxY;
 200                 break;
 201             default:
 202                 // Emergency code
 203                 assert false : "unexpected value=" + this;
 204                 newMinY = minY;
 205                 newMaxY = maxY;
 206                 break;
 207         }
 208 
 209         return new BoundingBox(newMinX, newMinY, newMaxX - newMinX, newMaxY - newMinY);
 210     }
 211 
 212 
 213     public Point2D clampVector(double dx, double dy) {
 214         final double resultDX, resultDY;
 215 
 216         switch(this) {
 217             case N:
 218             case S:
 219                 resultDX = 0.0;
 220                 resultDY = dy;
 221                 break;
 222             case E:
 223             case W:
 224                 resultDX = dx;
 225                 resultDY = 0.0;
 226                 break;
 227             default:
 228                 resultDX = dx;
 229                 resultDY = dy;
 230                 break;
 231         }
 232 
 233         return new Point2D(resultDX, resultDY);
 234     }
 235 
 236 
 237     public Bounds snapBounds(Bounds bounds, double ratio) {
 238         /*
 239          *
 240          *        NW                N                NE
 241          *         *----------------*----------------*
 242          *         |                                 |
 243          *         |                                 |
 244          *         |                                 |
 245          *       W *                                 * E
 246          *         |                                 |
 247          *         |                                 |
 248          *         |                                 |
 249          *         *----------------*----------------*
 250          *        SW                S                SE
 251          *
 252          *
 253          */
 254 
 255         final double minX = bounds.getMinX();
 256         final double minY = bounds.getMinY();
 257         final double maxX = bounds.getMaxX();
 258         final double maxY = bounds.getMaxY();
 259         final double snapWidth = bounds.getHeight() / ratio;
 260         final double snapDX = snapWidth - bounds.getWidth();
 261         final double snapHeight = bounds.getWidth() * ratio;
 262         final double snapDY = snapHeight - bounds.getHeight();
 263         final double newMinX, newMinY, newMaxX, newMaxY;
 264 
 265         // x axis
 266         switch(this) {
 267             case N:
 268             case S:
 269                 newMinX = minX - snapDX / 2.0;
 270                 newMaxX = maxX + snapDX / 2.0;
 271                 break;
 272             case E:
 273             case W:
 274                 newMinX = minX;
 275                 newMaxX = maxX;
 276                 break;
 277             case NW:
 278             case SW:
 279                 if (Math.abs(snapDX) >= Math.abs(snapDY)) {
 280                     newMinX = minX - snapDX;
 281                 } else {
 282                     newMinX = minX;
 283                 }
 284                 newMaxX = maxX;
 285                 break;
 286             case NE:
 287             case SE:
 288                 newMinX = minX;
 289                 if (Math.abs(snapDX) >= Math.abs(snapDY)) {
 290                     newMaxX = maxX + snapDX;
 291                 } else {
 292                     newMaxX = maxX;
 293                 }
 294                 break;
 295             default:
 296                 // Emergency code
 297                 assert false : "Unexpected " + this;
 298                 newMinX = minX;
 299                 newMaxX = maxX;
 300                 break;
 301         }
 302 
 303         // y axis
 304         switch(this) {
 305             case N:
 306             case S:
 307                 newMinY = minY;
 308                 newMaxY = maxY;
 309                 break;
 310             case E:
 311             case W:
 312                 newMinY = minY - snapDY / 2.0;
 313                 newMaxY = maxY + snapDY / 2.0;
 314                 break;
 315             case NW:
 316             case NE:
 317                 if (Math.abs(snapDY) > Math.abs(snapDX)) {
 318                     newMinY = minY - snapDY;
 319                 } else {
 320                     newMinY = minY;
 321                 }
 322                 newMaxY = maxY;
 323                 break;
 324             case SW:
 325             case SE:
 326                 newMinY = minY;
 327                 if (Math.abs(snapDY) > Math.abs(snapDX)) {
 328                     newMaxY = maxY + snapDY;
 329                 } else {
 330                     newMaxY = maxY;
 331                 }
 332                 break;
 333             default:
 334                 // Emergency code
 335                 assert false : "Unexpected " + this;
 336                 newMinY = minY;
 337                 newMaxY = maxY;
 338                 break;
 339         }
 340 
 341         return new BoundingBox(newMinX, newMinY, newMaxX - newMinX, newMaxY - newMinY);
 342     }
 343 }