1 package be
.nikiroo
.utils
;
3 import java
.util
.ArrayList
;
4 import java
.util
.EventListener
;
5 import java
.util
.HashMap
;
8 import java
.util
.Map
.Entry
;
11 * Progress reporting system, possibly nested.
15 public class Progress
{
16 public interface ProgressListener
extends EventListener
{
18 * A progression event.
21 * the {@link Progress} object that generated it, or a parent
23 * the first non-null name of the {@link Progress} step that
24 * generated this event
26 public void progress(Progress progress
, String name
);
30 private Map
<Progress
, Double
> children
;
31 private List
<ProgressListener
> listeners
;
34 private int localProgress
;
35 private int progress
; // children included
38 * Create a new default unnamed {@link Progress}, from 0 to 100.
45 * Create a new default {@link Progress}, from 0 to 100.
48 * the name of this {@link Progress} step
50 public Progress(String name
) {
55 * Create a new unnamed {@link Progress}, from min to max.
58 * the minimum progress value (and starting value) -- must be
61 * the maximum progress value
63 public Progress(int min
, int max
) {
68 * Create a new {@link Progress}, from min to max.
71 * the name of this {@link Progress} step
73 * the minimum progress value (and starting value) -- must be
76 * the maximum progress value
78 public Progress(String name
, int min
, int max
) {
80 this.children
= new HashMap
<Progress
, Double
>();
81 this.listeners
= new ArrayList
<Progress
.ProgressListener
>();
87 * The name of this {@link Progress} step.
91 public String
getName() {
96 * The minimum progress value.
100 public int getMin() {
105 * The minimum progress value.
110 public void setMin(int min
) {
112 throw new Error("negative values not supported");
117 "The minimum progress value must be <= the maximum progress value");
124 * The maximum progress value.
128 public int getMax() {
133 * The maximum progress value (must be >= the minimum progress value).
138 public void setMax(int max
) {
141 "The maximum progress value must be >= the minimum progress value");
148 * Set both the minimum and maximum progress values.
155 public void setMinMax(int min
, int max
) {
157 throw new Error("negative values not supported");
162 "The minimum progress value must be <= the maximum progress value");
170 * Get the total progress value (including the optional children
171 * {@link Progress}) on a {@link Progress#getMin()} to
172 * {@link Progress#getMax()} scale.
174 * @return the progress the value
176 public int getProgress() {
181 * Set the local progress value (not including the optional children
182 * {@link Progress}), on a {@link Progress#getMin()} to
183 * {@link Progress#getMax()} scale.
186 * the progress to set
188 public void setProgress(int progress
) {
189 int diff
= this.progress
- this.localProgress
;
190 this.localProgress
= progress
;
191 setTotalProgress(name
, progress
+ diff
);
195 * Check if the action corresponding to this {@link Progress} is done (i.e.,
196 * if its progress value is >= its max value).
198 * @return TRUE if it is
200 public boolean isDone() {
201 return progress
>= max
;
205 * Get the total progress value (including the optional children
206 * {@link Progress}) on a 0.0 to 1.0 scale.
208 * @return the progress
210 public double getRelativeProgress() {
211 return (((double) progress
) / (max
- min
));
215 * Set the total progress value (including the optional children
216 * {@link Progress}), on a {@link Progress#getMin()} to
217 * {@link Progress#getMax()} scale.
220 * the current name (if it is NULL, the first non-null name in
221 * the hierarchy will overwrite it)
223 * the progress to set
225 private void setTotalProgress(String name
, int progress
) {
226 this.progress
= progress
;
228 for (ProgressListener l
: listeners
) {
229 l
.progress(this, name
);
234 * Add a {@link ProgressListener} that will trigger on progress changes.
239 public void addProgressListener(ProgressListener l
) {
240 this.listeners
.add(l
);
244 * Add a child {@link Progress} of the given weight.
247 * the child {@link Progress} to add
249 * the weight (on a {@link Progress#getMin()} to
250 * {@link Progress#getMax()} scale) of this child
251 * {@link Progress} in relation to its parent
253 public void addProgress(Progress progress
, double weight
) {
254 if (weight
< min
|| weight
> max
) {
256 "A Progress object cannot have a weight outside its parent range");
259 // Note: this is quite inefficient, especially with many children
261 progress
.addProgressListener(new ProgressListener() {
262 public void progress(Progress progress
, String name
) {
263 double total
= ((double) localProgress
) / (max
- min
);
264 for (Entry
<Progress
, Double
> entry
: children
.entrySet()) {
265 total
+= (entry
.getValue() / (max
- min
))
266 * entry
.getKey().getRelativeProgress();
270 name
= Progress
.this.name
;
273 setTotalProgress(name
, (int) (total
* (max
- min
)));
277 this.children
.put(progress
, weight
);