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.layout;
029:
030: import java.util.logging.Logger;
031:
032: import thinwire.ui.Application;
033: import thinwire.ui.Component;
034: import thinwire.ui.Container;
035: import thinwire.ui.Window;
036: import thinwire.ui.event.ItemChangeEvent;
037: import thinwire.ui.event.ItemChangeListener;
038: import thinwire.ui.event.PropertyChangeEvent;
039: import thinwire.ui.event.PropertyChangeListener;
040: import thinwire.ui.event.ItemChangeEvent.Type;
041:
042: /**
043: * @author Joshua J. Gertzen
044: */
045: public abstract class AbstractLayout implements Layout {
046:
047: private static final Logger log = Logger
048: .getLogger(AbstractLayout.class.getName());
049:
050: protected Container<Component> container;
051: protected String[] autoLayoutProps;
052: protected boolean autoLayout;
053: protected boolean limitLayout;
054: protected int margin;
055: protected int spacing;
056: private boolean update;
057:
058: private Runnable updateTask = new Runnable() {
059: public void run() {
060: update();
061: update = false;
062: }
063: };
064:
065: private final PropertyChangeListener pclContainer = new PropertyChangeListener() {
066: public void propertyChange(PropertyChangeEvent pce) {
067: if (autoLayout)
068: apply();
069: }
070: };
071:
072: private final PropertyChangeListener pcl = new PropertyChangeListener() {
073: private boolean ignoreChange;
074:
075: public void propertyChange(PropertyChangeEvent pce) {
076: if (ignoreChange)
077: return;
078:
079: if (limitLayout
080: && pce.getPropertyName().equals(
081: Component.PROPERTY_LIMIT)) {
082: Component comp = (Component) pce.getSource();
083: Object limit = getFormalLimit(comp);
084:
085: if (!comp.getLimit().equals(limit)) {
086: ignoreChange = true;
087: comp.setLimit(limit);
088: ignoreChange = false;
089: }
090:
091: limitChanged(comp, pce.getOldValue());
092: }
093:
094: if (autoLayout)
095: apply();
096: }
097: };
098:
099: private final ItemChangeListener icl = new ItemChangeListener() {
100: public void itemChange(ItemChangeEvent ice) {
101: ItemChangeEvent.Type type = ice.getType();
102:
103: if (type == Type.REMOVE || type == Type.SET) {
104: Component comp = (Component) ice.getOldValue();
105:
106: if (autoLayoutProps != null && comp != null) {
107: removeComponent(comp);
108: comp.removePropertyChangeListener(pcl);
109: }
110: }
111:
112: if (type == Type.ADD || type == Type.SET) {
113: Component comp = (Component) ice.getNewValue();
114:
115: if (autoLayoutProps != null && comp != null) {
116: if (limitLayout)
117: comp.setLimit(getFormalLimit(comp));
118: addComponent(comp);
119: comp
120: .addPropertyChangeListener(autoLayoutProps,
121: pcl);
122: }
123: }
124:
125: if (autoLayout)
126: apply();
127: }
128: };
129:
130: protected AbstractLayout(String... autoLayoutProps) {
131: if (autoLayoutProps.length > 0) {
132:
133: for (String name : autoLayoutProps) {
134: if (name.equals(Component.PROPERTY_LIMIT)) {
135: limitLayout = true;
136: break;
137: }
138: }
139:
140: this .autoLayoutProps = autoLayoutProps;
141: update = false;
142: }
143: }
144:
145: protected void addComponent(Component comp) {
146:
147: }
148:
149: protected void removeComponent(Component comp) {
150:
151: }
152:
153: protected void limitChanged(Component comp, Object oldLimit) {
154:
155: }
156:
157: protected Object getFormalLimit(Component comp) {
158: return comp.getLimit();
159: }
160:
161: public void setContainer(Container<Component> container) {
162: if (container == this .container)
163: return;
164: boolean autoLayout = this .autoLayout;
165: this .autoLayout = false;
166:
167: if (this .container != null) {
168: for (Component comp : this .container.getChildren()) {
169: if (autoLayoutProps != null && comp != null) {
170: removeComponent(comp);
171: comp.removePropertyChangeListener(pcl);
172: }
173: }
174:
175: this .container.removeItemChangeListener(icl);
176: this .container.removePropertyChangeListener(pclContainer);
177: this .container.setLayout(null);
178: }
179:
180: this .container = container;
181:
182: if (container != null) {
183: for (Component comp : container.getChildren()) {
184: if (autoLayoutProps != null && comp != null) {
185: if (limitLayout)
186: comp.setLimit(getFormalLimit(comp));
187: addComponent(comp);
188: comp
189: .addPropertyChangeListener(autoLayoutProps,
190: pcl);
191: }
192: }
193:
194: container.addItemChangeListener(icl);
195: container.addPropertyChangeListener(
196: container instanceof Window ? new String[] {
197: Container.PROPERTY_WIDTH,
198: Container.PROPERTY_HEIGHT,
199: Window.PROPERTY_MENU } : new String[] {
200: Container.PROPERTY_WIDTH,
201: Container.PROPERTY_HEIGHT }, pclContainer);
202: if (container.getLayout() != this )
203: container.setLayout(this );
204: }
205:
206: this .autoLayout = autoLayout;
207: if (autoLayout)
208: apply();
209: }
210:
211: public Container<Component> getContainer() {
212: return container;
213: }
214:
215: public boolean isAutoApply() {
216: return autoLayout;
217: }
218:
219: public void setAutoApply(boolean autoLayout) {
220: this .autoLayout = autoLayout;
221: if (autoLayout)
222: apply();
223: }
224:
225: public int getMargin() {
226: return margin;
227: }
228:
229: public void setMargin(int margin) {
230: if (margin < 0 || margin >= Short.MAX_VALUE)
231: throw new IllegalArgumentException(
232: "margin < 0 || margin >= " + Short.MAX_VALUE);
233: this .margin = margin;
234: if (autoLayout)
235: apply();
236: }
237:
238: public int getSpacing() {
239: return spacing;
240: }
241:
242: public void setSpacing(int spacing) {
243: if (spacing < 0 || spacing >= Short.MAX_VALUE)
244: throw new IllegalArgumentException(
245: "spacing < 0 || spacing >= " + Short.MAX_VALUE);
246: this .spacing = spacing;
247: if (autoLayout)
248: apply();
249: }
250:
251: protected void update() {
252:
253: }
254:
255: public void apply() {
256: if (update)
257: return;
258: update = true;
259: Application.current().addTimerTask(updateTask, 0, false);
260: }
261: }
|