1 /* 2 * Copyright (c) 2010, 2014, 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 com.sun.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 */ 94 public ProgressIndicator(double progress) { 95 // focusTraversable is styleable through css. Calling setFocusTraversable 96 // makes it look to css like the user set the value and css will not 97 // override. Initializing focusTraversable by calling applyStyle with null 98 // StyleOrigin ensures that css will be able to override the value. 99 ((StyleableProperty<Boolean>)(WritableValue<Boolean>)focusTraversableProperty()).applyStyle(null, Boolean.FALSE); 100 setProgress(progress); 101 getStyleClass().setAll(DEFAULT_STYLE_CLASS); 102 setAccessibleRole(AccessibleRole.PROGRESS_INDICATOR); 103 104 // need to initialize pseudo-class state 105 final int c = Double.compare(INDETERMINATE_PROGRESS, progress); 106 pseudoClassStateChanged(PSEUDO_CLASS_INDETERMINATE, c == 0); 107 pseudoClassStateChanged(PSEUDO_CLASS_DETERMINATE, c != 0); 108 } 109 /*************************************************************************** 110 * * 111 * Properties * 112 * * 113 **************************************************************************/ 114 /** 115 * A flag indicating whether it is possible to determine the progress 116 * of the ProgressIndicator. Typically indeterminate progress bars are 117 * rendered with some form of animation indicating potentially "infinite" 118 * progress. 119 */ 120 private ReadOnlyBooleanWrapper indeterminate; 121 private void setIndeterminate(boolean value) { 122 indeterminatePropertyImpl().set(value); 123 } 124 125 public final boolean isIndeterminate() { 126 return indeterminate == null ? true : indeterminate.get(); 127 } 128 129 public final ReadOnlyBooleanProperty indeterminateProperty() { 130 return indeterminatePropertyImpl().getReadOnlyProperty(); 131 } 132 133 private ReadOnlyBooleanWrapper indeterminatePropertyImpl() { 134 if (indeterminate == null) { 135 indeterminate = new ReadOnlyBooleanWrapper(true) { 136 @Override protected void invalidated() { 137 final boolean active = get(); 138 pseudoClassStateChanged(PSEUDO_CLASS_INDETERMINATE, active); 139 pseudoClassStateChanged(PSEUDO_CLASS_DETERMINATE, !active); 140 } 141 142 @Override 143 public Object getBean() { 144 return ProgressIndicator.this; 145 } 146 147 @Override 148 public String getName() { 149 return "indeterminate"; 150 } 151 }; 152 } 153 return indeterminate; 154 } 155 /** 156 * The actual progress of the ProgressIndicator. A negative value for 157 * progress indicates that the progress is indeterminate. A positive value 158 * between 0 and 1 indicates the percentage of progress where 0 is 0% and 1 159 * is 100%. Any value greater than 1 is interpreted as 100%. 160 */ 161 private DoubleProperty progress; 162 public final void setProgress(double value) { 163 progressProperty().set(value); 164 } 165 166 public final double getProgress() { 167 return progress == null ? INDETERMINATE_PROGRESS : progress.get(); 168 } 169 170 public final DoubleProperty progressProperty() { 171 if (progress == null) { 172 progress = new DoublePropertyBase(-1.0) { 173 @Override protected void invalidated() { 174 setIndeterminate(getProgress() < 0.0); 175 } 176 177 @Override 178 public Object getBean() { 179 return ProgressIndicator.this; 180 } 181 182 @Override 183 public String getName() { 184 return "progress"; 185 } 186 }; 187 } 188 return progress; 189 } 190 191 /*************************************************************************** 192 * * 193 * Methods * 194 * * 195 **************************************************************************/ 196 197 /** {@inheritDoc} */ 198 @Override protected Skin<?> createDefaultSkin() { 199 return new ProgressIndicatorSkin(this); 200 } 201 202 /*************************************************************************** 203 * * 204 * Stylesheet Handling * 205 * * 206 **************************************************************************/ 207 208 /** 209 * Initialize the style class to 'progress-indicator'. 210 * 211 * This is the selector class from which CSS can be used to style 212 * this control. 213 */ 214 private static final String DEFAULT_STYLE_CLASS = "progress-indicator"; 215 216 /** 217 * Pseudoclass indicating this is a determinate (i.e., progress can be 218 * determined) progress indicator. 219 */ 220 private static final PseudoClass PSEUDO_CLASS_DETERMINATE = 221 PseudoClass.getPseudoClass("determinate"); 222 223 /** 224 * Pseudoclass indicating this is an indeterminate (i.e., progress cannot 225 * be determined) progress indicator. 226 */ 227 private static final PseudoClass PSEUDO_CLASS_INDETERMINATE = 228 PseudoClass.getPseudoClass("indeterminate"); 229 230 /** 231 * Most Controls return true for focusTraversable, so Control overrides 232 * this method to return true, but ProgressIndicator returns false for 233 * focusTraversable's initial value; hence the override of the override. 234 * This method is called from CSS code to get the correct initial value. 235 * @treatAsPrivate implementation detail 236 */ 237 @Deprecated @Override 238 protected /*do not make final*/ Boolean impl_cssGetFocusTraversableInitialValue() { 239 return Boolean.FALSE; 240 } 241 242 243 /*************************************************************************** 244 * * 245 * Accessibility handling * 246 * * 247 **************************************************************************/ 248 249 @Override 250 public Object queryAccessibleAttribute(AccessibleAttribute attribute, Object... parameters) { 251 switch (attribute) { 252 case VALUE: return getProgress(); 253 case MAX_VALUE: return 1.0; 254 case MIN_VALUE: return 0.0; 255 case INDETERMINATE: return isIndeterminate(); 256 default: return super.queryAccessibleAttribute(attribute, parameters); 257 } 258 } 259 260 }