changeset 4849:0339d4004e85

RT-32327 : Threading issues with ProgressBar / ProgressIndicator after fix for RT-27791
author mickf
date Fri, 30 Aug 2013 15:41:07 +0100
parents b2d31f6fb68d
children 79af5cf2bf70
files modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ProgressBarSkin.java modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ProgressIndicatorSkin.java
diffstat 2 files changed, 117 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ProgressBarSkin.java	Fri Aug 30 16:33:44 2013 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ProgressBarSkin.java	Fri Aug 30 15:41:07 2013 +0100
@@ -28,6 +28,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import javafx.application.Platform;
 import javafx.animation.KeyFrame;
 import javafx.animation.KeyValue;
 import javafx.animation.Timeline;
@@ -358,29 +359,6 @@
         return true;
     }
 
-    /*
-    ** see if we're clipped...
-    */
-    private void pauseIfNotVisibleInClip() {
-        if (!isVisibleInClip()) {
-            indeterminateTimeline.pause();
-            
-            Thread t = new Thread(new Runnable() {
-                 @Override
-                     public void run() {
-                        while (!isVisibleInClip()) {
-                            try {
-                                Thread.sleep(500);
-                            }
-                            catch (Exception e) {};
-                        }
-                        indeterminateTimeline.play();
-                    }
-                });
-            t.start();
-        }
-    }
-
     private boolean isInvisibleOrDisconnected() {
         Scene s = getSkinnable().getScene();
         if (s == null) {
@@ -409,14 +387,8 @@
         return false;
     }
 
-
-    private void stopIfNotNeeded() {
-        if (!stopIfInvisibleOrDisconnected()) {
-            pauseIfNotVisibleInClip();
-        }
-    }
-
-
+    static final private Duration CLIPPED_DELAY = new Duration(300);
+    static final private Duration UNCLIPPED_DELAY = new Duration(0);
 
     private void createIndeterminateTimeline() {
         if (indeterminateTimeline != null) indeterminateTimeline.stop();
@@ -429,6 +401,7 @@
         // Set up the timeline.  We do not want to reverse if we are not flipping.
         indeterminateTimeline = new Timeline();
         indeterminateTimeline.setCycleCount(Timeline.INDEFINITE);
+        indeterminateTimeline.setDelay(UNCLIPPED_DELAY);
 
         if (getIndeterminateBarFlip()) {
             indeterminateTimeline.getKeyFrames().addAll(
@@ -438,13 +411,40 @@
                                 @Override public void handle(ActionEvent event) {
                                     bar.setScaleX(-1);
 
-                                    /*
-                                    ** Stop the animation if the ProgressBar is removed
-                                    ** from a Scene, or is invisible.
-                                    ** Pause the animation if it's outside of a clipped
-                                    ** region (e.g. not visible in a ScrollPane)
-                                    */
-                                    stopIfNotNeeded();
+                                    /**
+                                     * Stop the animation if the ProgressBar is removed
+                                     * from a Scene, or is invisible.
+                                     * Pause the animation if it's outside of a clipped
+                                     * region (e.g. not visible in a ScrollPane)
+                                     */
+                                    if (indeterminateTimeline != null) {
+                                        stopIfInvisibleOrDisconnected();
+                                        if (!isVisibleInClip()) {
+                                            Platform.runLater(new Runnable() {
+                                              @Override public void run() {
+                                                  if (indeterminateTimeline != null) {
+                                                      if (indeterminateTimeline.getDelay().compareTo(CLIPPED_DELAY) != 0) {
+                                                          indeterminateTimeline.setDelay(CLIPPED_DELAY);
+                                                      }
+                                                      indeterminateTimeline.stop();
+                                                      indeterminateTimeline.jumpTo(Duration.ZERO);
+                                                      indeterminateTimeline.play();
+                                                  }
+                                              }
+                                            });
+                                        }
+                                        else {
+                                            Platform.runLater(new Runnable() {
+                                              @Override public void run() {
+                                                  if (indeterminateTimeline != null) {
+                                                      if (indeterminateTimeline.getDelay().compareTo(UNCLIPPED_DELAY) != 0) {
+                                                          indeterminateTimeline.setDelay(UNCLIPPED_DELAY);
+                                                      }
+                                                  }
+                                              }
+                                            });
+                                        }
+                                    }
                                 }
                             },
                             new KeyValue(clipRegion.translateXProperty(), startX-(w - getIndeterminateBarLength())),
@@ -475,13 +475,40 @@
                             Duration.millis(0),
                             new EventHandler<ActionEvent>() {
                                 @Override public void handle(ActionEvent event) {
-                                    /*
-                                    ** Stop the animation if the ProgressBar is removed
-                                    ** from a Scene, or is invisible.
-                                    ** Pause the animation if it's outside of a clipped
-                                    ** region (e.g. not visible in a ScrollPane)
-                                    */
-                                    stopIfNotNeeded();
+                                    /**
+                                     * Stop the animation if the ProgressBar is removed
+                                     * from a Scene, or is invisible.
+                                     * Pause the animation if it's outside of a clipped
+                                     * region (e.g. not visible in a ScrollPane)
+                                     */
+                                    if (indeterminateTimeline != null) {
+                                        stopIfInvisibleOrDisconnected();
+                                        if (!isVisibleInClip()) {
+                                            Platform.runLater(new Runnable() {
+                                              @Override public void run() {
+                                                  if (indeterminateTimeline != null) {
+                                                      if (indeterminateTimeline.getDelay().compareTo(CLIPPED_DELAY) != 0) {
+                                                          indeterminateTimeline.setDelay(CLIPPED_DELAY);
+                                                      }
+                                                      indeterminateTimeline.stop();
+                                                      indeterminateTimeline.jumpTo(Duration.ZERO);
+                                                      indeterminateTimeline.play();
+                                                  }
+                                              }
+                                            });
+                                        }
+                                        else {
+                                            Platform.runLater(new Runnable() {
+                                              @Override public void run() {
+                                                  if (indeterminateTimeline != null) {
+                                                      if (indeterminateTimeline.getDelay().compareTo(UNCLIPPED_DELAY) != 0) {
+                                                          indeterminateTimeline.setDelay(UNCLIPPED_DELAY);
+                                                      }
+                                                  }
+                                              }
+                                            });
+                                        }
+                                    }
                                 }
                             },
 
--- a/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ProgressIndicatorSkin.java	Fri Aug 30 16:33:44 2013 +1200
+++ b/modules/controls/src/main/java/com/sun/javafx/scene/control/skin/ProgressIndicatorSkin.java	Fri Aug 30 15:41:07 2013 +0100
@@ -28,6 +28,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import javafx.application.Platform;
 import javafx.animation.KeyFrame;
 import javafx.animation.KeyValue;
 import javafx.animation.Timeline;
@@ -447,6 +448,7 @@
 
             indeterminateTimeline = new Timeline();
             indeterminateTimeline.setCycleCount(Timeline.INDEFINITE);
+            indeterminateTimeline.setDelay(UNCLIPPED_DELAY);
             rebuildTimeline();
 
             rebuild();
@@ -479,29 +481,6 @@
         return true;
     }
 
-    /*
-    ** see if we're clipped...
-    */
-    private void pauseIfNotVisibleInClip() {
-        if (!isVisibleInClip()) {
-            indeterminateTimeline.pause();
-            
-            Thread t = new Thread(new Runnable() {
-                 @Override
-                     public void run() {
-                        while (!isVisibleInClip()) {
-                            try {
-                                Thread.sleep(500);
-                            }
-                            catch (Exception e) {};
-                        }
-                        indeterminateTimeline.play();
-                    }
-                });
-            t.start();
-        }
-    }
-
     private boolean isInvisibleOrDisconnected() {
         Scene s = control.getScene();
         if (s == null) {
@@ -531,32 +510,55 @@
     }
 
 
-        private void stopIfNotNeeded() {
-            if (!stopIfInvisibleOrDisconnected()) {
-                pauseIfNotVisibleInClip();
-            }
-        }
+        static final private Duration CLIPPED_DELAY = new Duration(300);
+        static final private Duration UNCLIPPED_DELAY = new Duration(0);
 
         private void rebuildTimeline() {
             final ObservableList<KeyFrame> keyFrames = FXCollections.<KeyFrame>observableArrayList();
+            keyFrames.add(
+              new KeyFrame(
+                Duration.millis(0), new EventHandler<ActionEvent>() {
+                  @Override public void handle(ActionEvent event) {
+                      /**
+                       * Stop the animation if the ProgressBar is removed
+                       * from a Scene, or is invisible.
+                       * Pause the animation if it's outside of a clipped
+                       * region (e.g. not visible in a ScrollPane)
+                       */
+                      if (indeterminateTimeline != null) {
+                          stopIfInvisibleOrDisconnected();
+                          if (!isVisibleInClip()) {
+                              Platform.runLater(new Runnable() {
+                                @Override public void run() {
+                                    if (indeterminateTimeline != null) {
+                                        if (indeterminateTimeline.getDelay().compareTo(CLIPPED_DELAY) != 0) {
+                                            indeterminateTimeline.setDelay(CLIPPED_DELAY);
+                                        }
+                                        indeterminateTimeline.stop();
+                                        indeterminateTimeline.jumpTo(Duration.ZERO);
+                                        indeterminateTimeline.play();
+                                    }
+                                }
+                              });
+                          }
+                          else {
+                              Platform.runLater(new Runnable() {
+                                @Override public void run() {
+                                    if (indeterminateTimeline != null) {
+                                        if (indeterminateTimeline.getDelay().compareTo(UNCLIPPED_DELAY) != 0) {
+                                            indeterminateTimeline.setDelay(UNCLIPPED_DELAY);
+                                        }
+                                    }
+                                }
+                              });
+                          }
+                      }
+                  }
+                }));
             if(spinEnabled) {
-                keyFrames.add(new KeyFrame(Duration.millis(0), new KeyValue(pathsG.rotateProperty(), 360)));
+                keyFrames.add(new KeyFrame(Duration.millis(1), new KeyValue(pathsG.rotateProperty(), 360)));
                 keyFrames.add(new KeyFrame(Duration.millis(3900), new KeyValue(pathsG.rotateProperty(), 0)));
             }
-            keyFrames.add(
-              new KeyFrame(
-                Duration.millis(50), new EventHandler<ActionEvent>() {
-                  @Override public void handle(ActionEvent event) {
-                      /*
-                      ** Stop the animation if the ProgressBar is removed
-                      ** from a Scene, or is invisible.
-                      ** Pause the animation if it's outside of a clipped
-                      ** region (e.g. not visible in a ScrollPane)
-                      */
-                      stopIfNotNeeded();
-                  }
-                }));
-
 
             for (int i = 100; i <= 3900; i += 100) {
                 keyFrames.add(