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