source: josm/trunk/src/org/openstreetmap/josm/gui/SplashScreen.java@ 9369

Last change on this file since 9369 was 9243, checked in by Don-vip, 8 years ago

javadoc update

  • Property svn:eol-style set to native
File size: 12.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Color;
7import java.awt.Component;
8import java.awt.Dimension;
9import java.awt.GridBagConstraints;
10import java.awt.GridBagLayout;
11import java.awt.Image;
12import java.awt.Insets;
13import java.awt.event.MouseAdapter;
14import java.awt.event.MouseEvent;
15import java.util.List;
16import java.util.Objects;
17import java.util.concurrent.CopyOnWriteArrayList;
18
19import javax.swing.BorderFactory;
20import javax.swing.ImageIcon;
21import javax.swing.JFrame;
22import javax.swing.JLabel;
23import javax.swing.JPanel;
24import javax.swing.JProgressBar;
25import javax.swing.JScrollPane;
26import javax.swing.JSeparator;
27import javax.swing.ScrollPaneConstants;
28import javax.swing.border.Border;
29import javax.swing.border.EmptyBorder;
30import javax.swing.border.EtchedBorder;
31import javax.swing.event.ChangeEvent;
32import javax.swing.event.ChangeListener;
33
34import org.openstreetmap.josm.Main;
35import org.openstreetmap.josm.data.Version;
36import org.openstreetmap.josm.gui.progress.ProgressMonitor;
37import org.openstreetmap.josm.gui.progress.ProgressTaskId;
38import org.openstreetmap.josm.gui.util.GuiHelper;
39import org.openstreetmap.josm.gui.widgets.JosmEditorPane;
40import org.openstreetmap.josm.tools.GBC;
41import org.openstreetmap.josm.tools.ImageProvider;
42import org.openstreetmap.josm.tools.Predicates;
43import org.openstreetmap.josm.tools.Utils;
44import org.openstreetmap.josm.tools.WindowGeometry;
45
46/**
47 * Show a splash screen so the user knows what is happening during startup.
48 * @since 976
49 */
50public class SplashScreen extends JFrame implements ChangeListener {
51
52 private final SplashProgressMonitor progressMonitor;
53 private final SplashScreenProgressRenderer progressRenderer;
54
55 /**
56 * Constructs a new {@code SplashScreen}.
57 */
58 public SplashScreen() {
59 setUndecorated(true);
60
61 // Add a nice border to the main splash screen
62 JPanel contentPane = (JPanel) this.getContentPane();
63 Border margin = new EtchedBorder(1, Color.white, Color.gray);
64 contentPane.setBorder(margin);
65
66 // Add a margin from the border to the content
67 JPanel innerContentPane = new JPanel();
68 innerContentPane.setBorder(new EmptyBorder(10, 10, 2, 10));
69 contentPane.add(innerContentPane);
70 innerContentPane.setLayout(new GridBagLayout());
71
72 // Add the logo
73 JLabel logo = new JLabel(new ImageIcon(ImageProvider.get("logo.svg").getImage().getScaledInstance(128, 129, Image.SCALE_SMOOTH)));
74 GridBagConstraints gbc = new GridBagConstraints();
75 gbc.gridheight = 2;
76 gbc.insets = new Insets(0, 0, 0, 70);
77 innerContentPane.add(logo, gbc);
78
79 // Add the name of this application
80 JLabel caption = new JLabel("JOSM – " + tr("Java OpenStreetMap Editor"));
81 caption.setFont(GuiHelper.getTitleFont());
82 gbc.gridheight = 1;
83 gbc.gridx = 1;
84 gbc.insets = new Insets(30, 0, 0, 0);
85 innerContentPane.add(caption, gbc);
86
87 // Add the version number
88 JLabel version = new JLabel(tr("Version {0}", Version.getInstance().getVersionString()));
89 gbc.gridy = 1;
90 gbc.insets = new Insets(0, 0, 0, 0);
91 innerContentPane.add(version, gbc);
92
93 // Add a separator to the status text
94 JSeparator separator = new JSeparator(JSeparator.HORIZONTAL);
95 gbc.gridx = 0;
96 gbc.gridy = 2;
97 gbc.gridwidth = 2;
98 gbc.fill = GridBagConstraints.HORIZONTAL;
99 gbc.insets = new Insets(15, 0, 5, 0);
100 innerContentPane.add(separator, gbc);
101
102 // Add a status message
103 progressRenderer = new SplashScreenProgressRenderer();
104 gbc.gridy = 3;
105 gbc.insets = new Insets(0, 0, 10, 0);
106 innerContentPane.add(progressRenderer, gbc);
107 progressMonitor = new SplashProgressMonitor(null, this);
108
109 pack();
110
111 WindowGeometry.centerOnScreen(this.getSize(), "gui.geometry").applySafe(this);
112
113 // Add ability to hide splash screen by clicking it
114 addMouseListener(new MouseAdapter() {
115 @Override
116 public void mousePressed(MouseEvent event) {
117 setVisible(false);
118 }
119 });
120 }
121
122 @Override
123 public void stateChanged(ChangeEvent ignore) {
124 GuiHelper.runInEDT(new Runnable() {
125 @Override
126 public void run() {
127 progressRenderer.setTasks(progressMonitor.toString());
128 }
129 });
130 }
131
132 /**
133 * A task (of a {@link ProgressMonitor}).
134 */
135 private abstract static class Task {
136
137 /**
138 * Returns a HTML representation for this task.
139 * @param sb a {@code StringBuilder} used to build the HTML code
140 * @return {@code sb}
141 */
142 public abstract StringBuilder toHtml(StringBuilder sb);
143
144 @Override
145 public final String toString() {
146 return toHtml(new StringBuilder(1024)).toString();
147 }
148 }
149
150 /**
151 * A single task (of a {@link ProgressMonitor}) which keeps track of its execution duration
152 * (requires a call to {@link #finish()}).
153 */
154 private static class MeasurableTask extends Task {
155 private final String name;
156 private final long start;
157 private String duration = "";
158
159 MeasurableTask(String name) {
160 this.name = name;
161 this.start = System.currentTimeMillis();
162 }
163
164 public void finish() {
165 if (!"".equals(duration)) {
166 throw new IllegalStateException("This tasks has already been finished");
167 }
168 duration = tr(" ({0})", Utils.getDurationString(System.currentTimeMillis() - start));
169 }
170
171 @Override
172 public StringBuilder toHtml(StringBuilder sb) {
173 return sb.append(name).append("<i style='color: #666666;'>").append(duration).append("</i>");
174 }
175
176 @Override
177 public boolean equals(Object o) {
178 if (this == o) return true;
179 if (o == null || getClass() != o.getClass()) return false;
180 MeasurableTask that = (MeasurableTask) o;
181 return Objects.equals(name, that.name);
182 }
183
184 @Override
185 public int hashCode() {
186 return Objects.hashCode(name);
187 }
188 }
189
190 /**
191 * A {@link ProgressMonitor} which stores the (sub)tasks in a tree.
192 */
193 public static class SplashProgressMonitor extends Task implements ProgressMonitor {
194
195 private final String name;
196 private final ChangeListener listener;
197 private final List<Task> tasks = new CopyOnWriteArrayList<>();
198 private SplashProgressMonitor latestSubtask;
199
200 public SplashProgressMonitor(String name, ChangeListener listener) {
201 this.name = name;
202 this.listener = listener;
203 }
204
205 @Override
206 public StringBuilder toHtml(StringBuilder sb) {
207 sb.append(Utils.firstNonNull(name, ""));
208 if (!tasks.isEmpty()) {
209 sb.append("<ul>");
210 for (Task i : tasks) {
211 sb.append("<li>");
212 i.toHtml(sb);
213 sb.append("</li>");
214 }
215 sb.append("</ul>");
216 }
217 return sb;
218 }
219
220 @Override
221 public void beginTask(String title) {
222 if (title != null) {
223 final MeasurableTask task = new MeasurableTask(title);
224 tasks.add(task);
225 listener.stateChanged(null);
226 }
227 }
228
229 @Override
230 public void beginTask(String title, int ticks) {
231 this.beginTask(title);
232 }
233
234 @Override
235 public void setCustomText(String text) {
236 this.beginTask(text);
237 }
238
239 @Override
240 public void setExtraText(String text) {
241 this.beginTask(text);
242 }
243
244 @Override
245 public void indeterminateSubTask(String title) {
246 this.subTask(title);
247 }
248
249 @Override
250 public void subTask(String title) {
251 latestSubtask = new SplashProgressMonitor(title, listener);
252 tasks.add(latestSubtask);
253 listener.stateChanged(null);
254 }
255
256 @Override
257 public ProgressMonitor createSubTaskMonitor(int ticks, boolean internal) {
258 return latestSubtask;
259 }
260
261 /**
262 * @deprecated Use {@link #finishTask(String)} instead.
263 */
264 @Override
265 @Deprecated
266 public void finishTask() {
267 // Not used
268 }
269
270 /**
271 * Displays the given task as finished.
272 * @param title the task title
273 */
274 public void finishTask(String title) {
275 final Task task = Utils.find(tasks, Predicates.<Task>equalTo(new MeasurableTask(title)));
276 if (task instanceof MeasurableTask) {
277 ((MeasurableTask) task).finish();
278 Main.debug(tr("{0} completed in {1}", title, ((MeasurableTask) task).duration));
279 listener.stateChanged(null);
280 }
281 }
282
283 @Override
284 public void invalidate() {
285 // Not used
286 }
287
288 @Override
289 public void setTicksCount(int ticks) {
290 // Not used
291 }
292
293 @Override
294 public int getTicksCount() {
295 return 0;
296 }
297
298 @Override
299 public void setTicks(int ticks) {
300 }
301
302 @Override
303 public int getTicks() {
304 return 0;
305 }
306
307 @Override
308 public void worked(int ticks) {
309 // Not used
310 }
311
312 @Override
313 public boolean isCanceled() {
314 return false;
315 }
316
317 @Override
318 public void cancel() {
319 // Not used
320 }
321
322 @Override
323 public void addCancelListener(CancelListener listener) {
324 // Not used
325 }
326
327 @Override
328 public void removeCancelListener(CancelListener listener) {
329 // Not used
330 }
331
332 @Override
333 public void appendLogMessage(String message) {
334 // Not used
335 }
336
337 @Override
338 public void setProgressTaskId(ProgressTaskId taskId) {
339 // Not used
340 }
341
342 @Override
343 public ProgressTaskId getProgressTaskId() {
344 return null;
345 }
346
347 @Override
348 public Component getWindowParent() {
349 return Main.parent;
350 }
351 }
352
353 /**
354 * Returns the progress monitor.
355 * @return The progress monitor
356 */
357 public SplashProgressMonitor getProgressMonitor() {
358 return progressMonitor;
359 }
360
361 private static class SplashScreenProgressRenderer extends JPanel {
362 private final JosmEditorPane lblTaskTitle = new JosmEditorPane();
363 private final JProgressBar progressBar = new JProgressBar(JProgressBar.HORIZONTAL);
364 private static final String LABEL_HTML = "<html>"
365 + "<style>ul {margin-top: 0; margin-bottom: 0; padding: 0;} li {margin: 0; padding: 0;}</style>";
366
367 protected void build() {
368 setLayout(new GridBagLayout());
369
370 JosmEditorPane.makeJLabelLike(lblTaskTitle, false);
371 lblTaskTitle.setText(LABEL_HTML);
372 final JScrollPane scrollPane = new JScrollPane(lblTaskTitle,
373 ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
374 scrollPane.setPreferredSize(new Dimension(0, 320));
375 scrollPane.setBorder(BorderFactory.createEmptyBorder());
376 add(scrollPane, GBC.eol().insets(5, 5, 0, 0).fill(GridBagConstraints.HORIZONTAL));
377
378 progressBar.setIndeterminate(true);
379 add(progressBar, GBC.eol().insets(5, 15, 0, 0).fill(GridBagConstraints.HORIZONTAL));
380 }
381
382 /**
383 * Constructs a new {@code SplashScreenProgressRenderer}.
384 */
385 SplashScreenProgressRenderer() {
386 build();
387 }
388
389 /**
390 * Sets the tasks to displayed. A HTML formatted list is expected.
391 * @param tasks HTML formatted list of tasks
392 */
393 public void setTasks(String tasks) {
394 lblTaskTitle.setText(LABEL_HTML + tasks);
395 lblTaskTitle.setCaretPosition(lblTaskTitle.getDocument().getLength());
396 }
397 }
398}
Note: See TracBrowser for help on using the repository browser.