X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2FProgress.java;h=38ce29f9c8b49e6c4a27dd939fbf4d89d330817f;hb=d827da2aba3d8b0e4a76426b5a76a9045ca584b2;hp=5ee32217d466c1ad7bbb13e21ecf24e6fe457f57;hpb=cac67ebc7e930733b55a381aa72e44c41eac224a;p=nikiroo-utils.git diff --git a/src/be/nikiroo/utils/Progress.java b/src/be/nikiroo/utils/Progress.java index 5ee3221..38ce29f 100644 --- a/src/be/nikiroo/utils/Progress.java +++ b/src/be/nikiroo/utils/Progress.java @@ -14,6 +14,12 @@ import java.util.Set; * @author niki */ public class Progress { + /** + * This event listener is designed to report progress events from + * {@link Progress}. + * + * @author niki + */ public interface ProgressListener extends EventListener { /** * A progression event. @@ -37,8 +43,8 @@ public class Progress { private List 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 +112,7 @@ public class Progress { */ public void setName(String name) { this.name = name; - changed(this); + changed(this, name); } /** @@ -125,17 +131,17 @@ public class Progress { * the min to set * * - * @throws Error + * @throws RuntimeException * if min < 0 or if min > max */ public void setMin(int min) { if (min < 0) { - throw new Error("negative values not supported"); + throw new RuntimeException("negative values not supported"); } synchronized (getLock()) { if (min > max) { - throw new Error( + throw new RuntimeException( "The minimum progress value must be <= the maximum progress value"); } @@ -159,7 +165,7 @@ public class Progress { * the max to set * * - * @throws Error + * @throws RuntimeException * if max < min */ public void setMax(int max) { @@ -181,16 +187,16 @@ public class Progress { * @param max * the max * - * @throws Error + * @throws RuntimeException * if min < 0 or if min > max */ public void setMinMax(int min, int max) { if (min < 0) { - throw new Error("negative values not supported"); + throw new RuntimeException("negative values not supported"); } if (min > max) { - throw new Error( + throw new RuntimeException( "The minimum progress value must be <= the maximum progress value"); } @@ -208,7 +214,7 @@ public class Progress { * @return the progress the value */ public int getProgress() { - return progress; + return (int) Math.round(relativeProgress * (max - min)); } /** @@ -221,12 +227,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 +288,7 @@ public class Progress { */ public void add(int step) { synchronized (getLock()) { - setProgress(localProgress + step); + setProgress(getLocalProgress() + step); } } @@ -246,28 +299,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,42 +323,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) { - 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); @@ -359,40 +384,36 @@ public class Progress { * {@link Progress#getMax()} scale) of this child * {@link Progress} in relation to its parent * - * @throws Error + * @throws RuntimeException * if weight exceed {@link Progress#getMax()} or if progress * already has a parent */ public void addProgress(Progress progress, double weight) { if (weight < min || weight > max) { - throw new Error(String.format( + throw new RuntimeException(String.format( "Progress object %s cannot have a weight of %f, " + "it is outside of its parent (%s) range (%f)", progress.name, weight, name, max)); } if (progress.parent != null) { - throw new Error(String.format( + throw new RuntimeException(String.format( "Progress object %s cannot be added to %s, " + "as it already has a parent (%s)", progress.name, name, progress.parent.name)); } progress.addProgressListener(new ProgressListener() { + @Override public void progress(Progress pg, String name) { synchronized (getLock()) { - double total = ((double) localProgress) / (max - min); + double total = relativeLocalProgress; for (Entry 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); } } });