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.ui; 030 031import java.util.List; 032 033import javax.swing.JComponent; 034 035import org.w3c.dom.Document; 036import org.w3c.dom.Element; 037 038import ucar.unidata.idv.IntegratedDataViewer; 039import ucar.unidata.idv.ui.IdvComponentHolder; 040import ucar.unidata.idv.ui.IdvUIManager; 041import ucar.unidata.idv.ui.IdvXmlUi; 042import ucar.unidata.idv.ViewManager; 043import ucar.unidata.util.WrapperException; 044import ucar.unidata.xml.XmlUtil; 045 046/** 047 * McIDAS-V needs its own ComponentHolder merely to associate ViewManagers with 048 * their parent ComponentHolders. This association is later used in 049 * McIDASVViewPanel to create a "hierarchical name" for each ViewManager. 050 * 051 * <p> 052 * Instead of having something like "Panel 1" appearing in the layer controls, 053 * we now have {@literal "ComponentHolder Name>Panel 1"}.</p> 054 * 055 * <p> 056 * Note: ComponentHolder names always double as tab names! McIDAS-V also 057 * intercepts ComponentHolder renaming and updates the layer controls instantly. 058 * </p> 059 */ 060public class McvComponentHolder extends IdvComponentHolder { 061 062 /** IDV friendly description of a dynamic XML skin. */ 063 public static final String CATEGORY_DESCRIPTION = "UI Skin"; 064 065 /** Used to distinguish a dynamic skin from other things. */ 066 public static final String TYPE_DYNAMIC_SKIN = "dynamicskin"; 067 068// private static Logger logger = LoggerFactory.getLogger(McvComponentHolder.class); 069 070// private Map<String, ViewManager> dynamicViewManagers = new HashMap<String, ViewManager>(); 071 072 /** Kept around to avoid annoying casting. */ 073 private UIManager uiManager; 074 075 private JComponent cached = null; 076 077 /** 078 * Default constructor for serialization. 079 */ 080 public McvComponentHolder() { 081 } 082 083 /** 084 * Fairly typical constructor. 085 * 086 * @param idv Reference to the main IDV object. 087 * @param obj object being held in this component holder. 088 */ 089 public McvComponentHolder(IntegratedDataViewer idv, Object obj) { 090 super(idv, obj); 091 uiManager = (UIManager)idv.getIdvUIManager(); 092 } 093 094 /** 095 * Overridden so that we can (one day) do the required extra work to write 096 * out the XML for this skin. 097 * 098 * @param doc Parent document we'll use for XML generation. 099 * 100 * @return XML representation of what is being held. 101 */ 102 @Override public Element createXmlNode(Document doc) { 103 if (!getType().equals(TYPE_DYNAMIC_SKIN)) { 104 return super.createXmlNode(doc); 105 } 106 107 // keep in mind that the IDV expects that we're holding a path 108 // to a skin... I don't think that this will work how you want it... 109 // TODO: investigate this! 110 Element node = doc.createElement(IdvUIManager.COMP_COMPONENT_SKIN); 111 node.setAttribute("url", getObject().toString()); 112 113 /* 114 * try { System.err.println(XmlUtil.toString((Element)getObject())); } 115 * catch (Exception e) { e.printStackTrace(); } 116 */ 117 118 return node; 119 } 120 121 /** 122 * Overridden so that McV can do the required extra work if this holder is 123 * holding a dynamic XML skin. 124 * 125 * @return Contents of this holder as a UI component. 126 */ 127 @Override public JComponent doMakeContents() { 128 JComponent contents; 129 if (!getType().equals(TYPE_DYNAMIC_SKIN)) { 130 contents = super.doMakeContents(); 131 } else { 132 contents = makeDynamicSkin(); 133 } 134// contents.addComponentListener(new ComponentListener() { 135// @Override public void componentHidden(ComponentEvent e) { 136// logger.trace("component hidden"); 137// GuiUtils.toggleHeavyWeightComponents(contents, false); 138// } 139// @Override public void componentShown(ComponentEvent e) { 140// logger.trace("component shown"); 141// GuiUtils.toggleHeavyWeightComponents(contents, false); 142// } 143// @Override public void componentMoved(ComponentEvent e) {} 144// @Override public void componentResized(ComponentEvent e) {} 145// }); 146 return contents; 147 } 148 149 /** 150 * Lets the IDV take care of the details, but does null out the local 151 * reference to the UIManager. 152 */ 153 @Override public void doRemove() { 154 super.doRemove(); 155 uiManager = null; 156 } 157 158 /** 159 * Overridden so that McV can return a more accurate category if this holder 160 * is holding a dynamic skin. 161 * 162 * @return Category name for the type of thing we're holding. 163 */ 164 @Override public String getCategory() { 165 if (!getType().equals(TYPE_DYNAMIC_SKIN)) { 166 return super.getCategory(); 167 } 168 return CATEGORY_DESCRIPTION; 169 } 170 171 /** 172 * Overridden so that McV can return a more accurate description if this 173 * holder is holding a dynamic skin. 174 * 175 * @return The description of what is being held. 176 */ 177 @Override public String getTypeName() { 178 if (!getType().equals(TYPE_DYNAMIC_SKIN)) { 179 return super.getTypeName(); 180 } 181 return CATEGORY_DESCRIPTION; 182 } 183 184 /** 185 * If the object being held in this component holder is a skin, calling this 186 * method will create a component based upon the skin. 187 * 188 * <p> 189 * Overridden so that McV can tell the UIManager to associate the skin's 190 * ViewManagers with this component holder. That association is used to 191 * build the hierarchical names in the ViewPanel. 192 * </p> 193 * 194 * @return The component represented by this holder's skin. 195 */ 196 @Override protected JComponent makeSkin() { 197 JComponent comp = super.makeSkin(); 198 199 // let's hope that *getViewManagers* only gives us a list of 200 // ViewManagers 201 @SuppressWarnings("unchecked") 202 List<ViewManager> vms = getViewManagers(); 203 if (vms != null) { 204 for (int i = 0; i < vms.size(); i++) { 205 uiManager.setViewManagerHolder(vms.get(i), this); 206 uiManager.getViewPanel().viewManagerChanged(vms.get(i)); 207 } 208 } 209 return comp; 210 } 211 212 /** 213 * Mostly used to ensure that the local reference to the UI manager is valid 214 * when deserializing. 215 * 216 * @param idv Main IDV reference! 217 */ 218 @Override 219 public void setIdv(IntegratedDataViewer idv) { 220 super.setIdv(idv); 221 uiManager = (UIManager)idv.getIdvUIManager(); 222 } 223 224 /** 225 * Set the name of this component holder to the contents of {@code value}. 226 * 227 * <p> 228 * Overridden so that McV can tell the ViewPanel to update upon a name 229 * change. 230 * </p> 231 * 232 * @param value New name of this component holder. 233 */ 234 @Override public void setName(String value) { 235 super.setName(value); 236 237 // let's hope that *getViewManagers* only gives us a list of 238 // ViewManagers 239 @SuppressWarnings("unchecked") 240 List<ViewManager> vms = getViewManagers(); 241 if (vms != null) { 242 for (ViewManager vm : vms) { 243 uiManager.getViewPanel().viewManagerChanged(vm); 244 } 245 } 246 } 247 248 /** 249 * Build the UI component using the XML skin contained by this holder. 250 * 251 * @return UI Component specified by the skin contained in this holder. 252 */ 253 public JComponent makeDynamicSkin() { 254 if (cached != null) { 255 return cached; 256 } 257 try { 258 Element root = XmlUtil.getRoot((String) getObject()); 259 260 IdvXmlUi ui = uiManager.doMakeIdvXmlUi(null, getViewManagers(), 261 root); 262 263 // look for any "embedded" ViewManagers. 264 Element startNode = XmlUtil.findElement(root, null, "embeddednode", 265 "true"); 266 if (startNode != null) { 267 ui.setStartNode(startNode); 268 } 269 270 JComponent contents = (JComponent)ui.getContents(); 271 setViewManagers(ui.getViewManagers()); 272 273 cached = contents; 274 return contents; 275 } catch (Exception e) { 276 throw new WrapperException(e); 277 } 278 } 279 280 /** 281 * Tell this component holder's component group that the tab corresponding 282 * to this holder should become the active tab. 283 */ 284 public void setAsActiveTab() { 285 McvComponentGroup parent = (McvComponentGroup)getParent(); 286 if (parent != null) { 287 parent.setActiveComponentHolder(this); 288 } 289 } 290}