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