Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.shape; 027 028import javafx.beans.property.DoubleProperty; 029import javafx.beans.property.DoublePropertyBase; 030import javafx.scene.paint.Paint; 031 032import com.sun.javafx.geom.BaseBounds; 033import com.sun.javafx.geom.Ellipse2D; 034import com.sun.javafx.geom.transform.BaseTransform; 035import com.sun.javafx.scene.DirtyBits; 036import com.sun.javafx.sg.PGCircle; 037import com.sun.javafx.sg.PGNode; 038import com.sun.javafx.sg.PGShape.Mode; 039import com.sun.javafx.tk.Toolkit; 040 041 042 043/** 044 * The {@code Circle} class creates a new circle 045 * with the specified radius and center location measured in pixels 046 * 047 * Example usage. The following code creates a circle with radius 50px centered 048 * at (100,100)px. 049 * 050<PRE> 051import javafx.scene.shape.*; 052 053Circle circle = new Circle(); 054circle.setCenterX(100.0f); 055circle.setCenterY(100.0f); 056circle.setRadius(50.0f); 057} 058</PRE> 059 */ 060public class Circle extends Shape { 061 062 private final Ellipse2D shape = new Ellipse2D(); 063 064 /** 065 * Creates a new instance of Circle with a specified radius. 066 * @param radius the radius of the circle in pixels 067 */ 068 public Circle(double radius) { 069 setRadius(radius); 070 } 071 072 /** 073 * Creates a new instance of Circle with a specified radius and fill. 074 * @param radius the radius of the circle 075 * @param fill determines how to fill the interior of the Circle 076 */ 077 public Circle(double radius, Paint fill) { 078 setRadius(radius); 079 setFill(fill); 080 } 081 082 /** 083 * Creates an empty instance of Circle. 084 */ 085 public Circle() { 086 } 087 088 /** 089 * Creates a new instance of Circle with a specified position and radius. 090 * @param centerX the horizontal position of the center of the circle in pixels 091 * @param centerY the vertical position of the center of the circle in pixels 092 * @param radius the radius of the circle in pixels 093 */ 094 public Circle(double centerX, double centerY, double radius) { 095 setCenterX(centerX); 096 setCenterY(centerY); 097 setRadius(radius); 098 } 099 100 /** 101 * Creates a new instance of Circle with a specified position, radius and fill. 102 * @param centerX the horizontal position of the center of the circle in pixels 103 * @param centerY the vertical position of the center of the circle in pixels 104 * @param radius the radius of the circle in pixels 105 * @param fill determines how to fill the interior of the Circle 106 */ 107 public Circle(double centerX, double centerY, double radius, Paint fill) { 108 setCenterX(centerX); 109 setCenterY(centerY); 110 setRadius(radius); 111 setFill(fill); 112 } 113 114 /** 115 * Defines the horizontal position of the center of the circle in pixels. 116 * 117 * @defaultValue 0.0 118 */ 119 private DoubleProperty centerX; 120 121 122 123 public final void setCenterX(double value) { 124 if (centerX != null || value != 0.0) { 125 centerXProperty().set(value); 126 } 127 } 128 129 public final double getCenterX() { 130 return centerX == null ? 0.0 : centerX.get(); 131 } 132 133 public final DoubleProperty centerXProperty() { 134 if (centerX == null) { 135 centerX = new DoublePropertyBase(0.0) { 136 137 @Override 138 public void invalidated() { 139 impl_markDirty(DirtyBits.NODE_GEOMETRY); 140 impl_geomChanged(); 141 } 142 143 @Override 144 public Object getBean() { 145 return Circle.this; 146 } 147 148 @Override 149 public String getName() { 150 return "centerX"; 151 } 152 }; 153 } 154 return centerX; 155 } 156 157 /** 158 * Defines the vertical position of the center of the circle in pixels. 159 * 160 * @defaultValue 0.0 161 */ 162 private DoubleProperty centerY; 163 164 165 166 public final void setCenterY(double value) { 167 if (centerY != null || value != 0.0) { 168 centerYProperty().set(value); 169 } 170 } 171 172 public final double getCenterY() { 173 return centerY == null ? 0.0 : centerY.get(); 174 } 175 176 public final DoubleProperty centerYProperty() { 177 if (centerY == null) { 178 centerY = new DoublePropertyBase(0.0) { 179 180 @Override 181 public void invalidated() { 182 impl_markDirty(DirtyBits.NODE_GEOMETRY); 183 impl_geomChanged(); 184 } 185 186 @Override 187 public Object getBean() { 188 return Circle.this; 189 } 190 191 @Override 192 public String getName() { 193 return "centerY"; 194 } 195 }; 196 } 197 return centerY; 198 } 199 200 /** 201 * Defines the radius of the circle in pixels. 202 * 203 * @defaultValue 0.0 204 */ 205 private DoubleProperty radius = new DoublePropertyBase() { 206 207 @Override 208 public void invalidated() { 209 impl_markDirty(DirtyBits.NODE_GEOMETRY); 210 impl_geomChanged(); 211 } 212 213 @Override 214 public Object getBean() { 215 return Circle.this; 216 } 217 218 @Override 219 public String getName() { 220 return "radius"; 221 } 222 }; 223 224 public final void setRadius(double value) { 225 radius.set(value); 226 } 227 228 public final double getRadius() { 229 return radius.get(); 230 } 231 232 public final DoubleProperty radiusProperty() { 233 return radius; 234 } 235 236 /** 237 * @treatAsPrivate implementation detail 238 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 239 */ 240 @Deprecated 241 @Override protected PGNode impl_createPGNode() { 242 return Toolkit.getToolkit().createPGCircle(); 243 } 244 245 PGCircle getPGCircle() { 246 return (PGCircle)impl_getPGNode(); 247 } 248 249 /** 250 * @treatAsPrivate implementation detail 251 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 252 */ 253 @Deprecated 254 @Override protected com.sun.javafx.sg.PGShape.StrokeLineJoin toPGLineJoin(StrokeLineJoin t) { 255 // The MITER join style can produce anomalous results for very thin or 256 // very wide ellipses when the bezier curves that approximate the arcs 257 // become so distorted that they shoot out MITER-like extensions. This 258 // effect complicates matters because it makes the circles very non-round, 259 // and also because it means we might have to pad the bounds to account 260 // for this rare and unpredictable circumstance. 261 // To avoid the problem, we set the Join style to BEVEL for any 262 // circle. The BEVEL join style is more predictable for 263 // anomalous angles and is the simplest join style to compute in 264 // the stroking code. 265 // These problems do not necessarily happen for circles which have a 266 // fixed and balanced aspect ratio, but why waste time computing a 267 // conversion of a MITER join style when it has no advantage for 268 // circles and technically requires more computation? 269 return com.sun.javafx.sg.PGShape.StrokeLineJoin.BEVEL; 270 } 271 272 /** 273 * @treatAsPrivate implementation detail 274 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 275 */ 276 @Deprecated 277 @Override public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) { 278 // if there is no fill or stroke, then there are no bounds. The bounds 279 // must be marked empty in this case to distinguish it from 0,0,0,0 280 // which would actually contribute to the bounds of a group. 281 if (impl_mode == Mode.EMPTY) { 282 return bounds.makeEmpty(); 283 } 284 285 final double cX = getCenterX(); 286 final double cY = getCenterY(); 287 288 if ((tx.getType() & ~(BaseTransform.TYPE_MASK_ROTATION | BaseTransform.TYPE_TRANSLATION)) == 0) { 289 290 double tCX = cX * tx.getMxx() + cY * tx.getMxy() + tx.getMxt(); 291 double tCY = cX * tx.getMyx() + cY * tx.getMyy() + tx.getMyt(); 292 double r = getRadius(); 293 294 if (impl_mode != Mode.FILL && getStrokeType() != StrokeType.INSIDE) { 295 double upad = getStrokeWidth(); 296 if (getStrokeType() == StrokeType.CENTERED) { 297 upad /= 2.0f; 298 } 299 r += upad; 300 } 301 302 return bounds.deriveWithNewBounds((float) (tCX - r), (float) (tCY - r), 0, 303 (float) (tCX + r), (float) (tCY + r), 0); 304 } else if ((tx.getType() & ~(BaseTransform.TYPE_MASK_SCALE | BaseTransform.TYPE_TRANSLATION | BaseTransform.TYPE_FLIP)) == 0) { 305 final double r = getRadius(); 306 final double x = getCenterX() - r; 307 final double y = getCenterY() - r; 308 final double width = 2.0 * r; 309 final double height = width; 310 double upad; 311 if (impl_mode == Mode.FILL || getStrokeType() == StrokeType.INSIDE) { 312 upad = 0.0f; 313 } else { 314 upad = getStrokeWidth(); 315 } 316 return computeBounds(bounds, tx, upad, 0, x, y, width, height); 317 } 318 319 return computeShapeBounds(bounds, tx, impl_configShape()); 320 } 321 322 /** 323 * @treatAsPrivate implementation detail 324 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 325 */ 326 @Deprecated 327 @Override public Ellipse2D impl_configShape() { 328 double r = getRadius(); 329 shape.setFrame( 330 (float)(getCenterX() - r), // x 331 (float)(getCenterY() - r), // y 332 (float)(r * 2.0), // w 333 (float)(r * 2.0)); // h 334 return shape; 335 } 336 337 /** 338 * @treatAsPrivate implementation detail 339 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 340 */ 341 @Deprecated 342 @Override public void impl_updatePG() { 343 super.impl_updatePG(); 344 345 if (impl_isDirty(DirtyBits.NODE_GEOMETRY)) { 346 PGCircle peer = getPGCircle(); 347 peer.updateCircle((float)getCenterX(), 348 (float)getCenterY(), 349 (float)getRadius()); 350 } 351 } 352 353 /** 354 * Returns a string representation of this {@code Circle} object. 355 * @return a string representation of this {@code Circle} object. 356 */ 357 @Override 358 public String toString() { 359 final StringBuilder sb = new StringBuilder("Circle["); 360 361 String id = getId(); 362 if (id != null) { 363 sb.append("id=").append(id).append(", "); 364 } 365 366 sb.append("centerX=").append(getCenterX()); 367 sb.append(", centerY=").append(getCenterY()); 368 sb.append(", radius=").append(getRadius()); 369 370 sb.append(", fill=").append(getFill()); 371 372 Paint stroke = getStroke(); 373 if (stroke != null) { 374 sb.append(", stroke=").append(stroke); 375 sb.append(", strokeWidth=").append(getStrokeWidth()); 376 } 377 378 return sb.append("]").toString(); 379 } 380} 381