Merge branch 'subtree'
[nikiroo-utils.git] / ui / ProgressBar.java
CommitLineData
b3aad1f9
NR
1package be.nikiroo.utils.ui;
2
88b36f83 3import java.awt.GridLayout;
b3aad1f9
NR
4import java.awt.event.ActionEvent;
5import java.awt.event.ActionListener;
6import java.util.ArrayList;
88b36f83 7import java.util.HashMap;
b3aad1f9 8import java.util.List;
88b36f83 9import java.util.Map;
b3aad1f9 10
b3aad1f9
NR
11import javax.swing.JPanel;
12import javax.swing.JProgressBar;
13import javax.swing.SwingUtilities;
14
15import be.nikiroo.utils.Progress;
16
2998b78a
NR
17/**
18 * A graphical control to show the progress of a {@link Progress}.
19 * <p>
20 * This control is <b>NOT</b> thread-safe.
21 *
22 * @author niki
23 */
b3aad1f9
NR
24public class ProgressBar extends JPanel {
25 private static final long serialVersionUID = 1L;
26
88b36f83 27 private Map<Progress, JProgressBar> bars;
2998b78a
NR
28 private List<ActionListener> actionListeners;
29 private List<ActionListener> updateListeners;
88b36f83 30 private Progress pg;
f4053377 31 private Object lock = new Object();
b3aad1f9
NR
32
33 public ProgressBar() {
88b36f83 34 bars = new HashMap<Progress, JProgressBar>();
2998b78a
NR
35 actionListeners = new ArrayList<ActionListener>();
36 updateListeners = new ArrayList<ActionListener>();
b3aad1f9 37 }
2b19abda
NR
38
39 public ProgressBar(Progress pg) {
40 this();
41 setProgress(pg);
42 }
b3aad1f9 43
88b36f83
NR
44 public void setProgress(final Progress pg) {
45 this.pg = pg;
46
2998b78a 47 SwingUtilities.invokeLater(new Runnable() {
cd0c27d2 48 @Override
2998b78a
NR
49 public void run() {
50 if (pg != null) {
51 final JProgressBar bar = new JProgressBar();
52 bar.setStringPainted(true);
53
54 bars.clear();
55 bars.put(pg, bar);
56
57 bar.setMinimum(pg.getMin());
58 bar.setMaximum(pg.getMax());
59 bar.setValue(pg.getProgress());
60 bar.setString(pg.getName());
61
62 pg.addProgressListener(new Progress.ProgressListener() {
cd0c27d2 63 @Override
2998b78a
NR
64 public void progress(Progress progress, String name) {
65 final Progress.ProgressListener l = this;
66 SwingUtilities.invokeLater(new Runnable() {
cd0c27d2 67 @Override
2998b78a
NR
68 public void run() {
69 Map<Progress, JProgressBar> newBars = new HashMap<Progress, JProgressBar>();
70 newBars.put(pg, bar);
71
72 bar.setMinimum(pg.getMin());
73 bar.setMaximum(pg.getMax());
74 bar.setValue(pg.getProgress());
75 bar.setString(pg.getName());
76
f4053377 77 synchronized (lock) {
9acc9360
NR
78 for (Progress pgChild : getChildrenAsOrderedList(pg)) {
79 JProgressBar barChild = bars
80 .get(pgChild);
81 if (barChild == null) {
82 barChild = new JProgressBar();
83 barChild.setStringPainted(true);
2998b78a
NR
84 }
85
9acc9360 86 newBars.put(pgChild, barChild);
2998b78a 87
9acc9360
NR
88 barChild.setMinimum(pgChild.getMin());
89 barChild.setMaximum(pgChild.getMax());
90 barChild.setValue(pgChild.getProgress());
91 barChild.setString(pgChild.getName());
2998b78a 92 }
f4053377 93
2998b78a
NR
94 if (ProgressBar.this.pg == null) {
95 bars.clear();
96 } else {
97 bars = newBars;
f4053377
NR
98 }
99 }
100
101 if (ProgressBar.this.pg != null) {
2998b78a
NR
102 if (pg.isDone()) {
103 pg.removeProgressListener(l);
104 for (ActionListener listener : actionListeners) {
105 listener.actionPerformed(new ActionEvent(
106 ProgressBar.this, 0,
107 "done"));
108 }
109 }
110
111 update();
112 }
b3aad1f9 113 }
2998b78a 114 });
b3aad1f9
NR
115 }
116 });
117 }
b3aad1f9 118
2998b78a
NR
119 update();
120 }
121 });
b3aad1f9
NR
122 }
123
2998b78a
NR
124 public void addActionListener(ActionListener l) {
125 actionListeners.add(l);
b3aad1f9
NR
126 }
127
128 public void clearActionListeners() {
2998b78a
NR
129 actionListeners.clear();
130 }
131
132 public void addUpdateListener(ActionListener l) {
133 updateListeners.add(l);
b3aad1f9
NR
134 }
135
2998b78a
NR
136 public void clearUpdateListeners() {
137 updateListeners.clear();
138 }
139
140 public int getProgress() {
141 if (pg == null) {
142 return 0;
143 }
144
145 return pg.getProgress();
146 }
147
148 // only named ones
88b36f83
NR
149 private List<Progress> getChildrenAsOrderedList(Progress pg) {
150 List<Progress> children = new ArrayList<Progress>();
f4053377
NR
151
152 synchronized (lock) {
153 for (Progress child : pg.getChildren()) {
2998b78a
NR
154 if (child.getName() != null && !child.getName().isEmpty()) {
155 children.add(child);
156 }
88b36f83
NR
157 children.addAll(getChildrenAsOrderedList(child));
158 }
f4053377
NR
159 }
160
88b36f83
NR
161 return children;
162 }
163
2998b78a 164 private void update() {
f4053377
NR
165 synchronized (lock) {
166 invalidate();
167 removeAll();
168
169 if (pg != null) {
170 setLayout(new GridLayout(bars.size(), 1));
171 add(bars.get(pg), 0);
172 for (Progress child : getChildrenAsOrderedList(pg)) {
173 JProgressBar jbar = bars.get(child);
174 if (jbar != null) {
175 add(jbar);
176 }
2998b78a 177 }
88b36f83 178 }
b3aad1f9 179
f4053377
NR
180 validate();
181 repaint();
182 }
2998b78a
NR
183
184 for (ActionListener listener : updateListeners) {
185 listener.actionPerformed(new ActionEvent(this, 0, "update"));
186 }
b3aad1f9
NR
187 }
188}