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;
030
031import com.sun.javafx.geom.BaseBounds;
032import com.sun.javafx.geom.Ellipse2D;
033import com.sun.javafx.geom.transform.BaseTransform;
034import com.sun.javafx.scene.DirtyBits;
035import com.sun.javafx.sg.PGEllipse;
036import com.sun.javafx.sg.PGNode;
037import com.sun.javafx.sg.PGShape.Mode;
038import com.sun.javafx.tk.Toolkit;
039import javafx.scene.paint.Paint;
040
041
042/**
043 * The {@code Ellipse} class creates a new ellipse
044 * with the specified size and location in pixels
045 *
046<PRE>
047import javafx.scene.shape.*;
048
049Ellipse ellipse = new Ellipse(); {
050ellipse.setCenterX(50.0f);
051ellipse.setCenterY(50.0f);
052ellipse.setRadiusX(50.0f);
053ellipse.setRadiusY(25.0f);
054</PRE>
055 */
056public class Ellipse extends Shape {
057
058    private final Ellipse2D shape = new Ellipse2D();
059
060    private static final int NON_RECTILINEAR_TYPE_MASK = ~(
061            BaseTransform.TYPE_TRANSLATION |
062            BaseTransform.TYPE_QUADRANT_ROTATION |
063            BaseTransform.TYPE_MASK_SCALE |
064            BaseTransform.TYPE_FLIP);
065
066
067    /**
068     * Creates an empty instance of Ellipse.
069     */
070    public Ellipse() {
071    }
072
073    /**
074     * Creates an instance of Ellipse of the given size.
075     * @param radiusX the horizontal radius of the ellipse in pixels
076     * @param radiusY the vertical radius of the ellipse in pixels
077     */
078    public Ellipse(double radiusX, double radiusY) {
079        setRadiusX(radiusX);
080        setRadiusY(radiusY);
081    }
082
083    /**
084     * Creates an instance of Ellipse of the given position and size.
085     * @param centerX the horizontal position of the center of the ellipse in pixels
086     * @param centerY the vertical position of the center of the ellipse in pixels
087     * @param radiusX the horizontal radius of the ellipse in pixels
088     * @param radiusY the vertical radius of the ellipse in pixels
089     */
090    public Ellipse(double centerX, double centerY, double radiusX, double radiusY) {
091        this(radiusX, radiusY);
092        setCenterX(centerX);
093        setCenterY(centerY);
094    }
095
096    /**
097     * Defines the horizontal position of the center of the ellipse in pixels.
098     *
099     * @defaultValue 0.0
100     */
101    private DoubleProperty centerX;
102
103    public final void setCenterX(double value) {
104        if (centerX != null || value != 0.0) {
105            centerXProperty().set(value);
106        }
107    }
108
109    public final double getCenterX() {
110        return centerX == null ? 0.0 : centerX.get();
111    }
112
113    public final DoubleProperty centerXProperty() {
114        if (centerX == null) {
115            centerX = new DoublePropertyBase() {
116
117                @Override
118                public void invalidated() {
119                    impl_markDirty(DirtyBits.NODE_GEOMETRY);
120                    impl_geomChanged();
121                }
122
123                @Override
124                public Object getBean() {
125                    return Ellipse.this;
126                }
127
128                @Override
129                public String getName() {
130                    return "centerX";
131                }
132            };
133        }
134        return centerX;
135    }
136
137    /**
138     * Defines the vertical position of the center of the ellipse in pixels.
139     *
140     * @defaultValue 0.0
141     */
142    private DoubleProperty centerY;
143
144    public final void setCenterY(double value) {
145        if (centerY != null || value != 0.0) {
146            centerYProperty().set(value);
147        }
148    }
149
150    public final double getCenterY() {
151        return centerY == null ? 0.0 : centerY.get();
152    }
153
154    public final DoubleProperty centerYProperty() {
155        if (centerY == null) {
156            centerY = new DoublePropertyBase() {
157
158                @Override
159                public void invalidated() {
160                    impl_markDirty(DirtyBits.NODE_GEOMETRY);
161                    impl_geomChanged();
162                }
163
164                @Override
165                public Object getBean() {
166                    return Ellipse.this;
167                }
168
169                @Override
170                public String getName() {
171                    return "centerY";
172                }
173            };
174        }
175        return centerY;
176    }
177
178    /**
179     * Defines the width of the ellipse in pixels.
180     *
181     * @defaultValue 0.0
182     */
183    private DoubleProperty radiusX = new DoublePropertyBase() {
184
185        @Override
186        public void invalidated() {
187            impl_markDirty(DirtyBits.NODE_GEOMETRY);
188            impl_geomChanged();
189        }
190
191        @Override
192        public Object getBean() {
193            return Ellipse.this;
194        }
195
196        @Override
197        public String getName() {
198            return "radiusX";
199        }
200    };
201
202    public final void setRadiusX(double value) {
203        radiusX.set(value);
204    }
205
206    public final double getRadiusX() {
207        return radiusX.get();
208    }
209
210    public final DoubleProperty radiusXProperty() {
211        return radiusX;
212    }
213
214    /**
215     * Defines the height of the ellipse in pixels.
216     *
217     * @defaultValue 0.0
218     */
219    private DoubleProperty radiusY = new DoublePropertyBase() {
220
221        @Override
222        public void invalidated() {
223            impl_markDirty(DirtyBits.NODE_GEOMETRY);
224            impl_geomChanged();
225        }
226
227        @Override
228        public Object getBean() {
229            return Ellipse.this;
230        }
231
232        @Override
233        public String getName() {
234            return "radiusY";
235        }
236    };
237
238    public final void setRadiusY(double value) {
239        radiusY.set(value);
240    }
241
242    public final double getRadiusY() {
243        return radiusY.get();
244    }
245
246    public final DoubleProperty radiusYProperty() {
247        return radiusY;
248    }
249
250    /**
251     * @treatAsPrivate implementation detail
252     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
253     */
254    @Deprecated
255    @Override
256    protected PGNode impl_createPGNode() {
257        return Toolkit.getToolkit().createPGEllipse();
258    }
259
260    PGEllipse getPGEllipse() {
261        return (PGEllipse)impl_getPGNode();
262    }
263
264    /**
265     * @treatAsPrivate implementation detail
266     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
267     */
268    @Deprecated
269    @Override
270    protected com.sun.javafx.sg.PGShape.StrokeLineJoin toPGLineJoin(StrokeLineJoin t) {
271        // The MITER join style can produce anomalous results for very thin or
272        // very wide ellipses when the bezier curves that approximate the arcs
273        // become so distorted that they shoot out MITER-like extensions.  This
274        // effect complicates matters because it makes the ellipses very non-round,
275        // and also because it means we might have to pad the bounds to account
276        // for this rare and unpredictable circumstance.
277        // To avoid the problem, we set the Join style to BEVEL for any
278        // ellipse.  The BEVEL join style is more predictable for
279        // anomalous angles and is the simplest join style to compute in
280        // the stroking code.
281        return com.sun.javafx.sg.PGShape.StrokeLineJoin.BEVEL;
282    }
283
284    /**
285     * @treatAsPrivate implementation detail
286     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
287     */
288    @Deprecated
289    @Override
290    public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) {
291        // if there is no fill or stroke, then there are no bounds. The bounds
292        // must be marked empty in this case to distinguish it from 0,0,0,0
293        // which would actually contribute to the bounds of a group.
294        if (impl_mode == Mode.EMPTY) {
295            return bounds.makeEmpty();
296        }
297        if ((tx.getType() & NON_RECTILINEAR_TYPE_MASK) != 0) {
298            return computeShapeBounds(bounds, tx, impl_configShape());
299        }
300
301        // compute the x, y, width and height of the ellipse
302        final double x = getCenterX() - getRadiusX();
303        final double y = getCenterY() - getRadiusY();
304        final double width = 2.0f * getRadiusX();
305        final double height = 2.0f * getRadiusY();
306        double upad;
307        double dpad;
308        if (impl_mode == Mode.FILL || getStrokeType() == StrokeType.INSIDE) {
309            upad = dpad = 0.0f;
310        } else {
311            upad = getStrokeWidth();
312            if (getStrokeType() == StrokeType.CENTERED) {
313                upad /= 2.0f;
314            }
315            dpad = 0.0f;
316        }
317        return computeBounds(bounds, tx, upad, dpad, x, y, width, height);
318    }
319
320    /**
321     * @treatAsPrivate implementation detail
322     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
323     */
324    @Deprecated
325    @Override
326        public Ellipse2D impl_configShape() {
327        shape.setFrame(
328            (float)(getCenterX() - getRadiusX()), // x
329            (float)(getCenterY() - getRadiusY()), // y
330            (float)(getRadiusX() * 2.0), // w
331            (float)(getRadiusY() * 2.0)); // h
332        return shape;
333    }
334
335    /**
336     * @treatAsPrivate implementation detail
337     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
338     */
339    @Deprecated
340    @Override
341    public void impl_updatePG() {
342        super.impl_updatePG();
343
344        if (impl_isDirty(DirtyBits.NODE_GEOMETRY)) {
345            PGEllipse peer = getPGEllipse();
346            peer.updateEllipse((float)getCenterX(),
347                (float)getCenterY(),
348                (float)getRadiusX(),
349                (float)getRadiusY());
350        }
351    }
352
353    /**
354     * Returns a string representation of this {@code Ellipse} object.
355     * @return a string representation of this {@code Ellipse} object.
356     */
357    @Override
358    public String toString() {
359        final StringBuilder sb = new StringBuilder("Ellipse[");
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(", radiusX=").append(getRadiusX());
369        sb.append(", radiusY=").append(getRadiusY());
370
371        sb.append(", fill=").append(getFill());
372
373        Paint stroke = getStroke();
374        if (stroke != null) {
375            sb.append(", stroke=").append(stroke);
376            sb.append(", strokeWidth=").append(getStrokeWidth());
377        }
378
379        return sb.append("]").toString();
380    }
381}