001/*
002 * $Id: XmlChooser.java,v 1.10 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.Component;
041import java.util.ArrayList;
042import java.util.List;
043
044import javax.swing.GroupLayout;
045import javax.swing.JButton;
046import javax.swing.JComboBox;
047import javax.swing.JComponent;
048import javax.swing.JLabel;
049import javax.swing.JPanel;
050
051import org.w3c.dom.Document;
052import org.w3c.dom.Element;
053
054import ucar.unidata.idv.chooser.IdvChooserManager;
055import ucar.unidata.idv.chooser.XmlHandler;
056import ucar.unidata.util.CatalogUtil;
057import ucar.unidata.util.GuiUtils;
058import ucar.unidata.util.WmsUtil;
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
066/**
067 * This handles a variety of flavors of xml documents (e.g., thredds
068 * query capability, thredds catalogs, idv menus) to create data
069 * choosers from. It provides a combobox to enter urls to xml
070 * documents. It retrieves the xml and creates a {@link XmlHandler}
071 * based on the type of xml. Currently this class handles two
072 * types of xml: Thredds catalog and Web Map Server (WMS)
073 * capability documents. The XmlHandler does most of the work.
074 * <p>
075 * This class maintains the different xml docs the user has gone
076 * to coupled with the XmlHandler for each doc. It uses this list
077 * to support navigating back and forth through the history of
078 * documents.
079 *
080 * @author IDV development team
081 * @version $Revision: 1.10 $Date: 2011/03/24 16:06:31 $
082 */
083
084
085public class XmlChooser extends ucar.unidata.idv.chooser.XmlChooser implements Constants {
086    
087    /** Catalog browser panel */
088    JPanel catalogPanel;
089    
090    /** Catalog browser panel label history */
091    int labelHistoryIdx = -1;
092    List labelHistory = new ArrayList();
093    
094    /**
095     * Create the <code>XmlChooser</code>
096     *
097     * @param mgr The <code>IdvChooserManager</code>
098     * @param root  The xml root that defines this chooser
099     *
100     */
101    public XmlChooser(IdvChooserManager mgr, Element root) {
102        super(mgr, root);
103        
104        loadButton = McVGuiUtils.makeImageTextButton(ICON_ACCEPT_SMALL, getLoadCommandName());
105        loadButton.setActionCommand(getLoadCommandName());
106        loadButton.addActionListener(this);
107
108    }
109    
110    private void repaintCatalog() {
111        if (catalogPanel != null) {
112            catalogPanel.invalidate();
113            catalogPanel.validate();
114            catalogPanel.repaint();
115        }
116        String labelName = (String)labelHistory.get(labelHistoryIdx);
117        catalogPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(labelName));
118    }
119    
120    /**
121     *  Go back and display  the previous  document.
122     */
123    public void goBack() {
124        super.goBack();
125        labelHistoryIdx--;
126        repaintCatalog();
127    }
128
129    /**
130     *  Go forward and display  the next   document in the history list.
131     */
132    public void goForward() {
133        super.goForward();
134        labelHistoryIdx++;
135        repaintCatalog();
136    }
137    
138    /**
139     * Add a labeled border to the catalog browser indicating the data type
140     */
141    protected void makeUi(Document doc, Element xmlRoot, String path) {
142        super.makeUi(doc, xmlRoot, path);
143
144        String tagName = xmlRoot.getTagName();
145        String labelName = "Unknown Catalog Type";
146        if (tagName.equals(WmsUtil.TAG_WMS1) || tagName.equals(WmsUtil.TAG_WMS2)) labelName = "Web Map Service";
147        else if (tagName.equals(CatalogUtil.TAG_CATALOG)) labelName = "THREDDS";
148        else if (tagName.equals("menus")) labelName = "Menu";
149        
150        labelHistoryIdx++;
151        labelHistory.add(labelHistoryIdx, labelName);
152        repaintCatalog();
153    }
154        
155    private JLabel statusLabel = new JLabel("Status");
156
157    @Override
158    public void setStatus(String statusString, String foo) {
159        if (statusString == null)
160            statusString = "";
161        statusLabel.setText(statusString);
162    }
163
164    /**
165     *  Create and return the Gui contents.
166     *
167     *  @return The gui contents.
168     */
169    protected JComponent doMakeContents() {
170        JComponent parentContents = super.doMakeContents();
171        
172        // Pull apart the panels
173        // Expected:
174        // Top: URL chooser
175        // Center: Catalog chooser
176        // Bottom: chooser buttons
177        // This takes a bit of digging--some of the components are really buried!
178        Component[] parentComps = parentContents.getComponents();
179        if (parentComps.length != 3 ||
180                !(parentComps[0] instanceof JPanel) ||
181                !(parentComps[1] instanceof JPanel) ||
182                !(parentComps[2] instanceof JPanel)
183        ) return parentContents;
184        
185        // Assign file picker to fileComponent
186        JPanel topPanel = (JPanel)parentComps[0];
187        Component[] panels = topPanel.getComponents();
188        if (panels.length != 2 ||
189                !(panels[0] instanceof JPanel) ||
190                !(panels[1] instanceof JPanel)
191        ) return parentContents;
192        // Found the navigation panel
193        JPanel navigationPanel = (JPanel)panels[0];
194        panels = ((JPanel)panels[1]).getComponents();
195        if (panels.length != 3 ||
196                !(panels[0] instanceof JLabel) ||
197                !(panels[1] instanceof JPanel) ||
198                !(panels[2] instanceof JButton)
199        ) return parentContents;
200        // Found the button
201        JButton fileButton = (JButton)panels[2];
202        panels = ((JPanel)panels[1]).getComponents();
203        if (panels.length != 1 ||
204                !(panels[0] instanceof JComboBox)
205        ) return parentContents;
206        JComboBox fileComponent = (JComboBox)panels[0];
207        McVGuiUtils.setButtonImage(fileButton, ICON_OPEN_SMALL);
208        McVGuiUtils.setComponentWidth(fileButton, Width.DOUBLE);
209        McVGuiUtils.setComponentWidth(fileComponent, Width.DOUBLEDOUBLE);
210        McVGuiUtils.setComponentHeight(fileComponent, fileButton);
211
212        // Deal with the navigation buttons
213        panels = navigationPanel.getComponents();
214        if (panels.length != 2 ||
215                !(panels[0] instanceof JButton) ||
216                !(panels[1] instanceof JButton)
217        ) return parentContents;
218        McVGuiUtils.setButtonImage((JButton)panels[0], Constants.ICON_PREVIOUS_SMALL);
219        McVGuiUtils.setButtonImage((JButton)panels[1], Constants.ICON_NEXT_SMALL);
220        JLabel navigationLabel = McVGuiUtils.makeLabelRight("History:");
221        navigationPanel = GuiUtils.hbox(panels[0], panels[1]);
222        
223        // Rearrange the catalog browser and assign it to innerPanel
224        catalogPanel = (JPanel)parentComps[1];
225        JPanel innerPanel = McVGuiUtils.makeLabeledComponent("Browse:", catalogPanel);
226
227        // Start building the whole thing here
228        JPanel outerPanel = new JPanel();
229
230        JLabel fileLabel = McVGuiUtils.makeLabelRight("Catalog:");
231
232        JLabel statusLabelLabel = McVGuiUtils.makeLabelRight("");
233
234        McVGuiUtils.setLabelPosition(statusLabel, Position.RIGHT);
235        McVGuiUtils.setComponentColor(statusLabel, TextColor.STATUS);
236
237        JButton helpButton = McVGuiUtils.makeImageButton(ICON_HELP, "Show help");
238        helpButton.setActionCommand(GuiUtils.CMD_HELP);
239        helpButton.addActionListener(this);
240
241        JButton refreshButton = McVGuiUtils.makeImageButton(ICON_REFRESH, "Refresh");
242        refreshButton.setActionCommand(GuiUtils.CMD_UPDATE);
243        refreshButton.addActionListener(this);
244
245        McVGuiUtils.setButtonImage(loadButton, ICON_ACCEPT_SMALL);
246        McVGuiUtils.setComponentWidth(loadButton, Width.DOUBLE);
247
248        GroupLayout layout = new GroupLayout(outerPanel);
249        outerPanel.setLayout(layout);
250        layout.setHorizontalGroup(
251                layout.createParallelGroup(LEADING)
252                .addGroup(TRAILING, layout.createSequentialGroup()
253                        .addGroup(layout.createParallelGroup(TRAILING)
254                                .addGroup(layout.createSequentialGroup()
255                                        .addContainerGap()
256                                        .addComponent(helpButton)
257                                        .addGap(GAP_RELATED)
258                                        .addComponent(refreshButton)
259                                        .addPreferredGap(RELATED)
260                                        .addComponent(loadButton))
261                                        .addGroup(LEADING, layout.createSequentialGroup()
262                                                .addContainerGap()
263                                                .addGroup(layout.createParallelGroup(LEADING)
264                                                        .addGroup(layout.createSequentialGroup()
265                                                                .addComponent(navigationLabel)
266                                                                .addGap(GAP_RELATED)
267                                                                .addComponent(navigationPanel))
268                                                        .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
269                                                        .addGroup(layout.createSequentialGroup()
270                                                                .addComponent(fileLabel)
271                                                                .addGap(GAP_RELATED)
272                                                                .addComponent(fileComponent)
273                                                                .addGap(GAP_UNRELATED)
274                                                                .addComponent(fileButton))
275                                                                .addGroup(layout.createSequentialGroup()
276                                                                        .addComponent(statusLabelLabel)
277                                                                        .addGap(GAP_RELATED)
278                                                                        .addComponent(statusLabel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)))))
279                                                                        .addContainerGap())
280        );
281        layout.setVerticalGroup(
282                layout.createParallelGroup(LEADING)
283                .addGroup(layout.createSequentialGroup()
284                        .addContainerGap()
285                        .addGroup(layout.createParallelGroup(BASELINE)
286                                .addComponent(fileLabel)
287                                .addComponent(fileComponent)
288                                .addComponent(fileButton))
289                                .addPreferredGap(UNRELATED)
290                                                .addGroup(layout.createParallelGroup(BASELINE)
291                    .addComponent(navigationLabel)
292                    .addComponent(navigationPanel))
293                .addPreferredGap(RELATED)
294
295                                .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
296                                .addPreferredGap(UNRELATED)
297                                .addGroup(layout.createParallelGroup(BASELINE)
298                                        .addComponent(statusLabelLabel)
299                                        .addComponent(statusLabel))
300                                        .addPreferredGap(UNRELATED)
301                                        .addGroup(layout.createParallelGroup(BASELINE)
302                                                .addComponent(loadButton)
303                                                .addComponent(refreshButton)
304                                                .addComponent(helpButton))
305                                                .addContainerGap())
306        );
307
308        return outerPanel;
309
310    }
311
312}
313