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