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

Last change on this file since 2657 was 2512, checked in by stoecker, 14 years ago

i18n updated, fixed files to reduce problems when applying patches, fix #4017

  • Property svn:mime-type set to text/plain
File size: 10.5 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 AbstractProgressMonitor originator;
13 int childTicks;
14 double currentValue;
15
16 String title;
17 String customText;
18 String extraText;
19 Boolean intermediate;
20
21 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 int ticksCount;
31 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<Request>();
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 public void beginTask(String title) {
68 beginTask(title, DEFAULT_TICKS);
69 }
70
71 public synchronized void beginTask(final String title, int ticks) {
72 this.taskTitle = title;
73 checkState(State.INIT);
74 state = State.IN_TASK;
75 doBeginTask();
76 setTicksCount(ticks);
77 resetState();
78 }
79
80 public synchronized void finishTask() {
81 if (state != State.FINISHED) {
82
83 if (state == State.IN_SUBTASK) {
84 requestedState.finishRequested = true;
85 } else {
86 checkState(State.IN_TASK);
87 state = State.FINISHED;
88 doFinishTask();
89 }
90 }
91 }
92
93 public synchronized void invalidate() {
94 if (state == State.INIT) {
95 state = State.FINISHED;
96 doFinishTask();
97 }
98 }
99
100 public synchronized void subTask(final String title) {
101 if (state == State.IN_SUBTASK) {
102 if (title != null) {
103 requestedState.title = title;
104 }
105 requestedState.intermediate = false;
106 } else {
107 checkState(State.IN_TASK);
108 if (title != null) {
109 this.taskTitle = title;
110 resetState();
111 }
112 this.intermediateTask = false;
113 doSetIntermediate(false);
114 }
115 }
116
117 public synchronized void indeterminateSubTask(String title) {
118 if (state == State.IN_SUBTASK) {
119 if (title != null) {
120 requestedState.title = title;
121 }
122 requestedState.intermediate = true;
123 } else {
124 checkState(State.IN_TASK);
125 if (title != null) {
126 this.taskTitle = title;
127 resetState();
128 }
129 this.intermediateTask = true;
130 doSetIntermediate(true);
131 }
132 }
133
134 public synchronized void setCustomText(String text) {
135 if (state == State.IN_SUBTASK) {
136 requestedState.customText = text;
137 } else {
138 this.customText = text;
139 resetState();
140 }
141 }
142
143 public synchronized void setExtraText(String text) {
144 if (state == State.IN_SUBTASK) {
145 requestedState.extraText = text;
146 } else {
147 this.extraText = text;
148 resetState();
149 }
150 }
151
152 /**
153 * Default implementation is empty. Override in subclasses to display the log messages.
154 */
155 public void appendLogMessage(String message) {
156 // do nothing
157 }
158
159 private void resetState() {
160 String newTitle;
161 if (extraText != null) {
162 newTitle = taskTitle + " " + extraText;
163 } else {
164 newTitle = taskTitle;
165 }
166
167 if (newTitle == null?shownTitle != null:!newTitle.equals(shownTitle)) {
168 shownTitle = newTitle;
169 doSetTitle(shownTitle);
170 }
171
172 if (customText == null?shownCustomText != null:!customText.equals(shownCustomText)) {
173 shownCustomText = customText;
174 doSetCustomText(shownCustomText);
175 }
176 doSetIntermediate(intermediateTask);
177 }
178
179 public void cancel() {
180 cancelHandler.cancel();
181 }
182
183 public boolean isCancelled() {
184 return cancelHandler.isCanceled();
185 }
186
187 public void addCancelListener(CancelListener listener) {
188 cancelHandler.addCancelListener(listener);
189 }
190
191 public void removeCancelListener(CancelListener listener) {
192 cancelHandler.removeCancelListener(listener);
193 }
194
195 /*=================
196 * Ticks handling
197 ==================*/
198
199 abstract void updateProgress(double value);
200
201 public synchronized void setTicks(int ticks) {
202 if (ticks >= ticksCount) {
203 ticks = ticksCount - 1;
204 }
205 this.ticks = ticks;
206 internalUpdateProgress(0);
207 }
208
209 public synchronized void setTicksCount(int ticks) {
210 this.ticksCount = ticks;
211 internalUpdateProgress(0);
212 }
213
214 public void worked(int ticks) {
215 if (ticks == ALL_TICKS) {
216 setTicks(this.ticksCount - 1);
217 } else {
218 setTicks(this.ticks + ticks);
219 }
220 }
221
222 private void internalUpdateProgress(double childProgress) {
223 if (childProgress > 1) {
224 childProgress = 1;
225 }
226 checkState(State.IN_TASK, State.IN_SUBTASK);
227 updateProgress(ticksCount == 0?0:(ticks + childProgress * childTicks) / ticksCount);
228 }
229
230 public synchronized int getTicks() {
231 return ticks;
232 }
233
234 public synchronized int getTicksCount() {
235 return ticksCount;
236 }
237
238 /*==========
239 * Subtasks
240 ==========*/
241
242 public synchronized ProgressMonitor createSubTaskMonitor(int ticks, boolean internal) {
243 if (ticks == ALL_TICKS) {
244 ticks = ticksCount - this.ticks;
245 }
246
247 if (state == State.IN_SUBTASK) {
248 Request request = new Request();
249 request.originator = new ChildProgress(this, cancelHandler, internal);
250 request.childTicks = ticks;
251 requests.add(request);
252 return request.originator;
253 } else {
254 checkState(State.IN_TASK);
255 state = State.IN_SUBTASK;
256 this.childTicks = ticks;
257 currentChild = new ChildProgress(this, cancelHandler, internal);
258 return currentChild;
259 }
260 }
261
262 private void applyChildRequest(Request request) {
263 if (request.customText != null) {
264 doSetCustomText(request.customText);
265 }
266
267 if (request.title != null) {
268 doSetTitle(request.title);
269 }
270
271 if (request.intermediate != null) {
272 doSetIntermediate(request.intermediate);
273 }
274
275 internalUpdateProgress(request.currentValue);
276 }
277
278 private void applyThisRequest(Request request) {
279 if (request.finishRequested) {
280 finishTask();
281 } else {
282 if (request.customText != null) {
283 this.customText = request.customText;
284 }
285
286 if (request.title != null) {
287 this.taskTitle = request.title;
288 }
289
290 if (request.intermediate != null) {
291 this.intermediateTask = request.intermediate;
292 }
293
294 if (request.extraText != null) {
295 this.extraText = request.extraText;
296 }
297
298 resetState();
299 }
300 }
301
302 protected synchronized void childFinished(AbstractProgressMonitor child) {
303 checkState(State.IN_SUBTASK);
304 if (currentChild == child) {
305 setTicks(ticks + childTicks);
306 if (requests.isEmpty()) {
307 state = State.IN_TASK;
308 applyThisRequest(requestedState);
309 requestedState = new Request();
310 } else {
311 Request newChild = requests.poll();
312 currentChild = newChild.originator;
313 childTicks = newChild.childTicks;
314 applyChildRequest(newChild);
315 }
316 } else {
317 Iterator<Request> it = requests.iterator();
318 while (it.hasNext()) {
319 if (it.next().originator == child) {
320 it.remove();
321 return;
322 }
323 }
324 throw new ProgressException("Subtask %s not found", child);
325 }
326 }
327
328 private Request getRequest(AbstractProgressMonitor child) {
329 for (Request request:requests) {
330 if (request.originator == child)
331 return request;
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}
Note: See TracBrowser for help on using the repository browser.