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 
  29 import com.sun.javafx.geom.QuadCurve2D;
  30 import com.sun.javafx.scene.DirtyBits;
  31 import com.sun.javafx.scene.NodeHelper;
  32 import com.sun.javafx.scene.shape.QuadCurveHelper;
  33 import com.sun.javafx.sg.prism.NGNode;
  34 import com.sun.javafx.sg.prism.NGQuadCurve;
  35 import javafx.beans.property.DoubleProperty;
  36 import javafx.beans.property.DoublePropertyBase;
  37 import javafx.scene.Node;
  38 import javafx.scene.paint.Paint;
  39 
  40 
  41 /**
  42  * The {@code Quadcurve} class defines a quadratic Bézier parametric curve
  43  * segment in (x,y) coordinate space. Drawing a curve that intersects both the
  44  * specified coordinates {@code (startX, startY)} and {@code (endX, enfY)},
  45  * using the specified point {@code (controlX, controlY)}
  46  * as Bézier control point.
  47  *
  48 <PRE>
  49 import javafx.scene.shape.*;
  50 
  51 QuadCurve quad = new QuadCurve();
  52 quad.setStartX(0.0f);
  53 quad.setStartY(50.0f);
  54 quad.setEndX(50.0f);
  55 quad.setEndY(50.0f);
  56 quad.setControlX(25.0f);
  57 quad.setControlY(0.0f);
  58 </PRE>
  59  * @since JavaFX 2.0
  60  */
  61 public  class QuadCurve extends Shape {
  62     static {
  63         QuadCurveHelper.setQuadCurveAccessor(new QuadCurveHelper.QuadCurveAccessor() {
  64             @Override
  65             public NGNode doCreatePeer(Node node) {
  66                 return ((QuadCurve) node).doCreatePeer();
  67             }
  68 
  69             @Override
  70             public void doUpdatePeer(Node node) {
  71                 ((QuadCurve) node).doUpdatePeer();
  72             }
  73 
  74             @Override
  75             public com.sun.javafx.geom.Shape doConfigShape(Shape shape) {
  76                 return ((QuadCurve) shape).doConfigShape();
  77             }
  78         });
  79     }
  80 
  81     private final QuadCurve2D shape = new QuadCurve2D();
  82 
  83     {
  84         // To initialize the class helper at the begining each constructor of this class
  85         QuadCurveHelper.initHelper(this);
  86     }
  87 
  88     /**
  89      * Creates an empty instance of QuadCurve.
  90      */
  91     public QuadCurve() {
  92     }
  93 
  94     /**
  95      * Creates a new instance of QuadCurve.
  96      * @param startX the X coordinate of the start point
  97      * @param startY the Y coordinate of the start point
  98      * @param controlX the X coordinate of the control point
  99      * @param controlY the Y coordinate of the control point
 100      * @param endX the X coordinate of the end point
 101      * @param endY the Y coordinate of the end point
 102      */
 103     public QuadCurve(double startX, double startY, double controlX, double controlY, double endX, double endY) {
 104         setStartX(startX);
 105         setStartY(startY);
 106         setControlX(controlX);
 107         setControlY(controlY);
 108         setEndX(endX);
 109         setEndY(endY);
 110     }
 111 
 112     /**
 113      * Defines the X coordinate of the start point
 114      * of the quadratic curve segment.
 115      *
 116      * @defaultValue 0.0
 117      */
 118     private DoubleProperty startX;
 119 
 120     public final void setStartX(double value) {
 121         if (startX != null || value != 0.0) {
 122             startXProperty().set(value);
 123         }
 124     }
 125 
 126     public final double getStartX() {
 127         return startX == null ? 0.0 : startX.get();
 128     }
 129 
 130     public final DoubleProperty startXProperty() {
 131         if (startX == null) {
 132             startX = new DoublePropertyBase() {
 133 
 134                 @Override
 135                 public void invalidated() {
 136                     NodeHelper.markDirty(QuadCurve.this, DirtyBits.NODE_GEOMETRY);
 137                     impl_geomChanged();
 138                 }
 139 
 140                 @Override
 141                 public Object getBean() {
 142                     return QuadCurve.this;
 143                 }
 144 
 145                 @Override
 146                 public String getName() {
 147                     return "startX";
 148                 }
 149             };
 150         }
 151         return startX;
 152     }
 153 
 154     /**
 155      * Defines the Y coordinate of the start point
 156      * of the quadratic curve segment.
 157      *
 158      * @defaultValue 0.0
 159      */
 160     private DoubleProperty startY;
 161 
 162     public final void setStartY(double value) {
 163         if (startY != null || value != 0.0) {
 164             startYProperty().set(value);
 165         }
 166     }
 167 
 168     public final double getStartY() {
 169         return startY == null ? 0.0 : startY.get();
 170     }
 171 
 172     public final DoubleProperty startYProperty() {
 173         if (startY == null) {
 174             startY = new DoublePropertyBase() {
 175 
 176                 @Override
 177                 public void invalidated() {
 178                     NodeHelper.markDirty(QuadCurve.this, DirtyBits.NODE_GEOMETRY);
 179                     impl_geomChanged();
 180                 }
 181 
 182                 @Override
 183                 public Object getBean() {
 184                     return QuadCurve.this;
 185                 }
 186 
 187                 @Override
 188                 public String getName() {
 189                     return "startY";
 190                 }
 191             };
 192         }
 193         return startY;
 194     }
 195 
 196     /**
 197      * Defines the X coordinate of the control point
 198      * of the quadratic curve segment.
 199      *
 200      * @defaultValue 0.0
 201      */
 202     private DoubleProperty controlX = new DoublePropertyBase() {
 203 
 204         @Override
 205         public void invalidated() {
 206             NodeHelper.markDirty(QuadCurve.this, DirtyBits.NODE_GEOMETRY);
 207             impl_geomChanged();
 208         }
 209 
 210         @Override
 211         public Object getBean() {
 212             return QuadCurve.this;
 213         }
 214 
 215         @Override
 216         public String getName() {
 217             return "controlX";
 218         }
 219     };
 220 
 221     public final void setControlX(double value) {
 222         controlX.set(value);
 223     }
 224 
 225     public final double getControlX() {
 226         return controlX.get();
 227     }
 228 
 229     public final DoubleProperty controlXProperty() {
 230         return controlX;
 231     }
 232 
 233     /**
 234      * Defines the Y coordinate of the control point
 235      * of the quadratic curve segment.
 236      *
 237      * @defaultValue 0.0
 238      */
 239     private DoubleProperty controlY = new DoublePropertyBase() {
 240 
 241         @Override
 242         public void invalidated() {
 243             NodeHelper.markDirty(QuadCurve.this, DirtyBits.NODE_GEOMETRY);
 244             impl_geomChanged();
 245         }
 246 
 247         @Override
 248         public Object getBean() {
 249             return QuadCurve.this;
 250         }
 251 
 252         @Override
 253         public String getName() {
 254             return "controlY";
 255         }
 256     };
 257 
 258 
 259     public final void setControlY(double value) {
 260         controlY.set(value);
 261     }
 262 
 263     public final double getControlY() {
 264         return controlY.get();
 265     }
 266 
 267     public final DoubleProperty controlYProperty() {
 268         return controlY;
 269     }
 270 
 271     /**
 272      * Defines the X coordinate of the end point
 273      * of the quadratic curve segment.
 274      *
 275      * @defaultValue 0.0
 276      */
 277     private DoubleProperty endX;
 278 
 279 
 280     public final void setEndX(double value) {
 281         if (endX != null || value != 0.0) {
 282             endXProperty().set(value);
 283         }
 284     }
 285 
 286     public final double getEndX() {
 287         return endX == null ? 0.0 : endX.get();
 288     }
 289 
 290     public final DoubleProperty endXProperty() {
 291         if (endX == null) {
 292             endX = new DoublePropertyBase() {
 293 
 294         @Override
 295         public void invalidated() {
 296             NodeHelper.markDirty(QuadCurve.this, DirtyBits.NODE_GEOMETRY);
 297             impl_geomChanged();
 298         }
 299 
 300         @Override
 301         public Object getBean() {
 302             return QuadCurve.this;
 303         }
 304 
 305         @Override
 306         public String getName() {
 307             return "endX";
 308         }
 309     };
 310     }
 311         return endX;
 312     }
 313 
 314     /**
 315      * Defines the Y coordinate of the end point
 316      * of the quadratic curve segment.
 317      *
 318      * @defaultValue 0.0
 319      */
 320     private DoubleProperty endY;
 321 
 322     public final void setEndY(double value) {
 323         if (endY != null || value != 0.0) {
 324             endYProperty().set(value);
 325         }
 326     }
 327 
 328     public final double getEndY() {
 329         return endY == null ? 0.0 : endY.get();
 330     }
 331 
 332     public final DoubleProperty endYProperty() {
 333         if (endY == null) {
 334             endY = new DoublePropertyBase() {
 335 
 336         @Override
 337         public void invalidated() {
 338             NodeHelper.markDirty(QuadCurve.this, DirtyBits.NODE_GEOMETRY);
 339             impl_geomChanged();
 340         }
 341 
 342         @Override
 343         public Object getBean() {
 344             return QuadCurve.this;
 345         }
 346 
 347         @Override
 348         public String getName() {
 349             return "endY";
 350         }
 351     };
 352     }
 353         return endY;
 354     }
 355 
 356     /*
 357      * Note: This method MUST only be called via its accessor method.
 358      */
 359     private NGNode doCreatePeer() {
 360         return new NGQuadCurve();
 361     }
 362 
 363     /*
 364      * Note: This method MUST only be called via its accessor method.
 365      */
 366     private QuadCurve2D doConfigShape() {
 367         shape.x1 = (float)getStartX();
 368         shape.y1 = (float)getStartY();
 369         shape.ctrlx = (float)getControlX();
 370         shape.ctrly = (float)getControlY();
 371         shape.x2 = (float)getEndX();
 372         shape.y2 = (float)getEndY();
 373         return shape;
 374     }
 375 
 376     /*
 377      * Note: This method MUST only be called via its accessor method.
 378      */
 379     private void doUpdatePeer() {
 380         if (NodeHelper.isDirty(this, DirtyBits.NODE_GEOMETRY)) {
 381             final NGQuadCurve peer = NodeHelper.getPeer(this);
 382             peer.updateQuadCurve((float)getStartX(),
 383                 (float)getStartY(),
 384                 (float)getEndX(),
 385                 (float)getEndY(),
 386                 (float)getControlX(),
 387                 (float)getControlY());
 388         }
 389     }
 390 
 391     /**
 392      * Returns a string representation of this {@code QuadCurve} object.
 393      * @return a string representation of this {@code QuadCurve} object.
 394      */
 395     @Override
 396     public String toString() {
 397         final StringBuilder sb = new StringBuilder("QuadCurve[");
 398 
 399         String id = getId();
 400         if (id != null) {
 401             sb.append("id=").append(id).append(", ");
 402         }
 403 
 404         sb.append("startX=").append(getStartX());
 405         sb.append(", startY=").append(getStartY());
 406         sb.append(", controlX=").append(getControlX());
 407         sb.append(", controlY=").append(getControlY());
 408         sb.append(", endX=").append(getEndX());
 409         sb.append(", endY=").append(getEndY());
 410 
 411         sb.append(", fill=").append(getFill());
 412 
 413         Paint stroke = getStroke();
 414         if (stroke != null) {
 415             sb.append(", stroke=").append(stroke);
 416             sb.append(", strokeWidth=").append(getStrokeWidth());
 417         }
 418 
 419         return sb.append("]").toString();
 420     }
 421 }
 422