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

Last change on this file was 19050, checked in by taylor.smock, 3 weeks 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.