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