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.control;
027
028import javafx.css.CssMetaData;
029import javafx.css.PseudoClass;
030import com.sun.javafx.scene.control.skin.ProgressIndicatorSkin;
031import javafx.beans.property.DoubleProperty;
032import javafx.beans.property.DoublePropertyBase;
033import javafx.beans.property.ReadOnlyBooleanProperty;
034import javafx.beans.property.ReadOnlyBooleanWrapper;
035import javafx.css.StyleableProperty;
036
037
038/**
039 * A circular control which is used for indicating progress, either
040 * infinite (aka indeterminate) or finite. Often used with the Task API for
041 * representing progress of background Tasks.
042 * <p>
043 * ProgressIndicator sets focusTraversable to false.
044 * </p>
045 *
046 * <p>
047 * This first example creates a ProgressIndicator with an indeterminate value :
048 * <pre><code>
049 * import javafx.scene.control.ProgressIndicator;
050 * ProgressIndicator p1 = new ProgressIndicator();
051 * </code></pre>
052 * 
053 * <p>
054 * This next example creates a ProgressIndicator which is 25% complete :
055 * <pre><code>
056 * import javafx.scene.control.ProgressIndicator;
057 * ProgressIndicator p2 = new ProgressIndicator();
058 * p2.setProgress(0.25F);
059 * </code></pre>
060 *
061 * Implementation of ProgressIndicator According to JavaFX UI Control API Specification
062 */
063
064public class ProgressIndicator extends Control {
065
066    /**
067     * Value for progress indicating that the progress is indeterminate.
068     * 
069     * @see #setProgress
070     */
071    public static final double INDETERMINATE_PROGRESS = -1;
072
073    /***************************************************************************
074     *                                                                         *
075     * Constructors                                                            *
076     *                                                                         *
077     **************************************************************************/
078
079    /**
080     * Creates a new indeterminate ProgressIndicator.
081     */
082    public ProgressIndicator() {
083        this(INDETERMINATE_PROGRESS);
084    }
085
086    /**
087     * Creates a new ProgressIndicator with the given progress value.
088     */
089    public ProgressIndicator(double progress) {
090        // focusTraversable is styleable through css. Calling setFocusTraversable
091        // makes it look to css like the user set the value and css will not 
092        // override. Initializing focusTraversable by calling applyStyle with null
093        // StyleOrigin ensures that css will be able to override the value.
094        ((StyleableProperty)focusTraversableProperty()).applyStyle(null, Boolean.FALSE);
095        setProgress(progress);
096        getStyleClass().setAll(DEFAULT_STYLE_CLASS);
097        
098        // need to initialize pseudo-class state
099        final int c = Double.compare(INDETERMINATE_PROGRESS, progress);
100        pseudoClassStateChanged(PSEUDO_CLASS_INDETERMINATE, c == 0);
101        pseudoClassStateChanged(PSEUDO_CLASS_DETERMINATE,   c != 0);
102    }
103    /***************************************************************************
104     *                                                                         *
105     * Properties                                                              *
106     *                                                                         *
107     **************************************************************************/
108    /**
109     * A flag indicating whether it is possible to determine the progress
110     * of the ProgressIndicator. Typically indeterminate progress bars are
111     * rendered with some form of animation indicating potentially "infinite"
112     * progress.
113     */
114    private ReadOnlyBooleanWrapper indeterminate;
115    private void setIndeterminate(boolean value) {
116        indeterminatePropertyImpl().set(value);
117    }
118
119    public final boolean isIndeterminate() {
120        return indeterminate == null ? true : indeterminate.get();
121    }
122
123    public final ReadOnlyBooleanProperty indeterminateProperty() {
124        return indeterminatePropertyImpl().getReadOnlyProperty();
125    }
126
127    private ReadOnlyBooleanWrapper indeterminatePropertyImpl() {
128        if (indeterminate == null) {
129            indeterminate = new ReadOnlyBooleanWrapper(true) {
130                @Override protected void invalidated() {
131                    final boolean active = get();
132                    pseudoClassStateChanged(PSEUDO_CLASS_INDETERMINATE, active);
133                    pseudoClassStateChanged(PSEUDO_CLASS_DETERMINATE,  !active);
134                }
135
136                @Override
137                public Object getBean() {
138                    return ProgressIndicator.this;
139                }
140
141                @Override
142                public String getName() {
143                    return "indeterminate";
144                }
145            };
146        }
147        return indeterminate;
148    }
149    /**
150     * The actual progress of the ProgressIndicator. A negative value for
151     * progress indicates that the progress is indeterminate. A positive value
152     * between 0 and 1 indicates the percentage of progress where 0 is 0% and 1
153     * is 100%. Any value greater than 1 is interpreted as 100%.
154     */
155    private DoubleProperty progress;
156    public final void setProgress(double value) {
157        progressProperty().set(value);
158    }
159
160    public final double getProgress() {
161        return progress == null ? INDETERMINATE_PROGRESS : progress.get();
162    }
163
164    public final DoubleProperty progressProperty() {
165        if (progress == null) {
166            progress = new DoublePropertyBase(-1.0) {
167                @Override protected void invalidated() {
168                    setIndeterminate(getProgress() < 0.0);
169                }
170
171                @Override
172                public Object getBean() {
173                    return ProgressIndicator.this;
174                }
175
176                @Override
177                public String getName() {
178                    return "progress";
179                }
180            };
181        }
182        return progress;
183    }
184
185    /***************************************************************************
186     *                                                                         *
187     * Methods                                                                 *
188     *                                                                         *
189     **************************************************************************/
190
191    /** {@inheritDoc} */
192    @Override protected Skin<?> createDefaultSkin() {
193        return new ProgressIndicatorSkin(this);
194    }
195
196    /***************************************************************************
197     *                                                                         *
198     * Stylesheet Handling                                                     *
199     *                                                                         *
200     **************************************************************************/
201
202    /**
203     * Initialize the style class to 'progress-indicator'.
204     *
205     * This is the selector class from which CSS can be used to style
206     * this control.
207     */
208    private static final String DEFAULT_STYLE_CLASS = "progress-indicator";
209
210    /**
211     * Pseudoclass indicating this is a determinate (i.e., progress can be
212     * determined) progress indicator.
213     */
214    private static final PseudoClass PSEUDO_CLASS_DETERMINATE =
215            PseudoClass.getPseudoClass("determinate");
216
217    /**
218     * Pseudoclass indicating this is an indeterminate (i.e., progress cannot
219     * be determined) progress indicator.
220     */
221    private static final PseudoClass PSEUDO_CLASS_INDETERMINATE =
222            PseudoClass.getPseudoClass("indeterminate");
223    
224    /**
225      * Most Controls return true for focusTraversable, so Control overrides
226      * this method to return true, but ProgressIndicator returns false for
227      * focusTraversable's initial value; hence the override of the override. 
228      * This method is called from CSS code to get the correct initial value.
229      * @treatAsPrivate implementation detail
230      */
231    @Deprecated @Override
232    protected /*do not make final*/ Boolean impl_cssGetFocusTraversableInitialValue() {
233        return Boolean.FALSE;
234    }
235    
236
237}