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

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

see #11591, see #11355 - disable blocking code + fix some sonar issues. Splash screen does not work anymore but at least JOSM starts correctly.

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