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.ui;
030
031 import java.util.List;
032
033 import javax.swing.JComponent;
034
035 import org.w3c.dom.Document;
036 import org.w3c.dom.Element;
037
038 import ucar.unidata.idv.IntegratedDataViewer;
039 import ucar.unidata.idv.ui.IdvComponentHolder;
040 import ucar.unidata.idv.ui.IdvUIManager;
041 import ucar.unidata.idv.ui.IdvXmlUi;
042 import ucar.unidata.idv.ViewManager;
043 import ucar.unidata.util.WrapperException;
044 import ucar.unidata.xml.XmlUtil;
045
046 /**
047 * <p>
048 * McIDAS-V needs its own ComponentHolder merely to associate ViewManagers with
049 * their parent ComponentHolders. This association is later used in
050 * McIDASVViewPanel to create a "hierarchical name" for each ViewManager.
051 * </p>
052 *
053 * <p>
054 * Instead of having something like "Panel 1" appearing in the layer controls,
055 * we now have "ComponentHolder Name>Panel 1". Note: ComponentHolder names
056 * always double as tab names! McV also intercepts ComponentHolder renaming and
057 * updates the layer controls instantly.
058 * </p>
059 */
060 public 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 * <p>
186 * If the object being held in this component holder is a skin, calling this
187 * method will create a component based upon the skin.
188 * </p>
189 *
190 * <p>
191 * Overridden so that McV can tell the UIManager to associate the skin's
192 * ViewManagers with this component holder. That association is used to
193 * build the hierarchical names in the ViewPanel.
194 * </p>
195 *
196 * @return The component represented by this holder's skin.
197 */
198 @Override protected JComponent makeSkin() {
199 JComponent comp = super.makeSkin();
200
201 // let's hope that *getViewManagers* only gives us a list of
202 // ViewManagers
203 @SuppressWarnings("unchecked")
204 List<ViewManager> vms = getViewManagers();
205 if (vms != null) {
206 for (int i = 0; i < vms.size(); i++) {
207 uiManager.setViewManagerHolder(vms.get(i), this);
208 uiManager.getViewPanel().viewManagerChanged(vms.get(i));
209 }
210 }
211 return comp;
212 }
213
214 /**
215 * Mostly used to ensure that the local reference to the UI manager is valid
216 * when deserializing.
217 *
218 * @param idv Main IDV reference!
219 */
220 @Override
221 public void setIdv(IntegratedDataViewer idv) {
222 super.setIdv(idv);
223 uiManager = (UIManager)idv.getIdvUIManager();
224 }
225
226 /**
227 * <p>
228 * Merely sets the name of this component holder to the contents of
229 * <tt>value</tt>.
230 * </p>
231 *
232 * <p>
233 * Overridden so that McV can tell the ViewPanel to update upon a name
234 * change.
235 * </p>
236 *
237 * @param value New name of this component holder.
238 */
239 @Override public void setName(String value) {
240 super.setName(value);
241
242 // let's hope that *getViewManagers* only gives us a list of
243 // ViewManagers
244 @SuppressWarnings("unchecked")
245 List<ViewManager> vms = getViewManagers();
246 if (vms != null) {
247 for (int i = 0; i < vms.size(); i++) {
248 uiManager.getViewPanel().viewManagerChanged(vms.get(i));
249 }
250 }
251 }
252
253 /**
254 * Build the UI component using the XML skin contained by this holder.
255 *
256 * @return UI Component specified by the skin contained in this holder.
257 */
258 public JComponent makeDynamicSkin() {
259 if (cached != null)
260 return cached;
261
262 try {
263 Element root = XmlUtil.getRoot((String) getObject());
264
265 IdvXmlUi ui = uiManager.doMakeIdvXmlUi(null, getViewManagers(),
266 root);
267
268 // look for any "embedded" ViewManagers.
269 Element startNode = XmlUtil.findElement(root, null, "embeddednode",
270 "true");
271 if (startNode != null) {
272 ui.setStartNode(startNode);
273 }
274
275 JComponent contents = (JComponent)ui.getContents();
276 setViewManagers(ui.getViewManagers());
277
278 cached = contents;
279 return contents;
280
281 } catch (Exception e) {
282 throw new WrapperException(e);
283 }
284 }
285
286 /**
287 * <p>
288 * Tell this component holder's component group that the tab corresponding
289 * to this holder should become the active tab.
290 * </p>
291 */
292 public void setAsActiveTab() {
293 McvComponentGroup parent = (McvComponentGroup)getParent();
294 if (parent != null) {
295 parent.setActiveComponentHolder(this);
296 }
297 }
298 }