001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2015
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 * 
010 * All Rights Reserved
011 * 
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.  
014 * 
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 * 
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU Lesser Public License for more details.
024 * 
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program.  If not, see http://www.gnu.org/licenses.
027 */
028package edu.wisc.ssec.mcidasv.util;
029
030import static edu.wisc.ssec.mcidasv.util.McVGuiUtils.setButtonImage;
031
032import java.awt.Dimension;
033import java.awt.EventQueue;
034import java.awt.GridBagConstraints;
035import java.awt.GridBagLayout;
036import java.awt.event.ActionEvent;
037import java.awt.event.ActionListener;
038import java.awt.event.WindowAdapter;
039import java.awt.event.WindowEvent;
040import java.io.IOException;
041
042import javax.swing.GroupLayout;
043import javax.swing.ImageIcon;
044import javax.swing.JButton;
045import javax.swing.JFrame;
046import javax.swing.JLabel;
047import javax.swing.JPanel;
048import javax.swing.JScrollPane;
049import javax.swing.JTextPane;
050import javax.swing.LayoutStyle;
051import javax.swing.WindowConstants;
052import javax.swing.event.HyperlinkEvent;
053import javax.swing.event.HyperlinkListener;
054
055/**
056 * {@code WelcomeWindow} is really just intended to <i>try</i> to detect known
057 * hardware problems and inform the user about any problems.
058 *
059 * <p>The current implementation does not perform <i>any</i> detection, but
060 * expect this to change.
061 */
062// NOTE TO MCV CODERS:
063// **DOCUMENT WHAT CHECKS AND/OR DETECTION ARE BEING PERFORMED**
064public class WelcomeWindow extends JFrame {
065
066    /** Path to {@literal "header"} image. */
067    private static final String LOGO_PATH = 
068        "/edu/wisc/ssec/mcidasv/images/mcidasv_logo.gif";
069
070    /** Path to the HTML to display within {@link #textPane}. */
071    private static final String WELCOME_HTML =
072        "/edu/wisc/ssec/mcidasv/resources/welcome.html";
073
074    /**
075     * Message to display if there was a problem loading
076     * {@link #WELCOME_HTML}.
077     */
078    private static final String ERROR_MESSAGE =
079        "McIDAS-V had a problem displaying its welcome message. Please"
080        + " contact the McIDAS Help Desk for assistance.";
081
082    /** Dimensions of the welcome window frame. */
083    private static final Dimension WINDOW_SIZE = new Dimension(495, 431);
084
085    /** Java-friendly location of the path to the welcome message. */
086    private final java.net.URL contents;
087
088    /** 
089     * Creates new form WelcomeWindow.
090     */
091    public WelcomeWindow() {
092        this.contents = WelcomeWindow.class.getResource(WELCOME_HTML);
093        initComponents();
094    }
095
096    /** 
097     * This method is called from within the constructor to
098     * initialize the form.
099     * WARNING: Do NOT modify this code. The content of this method is
100     * always regenerated by the Form Editor.
101     */
102    // <editor-fold defaultstate="collapsed" desc="Generated Code">
103    private void initComponents() {
104
105        setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
106        setTitle("Welcome to McIDAS-V");
107        setLocationByPlatform(true);
108        addWindowListener(new WindowAdapter() {
109            @Override public void windowClosing(WindowEvent evt) {
110                formWindowClosing(evt);
111            }
112        });
113
114        logoPanel.setLayout(new GridBagLayout());
115
116        logoLabel.setIcon(new ImageIcon(getClass().getResource(LOGO_PATH))); // NOI18N
117        logoPanel.add(logoLabel, new GridBagConstraints());
118
119        textPane.setEditable(false);
120        try {
121            textPane.setPage(contents);
122        } catch (IOException e) {
123            textPane.setText(ERROR_MESSAGE);
124            e.printStackTrace();
125        }
126        textPane.addHyperlinkListener(new HyperlinkListener() {
127            @Override public void hyperlinkUpdate(HyperlinkEvent evt) {
128                textPaneHyperlinkUpdate(evt);
129            }
130        });
131        scrollPane.setViewportView(textPane);
132
133        GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
134        mainPanel.setLayout(mainPanelLayout);
135        mainPanelLayout.setHorizontalGroup(
136            mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
137            .addComponent(scrollPane, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE)
138        );
139        mainPanelLayout.setVerticalGroup(
140            mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
141            .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 273, Short.MAX_VALUE)
142        );
143
144        setButtonImage(startButton, McVGuiUtils.ICON_APPLY_SMALL);
145        startButton.addActionListener(new ActionListener() {
146            @Override public void actionPerformed(ActionEvent evt) {
147                startButtonActionPerformed(evt);
148            }
149        });
150
151        setButtonImage(quitButton, McVGuiUtils.ICON_CANCEL_SMALL);
152        quitButton.addActionListener(new ActionListener() {
153            @Override public void actionPerformed(ActionEvent evt) {
154                quitButtonActionPerformed(evt);
155            }
156        });
157
158        GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
159        buttonPanel.setLayout(buttonPanelLayout);
160        buttonPanelLayout.setHorizontalGroup(
161            buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
162            .addGroup(GroupLayout.Alignment.TRAILING, buttonPanelLayout.createSequentialGroup()
163                .addContainerGap(144, Short.MAX_VALUE)
164                .addComponent(quitButton)
165                .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
166                .addComponent(startButton))
167        );
168        buttonPanelLayout.setVerticalGroup(
169            buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
170            .addGroup(buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
171                .addComponent(startButton)
172                .addComponent(quitButton))
173        );
174
175        GroupLayout layout = new GroupLayout(getContentPane());
176        getContentPane().setLayout(layout);
177        layout.setHorizontalGroup(
178            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
179            .addGroup(layout.createSequentialGroup()
180                .addContainerGap()
181                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
182                    .addComponent(mainPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
183                    .addComponent(buttonPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
184                    .addComponent(logoPanel, GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE))
185                .addContainerGap())
186        );
187        layout.setVerticalGroup(
188            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
189            .addGroup(layout.createSequentialGroup()
190                .addContainerGap()
191                .addComponent(logoPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
192                .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
193                .addComponent(mainPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
194                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
195                .addComponent(buttonPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
196                .addContainerGap())
197        );
198
199        pack();
200        setLocationRelativeTo(null);
201        setSize(WINDOW_SIZE);
202    }// </editor-fold>
203
204    /**
205     * Handles the user clicking on {@link #startButton}. 
206     * Executes {@code System.exit(0)} in an effort to signal to the startup
207     * scripts that the window terminated {@literal "normally"}.
208     * 
209     * @param evt Event to handle. Currently ignored.
210     */
211    private void startButtonActionPerformed(ActionEvent evt) {
212        System.exit(0);
213    }
214
215    /**
216     * Handles the user clicking on {@link #quitButton}. Doesn't do anything
217     * aside from handing off things to
218     * {@link #formWindowClosing(WindowEvent)}
219     *
220     * @param evt Event to handle. Currently ignored.
221     *
222     * @see #formWindowClosing(WindowEvent)
223     */
224    private void quitButtonActionPerformed(ActionEvent evt) {
225        formWindowClosing(null);
226    }
227
228    /**
229     * Handles the user opting to close the welcome window
230     * {@link JFrame}. Executes {@code System.exit(1)} in an
231     * effort to signal to the startup scripts that window terminated 
232     * {@literal "abnormally"}.
233     * 
234     * <p>An abnormal termination will result in the startup script 
235     * terminating the launch of McIDAS-V.
236     * 
237     * @param evt Note that this parameter is currently ignored.
238     */
239    private void formWindowClosing(WindowEvent evt) {
240        System.exit(1);
241    }
242
243    /**
244     * Listens to {@link #textPane} in order to handle the user clicking on
245     * HTML links.
246     *
247     * @param evt Event to handle. Anything other than
248     * an {@literal "ACTIVATED"}
249     * {@link javax.swing.event.HyperlinkEvent.EventType HyperlinkEvent.EventType}
250     * is ignored.
251     *
252     * @see WebBrowser#browse(String)
253     */
254    private void textPaneHyperlinkUpdate(HyperlinkEvent evt) {
255        if (evt.getEventType() != HyperlinkEvent.EventType.ACTIVATED) {
256            return;
257        }
258
259        String url = null;
260        if (evt.getURL() == null) {
261            url = evt.getDescription();
262        } else {
263            url = evt.getURL().toString();
264        }
265
266        WebBrowser.browse(url);
267    }
268
269    /**
270     * @param args the command line arguments
271     */
272    public static void main(String[] args) {
273        EventQueue.invokeLater(new Runnable() {
274            public void run() {
275                new WelcomeWindow().setVisible(true);
276            }
277        });
278    }
279
280    // boring gui components
281    private final JPanel buttonPanel = new JPanel();
282    private final JLabel logoLabel = new JLabel();
283    private final JPanel logoPanel = new JPanel();
284    private final JPanel mainPanel = new JPanel();
285    private final JButton quitButton = new JButton("Quit");
286    private final JScrollPane scrollPane = new JScrollPane();
287    private final JButton startButton = new JButton("Start McIDAS-V");
288    private final JTextPane textPane = new JTextPane();
289}