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 }