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 */
028
029package edu.wisc.ssec.mcidasv.chooser;
030
031import static javax.swing.GroupLayout.DEFAULT_SIZE;
032import static javax.swing.GroupLayout.Alignment.BASELINE;
033import static javax.swing.GroupLayout.Alignment.LEADING;
034import static javax.swing.GroupLayout.Alignment.TRAILING;
035import static javax.swing.LayoutStyle.ComponentPlacement.RELATED;
036import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED;
037
038import java.awt.event.ActionEvent;
039import java.awt.event.ActionListener;
040import java.awt.event.KeyEvent;
041import java.awt.event.KeyListener;
042import java.util.Hashtable;
043import java.util.List;
044
045import javax.swing.GroupLayout;
046import javax.swing.JButton;
047import javax.swing.JComboBox;
048import javax.swing.JComponent;
049import javax.swing.JLabel;
050import javax.swing.JPanel;
051import javax.swing.JRadioButton;
052import javax.swing.JScrollPane;
053import javax.swing.JTextArea;
054import javax.swing.JTextField;
055
056import org.w3c.dom.Element;
057
058import edu.wisc.ssec.mcidasv.Constants;
059import edu.wisc.ssec.mcidasv.util.McVGuiUtils;
060import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Position;
061import edu.wisc.ssec.mcidasv.util.McVGuiUtils.TextColor;
062import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Width;
063
064import ucar.unidata.data.DataManager;
065import ucar.unidata.idv.IntegratedDataViewer;
066import ucar.unidata.idv.chooser.IdvChooserManager;
067import ucar.unidata.util.GuiUtils;
068import ucar.unidata.util.PreferenceList;
069import ucar.unidata.util.StringUtil;
070
071/**
072 * Allows the user to select a url as a data source
073 *
074 * @author IDV development team
075 * @version $Revision$Date: 2011/03/24 16:06:31 $
076 */
077public class UrlChooser extends ucar.unidata.idv.chooser.UrlChooser implements Constants {
078
079    /** Manages the pull down list of urls */
080    private PreferenceList prefList;
081
082    /** The list of urls */
083    private JComboBox box;
084    private JTextField boxEditor;
085
086    /** The text area for multi-line urls */
087    private JTextArea textArea;
088
089    /** text scroller */
090    private JScrollPane textScroller;
091
092    /** Holds the combo box */
093    private JPanel urlPanel;
094
095    /** Holds the text area */
096    private JPanel textPanel;
097
098    /** Are we showing the combo box */
099    private boolean showBox = true;
100
101    /** Swtich */
102    private JButton switchBtn;
103
104    /** panel */
105    private GuiUtils.CardLayoutPanel cardLayoutPanel;
106    
107    /**
108     * Get a handle on the IDV
109     */
110    protected IntegratedDataViewer idv = getIdv();
111
112    /**
113     * Create the {@code UrlChooser}.
114     *
115     * @param mgr {@code IdvChooserManager}.
116     * @param root XML root that defines this chooser.
117     *
118     */
119    public UrlChooser(IdvChooserManager mgr, Element root) {
120        super(mgr, root);
121        
122        loadButton = McVGuiUtils.makeImageTextButton(ICON_ACCEPT_SMALL, getLoadCommandName());
123        loadButton.setActionCommand(getLoadCommandName());
124        loadButton.addActionListener(this);
125
126    }
127
128    /**
129     * Toggle the combobox with the text area.
130     */
131    public void switchFields() {
132        if (showBox) {
133            cardLayoutPanel.show(urlPanel);
134        } else {
135            cardLayoutPanel.show(textPanel);
136        }
137        updateStatus();
138    }
139
140    /**
141     * Disable/enable any components that depend on the server.
142     * Try to update the status label with what we know here.
143     */
144    protected void updateStatus() {
145        if (boxEditor==null || textArea==null) return;
146        if (showBox) {
147            if (!boxEditor.getText().trim().equals(""))
148                setHaveData(true);
149            else
150                setHaveData(false);
151        } else {
152            if (!textArea.getText().trim().equals(""))
153                setHaveData(true);
154            else
155                setHaveData(false);
156        }
157        super.updateStatus();
158        if (!getHaveData()) {
159            if (showBox) setStatus("Enter a URL");
160            else setStatus("Enter one or more URLs");
161        }
162    }
163
164    /**
165     * Handle the action event from the GUI.
166     */
167    @Override public void doLoadInThread() {
168        loadURL();
169    }
170
171    /**
172     * Wrapper around {@link #loadURLInner()}, showing the wait cursor.
173     */
174    private void loadURL() {
175        showWaitCursor();
176        loadURLInner();
177        showNormalCursor();
178    }
179
180    /**
181     * Load the URL.
182     */
183    private void loadURLInner() {
184
185        String url = "";
186        String    dataSourceId = getDataSourceId();
187        if (showBox) {
188            Object selectedItem = box.getSelectedItem();
189            if (selectedItem != null) {
190                url = selectedItem.toString().trim();
191            }
192            if (url.length() == 0 && dataSourceId == null) {
193                userMessage("Please specify a url");
194                return;
195            }
196        }
197
198        Hashtable properties   = new Hashtable();
199        if (dataSourceId != null) {
200            properties.put(DataManager.DATATYPE_ID, dataSourceId);
201        }
202
203        if (showBox) {
204            if (idv.handleAction(url, properties)) {
205                closeChooser();
206                prefList.saveState(box);
207            }
208        } else {
209            List urls = StringUtil.split(textArea.getText(), "\n", true,
210                                         true);
211
212            if ((urls.size() > 0)
213                    && makeDataSource(urls, dataSourceId, properties)) {
214                closeChooser();
215            }
216        }
217    }
218        
219    /**
220     * Make the contents
221     *
222     * @return  the contents
223     */
224    protected JPanel doMakeInnerPanel() {
225        JRadioButton singleBtn = new JRadioButton("Single", true);
226        JRadioButton multipleBtn = new JRadioButton("Multiple", false);
227        singleBtn.addActionListener(new ActionListener() {
228            public void actionPerformed(ActionEvent e) {
229                showBox = true;
230                switchFields();
231            }
232        });
233        multipleBtn.addActionListener(new ActionListener() {
234            public void actionPerformed(ActionEvent e) {
235                showBox = false;
236                switchFields();
237            }
238        });
239        GuiUtils.buttonGroup(singleBtn, multipleBtn);
240        JPanel radioPanel = GuiUtils.hbox(singleBtn, multipleBtn);
241        
242        prefList = getPreferenceList(PREF_URLLIST);
243        box = prefList.createComboBox(CMD_LOAD, this);
244        boxEditor = (JTextField)box.getEditor().getEditorComponent();
245        boxEditor.addKeyListener(new KeyListener() {
246            public void keyPressed(KeyEvent e) {}
247            public void keyReleased(KeyEvent e) {
248                updateStatus();
249            }
250            public void keyTyped(KeyEvent e) {}
251        });
252        
253        textArea = new JTextArea(5, 30);
254        textScroller = new JScrollPane(textArea);
255        textArea.addKeyListener(new KeyListener() {
256            public void keyPressed(KeyEvent e) {}
257            public void keyReleased(KeyEvent e) {
258                updateStatus();
259            }
260            public void keyTyped(KeyEvent e) {}
261        });
262        
263        urlPanel = GuiUtils.top(box);
264        textPanel = GuiUtils.top(textScroller);
265        
266        cardLayoutPanel = new GuiUtils.CardLayoutPanel();
267        cardLayoutPanel.addCard(urlPanel);
268        cardLayoutPanel.addCard(textPanel);
269        
270        JPanel showPanel = McVGuiUtils.topBottom(radioPanel, cardLayoutPanel, null);
271        
272        setHaveData(false);
273        updateStatus();
274        return McVGuiUtils.makeLabeledComponent("URL:", showPanel);
275    }
276
277    private JLabel statusLabel = new JLabel("Status");
278
279    @Override
280    public void setStatus(String statusString, String foo) {
281        if (statusString == null)
282            statusString = "";
283        statusLabel.setText(statusString);
284    }
285        
286    /**
287     * Create a more McIDAS-V-like GUI layout
288     */
289    protected JComponent doMakeContents() {
290        JComponent typeComponent = getDataSourcesComponent();
291        if (typeComponent==null) typeComponent=new JLabel("No data type specified");
292
293        JPanel innerPanel = doMakeInnerPanel();
294        
295        // Start building the whole thing here
296        JPanel outerPanel = new JPanel();
297
298        JLabel typeLabel = McVGuiUtils.makeLabelRight("Data Type:");
299                
300        JLabel statusLabelLabel = McVGuiUtils.makeLabelRight("");
301        
302        statusLabel.setText("Status");
303        McVGuiUtils.setLabelPosition(statusLabel, Position.RIGHT);
304        McVGuiUtils.setComponentColor(statusLabel, TextColor.STATUS);
305        
306        JButton helpButton = McVGuiUtils.makeImageButton(ICON_HELP, "Show help");
307        helpButton.setActionCommand(GuiUtils.CMD_HELP);
308        helpButton.addActionListener(this);
309        
310        JButton refreshButton = McVGuiUtils.makeImageButton(ICON_REFRESH, "Refresh");
311        refreshButton.setActionCommand(GuiUtils.CMD_UPDATE);
312        refreshButton.addActionListener(this);
313        
314        McVGuiUtils.setComponentWidth(loadButton, Width.DOUBLE);
315
316        GroupLayout layout = new GroupLayout(outerPanel);
317        outerPanel.setLayout(layout);
318        layout.setHorizontalGroup(
319            layout.createParallelGroup(LEADING)
320            .addGroup(TRAILING, layout.createSequentialGroup()
321                .addGroup(layout.createParallelGroup(TRAILING)
322                    .addGroup(layout.createSequentialGroup()
323                        .addContainerGap()
324                        .addComponent(helpButton)
325                        .addGap(GAP_RELATED)
326                        .addComponent(refreshButton)
327                        .addPreferredGap(RELATED)
328                        .addComponent(loadButton))
329                        .addGroup(LEADING, layout.createSequentialGroup()
330                        .addContainerGap()
331                        .addGroup(layout.createParallelGroup(LEADING)
332                            .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
333                            .addGroup(layout.createSequentialGroup()
334                                .addComponent(typeLabel)
335                                .addGap(GAP_RELATED)
336                                .addComponent(typeComponent))
337                            .addGroup(layout.createSequentialGroup()
338                                .addComponent(statusLabelLabel)
339                                .addGap(GAP_RELATED)
340                                .addComponent(statusLabel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)))))
341                .addContainerGap())
342        );
343        layout.setVerticalGroup(
344            layout.createParallelGroup(LEADING)
345            .addGroup(layout.createSequentialGroup()
346                .addContainerGap()
347                .addGroup(layout.createParallelGroup(BASELINE)
348                    .addComponent(typeLabel)
349                    .addComponent(typeComponent))
350                .addPreferredGap(UNRELATED)
351                .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
352                .addPreferredGap(UNRELATED)
353                .addGroup(layout.createParallelGroup(BASELINE)
354                    .addComponent(statusLabelLabel)
355                    .addComponent(statusLabel))
356                .addPreferredGap(UNRELATED)
357                .addGroup(layout.createParallelGroup(BASELINE)
358                    .addComponent(loadButton)
359                    .addComponent(refreshButton)
360                    .addComponent(helpButton))
361                .addContainerGap())
362        );
363    
364        return outerPanel;
365
366    }
367
368}
369