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