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

Last change on this file since 12369 was 12369, checked in by michael2402, 7 years ago

Javadoc for gui.progress package

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