001    /*
002     * $Id: UrlChooser.java,v 1.10 2012/02/19 17:35:37 davep Exp $
003     *
004     * This file is part of McIDAS-V
005     *
006     * Copyright 2007-2012
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    
031    package edu.wisc.ssec.mcidasv.chooser;
032    
033    import static javax.swing.GroupLayout.DEFAULT_SIZE;
034    import static javax.swing.GroupLayout.Alignment.BASELINE;
035    import static javax.swing.GroupLayout.Alignment.LEADING;
036    import static javax.swing.GroupLayout.Alignment.TRAILING;
037    import static javax.swing.LayoutStyle.ComponentPlacement.RELATED;
038    import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED;
039    
040    import java.awt.event.ActionEvent;
041    import java.awt.event.ActionListener;
042    import java.awt.event.KeyEvent;
043    import java.awt.event.KeyListener;
044    import java.util.Hashtable;
045    import java.util.List;
046    
047    import javax.swing.GroupLayout;
048    import javax.swing.JButton;
049    import javax.swing.JComboBox;
050    import javax.swing.JComponent;
051    import javax.swing.JLabel;
052    import javax.swing.JPanel;
053    import javax.swing.JRadioButton;
054    import javax.swing.JScrollPane;
055    import javax.swing.JTextArea;
056    import javax.swing.JTextField;
057    
058    import org.w3c.dom.Element;
059    
060    import edu.wisc.ssec.mcidasv.Constants;
061    import edu.wisc.ssec.mcidasv.util.McVGuiUtils;
062    import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Position;
063    import edu.wisc.ssec.mcidasv.util.McVGuiUtils.TextColor;
064    import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Width;
065    
066    import ucar.unidata.data.DataManager;
067    import ucar.unidata.idv.IntegratedDataViewer;
068    import ucar.unidata.idv.chooser.IdvChooserManager;
069    import ucar.unidata.util.GuiUtils;
070    import ucar.unidata.util.PreferenceList;
071    import 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.10 $Date: 2012/02/19 17:35:37 $
078     */
079    
080    
081    public 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