001: /*
002: * Copyright Javelin Software, All rights reserved.
003: */
004:
005: package com.javelin.swinglets;
006:
007: import java.util.*;
008: import java.awt.*;
009: import java.awt.event.*;
010:
011: import com.javelin.swinglets.plaf.*;
012:
013: /**
014: * SComponent is the container component in the SDOM.
015: *
016: * @author Robin Sharp
017: */
018:
019: public abstract class SContainer extends SComponent {
020: /**
021: * Constructs a new SContainer.
022: */
023: public SContainer() {
024: }
025:
026: /**
027: * Returns the name of the L&F class that renders this component.
028: */
029: public Class getUIClass() {
030: return SContainer.class;
031: }
032:
033: /**
034: * Set the Look and Feel, and update the UI.
035: */
036: public SComponent setLookAndFeel(SLookAndFeel lookAndFeel) {
037: super .setLookAndFeel(lookAndFeel);
038:
039: //Update the LayoutManager.
040: if (layoutManager != null) {
041: layoutManager.setLookAndFeel(getLookAndFeel());
042: }
043:
044: //Updte all the child components.
045: for (int index = 0; index < components.size(); index++) {
046: ((SComponent) components.elementAt(index))
047: .setLookAndFeel(lookAndFeel);
048: }
049:
050: return this ;
051: }
052:
053: /**
054: * Get the SLayoutManager.
055: */
056: public SLayoutManager getLayoutManager() {
057: return layoutManager;
058: }
059:
060: /**
061: * Set the SLayoutManager.
062: */
063: public SContainer setLayoutManager(SLayoutManager layoutManager) {
064: if (this .layoutManager == layoutManager)
065: return this ;
066:
067: if (layoutManager != null) {
068: layoutManager.setLookAndFeel(getLookAndFeel());
069: }
070:
071: firePropertyChange("layoutManager", this .layoutManager,
072: this .layoutManager = layoutManager);
073:
074: return this ;
075: }
076:
077: /**
078: * Validate. This will invalidate the LayoutManager if one exists.
079: */
080: public void validate() {
081: if (layoutManager != null && !valid) {
082: layoutManager.invalidateLayout(this );
083: valid = true;
084: }
085: }
086:
087: /**
088: * Returns whether the first component is enabled,
089: */
090: public boolean isEnabled() {
091: if (components.size() > 0) {
092: return ((SRadioButton) components.elementAt(0)).isEnabled();
093: }
094:
095: return false;
096: }
097:
098: /**
099: * Sets the enabled property on all the components.
100: */
101: public SComponent setEnabled(boolean enabled) {
102: for (int index = 0; index < components.size(); index++) {
103: getComponent(index).setEnabled(enabled);
104: }
105: super .setEnabled(enabled);
106: return this ;
107: }
108:
109: /**
110: * Gets the number of components in this panel.
111: */
112: public int getComponentCount() {
113: return components.size();
114: }
115:
116: /**
117: * Get a sub component by name. This will descend the component
118: * hierarchy and return the SComponent, or null.
119: */
120: public SComponent getComponent(String name) {
121: if (getName().equals(name))
122: return this ;
123:
124: SComponent component = null;
125: for (int index = 0; index < components.size(); index++) {
126: if ((component = getComponent(index).getComponent(name)) != null) {
127: return component;
128: }
129: }
130:
131: return null;
132: }
133:
134: /**
135: * Gets the nth component in this container.
136: */
137: public SComponent getComponent(int index) {
138: return (SComponent) components.elementAt(index);
139: }
140:
141: /**
142: * Gets the index of this component, or -1
143: */
144: public int getComponentIndex(SComponent c) {
145: return components.indexOf(c);
146: }
147:
148: /**
149: * Gets all the components in this container.
150: */
151: public SComponent[] getComponents() {
152: SComponent[] array = new SComponent[components.size()];
153: for (int index = 0; index < components.size(); index++) {
154: array[index] = getComponent(index);
155: }
156: return array;
157: }
158:
159: /**
160: * Recursively gets all child components, including those in sub-containers.
161: */
162: public Enumeration getAllComponents() {
163: Vector v = new Vector();
164: addChildren(this , v);
165: return v.elements();
166: }
167:
168: /**
169: * Step through child containers, adding their components to v.
170: */
171: protected void addChildren(SContainer container, Vector v) {
172: SComponent[] array = container.getComponents();
173: for (int count = 0; count < array.length; count++) {
174: SComponent comp = array[count];
175: v.addElement(comp);
176: Class super class = comp.getClass().getSuperclass();
177: while (super class != null) // step upwards through all superclasses, in case SContainer isn't the immediate ancestor.
178: {
179: if (super class.equals(SContainer.class)) {
180: addChildren((SContainer) comp, v);
181: break;
182: }
183: super class = super class.getSuperclass();
184: }
185: }
186: }
187:
188: /**
189: * Adds the specified component to the end of this container.
190: */
191: public SContainer add(SComponent component) {
192: valid = false;
193:
194: component.setLookAndFeel(getLookAndFeel());
195: component.setParent(this );
196:
197: components.addElement(component);
198:
199: component.addNotify();
200:
201: ((SComponentUI) getUI()).update(component,
202: SContainerUI.COMPONENT_ADDED, -1);
203:
204: return this ;
205: }
206:
207: /**
208: * Adds the specified component to this container at the given
209: * position.
210: */
211: public SContainer add(SComponent component, int index) {
212: valid = false;
213:
214: component.setLookAndFeel(getLookAndFeel());
215: component.setParent(this );
216:
217: if (index >= components.size()) {
218: components.addElement(component);
219: } else {
220: components.insertElementAt(component, index);
221: }
222:
223: component.addNotify();
224:
225: ((SContainerUI) getUI()).update(component,
226: SContainerUI.COMPONENT_ADDED, index);
227:
228: return this ;
229: }
230:
231: /**
232: * Adds the specified with constraints to the layout manager.
233: */
234: public SContainer add(SComponent component, Object constraint) {
235: if (layoutManager == null) {
236: throw new IllegalStateException(
237: "Cannot add a component with no LayoutManager.");
238: }
239:
240: //Add the component to the list
241: components.addElement(component);
242:
243: //Bind the component to the constraint
244: layoutManager.addComponent(component, constraint);
245:
246: component.addNotify();
247:
248: ((SContainerUI) getUI()).update(component,
249: SContainerUI.COMPONENT_ADDED, constraint);
250:
251: return this ;
252: }
253:
254: /**
255: * Removes the component, specified by index from this container.
256: */
257: public void remove(int index) {
258: valid = false;
259:
260: ((SContainerUI) getUI()).update(null,
261: SContainerUI.COMPONENT_ADDED, index);
262:
263: if (layoutManager != null) {
264: layoutManager.removeComponent(getComponent(index));
265: }
266:
267: getComponent(index).removeNotify();
268: getComponent(index).setParent(null);
269: components.removeElementAt(index);
270:
271: }
272:
273: /**
274: * Removes the specified component from this container.
275: */
276: public void remove(SComponent component) {
277: valid = false;
278:
279: ((SContainerUI) getUI()).update(component,
280: SContainerUI.COMPONENT_REMOVED, -1);
281:
282: if (layoutManager != null) {
283: layoutManager.removeComponent(component);
284: }
285:
286: component.removeNotify();
287: component.setParent(null);
288: components.removeElement(component);
289: }
290:
291: /**
292: * Removes all the components from this container.
293: */
294: public void removeAll() {
295: valid = false;
296:
297: for (int index = 0; index < components.size(); index++) {
298: getComponent(index).removeNotify();
299: getComponent(index).setParent(null);
300: }
301:
302: components.removeAllElements();
303: }
304:
305: /**
306: * Notifies the container to create a JFC peer. It will also
307: * notify the components contained in this container.
308: */
309: public void addNotify() {
310: for (int index = 0; index < components.size(); index++) {
311: getComponent(index).addNotify();
312: }
313: super .addNotify();
314: }
315:
316: /**
317: * Notifies this container to remove a JFC perr, and all of its subcomponents
318: * to remove their peers.
319: */
320: public void removeNotify() {
321: for (int index = 0; index < components.size(); index++) {
322: getComponent(index).removeNotify();
323: }
324:
325: super .removeNotify();
326: }
327:
328: // DISPATCH & EVENTS //////////////////////////////////////////////////////
329:
330: /**
331: * Adds the specified container listener to receive container events
332: * from this container.
333: */
334: public SContainer addContainerListener(ContainerListener listener) {
335: getUI().addListener(listener);
336: return this ;
337: }
338:
339: /**
340: * Removes the specified container listener so it no longer receives
341: * container events from this container.
342: */
343: public SContainer removeContainerListener(ContainerListener listener) {
344: getUI().removeListener(listener);
345: return this ;
346: }
347:
348: // PAINTING /////////////////////////////////////////////////////////
349:
350: /**
351: * Paint this container by using the LayoutManager.
352: */
353: public void paint(Object out) {
354: if (layoutManager != null) {
355: validate();
356: }
357:
358: paintHeader(out);
359:
360: paintComponentHeader(out);
361: paintComponent(out);
362: paintComponentFooter(out);
363: }
364:
365: // PRIVATE //////////////////////////////////////////////////////////
366:
367: protected Vector components = new Vector();
368: protected SComponent parent;
369: protected SLayoutManager layoutManager; // = new SFlowLayout();
370:
371: protected boolean valid; //Is the layout valid
372:
373: }
|