001 /*
002 * $Id: XmlChooser.java,v 1.11 2012/02/19 17:35:36 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.Component;
041 import java.util.ArrayList;
042 import java.util.List;
043
044 import javax.swing.GroupLayout;
045 import javax.swing.JButton;
046 import javax.swing.JComboBox;
047 import javax.swing.JComponent;
048 import javax.swing.JLabel;
049 import javax.swing.JPanel;
050
051 import org.w3c.dom.Document;
052 import org.w3c.dom.Element;
053
054 import ucar.unidata.idv.chooser.IdvChooserManager;
055 import ucar.unidata.idv.chooser.XmlHandler;
056 import ucar.unidata.util.CatalogUtil;
057 import ucar.unidata.util.GuiUtils;
058 import ucar.unidata.util.WmsUtil;
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 /**
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.11 $Date: 2012/02/19 17:35:36 $
082 */
083
084
085 public 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