source: josm/trunk/src/org/openstreetmap/josm/gui/progress/AbstractProgressMonitor.java@ 9529

Last change on this file since 9529 was 9529, checked in by simon04, 8 years ago

HttpClient: test progress monitor handling

  • Property svn:eol-style set to native
File size: 10.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.progress;
3
4import java.util.Arrays;
5import java.util.Iterator;
6import java.util.LinkedList;
7import java.util.Queue;
8
9public abstract class AbstractProgressMonitor implements ProgressMonitor {
10
11 private static class Request {
12 private AbstractProgressMonitor originator;
13 private int childTicks;
14 private double currentValue;
15
16 private String title;
17 private String customText;
18 private String extraText;
19 private Boolean intermediate;
20
21 private boolean finishRequested;
22 }
23
24 private final CancelHandler cancelHandler;
25
26 protected enum State {
27 INIT,
28 IN_TASK,
29 IN_SUBTASK,
30 FINISHED
31 }
32
33 protected State state = State.INIT;
34
35 private int ticksCount;
36 private int ticks;
37 private int childTicks;
38
39 private String taskTitle;
40 private String customText;
41 private String extraText;
42 private String shownTitle;
43 private String shownCustomText;
44 private boolean intermediateTask;
45
46 private final Queue<Request> requests = new LinkedList<>();
47 private AbstractProgressMonitor currentChild;
48 private Request requestedState = new Request();
49
50 protected abstract void doBeginTask();
51
52 protected abstract void doFinishTask();
53
54 protected abstract void doSetIntermediate(boolean value);
55
56 protected abstract void doSetTitle(String title);
57
58 protected abstract void doSetCustomText(String title);
59
60 protected AbstractProgressMonitor(CancelHandler cancelHandler) {
61 this.cancelHandler = cancelHandler;
62 }
63
64 protected void checkState(State... expectedStates) {
65 for (State s:expectedStates) {
66 if (s == state)
67 return;
68 }
69 throw new ProgressException("Expected states are %s but current state is %s", Arrays.asList(expectedStates).toString(), state);
70 }
71
72 /*=======
73 * Tasks
74 =======*/
75
76 @Override
77 public void beginTask(String title) {
78 beginTask(title, DEFAULT_TICKS);
79 }
80
81 @Override
82 public synchronized void beginTask(String title, int ticks) {
83 this.taskTitle = title;
84 checkState(State.INIT);
85 state = State.IN_TASK;
86 doBeginTask();
87 setTicksCount(ticks);
88 resetState();
89 }
90
91 @Override
92 public synchronized void finishTask() {
93 if (state != State.FINISHED) {
94
95 if (state == State.IN_SUBTASK) {
96 requestedState.finishRequested = true;
97 } else {
98 checkState(State.IN_TASK);
99 state = State.FINISHED;
100 doFinishTask();
101 }
102 }
103 }
104
105 @Override
106 public synchronized void invalidate() {
107 if (state == State.INIT) {
108 state = State.FINISHED;
109 doFinishTask();
110 }
111 }
112
113 @Override
114 public synchronized void subTask(final String title) {
115 if (state == State.IN_SUBTASK) {
116 if (title != null) {
117 requestedState.title = title;
118 }
119 requestedState.intermediate = Boolean.FALSE;
120 } else {
121 checkState(State.IN_TASK);
122 if (title != null) {
123 this.taskTitle = title;
124 resetState();
125 }
126 this.intermediateTask = false;
127 doSetIntermediate(false);
128 }
129 }
130
131 @Override
132 public synchronized void indeterminateSubTask(String title) {
133 if (state == State.IN_SUBTASK) {
134 if (title != null) {
135 requestedState.title = title;
136 }
137 requestedState.intermediate = Boolean.TRUE;
138 } else {
139 checkState(State.IN_TASK);
140 if (title != null) {
141 this.taskTitle = title;
142 resetState();
143 }
144 this.intermediateTask = true;
145 doSetIntermediate(true);
146 }
147 }
148
149 @Override
150 public synchronized void setCustomText(String text) {
151 if (state == State.IN_SUBTASK) {
152 requestedState.customText = text;
153 } else {
154 this.customText = text;
155 resetState();
156 }
157 }
158
159 @Override
160 public synchronized void setExtraText(String text) {
161 if (state == State.IN_SUBTASK) {
162 requestedState.extraText = text;
163 } else {
164 this.extraText = text;
165 resetState();
166 }
167 }
168
169 /**
170 * Default implementation is empty. Override in subclasses to display the log messages.
171 */
172 @Override
173 public void appendLogMessage(String message) {
174 // do nothing
175 }
176
177 private void resetState() {
178 String newTitle;
179 if (extraText != null) {
180 newTitle = taskTitle + ' ' + extraText;
181 } else {
182 newTitle = taskTitle;
183 }
184
185 if (newTitle == null ? shownTitle != null : !newTitle.equals(shownTitle)) {
186 shownTitle = newTitle;
187 doSetTitle(shownTitle);
188 }
189
190 if (customText == null ? shownCustomText != null : !customText.equals(shownCustomText)) {
191 shownCustomText = customText;
192 doSetCustomText(shownCustomText);
193 }
194 doSetIntermediate(intermediateTask);
195 }
196
197 @Override
198 public void cancel() {
199 cancelHandler.cancel();
200 }
201
202 @Override
203 public boolean isCanceled() {
204 return cancelHandler.isCanceled();
205 }
206
207 @Override
208 public void addCancelListener(CancelListener listener) {
209 cancelHandler.addCancelListener(listener);
210 }
211
212 @Override
213 public void removeCancelListener(CancelListener listener) {
214 cancelHandler.removeCancelListener(listener);
215 }
216
217 /*=================
218 * Ticks handling
219 ==================*/
220
221 protected abstract void updateProgress(double value);
222
223 @Override
224 public synchronized void setTicks(int ticks) {
225 if (ticks >= ticksCount) {
226 ticks = ticksCount - 1;
227 }
228 this.ticks = ticks;
229 internalUpdateProgress(0);
230 }
231
232 @Override
233 public synchronized void setTicksCount(int ticks) {
234 this.ticksCount = ticks;
235 internalUpdateProgress(0);
236 }
237
238 @Override
239 public void worked(int ticks) {
240 if (ticks == ALL_TICKS) {
241 setTicks(this.ticksCount - 1);
242 } else {
243 setTicks(this.ticks + ticks);
244 }
245 }
246
247 private void internalUpdateProgress(double childProgress) {
248 if (childProgress > 1) {
249 childProgress = 1;
250 }
251 checkState(State.IN_TASK, State.IN_SUBTASK);
252 updateProgress(ticksCount == 0 ? 0 : (ticks + childProgress * childTicks) / ticksCount);
253 }
254
255 @Override
256 public synchronized int getTicks() {
257 return ticks;
258 }
259
260 @Override
261 public synchronized int getTicksCount() {
262 return ticksCount;
263 }
264
265 /*==========
266 * Subtasks
267 ==========*/
268
269 @Override
270 public synchronized ProgressMonitor createSubTaskMonitor(int ticks, boolean internal) {
271 if (ticks == ALL_TICKS) {
272 ticks = ticksCount - this.ticks;
273 }
274
275 if (state == State.IN_SUBTASK) {
276 Request request = new Request();
277 request.originator = new ChildProgress(this, cancelHandler, internal);
278 request.childTicks = ticks;
279 requests.add(request);
280 return request.originator;
281 } else {
282 checkState(State.IN_TASK);
283 state = State.IN_SUBTASK;
284 this.childTicks = ticks;
285 currentChild = new ChildProgress(this, cancelHandler, internal);
286 return currentChild;
287 }
288 }
289
290 private void applyChildRequest(Request request) {
291 if (request.customText != null) {
292 doSetCustomText(request.customText);
293 }
294
295 if (request.title != null) {
296 doSetTitle(request.title);
297 }
298
299 if (request.intermediate != null) {
300 doSetIntermediate(request.intermediate);
301 }
302
303 internalUpdateProgress(request.currentValue);
304 }
305
306 private void applyThisRequest(Request request) {
307 if (request.finishRequested) {
308 finishTask();
309 } else {
310 if (request.customText != null) {
311 this.customText = request.customText;
312 }
313
314 if (request.title != null) {
315 this.taskTitle = request.title;
316 }
317
318 if (request.intermediate != null) {
319 this.intermediateTask = request.intermediate;
320 }
321
322 if (request.extraText != null) {
323 this.extraText = request.extraText;
324 }
325
326 resetState();
327 }
328 }
329
330 protected synchronized void childFinished(AbstractProgressMonitor child) {
331 checkState(State.IN_SUBTASK);
332 if (currentChild == child) {
333 setTicks(ticks + childTicks);
334 if (requests.isEmpty()) {
335 state = State.IN_TASK;
336 applyThisRequest(requestedState);
337 requestedState = new Request();
338 } else {
339 Request newChild = requests.poll();
340 currentChild = newChild.originator;
341 childTicks = newChild.childTicks;
342 applyChildRequest(newChild);
343 }
344 } else {
345 Iterator<Request> it = requests.iterator();
346 while (it.hasNext()) {
347 if (it.next().originator == child) {
348 it.remove();
349 return;
350 }
351 }
352 throw new ProgressException("Subtask %s not found", child);
353 }
354 }
355
356 private Request getRequest(AbstractProgressMonitor child) {
357 for (Request request:requests) {
358 if (request.originator == child)
359 return request;
360 }
361 throw new ProgressException("Subtask %s not found", child);
362 }
363
364 protected synchronized void childSetProgress(AbstractProgressMonitor child, double value) {
365 checkState(State.IN_SUBTASK);
366 if (currentChild == child) {
367 internalUpdateProgress(value);
368 } else {
369 getRequest(child).currentValue = value;
370 }
371 }
372
373 protected synchronized void childSetTitle(AbstractProgressMonitor child, String title) {
374 checkState(State.IN_SUBTASK);
375 if (currentChild == child) {
376 doSetTitle(title);
377 } else {
378 getRequest(child).title = title;
379 }
380 }
381
382 protected synchronized void childSetCustomText(AbstractProgressMonitor child, String customText) {
383 checkState(State.IN_SUBTASK);
384 if (currentChild == child) {
385 doSetCustomText(customText);
386 } else {
387 getRequest(child).customText = customText;
388 }
389 }
390
391 protected synchronized void childSetIntermediate(AbstractProgressMonitor child, boolean value) {
392 checkState(State.IN_SUBTASK);
393 if (currentChild == child) {
394 doSetIntermediate(value);
395 } else {
396 getRequest(child).intermediate = value;
397 }
398 }
399}
Note: See TracBrowser for help on using the repository browser.