001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Color; 007import java.awt.Dimension; 008import java.awt.GridBagConstraints; 009import java.awt.GridBagLayout; 010import java.awt.Image; 011import java.awt.Insets; 012import java.awt.event.MouseAdapter; 013import java.awt.event.MouseEvent; 014import java.util.Arrays; 015import java.util.LinkedList; 016 017import javax.swing.ImageIcon; 018import javax.swing.JFrame; 019import javax.swing.JLabel; 020import javax.swing.JPanel; 021import javax.swing.JProgressBar; 022import javax.swing.JSeparator; 023import javax.swing.border.Border; 024import javax.swing.border.EmptyBorder; 025import javax.swing.border.EtchedBorder; 026 027import org.openstreetmap.josm.data.Version; 028import org.openstreetmap.josm.gui.progress.ProgressMonitor; 029import org.openstreetmap.josm.gui.progress.ProgressRenderer; 030import org.openstreetmap.josm.gui.progress.SwingRenderingProgressMonitor; 031import org.openstreetmap.josm.gui.util.GuiHelper; 032import org.openstreetmap.josm.tools.ImageProvider; 033import org.openstreetmap.josm.tools.Utils; 034import org.openstreetmap.josm.tools.WindowGeometry; 035 036/** 037 * Show a splash screen so the user knows what is happening during startup. 038 * @since 976 039 */ 040public class SplashScreen extends JFrame { 041 042 private final SwingRenderingProgressMonitor progressMonitor; 043 044 /** 045 * Constructs a new {@code SplashScreen}. 046 */ 047 public SplashScreen() { 048 setUndecorated(true); 049 050 // Add a nice border to the main splash screen 051 JPanel contentPane = (JPanel)this.getContentPane(); 052 Border margin = new EtchedBorder(1, Color.white, Color.gray); 053 contentPane.setBorder(margin); 054 055 // Add a margin from the border to the content 056 JPanel innerContentPane = new JPanel(); 057 innerContentPane.setBorder(new EmptyBorder(10, 10, 2, 10)); 058 contentPane.add(innerContentPane); 059 innerContentPane.setLayout(new GridBagLayout()); 060 061 // Add the logo 062 JLabel logo = new JLabel(new ImageIcon(ImageProvider.get("logo.png").getImage().getScaledInstance(128, 129, Image.SCALE_SMOOTH))); 063 GridBagConstraints gbc = new GridBagConstraints(); 064 gbc.gridheight = 2; 065 gbc.insets = new Insets(0, 0, 0, 70); 066 innerContentPane.add(logo, gbc); 067 068 // Add the name of this application 069 JLabel caption = new JLabel("JOSM ? " + tr("Java OpenStreetMap Editor")); 070 caption.setFont(GuiHelper.getTitleFont()); 071 gbc.gridheight = 1; 072 gbc.gridx = 1; 073 gbc.insets = new Insets(30, 0, 0, 0); 074 innerContentPane.add(caption, gbc); 075 076 // Add the version number 077 JLabel version = new JLabel(tr("Version {0}", Version.getInstance().getVersionString())); 078 gbc.gridy = 1; 079 gbc.insets = new Insets(0, 0, 0, 0); 080 innerContentPane.add(version, gbc); 081 082 // Add a separator to the status text 083 JSeparator separator = new JSeparator(JSeparator.HORIZONTAL); 084 gbc.gridx = 0; 085 gbc.gridy = 2; 086 gbc.gridwidth = 2; 087 gbc.fill = GridBagConstraints.HORIZONTAL; 088 gbc.insets = new Insets(15, 0, 5, 0); 089 innerContentPane.add(separator, gbc); 090 091 // Add a status message 092 SplashScreenProgressRenderer progressRenderer = new SplashScreenProgressRenderer(); 093 gbc.gridy = 3; 094 gbc.insets = new Insets(0, 0, 10, 0); 095 innerContentPane.add(progressRenderer, gbc); 096 progressMonitor = new SwingRenderingProgressMonitor(progressRenderer); 097 098 pack(); 099 100 WindowGeometry.centerOnScreen(this.getSize(), "gui.geometry").applySafe(this); 101 102 // Add ability to hide splash screen by clicking it 103 addMouseListener(new MouseAdapter() { 104 @Override 105 public void mousePressed(MouseEvent event) { 106 setVisible(false); 107 } 108 }); 109 } 110 111 /** 112 * Returns the progress monitor. 113 * @return The progress monitor 114 */ 115 public ProgressMonitor getProgressMonitor() { 116 return progressMonitor; 117 } 118 119 private static class SplashScreenProgressRenderer extends JPanel implements ProgressRenderer { 120 private JLabel lblTaskTitle; 121 private JLabel lblCustomText; 122 private JProgressBar progressBar; 123 124 protected void build() { 125 setLayout(new GridBagLayout()); 126 GridBagConstraints gc = new GridBagConstraints(); 127 gc.gridx = 0; 128 gc.gridy = 0; 129 gc.fill = GridBagConstraints.HORIZONTAL; 130 gc.weightx = 1.0; 131 gc.weighty = 0.0; 132 gc.insets = new Insets(5,0,0,0); 133 add(lblTaskTitle = new JLabel(" "), gc); 134 135 gc.gridx = 0; 136 gc.gridy = 1; 137 gc.fill = GridBagConstraints.HORIZONTAL; 138 gc.weightx = 1.0; 139 gc.weighty = 0.0; 140 gc.insets = new Insets(5,0,0,0); 141 add(lblCustomText = new JLabel(" ") { 142 @Override 143 public Dimension getPreferredSize() { 144 Dimension d = super.getPreferredSize(); 145 if(d.width < 600) d.width = 600; 146 d.height *= MAX_NUMBER_OF_MESSAGES; 147 return d; 148 } 149 }, gc); 150 151 gc.gridx = 0; 152 gc.gridy = 2; 153 gc.fill = GridBagConstraints.HORIZONTAL; 154 gc.weightx = 1.0; 155 gc.weighty = 0.0; 156 gc.insets = new Insets(5,0,0,0); 157 add(progressBar = new JProgressBar(JProgressBar.HORIZONTAL), gc); 158 } 159 160 public SplashScreenProgressRenderer() { 161 build(); 162 } 163 164 @Override 165 public void setCustomText(String message) { 166 if(message.isEmpty()) 167 message = " "; // prevent killing of additional line 168 lblCustomText.setText(message); 169 repaint(); 170 } 171 172 @Override 173 public void setIndeterminate(boolean indeterminate) { 174 progressBar.setIndeterminate(indeterminate); 175 repaint(); 176 } 177 178 @Override 179 public void setMaximum(int maximum) { 180 progressBar.setMaximum(maximum); 181 repaint(); 182 } 183 184 private static final int MAX_NUMBER_OF_MESSAGES = 3; 185 private LinkedList<String> messages = new LinkedList<>(Arrays.asList("", "", "")); //update when changing MAX_NUMBER_OF_MESSAGES 186 private long time = System.currentTimeMillis(); 187 188 /** 189 * Stores and displays the {@code MAX_NUMBER_OF_MESSAGES} most recent 190 * task titles together with their execution time. 191 */ 192 @Override 193 public void setTaskTitle(String taskTitle) { 194 195 while (messages.size() >= MAX_NUMBER_OF_MESSAGES) { 196 messages.removeFirst(); 197 } 198 long now = System.currentTimeMillis(); 199 String prevMessageTitle = messages.getLast(); 200 // now should always be >= time but if can be inferior sometimes, see #10287 201 if (!prevMessageTitle.isEmpty() && now >= time) { 202 messages.removeLast(); 203 messages.add(tr("{0} ({1})", prevMessageTitle, Utils.getDurationString(now - time))); 204 } 205 time = now; 206 if (!taskTitle.isEmpty()) { 207 messages.add(taskTitle); 208 } 209 StringBuilder html = new StringBuilder(); 210 int i = 0; 211 for (String m : messages) { 212 html.append("<p class=\"entry").append(++i).append("\">").append(m).append("</p>"); 213 } 214 215 lblTaskTitle.setText("<html><style>" 216 + ".entry1{color:#CCCCCC;}" 217 + ".entry2{color:#999999;}" 218 + ".entry3{color:#000000;}</style>" + html + "</html>"); //update when changing MAX_NUMBER_OF_MESSAGES 219 repaint(); 220 } 221 222 @Override 223 public void setValue(int value) { 224 progressBar.setValue(value); 225 repaint(); 226 } 227 } 228}