001: /*
002: * Copyright (c) 2004 JETA Software, Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without modification,
005: * are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JETA Software nor the names of its contributors may
015: * be used to endorse or promote products derived from this software without
016: * specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
021: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
022: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
023: * INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
024: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
025: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026: * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package com.jeta.open.support;
031:
032: import java.awt.Component;
033: import java.awt.Container;
034: import java.awt.event.ContainerEvent;
035: import java.awt.event.ContainerListener;
036: import java.lang.ref.WeakReference;
037: import java.util.Collection;
038: import java.util.HashMap;
039: import java.util.Iterator;
040: import java.util.LinkedList;
041: import java.util.Set;
042:
043: import javax.swing.JMenu;
044:
045: /**
046: * Interface used to define a service for locating child components within a
047: * container that have a given name. Specialized implementations of this
048: * interface are responsible for managing the parent container assocation.
049: *
050: * @author Jeff Tassin
051: */
052: public class DefaultComponentFinder implements ComponentFinder,
053: ContainerListener {
054: /**
055: * A map of component name to Component m_components<String,WeakReference(Component)>
056: */
057: private HashMap m_components;
058:
059: /**
060: * The parent container that we search.
061: */
062: private WeakReference m_container_ref;
063:
064: /**
065: * ctor
066: */
067: public DefaultComponentFinder(Container parent) {
068: m_container_ref = new WeakReference(parent);
069: }
070:
071: /**
072: * Recursively searches all Components owned by this container. If the
073: * Component has a name, we store it in the m_components hash table
074: *
075: * @param container
076: * the container to search
077: */
078: protected void buildNames(Container container) {
079: if (container != null) {
080: if (container instanceof JMenu) {
081: buildNames(((JMenu) container).getPopupMenu());
082: } else {
083: registerComponent(container);
084:
085: container.removeContainerListener(this );
086: container.addContainerListener(this );
087:
088: int count = container.getComponentCount();
089:
090: for (int index = 0; index < count; index++) {
091: Component comp = container.getComponent(index);
092:
093: if (comp instanceof Container)
094: buildNames((Container) comp);
095: else {
096: registerComponent(comp);
097: }
098: }
099: }
100: } else {
101: assert (false);
102: }
103: }
104:
105: /**
106: * A component was added to the container
107: */
108: public void componentAdded(ContainerEvent e) {
109: /**
110: * ignore table cell renderers because the JTable creates/destroys these
111: * objects quite often
112: */
113: Object child = e.getChild();
114: if (child instanceof javax.swing.table.TableCellRenderer
115: || child instanceof javax.swing.ListCellRenderer) {
116: return;
117: }
118:
119: if (child instanceof Container) {
120: buildNames((Container) child);
121: } else if (child instanceof Component) {
122: registerComponent((Component) child);
123: }
124: }
125:
126: /**
127: * A component was remove from the container
128: */
129: public void componentRemoved(ContainerEvent e) {
130: /**
131: * ignore table cell renderers because the JTable creates/destroys these
132: * objects quite often
133: */
134: Object child = e.getChild();
135: if (child instanceof javax.swing.table.TableCellRenderer
136: || child instanceof javax.swing.ListCellRenderer) {
137: return;
138: }
139:
140: // System.out.println( "DefaultComponentFinder.componentRemoved..." );
141: if (child instanceof Component)
142: unregisterComponent((Component) child);
143: }
144:
145: /**
146: * Enables/Disables the menu/toolbar button associated with the commandid
147: *
148: * @param commandId
149: * the id of the command whose button to enable/disable
150: * @param bEnable
151: * true/false to enable/disable
152: */
153: public void enableComponent(String commandId, boolean bEnable) {
154: Component comp = getComponentByName(commandId);
155: if (comp != null) {
156: comp.setEnabled(bEnable);
157: }
158: }
159:
160: /*
161: * This method looks at all components owned by a container. It will
162: * recursively search into child containers as well. @param componentName
163: * the name of the component to search for @return the named component
164: */
165: public Component getComponentByName(String componentName) {
166: if (m_components == null) {
167: m_components = new HashMap();
168: buildNames((Container) m_container_ref.get());
169: }
170:
171: WeakReference wref = (WeakReference) m_components
172: .get(componentName);
173: if (wref != null)
174: return (Component) wref.get();
175: else
176: return null;
177: }
178:
179: /**
180: * Recursively searches an associated parent container for all components
181: * with the given name. An empty collection is returned if no components are
182: * found with the given name.
183: */
184: public Collection getComponentsByName(String compName) {
185: Component comp = getComponentByName(compName);
186: if (comp == null)
187: return EmptyCollection.getInstance();
188: else {
189: LinkedList list = new LinkedList();
190: list.add(comp);
191: return list;
192: }
193: }
194:
195: /**
196: * Returns the container associated with this component finder.
197: *
198: * @return the container associated with this component finder.
199: */
200: public Container getContainer() {
201: return (Container) m_container_ref.get();
202: }
203:
204: private void registerComponent(Component comp) {
205: if (comp == null)
206: return;
207:
208: String name = comp.getName();
209: if (name != null && name.length() > 0) {
210: m_components.put(name, new WeakReference(comp));
211: }
212: }
213:
214: /**
215: * Tells the implementation that any cached components should be flushed and
216: * reloaded because the parent container might have changed.
217: */
218: public void unregisterComponent(Component c) {
219: if (c instanceof Container)
220: ((Container) c).removeContainerListener(this );
221:
222: Iterator iter = m_components.values().iterator();
223: while (iter.hasNext()) {
224: WeakReference wref = (WeakReference) iter.next();
225: if (wref == null || wref.get() == c)
226: iter.remove();
227: }
228: }
229:
230: /**
231: * Shows/Hides the menu/toolbar button associated with the commandid
232: *
233: * @param commandId
234: * the id of the command whose button to enable/disable
235: * @param bVisible
236: * show/hide the component/disable
237: */
238: public void setVisible(String commandId, boolean bVisible) {
239: Component comp = getComponentByName(commandId);
240: if (comp != null) {
241: comp.setVisible(bVisible);
242: }
243: }
244:
245: /**
246: * Tells the implementation that any cached components should be flushed and
247: * reloaded because the parent container might have changed.
248: */
249: public void reset() {
250: m_components = null;
251: }
252:
253: /**
254: * Recursively searches an associated parent container for all components
255: * that are named. An empty collection is returned if no names components
256: * exist.
257: *
258: * @return a collection of all named Component objects.
259: */
260: public Collection getAllNamedComponents() {
261: if (m_components == null) {
262: m_components = new HashMap();
263: buildNames((Container) m_container_ref.get());
264: }
265:
266: LinkedList components = new LinkedList();
267:
268: Iterator names = m_components.keySet().iterator();
269: while (names.hasNext()) {
270: String name = (String) names.next();
271: WeakReference wref = (WeakReference) m_components.get(name);
272: if (wref != null)
273: components.addLast((Component) wref.get());
274: }
275:
276: return components;
277: }
278: }
|