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