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