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