1 /*
2 * Copyright (c) 2010, 2013, 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 com.sun.javafx.scene.control.skin;
27
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.List;
31
32 import javafx.animation.KeyFrame;
33 import javafx.animation.KeyValue;
34 import javafx.animation.Timeline;
35 import javafx.beans.InvalidationListener;
36 import javafx.beans.Observable;
37 import javafx.beans.binding.BooleanExpression;
38 import javafx.beans.property.BooleanProperty;
39 import javafx.beans.property.DoubleProperty;
40 import javafx.beans.property.IntegerProperty;
41 import javafx.beans.property.ObjectProperty;
42 import javafx.beans.value.WritableValue;
43 import javafx.collections.FXCollections;
44 import javafx.collections.ObservableList;
45 import javafx.geometry.Bounds;
46 import javafx.geometry.NodeOrientation;
47 import javafx.geometry.VPos;
48 import javafx.scene.Node;
49 import javafx.scene.Parent;
50 import javafx.scene.Scene;
51 import javafx.scene.control.ProgressIndicator;
52 import javafx.scene.control.SkinBase;
53 import javafx.scene.layout.Pane;
54 import javafx.scene.layout.Region;
55 import javafx.scene.layout.StackPane;
56 import javafx.scene.paint.Color;
57 import javafx.scene.paint.Paint;
58 import javafx.scene.shape.Arc;
59 import javafx.scene.shape.ArcType;
60 import javafx.scene.shape.Circle;
61 import javafx.scene.text.Text;
89 static {
90 doneText.getStyleClass().add("text");
91 }
92
93 private IndeterminateSpinner spinner;
94 private DeterminateIndicator determinateIndicator;
95 private ProgressIndicator control;
96
97 /***************************************************************************
98 * *
99 * Constructors *
100 * *
101 **************************************************************************/
102
103 public ProgressIndicatorSkin(ProgressIndicator control) {
104 super(control, new ProgressIndicatorBehavior<ProgressIndicator>(control));
105
106 this.control = control;
107 this.control.indeterminateProperty().addListener(indeterminateListener);
108 this.control.progressProperty().addListener(progressListener);
109
110 initialize();
111 }
112
113 private void initialize() {
114 boolean isIndeterminate = control.isIndeterminate();
115 if (isIndeterminate) {
116 // clean up determinateIndicator
117 determinateIndicator = null;
118 // create spinner
119 spinner = new IndeterminateSpinner(spinEnabled.get(), progressColor.get());
120 getChildren().setAll(spinner);
121 if (control.impl_isTreeVisible()) {
122 if (spinner.indeterminateTimeline != null) {
123 spinner.indeterminateTimeline.play();
124 }
125 }
126 } else {
127 // clean up after spinner
128 if (spinner != null) {
129 if (spinner.indeterminateTimeline != null) {
130 spinner.indeterminateTimeline.stop();
131 }
132 spinner = null;
133 }
134 // create determinateIndicator
135 determinateIndicator = new DeterminateIndicator(control, this, progressColor.get());
136 getChildren().setAll(determinateIndicator);
137 }
138 }
139
140 @Override public void dispose() {
141 super.dispose();
142 if (spinner != null) {
143 if (spinner.indeterminateTimeline != null) {
144 spinner.indeterminateTimeline.stop();
145 }
146 spinner = null;
147 }
148 control.indeterminateProperty().removeListener(indeterminateListener);
149 control.progressProperty().removeListener(progressListener);
150 control = null;
151 }
152
153 @Override protected void layoutChildren(final double x, final double y,
154 final double w, final double h) {
155 if (spinner != null && control.isIndeterminate()) {
156 spinner.layoutChildren();
157 spinner.resizeRelocate(0, 0, w, h);
158 } else if (determinateIndicator != null) {
159 determinateIndicator.layoutChildren();
160 determinateIndicator.resizeRelocate(0, 0, w, h);
161 }
162 }
163
164 /***************************************************************************
165 * *
166 * Listeners *
167 * *
168 **************************************************************************/
169
170 // Listen to ProgressIndicator indeterminateProperty
171 private final InvalidationListener indeterminateListener = valueModel -> {
172 initialize();
173 };
174
175 private final InvalidationListener progressListener = new InvalidationListener() {
176 @Override public void invalidated(Observable valueModel) {
177 if (determinateIndicator != null) {
178 determinateIndicator.updateProgress(((DoubleProperty)valueModel).doubleValue());
179 }
180 }
181 };
182
183 /***************************************************************************
184 * *
185 * DeterminateIndicator *
186 * *
187 **************************************************************************/
188
189 private class DeterminateIndicator extends Region {
190 private double textGap = 2.0F;
191
192 // only update progress text on whole percentages
193 private int intProgress;
194
195 // only update pie arc to nearest degree
196 private int degProgress;
197 private Text text;
198 private StackPane indicator;
199 private StackPane progress;
|
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 com.sun.javafx.scene.control.skin;
27
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.List;
31
32 import javafx.animation.KeyFrame;
33 import javafx.animation.KeyValue;
34 import javafx.animation.Timeline;
35 import javafx.beans.InvalidationListener;
36 import javafx.beans.Observable;
37 import javafx.beans.binding.BooleanExpression;
38 import javafx.beans.property.BooleanProperty;
39 import javafx.beans.property.DoubleProperty;
40 import javafx.beans.property.IntegerProperty;
41 import javafx.beans.property.ObjectProperty;
42 import javafx.beans.value.ChangeListener;
43 import javafx.beans.value.WritableValue;
44 import javafx.collections.FXCollections;
45 import javafx.collections.ObservableList;
46 import javafx.geometry.Bounds;
47 import javafx.geometry.NodeOrientation;
48 import javafx.geometry.VPos;
49 import javafx.scene.Node;
50 import javafx.scene.Parent;
51 import javafx.scene.Scene;
52 import javafx.scene.control.ProgressIndicator;
53 import javafx.scene.control.SkinBase;
54 import javafx.scene.layout.Pane;
55 import javafx.scene.layout.Region;
56 import javafx.scene.layout.StackPane;
57 import javafx.scene.paint.Color;
58 import javafx.scene.paint.Paint;
59 import javafx.scene.shape.Arc;
60 import javafx.scene.shape.ArcType;
61 import javafx.scene.shape.Circle;
62 import javafx.scene.text.Text;
90 static {
91 doneText.getStyleClass().add("text");
92 }
93
94 private IndeterminateSpinner spinner;
95 private DeterminateIndicator determinateIndicator;
96 private ProgressIndicator control;
97
98 /***************************************************************************
99 * *
100 * Constructors *
101 * *
102 **************************************************************************/
103
104 public ProgressIndicatorSkin(ProgressIndicator control) {
105 super(control, new ProgressIndicatorBehavior<ProgressIndicator>(control));
106
107 this.control = control;
108 this.control.indeterminateProperty().addListener(indeterminateListener);
109 this.control.progressProperty().addListener(progressListener);
110 this.control.sceneProperty().addListener(sceneChangeListener);
111 initialize();
112 }
113
114 private void initialize() {
115 boolean isIndeterminate = control.isIndeterminate();
116 if (isIndeterminate) {
117 // clean up determinateIndicator
118 determinateIndicator = null;
119 // create spinner
120 spinner = new IndeterminateSpinner(spinEnabled.get(), progressColor.get());
121 getChildren().setAll(spinner);
122 if (control.impl_isTreeVisible()) {
123 if (spinner.indeterminateTimeline != null) {
124 spinner.indeterminateTimeline.play();
125 }
126 }
127 } else {
128 // clean up after spinner
129 if (spinner != null) {
130 if (spinner.indeterminateTimeline != null) {
131 spinner.indeterminateTimeline.stop();
132 }
133 spinner = null;
134 }
135 // create determinateIndicator
136 determinateIndicator = new DeterminateIndicator(control, this, progressColor.get());
137 getChildren().setAll(determinateIndicator);
138 }
139 }
140
141 @Override public void dispose() {
142 if (spinner != null) {
143 if (spinner.indeterminateTimeline != null) {
144 spinner.indeterminateTimeline.stop();
145 }
146 spinner = null;
147 }
148 control.indeterminateProperty().removeListener(indeterminateListener);
149 control.progressProperty().removeListener(progressListener);
150 control.sceneProperty().removeListener(sceneChangeListener);
151
152 super.dispose();
153 }
154
155 @Override protected void layoutChildren(final double x, final double y,
156 final double w, final double h) {
157 if (spinner != null && control.isIndeterminate()) {
158 spinner.layoutChildren();
159 spinner.resizeRelocate(0, 0, w, h);
160 } else if (determinateIndicator != null) {
161 determinateIndicator.layoutChildren();
162 determinateIndicator.resizeRelocate(0, 0, w, h);
163 }
164 }
165
166 /***************************************************************************
167 * *
168 * Listeners *
169 * *
170 **************************************************************************/
171
172 // Listen to ProgressIndicator indeterminateProperty
173 private final InvalidationListener indeterminateListener = valueModel -> {
174 initialize();
175 };
176
177 private final InvalidationListener progressListener = valueModel -> {
178 if (determinateIndicator != null) {
179 determinateIndicator.updateProgress(((DoubleProperty)valueModel).doubleValue());
180 }
181 };
182
183 private final ChangeListener<Scene> sceneChangeListener = (observable, oldValue, newValue) -> {
184 // if ProgressIndicator was removed from scene and then added back in...
185 if (oldValue == null) {
186 initialize();
187 }
188 };
189
190 /***************************************************************************
191 * *
192 * DeterminateIndicator *
193 * *
194 **************************************************************************/
195
196 private class DeterminateIndicator extends Region {
197 private double textGap = 2.0F;
198
199 // only update progress text on whole percentages
200 private int intProgress;
201
202 // only update pie arc to nearest degree
203 private int degProgress;
204 private Text text;
205 private StackPane indicator;
206 private StackPane progress;
|