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