Fix progress
[nikiroo-utils.git] / src / be / nikiroo / utils / Progress.java
index 2872530b68542585783467e3241835072e75570a..ae5960379f12bcd2cecc17d3f7a81134f38ca018 100644 (file)
@@ -37,8 +37,8 @@ public class Progress {
        private List<ProgressListener> listeners;
        private int min;
        private int max;
-       private int localProgress;
-       private int progress; // children included
+       private double relativeLocalProgress;
+       private double relativeProgress; // children included
 
        /**
         * Create a new default unnamed {@link Progress}, from 0 to 100.
@@ -106,7 +106,7 @@ public class Progress {
         */
        public void setName(String name) {
                this.name = name;
-               changed(this);
+               changed(this, name);
        }
 
        /**
@@ -208,7 +208,7 @@ public class Progress {
         * @return the progress the value
         */
        public int getProgress() {
-               return progress;
+               return (int) Math.round(relativeProgress * (max - min));
        }
 
        /**
@@ -221,12 +221,59 @@ public class Progress {
         */
        public void setProgress(int progress) {
                synchronized (getLock()) {
-                       int diff = this.progress - this.localProgress;
-                       this.localProgress = progress;
-                       setTotalProgress(this, name, progress + diff);
+                       double childrenProgress = relativeProgress - relativeLocalProgress;
+
+                       relativeLocalProgress = ((double) progress) / (max - min);
+
+                       setRelativeProgress(this, name, relativeLocalProgress
+                                       + childrenProgress);
                }
        }
 
+       /**
+        * Get the total progress value (including the optional children
+        * {@link Progress}) on a 0.0 to 1.0 scale.
+        * 
+        * @return the progress
+        */
+       public double getRelativeProgress() {
+               return relativeProgress;
+       }
+
+       /**
+        * Set the total progress value (including the optional children
+        * {@link Progress}), on a 0 to 1 scale.
+        * 
+        * @param pg
+        *            the {@link Progress} to report as the progression emitter
+        * @param name
+        *            the current name (if it is NULL, the first non-null name in
+        *            the hierarchy will overwrite it) of the {@link Progress} who
+        *            emitted this change
+        * @param relativeProgress
+        *            the progress to set
+        */
+       private void setRelativeProgress(Progress pg, String name,
+                       double relativeProgress) {
+               synchronized (getLock()) {
+                       relativeProgress = Math.max(0, relativeProgress);
+                       relativeProgress = Math.min(1, relativeProgress);
+                       this.relativeProgress = relativeProgress;
+
+                       changed(pg, name);
+               }
+       }
+
+       /**
+        * Get the total progress value (including the optional children
+        * {@link Progress}) on a 0 to 1 scale.
+        * 
+        * @return the progress the value
+        */
+       private int getLocalProgress() {
+               return (int) Math.round(relativeLocalProgress * (max - min));
+       }
+
        /**
         * Add some value to the current progression of this {@link Progress}.
         * 
@@ -235,7 +282,7 @@ public class Progress {
         */
        public void add(int step) {
                synchronized (getLock()) {
-                       setProgress(localProgress + step);
+                       setProgress(getLocalProgress() + step);
                }
        }
 
@@ -246,28 +293,18 @@ public class Progress {
         * @return TRUE if it is
         */
        public boolean isDone() {
-               return progress >= max;
+               return getProgress() == max;
        }
 
        /**
         * Mark the {@link Progress} as done by setting its value to max.
         */
        public void done() {
-               setProgress(getMax());
-       }
-
-       /**
-        * Get the total progress value (including the optional children
-        * {@link Progress}) on a 0.0 to 1.0 scale.
-        * 
-        * @return the progress
-        */
-       public double getRelativeProgress() {
-               if (max == min) {
-                       return 1;
+               synchronized (getLock()) {
+                       double childrenProgress = relativeProgress - relativeLocalProgress;
+                       relativeLocalProgress = 1 - childrenProgress;
+                       setRelativeProgress(this, name, 1d);
                }
-
-               return (((double) progress) / (max - min));
        }
 
        /**
@@ -280,43 +317,24 @@ public class Progress {
        }
 
        /**
-        * Set the total progress value (including the optional children
-        * {@link Progress}), on a {@link Progress#getMin()} to
-        * {@link Progress#getMax()} scale.
+        * Notify the listeners that this {@link Progress} changed value.
         * 
         * @param pg
-        *            the {@link Progress} to report as the progression emitter
+        *            the emmiter
         * @param name
         *            the current name (if it is NULL, the first non-null name in
         *            the hierarchy will overwrite it) of the {@link Progress} who
         *            emitted this change
-        * @param progress
-        *            the progress to set
         */
-       private void setTotalProgress(Progress pg, String name, int progress) {
-               // TODO: name is not used... and this is probably a bug in this case
-               synchronized (getLock()) {
-                       progress = Math.max(min, progress);
-                       progress = Math.min(max, progress);
-
-                       if (progress != this.progress) {
-                               this.progress = progress;
-                               changed(pg);
-                       }
-               }
-       }
-
-       /**
-        * Notify the listeners that this {@link Progress} changed value.
-        * 
-        * @param pg
-        *            the emmiter
-        */
-       private void changed(Progress pg) {
+       private void changed(Progress pg, String name) {
                if (pg == null) {
                        pg = this;
                }
 
+               if (name == null) {
+                       name = this.name;
+               }
+
                synchronized (getLock()) {
                        for (ProgressListener l : listeners) {
                                l.progress(pg, name);
@@ -383,18 +401,13 @@ public class Progress {
                        @Override
                        public void progress(Progress pg, String name) {
                                synchronized (getLock()) {
-                                       double total = ((double) localProgress) / (max - min);
+                                       double total = relativeLocalProgress;
                                        for (Entry<Progress, Double> entry : children.entrySet()) {
                                                total += (entry.getValue() / (max - min))
                                                                * entry.getKey().getRelativeProgress();
                                        }
 
-                                       if (name == null) {
-                                               name = Progress.this.name;
-                                       }
-
-                                       setTotalProgress(pg, name,
-                                                       (int) Math.round(total * (max - min)));
+                                       setRelativeProgress(pg, name, total);
                                }
                        }
                });