001: /*
002: #IFNDEF ALT_LICENSE
003: ThinWire(R) RIA Ajax Framework
004: Copyright (C) 2003-2007 Custom Credit Systems
005:
006: This library is free software; you can redistribute it and/or modify it under
007: the terms of the GNU Lesser General Public License as published by the Free
008: Software Foundation; either version 2.1 of the License, or (at your option) any
009: later version.
010:
011: This library is distributed in the hope that it will be useful, but WITHOUT ANY
012: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
013: PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
014:
015: You should have received a copy of the GNU Lesser General Public License along
016: with this library; if not, write to the Free Software Foundation, Inc., 59
017: Temple Place, Suite 330, Boston, MA 02111-1307 USA
018:
019: Users who would rather have a commercial license, warranty or support should
020: contact the following company who invented, built and supports the technology:
021:
022: Custom Credit Systems, Richardson, TX 75081, USA.
023: email: info@thinwire.com ph: +1 (888) 644-6405
024: http://www.thinwire.com
025: #ENDIF
026: [ v1.2_RC2 ]
027: */
028: package thinwire.ui;
029:
030: import java.util.AbstractList;
031: import java.util.ArrayList;
032: import java.util.List;
033:
034: import thinwire.ui.event.ItemChangeListener;
035: import thinwire.ui.event.ItemChangeEvent.Type;
036: import thinwire.ui.layout.Layout;
037:
038: /**
039: * @author Joshua J. Gertzen
040: */
041: abstract class AbstractContainer<T extends Component> extends
042: AbstractComponent implements Container<T> {
043: private class ChildList extends AbstractList<T> {
044: private ArrayList<T> l = new ArrayList<T>();
045:
046: private void processRemove(T c) {
047: ((AbstractComponent) c).setParent(null);
048: if (standardButton == c)
049: updateStandardButton((Button) c, false);
050: if (childWithFocus == c)
051: AbstractContainer.this .setChildWithFocus(null);
052: }
053:
054: private void processAdd(T c) {
055: ((AbstractComponent) c).setParent(AbstractContainer.this );
056:
057: if (c instanceof Button && ((Button) c).isStandard()) {
058: updateStandardButton((Button) c, true);
059: } else if (c instanceof AbstractContainer) {
060: Button b = ((AbstractContainer) c).getStandardButton();
061: if (b != null)
062: updateStandardButton(b, true);
063: }
064:
065: if (c.isFocus()) {
066: if (!c.isFocus())
067: c.setFocus(true);
068: Container<T> container = AbstractContainer.this ;
069:
070: while (childWithFocus == null) {
071: container = (Container<T>) container.getParent();
072: if (container == null)
073: break;
074: childWithFocus = container.getChildWithFocus();
075: }
076:
077: if (childWithFocus != null)
078: childWithFocus.setFocus(false);
079: AbstractContainer.this .setChildWithFocus(c);
080: AbstractContainer.this .setFocus(true);
081: }
082: }
083:
084: public T get(int index) {
085: return l.get(index);
086: }
087:
088: public void add(int index, T o) {
089: if (o == null)
090: throw new IllegalArgumentException("o == null");
091: if (o == AbstractContainer.this )
092: throw new IllegalArgumentException(
093: "cannot add component to itself");
094: if (o.getParent() != null)
095: throw new IllegalArgumentException(
096: "cannot add component to multiple containers or twice to the same container");
097: if (o instanceof Dialog)
098: throw new IllegalArgumentException(
099: "cannot add a dialog to a container");
100: if (!TabFolder.class.isInstance(AbstractContainer.this )
101: && o instanceof TabSheet)
102: throw new IllegalArgumentException(
103: "cannot add a TabSheet to a container that is not a TabFolder");
104: l.add(index, o);
105: processAdd(o);
106: icei.fireItemChange(null, Type.ADD, new Integer(index),
107: null, o);
108: }
109:
110: public T remove(int index) {
111: T ret = l.get(index);
112: l.remove(index);
113: processRemove(ret);
114: icei.fireItemChange(null, Type.REMOVE, new Integer(index),
115: ret, null);
116: return ret;
117: }
118:
119: public T set(int index, T o) {
120: if (o == null)
121: throw new IllegalArgumentException("o == null");
122: if (o == AbstractContainer.this )
123: throw new IllegalArgumentException(
124: "cannot add component to itself");
125: if (o.getParent() != null) {
126: if (o == l.get(index))
127: return o;
128: throw new IllegalArgumentException(
129: "cannot add component to multiple containers or twice to the same container");
130: }
131:
132: T ret = l.set(index, o);
133: processRemove(ret);
134: processAdd(o);
135: icei.fireItemChange(null, Type.SET, new Integer(index),
136: ret, o);
137: return ret;
138: }
139:
140: public int size() {
141: return l.size();
142: }
143: }
144:
145: private EventListenerImpl<ItemChangeListener> icei;
146: private List<T> children;
147: private ScrollType scroll = ScrollType.NONE;
148: private Layout layout;
149: private T childWithFocus;
150: private Button standardButton;
151:
152: AbstractContainer() {
153: EventListenerImpl<ItemChangeListener> gicei = app == null ? null
154: : app.getGlobalListenerSet(ItemChangeListener.class,
155: false);
156: icei = new EventListenerImpl<ItemChangeListener>(this ,
157: ItemChangeListener.class, null, gicei);
158: children = new ChildList();
159: }
160:
161: void updateStandardButton(Button button, boolean standard) {
162: if (this .standardButton == button) {
163: if (!standard) {
164: this .standardButton.setStandard(false);
165: this .standardButton = null;
166: } else {
167: //nothing, because it's already set;
168: }
169: } else {
170: if (standard) {
171: if (this .standardButton != null)
172: this .standardButton.setStandard(false);
173: this .standardButton = button;
174: } else {
175: //nothing, because a non-standard button that doesn't match, does not update the current
176: }
177: }
178:
179: Object parent = getParent();
180: if (parent instanceof AbstractContainer)
181: ((AbstractContainer) parent).updateStandardButton(button,
182: standard);
183: }
184:
185: Button getStandardButton() {
186: return standardButton;
187: }
188:
189: public ScrollType getScrollType() {
190: return scroll;
191: }
192:
193: public void setScrollType(ScrollType scrollType) {
194: if (scrollType == null)
195: throw new IllegalArgumentException("scrollType == null");
196: ScrollType oldScroll = this .scroll;
197: this .scroll = scrollType;
198: firePropertyChange(this , PROPERTY_SCROLL_TYPE, oldScroll,
199: scrollType);
200: }
201:
202: public Layout getLayout() {
203: return layout;
204: }
205:
206: public void setLayout(Layout layout) {
207: Layout oldLayout = this .layout;
208: this .layout = layout;
209: if (oldLayout != null && oldLayout.getContainer() == this )
210: oldLayout.setContainer(null);
211: if (layout != null && layout.getContainer() != this )
212: layout.setContainer((Container<Component>) this );
213: firePropertyChange(this , PROPERTY_LAYOUT, oldLayout, layout);
214: }
215:
216: public void addItemChangeListener(ItemChangeListener listener) {
217: icei.addListener(listener);
218: }
219:
220: public void removeItemChangeListener(ItemChangeListener listener) {
221: icei.removeListener(listener);
222: }
223:
224: public List<T> getChildren() {
225: return children;
226: }
227:
228: void setChildWithFocus(T childWithFocus) {
229: this .childWithFocus = childWithFocus;
230: }
231:
232: public T getChildWithFocus() {
233: return childWithFocus;
234: }
235:
236: public T getComponentWithFocus() {
237: T ret = null;
238: Object root = app != null ? app.getFrame() : this ;
239: Object parent;
240:
241: //Walk up the tree to the root container
242: while (root instanceof Container
243: && (parent = ((Container) root).getParent()) != null) {
244: root = parent;
245: }
246:
247: //If the root is a container, walk down the children with focus to get the component with focus.
248: if (root instanceof Container) {
249: ret = (T) root;
250:
251: while (ret instanceof Container) {
252: ret = ((Container<T>) ret).getChildWithFocus();
253: }
254: }
255:
256: return ret;
257: }
258:
259: public int getInnerWidth() {
260: int innerWidth = getWidth() - getStyle().getBorder().getSize()
261: * 2;
262: return innerWidth < 0 ? 0 : innerWidth;
263: }
264:
265: public int getInnerHeight() {
266: int innerHeight = getHeight()
267: - getStyle().getBorder().getSize() * 2;
268: return innerHeight < 0 ? 0 : innerHeight;
269: }
270: }
|