2626import javafx .animation .KeyValue ;
2727import javafx .animation .Timeline ;
2828import javafx .scene .Group ;
29- import javafx .scene .control .ProgressIndicator ;
3029import javafx .scene .control .SkinBase ;
3130import javafx .scene .layout .Region ;
3231import javafx .scene .layout .StackPane ;
3332import javafx .scene .paint .Color ;
34- import javafx .scene .paint .Paint ;
3533import javafx .scene .shape .Arc ;
3634import javafx .scene .shape .Rectangle ;
3735import javafx .scene .shape .StrokeLineCap ;
3836import javafx .util .Duration ;
37+ import org .jackhuang .hmcl .ui .animation .AnimationUtils ;
38+
39+ import java .util .ArrayList ;
40+ import java .util .List ;
3941
4042/// JFXSpinner material design skin
4143///
@@ -46,11 +48,6 @@ public class JFXSpinnerSkin extends SkinBase<JFXSpinner> {
4648
4749 private static final double DEFAULT_STROKE_WIDTH = 4 ;
4850
49- private static final Color GREEN_COLOR = Color .valueOf ("#0F9D58" );
50- private static final Color RED_COLOR = Color .valueOf ("#db4437" );
51- private static final Color YELLOW_COLOR = Color .valueOf ("#f4b400" );
52- private static final Color BLUE_COLOR = Color .valueOf ("#4285f4" );
53-
5451 private JFXSpinner control ;
5552 private final TreeShowingProperty treeShowingProperty ;
5653 private boolean isValid = false ;
@@ -60,7 +57,6 @@ public class JFXSpinnerSkin extends SkinBase<JFXSpinner> {
6057 private Arc track ;
6158 private final StackPane arcPane ;
6259 private final Rectangle fillRect ;
63- private double arcLength = -1 ;
6460
6561 private final double startingAngle ;
6662
@@ -73,7 +69,6 @@ public JFXSpinnerSkin(JFXSpinner control) {
7369
7470 arc = new Arc ();
7571 arc .setManaged (false );
76- arc .setStartAngle (0 );
7772 arc .setLength (180 );
7873 arc .getStyleClass ().setAll ("arc" );
7974 arc .setFill (Color .TRANSPARENT );
@@ -82,7 +77,6 @@ public JFXSpinnerSkin(JFXSpinner control) {
8277
8378 track = new Arc ();
8479 track .setManaged (false );
85- track .setStartAngle (0 );
8680 track .setLength (360 );
8781 track .setStrokeWidth (DEFAULT_STROKE_WIDTH );
8882 track .getStyleClass ().setAll ("track" );
@@ -97,72 +91,28 @@ public JFXSpinnerSkin(JFXSpinner control) {
9791 getChildren ().setAll (arcPane );
9892
9993 // register listeners
100- registerChangeListener (control .indeterminateProperty (), obs -> initialize ());
10194 registerChangeListener (control .progressProperty (), obs -> updateProgress ());
102- registerChangeListener (treeShowingProperty , obs -> updateAnimation ());
103- registerChangeListener (control .sceneProperty (), obs -> updateAnimation ());
95+ registerChangeListener (treeShowingProperty , obs -> updateProgress ());
10496 }
10597
106- private void initialize () {
107- if (getSkinnable ().isIndeterminate ()) {
108- if (timeline == null ) {
109- createTransition ();
110- if (treeShowingProperty .get ()) {
98+ private void updateProgress () {
99+ double progress = Double .min (getSkinnable ().getProgress (), 1.0 );
100+ if (progress < 0 ) { // indeterminate
101+ boolean treeShowing = treeShowingProperty .get ();
102+ if (treeShowing ) {
103+ if (timeline == null ) {
104+ timeline = createTransition ();
105+ timeline .playFromStart ();
106+ } else {
111107 timeline .play ();
112108 }
109+ } else if (timeline != null ) {
110+ timeline .pause ();
113111 }
114- } else {
112+ } else { // determinate
115113 clearAnimation ();
116114 arc .setStartAngle (90 );
117- updateProgress ();
118- }
119- }
120-
121- private KeyFrame [] getKeyFrames (double angle , double duration , Paint color ) {
122- KeyFrame [] frames = new KeyFrame [4 ];
123- frames [0 ] = new KeyFrame (Duration .seconds (duration ),
124- new KeyValue (arc .lengthProperty (), 5 , Interpolator .LINEAR ),
125- new KeyValue (arc .startAngleProperty (),
126- angle + 45 + startingAngle ,
127- Interpolator .LINEAR ));
128- frames [1 ] = new KeyFrame (Duration .seconds (duration + 0.4 ),
129- new KeyValue (arc .lengthProperty (), 250 , Interpolator .LINEAR ),
130- new KeyValue (arc .startAngleProperty (),
131- angle + 90 + startingAngle ,
132- Interpolator .LINEAR ));
133- frames [2 ] = new KeyFrame (Duration .seconds (duration + 0.7 ),
134- new KeyValue (arc .lengthProperty (), 250 , Interpolator .LINEAR ),
135- new KeyValue (arc .startAngleProperty (),
136- angle + 135 + startingAngle ,
137- Interpolator .LINEAR ));
138- frames [3 ] = new KeyFrame (Duration .seconds (duration + 1.1 ),
139- new KeyValue (arc .lengthProperty (), 5 , Interpolator .LINEAR ),
140- new KeyValue (arc .startAngleProperty (),
141- angle + 435 + startingAngle ,
142- Interpolator .LINEAR ),
143- new KeyValue (arc .strokeProperty (), color , Interpolator .EASE_BOTH ));
144- return frames ;
145- }
146-
147- private void pauseTimeline (boolean pause ) {
148- if (getSkinnable ().isIndeterminate ()) {
149- if (timeline == null ) {
150- createTransition ();
151- }
152- if (pause ) {
153- timeline .pause ();
154- } else {
155- timeline .play ();
156- }
157- }
158- }
159-
160- private void updateAnimation () {
161- final boolean isTreeShowing = treeShowingProperty .get ();
162- if (timeline != null ) {
163- pauseTimeline (!isTreeShowing );
164- } else if (isTreeShowing ) {
165- createTransition ();
115+ arc .setLength (-360 * progress );
166116 }
167117 }
168118
@@ -222,13 +172,9 @@ protected void layoutChildren(double contentX, double contentY, double contentWi
222172 fillRect .setHeight (arcSize );
223173
224174 if (!isValid ) {
225- initialize ();
175+ updateProgress ();
226176 isValid = true ;
227177 }
228-
229- if (!getSkinnable ().isIndeterminate ()) {
230- arc .setLength (arcLength );
231- }
232178 }
233179
234180 private void updateArcLayout (double radius , double arcSize ) {
@@ -244,66 +190,64 @@ private void updateArcLayout(double radius, double arcSize) {
244190 track .setStrokeWidth (arc .getStrokeWidth ());
245191 }
246192
247- boolean wasIndeterminate = false ;
248-
249- protected void updateProgress () {
250- final ProgressIndicator control = getSkinnable ();
251- final boolean isIndeterminate = control .isIndeterminate ();
252- if (!(isIndeterminate && wasIndeterminate )) {
253- arcLength = -360 * control .getProgress ();
254- control .requestLayout ();
255- }
256- wasIndeterminate = isIndeterminate ;
257- }
258-
259- private void createTransition () {
260- if (!getSkinnable ().isIndeterminate ()) return ;
261- final Paint initialColor = arc .getStroke ();
262- if (initialColor == null ) {
263- arc .setStroke (BLUE_COLOR );
264- }
265-
266- KeyFrame [] blueFrame = getKeyFrames (0 , 0 , initialColor == null ? BLUE_COLOR : initialColor );
267- KeyFrame [] redFrame = getKeyFrames (450 , 1.4 , initialColor == null ? RED_COLOR : initialColor );
268- KeyFrame [] yellowFrame = getKeyFrames (900 , 2.8 , initialColor == null ? YELLOW_COLOR : initialColor );
269- KeyFrame [] greenFrame = getKeyFrames (1350 , 4.2 , initialColor == null ? GREEN_COLOR : initialColor );
270-
271- KeyFrame endingFrame = new KeyFrame (Duration .seconds (5.6 ),
193+ private void addKeyFrames (List <KeyFrame > frames , double angle , double duration ) {
194+ frames .add (new KeyFrame (Duration .seconds (duration ),
272195 new KeyValue (arc .lengthProperty (), 5 , Interpolator .LINEAR ),
273196 new KeyValue (arc .startAngleProperty (),
274- 1845 + startingAngle ,
275- Interpolator .LINEAR ));
197+ angle + 45 + startingAngle ,
198+ Interpolator .LINEAR )));
199+ frames .add (new KeyFrame (Duration .seconds (duration + 0.4 ),
200+ new KeyValue (arc .lengthProperty (), 250 , Interpolator .LINEAR ),
201+ new KeyValue (arc .startAngleProperty (),
202+ angle + 90 + startingAngle ,
203+ Interpolator .LINEAR )));
204+ frames .add (new KeyFrame (Duration .seconds (duration + 0.7 ),
205+ new KeyValue (arc .lengthProperty (), 250 , Interpolator .LINEAR ),
206+ new KeyValue (arc .startAngleProperty (),
207+ angle + 135 + startingAngle ,
208+ Interpolator .LINEAR )));
209+ frames .add (new KeyFrame (Duration .seconds (duration + 1.1 ),
210+ new KeyValue (arc .lengthProperty (), 5 , Interpolator .LINEAR ),
211+ new KeyValue (arc .startAngleProperty (),
212+ angle + 435 + startingAngle ,
213+ Interpolator .LINEAR )));
214+ }
276215
277- if (timeline != null ) {
278- timeline .stop ();
279- timeline .getKeyFrames ().clear ();
216+ private Timeline createTransition () {
217+ Timeline timeline ;
218+ if (AnimationUtils .isAnimationEnabled ()) {
219+ var keyFrames = new ArrayList <KeyFrame >(17 );
220+ addKeyFrames (keyFrames , 0 , 0 );
221+ addKeyFrames (keyFrames , 450 , 1.4 );
222+ addKeyFrames (keyFrames , 900 , 2.8 );
223+ addKeyFrames (keyFrames , 1350 , 4.2 );
224+ keyFrames .add (new KeyFrame (Duration .seconds (5.6 ),
225+ new KeyValue (arc .lengthProperty (), 5 , Interpolator .LINEAR ),
226+ new KeyValue (arc .startAngleProperty (),
227+ 1845 + startingAngle ,
228+ Interpolator .LINEAR )));
229+
230+ timeline = new Timeline ();
231+ timeline .getKeyFrames ().setAll (keyFrames );
232+ } else {
233+ final double arcLength = 250 ;
234+ timeline = new Timeline (
235+ new KeyFrame (Duration .ZERO ,
236+ new KeyValue (arc .startAngleProperty (), 45 + startingAngle , Interpolator .LINEAR ),
237+ new KeyValue (arc .lengthProperty (), arcLength , Interpolator .DISCRETE )),
238+ new KeyFrame (Duration .seconds (1.2 ),
239+ new KeyValue (arc .startAngleProperty (), 45 + 360 + startingAngle , Interpolator .LINEAR ),
240+ new KeyValue (arc .lengthProperty (), arcLength , Interpolator .DISCRETE ))
241+ );
280242 }
281- timeline = new Timeline (blueFrame [0 ],
282- blueFrame [1 ],
283- blueFrame [2 ],
284- blueFrame [3 ],
285- redFrame [0 ],
286- redFrame [1 ],
287- redFrame [2 ],
288- redFrame [3 ],
289- yellowFrame [0 ],
290- yellowFrame [1 ],
291- yellowFrame [2 ],
292- yellowFrame [3 ],
293- greenFrame [0 ],
294- greenFrame [1 ],
295- greenFrame [2 ],
296- greenFrame [3 ],
297- endingFrame );
243+
298244 timeline .setCycleCount (Timeline .INDEFINITE );
299- timeline .setDelay (Duration .ZERO );
300- timeline .playFromStart ();
245+ return timeline ;
301246 }
302247
303248 private void clearAnimation () {
304249 if (timeline != null ) {
305250 timeline .stop ();
306- timeline .getKeyFrames ().clear ();
307251 timeline = null ;
308252 }
309253 }
0 commit comments