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