// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.gui;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.LinkedList;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSeparator;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import org.openstreetmap.josm.data.Version;
import org.openstreetmap.josm.gui.progress.ProgressMonitor;
import org.openstreetmap.josm.gui.progress.ProgressRenderer;
import org.openstreetmap.josm.gui.progress.SwingRenderingProgressMonitor;
import org.openstreetmap.josm.gui.util.GuiHelper;
import org.openstreetmap.josm.tools.ImageProvider;
import org.openstreetmap.josm.tools.Utils;
import org.openstreetmap.josm.tools.WindowGeometry;
/**
* Show a splash screen so the user knows what is happening during startup.
*
*/
public class SplashScreen extends JFrame {
private final SwingRenderingProgressMonitor progressMonitor;
/**
* Constructs a new {@code SplashScreen}.
*/
public SplashScreen() {
super();
setUndecorated(true);
// Add a nice border to the main splash screen
JPanel contentPane = (JPanel)this.getContentPane();
Border margin = new EtchedBorder(1, Color.white, Color.gray);
contentPane.setBorder(margin);
// Add a margin from the border to the content
JPanel innerContentPane = new JPanel();
innerContentPane.setBorder(new EmptyBorder(10, 10, 2, 10));
contentPane.add(innerContentPane);
innerContentPane.setLayout(new GridBagLayout());
// Add the logo
JLabel logo = new JLabel(ImageProvider.get("logo.png"));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridheight = 2;
gbc.insets = new Insets(0, 0, 0, 70);
innerContentPane.add(logo, gbc);
// Add the name of this application
JLabel caption = new JLabel("JOSM – " + tr("Java OpenStreetMap Editor"));
caption.setFont(GuiHelper.getTitleFont());
gbc.gridheight = 1;
gbc.gridx = 1;
gbc.insets = new Insets(30, 0, 0, 0);
innerContentPane.add(caption, gbc);
// Add the version number
JLabel version = new JLabel(tr("Version {0}", Version.getInstance().getVersionString()));
gbc.gridy = 1;
gbc.insets = new Insets(0, 0, 0, 0);
innerContentPane.add(version, gbc);
// Add a separator to the status text
JSeparator separator = new JSeparator(JSeparator.HORIZONTAL);
gbc.gridx = 0;
gbc.gridy = 2;
gbc.gridwidth = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(15, 0, 5, 0);
innerContentPane.add(separator, gbc);
// Add a status message
SplashScreenProgressRenderer progressRenderer = new SplashScreenProgressRenderer();
gbc.gridy = 3;
gbc.insets = new Insets(0, 0, 10, 0);
innerContentPane.add(progressRenderer, gbc);
progressMonitor = new SwingRenderingProgressMonitor(progressRenderer);
pack();
WindowGeometry.centerOnScreen(this.getSize(), "gui.geometry").applySafe(this);
// Add ability to hide splash screen by clicking it
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent event) {
setVisible(false);
}
});
}
/**
* Returns the progress monitor.
* @return The progress monitor
*/
public ProgressMonitor getProgressMonitor() {
return progressMonitor;
}
private static class SplashScreenProgressRenderer extends JPanel implements ProgressRenderer {
private JLabel lblTaskTitle;
private JLabel lblCustomText;
private JProgressBar progressBar;
protected void build() {
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.gridx = 0;
gc.gridy = 0;
gc.fill = GridBagConstraints.HORIZONTAL;
gc.weightx = 1.0;
gc.weighty = 0.0;
gc.insets = new Insets(5,0,0,0);
add(lblTaskTitle = new JLabel(" "), gc);
gc.gridx = 0;
gc.gridy = 1;
gc.fill = GridBagConstraints.HORIZONTAL;
gc.weightx = 1.0;
gc.weighty = 0.0;
gc.insets = new Insets(5,0,0,0);
add(lblCustomText = new JLabel(" ") {
@Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
if(d.width < 600) d.width = 600;
d.height *= MAX_NUMBER_OF_MESSAGES;
return d;
}
}, gc);
gc.gridx = 0;
gc.gridy = 2;
gc.fill = GridBagConstraints.HORIZONTAL;
gc.weightx = 1.0;
gc.weighty = 0.0;
gc.insets = new Insets(5,0,0,0);
add(progressBar = new JProgressBar(JProgressBar.HORIZONTAL), gc);
}
public SplashScreenProgressRenderer() {
build();
}
@Override
public void setCustomText(String message) {
if(message.isEmpty())
message = " "; // prevent killing of additional line
lblCustomText.setText(message);
repaint();
}
@Override
public void setIndeterminate(boolean indeterminate) {
progressBar.setIndeterminate(indeterminate);
repaint();
}
@Override
public void setMaximum(int maximum) {
progressBar.setMaximum(maximum);
repaint();
}
private static final int MAX_NUMBER_OF_MESSAGES = 3;
private LinkedList<String> messages = new LinkedList<>(Arrays.asList("", "", "")); //update when changing MAX_NUMBER_OF_MESSAGES
private long time = System.currentTimeMillis();
/**
* Stores and displays the {@code MAX_NUMBER_OF_MESSAGES} most recent
* task titles together with their execution time.
*/
@Override
public void setTaskTitle(String taskTitle) {
while (messages.size() >= MAX_NUMBER_OF_MESSAGES) {
messages.removeFirst();
}
long now = System.currentTimeMillis();
String prevMessageTitle = messages.getLast();
// now should always be >= time but if can be inferior sometimes, see #10287
if (!prevMessageTitle.isEmpty() && now >= time) {
messages.removeLast();
messages.add(tr("{0} ({1})", prevMessageTitle, Utils.getDurationString(now - time)));
}
time = now;
if (!taskTitle.isEmpty()) {
messages.add(taskTitle);
}
StringBuilder html = new StringBuilder();
int i = 0;
for (String m : messages) {
html.append("<p class=\"entry").append(++i).append("\">").append(m).append("</p>");
}
lblTaskTitle.setText("<html><style>"
+ ".entry1{color:#CCCCCC;}"
+ ".entry2{color:#999999;}"
+ ".entry3{color:#000000;}</style>" + html + "</html>"); //update when changing MAX_NUMBER_OF_MESSAGES
repaint();
}
@Override
public void setValue(int value) {
progressBar.setValue(value);
repaint();
}
}
}