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

Last change on this file since 1875 was 1875, checked in by jttt, 15 years ago

Fix #3134

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