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

Last change on this file since 8285 was 8285, checked in by Don-vip, 9 years ago

fix sonar squid:S2039 - Member variable visibility should be specified

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