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.control; 27 28 import javafx.css.PseudoClass; 29 30 import javafx.scene.control.skin.ProgressIndicatorSkin; 31 32 import javafx.beans.property.DoubleProperty; 33 import javafx.beans.property.DoublePropertyBase; 34 import javafx.beans.property.ReadOnlyBooleanProperty; 35 import javafx.beans.property.ReadOnlyBooleanWrapper; 36 import javafx.beans.value.WritableValue; 37 import javafx.css.StyleableProperty; 38 import javafx.scene.AccessibleAttribute; 39 import javafx.scene.AccessibleRole; 40 41 42 /** 43 * A circular control which is used for indicating progress, either 44 * infinite (aka indeterminate) or finite. Often used with the Task API for 45 * representing progress of background Tasks. 46 * <p> 47 * ProgressIndicator sets focusTraversable to false. 48 * </p> 49 * 50 * <p> 51 * This first example creates a ProgressIndicator with an indeterminate value : 52 * <pre><code> 53 * import javafx.scene.control.ProgressIndicator; 54 * ProgressIndicator p1 = new ProgressIndicator(); 55 * </code></pre> 56 * 57 * <p> 58 * This next example creates a ProgressIndicator which is 25% complete : 59 * <pre><code> 60 * import javafx.scene.control.ProgressIndicator; 61 * ProgressIndicator p2 = new ProgressIndicator(); 62 * p2.setProgress(0.25F); 63 * </code></pre> 64 * 65 * Implementation of ProgressIndicator According to JavaFX UI Control API Specification 66 * @since JavaFX 2.0 67 */ 68 69 public class ProgressIndicator extends Control { 70 71 /** 72 * Value for progress indicating that the progress is indeterminate. 73 * 74 * @see #setProgress 75 */ 76 public static final double INDETERMINATE_PROGRESS = -1; 77 78 /*************************************************************************** 79 * * 80 * Constructors * 81 * * 82 **************************************************************************/ 83 84 /** 85 * Creates a new indeterminate ProgressIndicator. 86 */ 87 public ProgressIndicator() { 88 this(INDETERMINATE_PROGRESS); 89 } 90 91 /** 92 * Creates a new ProgressIndicator with the given progress value. 93 * @param progress the progress 94 */ 95 public ProgressIndicator(double progress) { 96 // focusTraversable is styleable through css. Calling setFocusTraversable 97 // makes it look to css like the user set the value and css will not 98 // override. Initializing focusTraversable by calling applyStyle with null 99 // StyleOrigin ensures that css will be able to override the value. 100 ((StyleableProperty<Boolean>)(WritableValue<Boolean>)focusTraversableProperty()).applyStyle(null, Boolean.FALSE); 101 setProgress(progress); 102 getStyleClass().setAll(DEFAULT_STYLE_CLASS); 103 setAccessibleRole(AccessibleRole.PROGRESS_INDICATOR); 104 105 // need to initialize pseudo-class state 106 final int c = Double.compare(INDETERMINATE_PROGRESS, progress); 107 pseudoClassStateChanged(PSEUDO_CLASS_INDETERMINATE, c == 0); 108 pseudoClassStateChanged(PSEUDO_CLASS_DETERMINATE, c != 0); 109 } 110 /*************************************************************************** 111 * * 112 * Properties * 113 * * 114 **************************************************************************/ 115 /** 116 * A flag indicating whether it is possible to determine the progress 117 * of the ProgressIndicator. Typically indeterminate progress bars are 118 * rendered with some form of animation indicating potentially "infinite" 119 * progress. 120 */ 121 private ReadOnlyBooleanWrapper indeterminate; 122 private void setIndeterminate(boolean value) { 123 indeterminatePropertyImpl().set(value); 124 } 125 126 public final boolean isIndeterminate() { 127 return indeterminate == null ? true : indeterminate.get(); 128 } 129 130 public final ReadOnlyBooleanProperty indeterminateProperty() { 131 return indeterminatePropertyImpl().getReadOnlyProperty(); 132 } 133 134 private ReadOnlyBooleanWrapper indeterminatePropertyImpl() { 135 if (indeterminate == null) { 136 indeterminate = new ReadOnlyBooleanWrapper(true) { 137 @Override protected void invalidated() { 138 final boolean active = get(); 139 pseudoClassStateChanged(PSEUDO_CLASS_INDETERMINATE, active); 140 pseudoClassStateChanged(PSEUDO_CLASS_DETERMINATE, !active); 141 } 142 143 @Override 144 public Object getBean() { 145 return ProgressIndicator.this; 146 } 147 148 @Override 149 public String getName() { 150 return "indeterminate"; 151 } 152 }; 153 } 154 return indeterminate; 155 } 156 /** 157 * The actual progress of the ProgressIndicator. A negative value for 158 * progress indicates that the progress is indeterminate. A positive value 159 * between 0 and 1 indicates the percentage of progress where 0 is 0% and 1 160 * is 100%. Any value greater than 1 is interpreted as 100%. 161 */ 162 private DoubleProperty progress; 163 public final void setProgress(double value) { 164 progressProperty().set(value); 165 } 166 167 public final double getProgress() { 168 return progress == null ? INDETERMINATE_PROGRESS : progress.get(); 169 } 170 171 public final DoubleProperty progressProperty() { 172 if (progress == null) { 173 progress = new DoublePropertyBase(-1.0) { 174 @Override protected void invalidated() { 175 setIndeterminate(getProgress() < 0.0); 176 } 177 178 @Override 179 public Object getBean() { 180 return ProgressIndicator.this; 181 } 182 183 @Override 184 public String getName() { 185 return "progress"; 186 } 187 }; 188 } 189 return progress; 190 } 191 192 /*************************************************************************** 193 * * 194 * Methods * 195 * * 196 **************************************************************************/ 197 198 /** {@inheritDoc} */ 199 @Override protected Skin<?> createDefaultSkin() { 200 return new ProgressIndicatorSkin(this); 201 } 202 203 /*************************************************************************** 204 * * 205 * Stylesheet Handling * 206 * * 207 **************************************************************************/ 208 209 /** 210 * Initialize the style class to 'progress-indicator'. 211 * 212 * This is the selector class from which CSS can be used to style 213 * this control. 214 */ 215 private static final String DEFAULT_STYLE_CLASS = "progress-indicator"; 216 217 /** 218 * Pseudoclass indicating this is a determinate (i.e., progress can be 219 * determined) progress indicator. 220 */ 221 private static final PseudoClass PSEUDO_CLASS_DETERMINATE = 222 PseudoClass.getPseudoClass("determinate"); 223 224 /** 225 * Pseudoclass indicating this is an indeterminate (i.e., progress cannot 226 * be determined) progress indicator. 227 */ 228 private static final PseudoClass PSEUDO_CLASS_INDETERMINATE = 229 PseudoClass.getPseudoClass("indeterminate"); 230 231 /** 232 * Returns the initial focus traversable state of this control, for use 233 * by the JavaFX CSS engine to correctly set its initial value. This method 234 * is overridden as by default UI controls have focus traversable set to true, 235 * but that is not appropriate for this control. 236 * 237 * @since 9 238 */ 239 @Override protected Boolean getInitialFocusTraversable() { 240 return Boolean.FALSE; 241 } 242 243 244 /*************************************************************************** 245 * * 246 * Accessibility handling * 247 * * 248 **************************************************************************/ 249 250 @Override 251 public Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) { 252 switch (attribute) { 253 case VALUE: return getProgress(); 254 case MAX_VALUE: return 1.0; 255 case MIN_VALUE: return 0.0; 256 case INDETERMINATE: return isIndeterminate(); 257 default: return super.queryAccessibleAttribute(attribute, parameters); 258 } 259 } 260 261 }