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

Last change on this file was 19050, checked in by taylor.smock, 15 months ago

Revert most var changes from r19048, fix most new compile warnings and checkstyle issues

Also, document why various ErrorProne checks were originally disabled and fix
generic SonarLint issues.

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