1 /* 2 * Copyright (c) 2010, 2016, 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.shape; 27 28 import com.sun.javafx.geom.CubicCurve2D; 29 import com.sun.javafx.scene.DirtyBits; 30 import com.sun.javafx.scene.NodeHelper; 31 import com.sun.javafx.scene.shape.CubicCurveHelper; 32 import com.sun.javafx.sg.prism.NGCubicCurve; 33 import com.sun.javafx.sg.prism.NGNode; 34 import javafx.beans.property.DoubleProperty; 35 import javafx.beans.property.DoublePropertyBase; 36 import javafx.scene.Node; 37 import javafx.scene.paint.Paint; 38 39 40 /** 41 * <p>The {@code CubiCurve} class defines a cubic Bézier parametric curve segment 42 * in (x,y) coordinate space. Drawing a curve that intersects both the specified 43 * coordinates {@code (startX, startY)} and {@code (endX, enfY)}, using the 44 * specified points {@code (controlX1, controlY1)} and {@code (controlX2, controlY2)} 45 * as Bézier control points. 46 * Example:</p> 47 * 48 <PRE> 49 import javafx.scene.shape.*; 50 51 CubicCurve cubic = new CubicCurve(); 52 cubic.setStartX(0.0f); 53 cubic.setStartY(50.0f); 54 cubic.setControlX1(25.0f); 55 cubic.setControlY1(0.0f); 56 cubic.setControlX2(75.0f); 57 cubic.setControlY2(100.0f); 58 cubic.setEndX(100.0f); 59 cubic.setEndY(50.0f); 60 } 61 </PRE> 62 * @since JavaFX 2.0 63 */ 64 public class CubicCurve extends Shape { 65 static { 66 CubicCurveHelper.setCubicCurveAccessor(new CubicCurveHelper.CubicCurveAccessor() { 67 @Override 68 public NGNode doCreatePeer(Node node) { 69 return ((CubicCurve) node).doCreatePeer(); 70 } 71 72 @Override 73 public void doUpdatePeer(Node node) { 74 ((CubicCurve) node).doUpdatePeer(); 75 } 76 77 @Override 78 public com.sun.javafx.geom.Shape doConfigShape(Shape shape) { 79 return ((CubicCurve) shape).doConfigShape(); 80 } 81 }); 82 } 83 84 private final CubicCurve2D shape = new CubicCurve2D(); 85 /** 86 * Defines the X coordinate of the start point of the cubic curve segment. 87 * 88 * @defaultValue 0.0 89 */ 90 private DoubleProperty startX; 91 92 { 93 // To initialize the class helper at the begining each constructor of this class 94 CubicCurveHelper.initHelper(this); 95 } 96 97 /** 98 * Creates an empty instance of CubicCurve. 99 */ 100 public CubicCurve() { 101 } 102 103 /** 104 * Creates a new instance of CubicCurve. 105 * @param startX the X coordinate of the start point 106 * @param startY the Y coordinate of the start point 107 * @param controlX1 the X coordinate of the first control point 108 * @param controlY1 the Y coordinate of the first control point 109 * @param controlX2 the X coordinate of the second control point 110 * @param controlY2 the Y coordinate of the second control point 111 * @param endX the X coordinate of the end point 112 * @param endY the Y coordinate of the end point 113 * @since JavaFX 2.1 114 */ 115 public CubicCurve(double startX, double startY, double controlX1, 116 double controlY1, double controlX2, double controlY2, 117 double endX, double endY) { 118 setStartX(startX); 119 setStartY(startY); 120 setControlX1(controlX1); 121 setControlY1(controlY1); 122 setControlX2(controlX2); 123 setControlY2(controlY2); 124 setEndX(endX); 125 setEndY(endY); 126 } 127 128 public final void setStartX(double value) { 129 if (startX != null || value != 0.0) { 130 startXProperty().set(value); 131 } 132 } 133 134 public final double getStartX() { 135 return startX == null ? 0.0 : startX.get(); 136 } 137 138 public final DoubleProperty startXProperty() { 139 if (startX == null) { 140 startX = new DoublePropertyBase() { 141 142 @Override 143 public void invalidated() { 144 NodeHelper.markDirty(CubicCurve.this, DirtyBits.NODE_GEOMETRY); 145 impl_geomChanged(); 146 } 147 148 @Override 149 public Object getBean() { 150 return CubicCurve.this; 151 } 152 153 @Override 154 public String getName() { 155 return "startX"; 156 } 157 }; 158 } 159 return startX; 160 } 161 162 /** 163 * Defines the Y coordinate of the start point of the cubic curve segment. 164 * 165 * @defaultValue 0.0 166 */ 167 private DoubleProperty startY; 168 169 public final void setStartY(double value) { 170 if (startY != null || value != 0.0) { 171 startYProperty().set(value); 172 } 173 } 174 175 public final double getStartY() { 176 return startY == null ? 0.0 : startY.get(); 177 } 178 179 public final DoubleProperty startYProperty() { 180 if (startY == null) { 181 startY = new DoublePropertyBase() { 182 183 @Override 184 public void invalidated() { 185 NodeHelper.markDirty(CubicCurve.this, DirtyBits.NODE_GEOMETRY); 186 impl_geomChanged(); 187 } 188 189 @Override 190 public Object getBean() { 191 return CubicCurve.this; 192 } 193 194 @Override 195 public String getName() { 196 return "startY"; 197 } 198 }; 199 } 200 return startY; 201 } 202 203 /** 204 * Defines the X coordinate of the first control point 205 * of the cubic curve segment. 206 * 207 * @defaultValue 0.0 208 */ 209 private DoubleProperty controlX1; 210 211 public final void setControlX1(double value) { 212 if (controlX1 != null || value != 0.0) { 213 controlX1Property().set(value); 214 } 215 } 216 217 public final double getControlX1() { 218 return controlX1 == null ? 0.0 : controlX1.get(); 219 } 220 221 public final DoubleProperty controlX1Property() { 222 if (controlX1 == null) { 223 controlX1 = new DoublePropertyBase() { 224 225 @Override 226 public void invalidated() { 227 NodeHelper.markDirty(CubicCurve.this, DirtyBits.NODE_GEOMETRY); 228 impl_geomChanged(); 229 } 230 231 @Override 232 public Object getBean() { 233 return CubicCurve.this; 234 } 235 236 @Override 237 public String getName() { 238 return "controlX1"; 239 } 240 }; 241 } 242 return controlX1; 243 } 244 245 /** 246 * Defines the Y coordinate of the first control point 247 * of the cubic curve segment. 248 * 249 * @defaultValue 0.0 250 */ 251 private DoubleProperty controlY1; 252 253 public final void setControlY1(double value) { 254 if (controlY1 != null || value != 0.0) { 255 controlY1Property().set(value); 256 } 257 } 258 259 public final double getControlY1() { 260 return controlY1 == null ? 0.0 : controlY1.get(); 261 } 262 263 public final DoubleProperty controlY1Property() { 264 if (controlY1 == null) { 265 controlY1 = new DoublePropertyBase() { 266 267 @Override 268 public void invalidated() { 269 NodeHelper.markDirty(CubicCurve.this, DirtyBits.NODE_GEOMETRY); 270 impl_geomChanged(); 271 } 272 273 @Override 274 public Object getBean() { 275 return CubicCurve.this; 276 } 277 278 @Override 279 public String getName() { 280 return "controlY1"; 281 } 282 }; 283 } 284 return controlY1; 285 } 286 287 /** 288 * Defines the X coordinate of the second control point 289 * of the cubic curve segment. 290 * 291 * @defaultValue 0.0 292 */ 293 private DoubleProperty controlX2; 294 295 public final void setControlX2(double value) { 296 if (controlX2 != null || value != 0.0) { 297 controlX2Property().set(value); 298 } 299 } 300 301 public final double getControlX2() { 302 return controlX2 == null ? 0.0 : controlX2.get(); 303 } 304 305 public final DoubleProperty controlX2Property() { 306 if (controlX2 == null) { 307 controlX2 = new DoublePropertyBase() { 308 309 @Override 310 public void invalidated() { 311 NodeHelper.markDirty(CubicCurve.this, DirtyBits.NODE_GEOMETRY); 312 impl_geomChanged(); 313 } 314 315 @Override 316 public Object getBean() { 317 return CubicCurve.this; 318 } 319 320 @Override 321 public String getName() { 322 return "controlX2"; 323 } 324 }; 325 } 326 return controlX2; 327 } 328 329 /** 330 * Defines the Y coordinate of the second control point 331 * of the cubic curve segment. 332 * 333 * @defaultValue 0.0 334 */ 335 private DoubleProperty controlY2; 336 337 public final void setControlY2(double value) { 338 if (controlY2 != null || value != 0.0) { 339 controlY2Property().set(value); 340 } 341 } 342 343 public final double getControlY2() { 344 return controlY2 == null ? 0.0 : controlY2.get(); 345 } 346 347 public final DoubleProperty controlY2Property() { 348 if (controlY2 == null) { 349 controlY2 = new DoublePropertyBase() { 350 351 @Override 352 public void invalidated() { 353 NodeHelper.markDirty(CubicCurve.this, DirtyBits.NODE_GEOMETRY); 354 impl_geomChanged(); 355 } 356 357 @Override 358 public Object getBean() { 359 return CubicCurve.this; 360 } 361 362 @Override 363 public String getName() { 364 return "controlY2"; 365 } 366 }; 367 } 368 return controlY2; 369 } 370 371 /** 372 * Defines the X coordinate of the end point of the cubic curve segment. 373 * 374 * @defaultValue 0.0 375 */ 376 private DoubleProperty endX; 377 378 public final void setEndX(double value) { 379 if (endX != null || value != 0.0) { 380 endXProperty().set(value); 381 } 382 } 383 384 public final double getEndX() { 385 return endX == null ? 0.0 : endX.get(); 386 } 387 388 public final DoubleProperty endXProperty() { 389 if (endX == null) { 390 endX = new DoublePropertyBase() { 391 392 @Override 393 public void invalidated() { 394 NodeHelper.markDirty(CubicCurve.this, DirtyBits.NODE_GEOMETRY); 395 impl_geomChanged(); 396 } 397 398 @Override 399 public Object getBean() { 400 return CubicCurve.this; 401 } 402 403 @Override 404 public String getName() { 405 return "endX"; 406 } 407 }; 408 } 409 return endX; 410 } 411 412 /** 413 * Defines the Y coordinate of the end point of the cubic curve segment. 414 * 415 * @defaultValue 0.0 416 */ 417 private DoubleProperty endY; 418 419 public final void setEndY(double value) { 420 if (endY != null || value != 0.0) { 421 endYProperty().set(value); 422 } 423 } 424 425 public final double getEndY() { 426 return endY == null ? 0.0 : endY.get(); 427 } 428 429 public final DoubleProperty endYProperty() { 430 if (endY == null) { 431 endY = new DoublePropertyBase() { 432 433 @Override 434 public void invalidated() { 435 NodeHelper.markDirty(CubicCurve.this, DirtyBits.NODE_GEOMETRY); 436 impl_geomChanged(); 437 } 438 439 @Override 440 public Object getBean() { 441 return CubicCurve.this; 442 } 443 444 @Override 445 public String getName() { 446 return "endY"; 447 } 448 }; 449 } 450 return endY; 451 } 452 453 /* 454 * Note: This method MUST only be called via its accessor method. 455 */ 456 private CubicCurve2D doConfigShape() { 457 shape.x1 = (float)getStartX(); 458 shape.y1 = (float)getStartY(); 459 shape.ctrlx1 = (float)getControlX1(); 460 shape.ctrly1 = (float)getControlY1(); 461 shape.ctrlx2 = (float)getControlX2(); 462 shape.ctrly2 = (float)getControlY2(); 463 shape.x2 = (float)getEndX(); 464 shape.y2 = (float)getEndY(); 465 return shape; 466 } 467 468 /* 469 * Note: This method MUST only be called via its accessor method. 470 */ 471 private NGNode doCreatePeer() { 472 return new NGCubicCurve(); 473 } 474 475 /* 476 * Note: This method MUST only be called via its accessor method. 477 */ 478 private void doUpdatePeer() { 479 if (NodeHelper.isDirty(this, DirtyBits.NODE_GEOMETRY)) { 480 final NGCubicCurve peer = NodeHelper.getPeer(this); 481 peer.updateCubicCurve((float)getStartX(), 482 (float)getStartY(), 483 (float)getEndX(), 484 (float)getEndY(), 485 (float)getControlX1(), 486 (float)getControlY1(), 487 (float)getControlX2(), 488 (float)getControlY2()); 489 } 490 } 491 492 /** 493 * Returns a string representation of this {@code CubicCurve} object. 494 * @return a string representation of this {@code CubicCurve} object. 495 */ 496 @Override 497 public String toString() { 498 final StringBuilder sb = new StringBuilder("CubicCurve["); 499 500 String id = getId(); 501 if (id != null) { 502 sb.append("id=").append(id).append(", "); 503 } 504 505 sb.append("startX=").append(getStartX()); 506 sb.append(", startY=").append(getStartY()); 507 sb.append(", controlX1=").append(getControlX1()); 508 sb.append(", controlY1=").append(getControlY1()); 509 sb.append(", controlX2=").append(getControlX2()); 510 sb.append(", controlY2=").append(getControlY2()); 511 sb.append(", endX=").append(getEndX()); 512 sb.append(", endY=").append(getEndY()); 513 514 sb.append(", fill=").append(getFill()); 515 516 Paint stroke = getStroke(); 517 if (stroke != null) { 518 sb.append(", stroke=").append(stroke); 519 sb.append(", strokeWidth=").append(getStrokeWidth()); 520 } 521 522 return sb.append("]").toString(); 523 } 524 } 525