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 thinwire.render.Renderer;
031: import thinwire.ui.event.ActionEvent;
032: import thinwire.ui.event.ActionListener;
033: import thinwire.ui.event.DropEvent;
034: import thinwire.ui.event.DropListener;
035: import thinwire.ui.event.KeyPressEvent;
036: import thinwire.ui.event.PropertyChangeListener;
037: import thinwire.ui.event.KeyPressListener;
038: import thinwire.ui.style.*;
039:
040: /**
041: * @author Joshua J. Gertzen
042: */
043: abstract class AbstractComponent implements Component {
044:
045: Application app;
046: private Object parent;
047: private Label label;
048: private Style style;
049: private EventListenerImpl<PropertyChangeListener> pcei;
050: private EventListenerImpl<ActionListener> aei;
051: private EventListenerImpl<DropListener> dei;
052: private EventListenerImpl<KeyPressListener> kpei;
053: private Object userObject;
054: private boolean focusCapable = true;
055: private boolean focus;
056: private boolean enabled = true;
057: private int x;
058: private int y;
059: private int width;
060: private int height;
061: private Object limit;
062: private boolean visible;
063: private boolean ignoreFirePropertyChange;
064:
065: AbstractComponent() {
066: this (EventListenerImpl.ACTION_VALIDATOR);
067: }
068:
069: AbstractComponent(EventListenerImpl.SubTypeValidator actionValidator) {
070: this .visible = true;
071: app = Application.current();
072:
073: EventListenerImpl<PropertyChangeListener> gpcei;
074: EventListenerImpl<ActionListener> gaei;
075: EventListenerImpl<DropListener> gdei;
076: EventListenerImpl<KeyPressListener> gkpei;
077:
078: if (app == null) {
079: gpcei = null;
080: gaei = null;
081: gdei = null;
082: gkpei = null;
083: } else {
084: gpcei = app.getGlobalListenerSet(
085: PropertyChangeListener.class, false);
086: gaei = app
087: .getGlobalListenerSet(ActionListener.class, false);
088: gdei = app.getGlobalListenerSet(DropListener.class, false);
089: gkpei = app.getGlobalListenerSet(KeyPressListener.class,
090: false);
091: }
092:
093: pcei = new EventListenerImpl<PropertyChangeListener>(this ,
094: PropertyChangeListener.class, null, gpcei);
095: aei = new EventListenerImpl<ActionListener>(this ,
096: ActionListener.class, actionValidator, gaei);
097: dei = new EventListenerImpl<DropListener>(this ,
098: DropListener.class, null, gdei);
099: kpei = new EventListenerImpl<KeyPressListener>(this ,
100: KeyPressListener.class,
101: EventListenerImpl.KEY_PRESS_VALIDATOR, gkpei);
102:
103: this .style = new Style(Application.getDefaultStyle(this
104: .getClass()), this ) {
105: protected void firePropertyChange(Object source,
106: String propertyName, Object oldValue,
107: Object newValue) {
108: AbstractComponent.this .firePropertyChange(source,
109: propertyName, oldValue, newValue);
110: }
111: };
112: }
113:
114: void setRenderer(Renderer r) {
115: pcei.setRenderer(r);
116: aei.setRenderer(r);
117: dei.setRenderer(r);
118: kpei.setRenderer(r);
119: }
120:
121: String getStandardPropertyUnsupportedMsg(String propertyName,
122: boolean read) {
123: return this .getClass().getName() + " does not support "
124: + (read ? "reading from" : "writing to")
125: + " the property: " + propertyName;
126: }
127:
128: public void addPropertyChangeListener(String propertyName,
129: PropertyChangeListener listener) {
130: pcei.addListener(propertyName, listener);
131: }
132:
133: public void addPropertyChangeListener(String[] propertyNames,
134: PropertyChangeListener listener) {
135: pcei.addListener(propertyNames, listener);
136: }
137:
138: public void removePropertyChangeListener(
139: PropertyChangeListener listener) {
140: pcei.removeListener(listener);
141: }
142:
143: protected final boolean firePropertyChange(Object source,
144: String propertyName, int oldValue, int newValue) {
145: if (oldValue == newValue)
146: return false;
147: if (ignoreFirePropertyChange)
148: return true;
149: pcei.firePropertyChange(source, propertyName, oldValue,
150: newValue);
151: return true;
152: }
153:
154: protected final boolean firePropertyChange(Object source,
155: String propertyName, boolean oldValue, boolean newValue) {
156: if (oldValue == newValue)
157: return false;
158: if (ignoreFirePropertyChange)
159: return true;
160: pcei.firePropertyChange(source, propertyName, oldValue,
161: newValue);
162: return true;
163: }
164:
165: protected final boolean firePropertyChange(Object source,
166: String propertyName, Object oldValue, Object newValue) {
167: if (oldValue == newValue
168: || (oldValue != null && oldValue.equals(newValue))
169: || (newValue != null && newValue.equals(oldValue)))
170: return false;
171: if (ignoreFirePropertyChange)
172: return true;
173: pcei.firePropertyChange(source, propertyName, oldValue,
174: newValue);
175: return true;
176: }
177:
178: public void addActionListener(String action, ActionListener listener) {
179: aei.addListener(action, listener);
180: }
181:
182: public void addActionListener(String[] actions,
183: ActionListener listener) {
184: aei.addListener(actions, listener);
185: }
186:
187: public void removeActionListener(ActionListener listener) {
188: aei.removeListener(listener);
189: }
190:
191: public void fireAction(ActionEvent ev) {
192: aei.fireAction(ev);
193: }
194:
195: public void fireAction(String action) {
196: fireAction(new ActionEvent(action, this ));
197: }
198:
199: public void fireAction(String action, Object source) {
200: fireAction(new ActionEvent(action, this , source));
201: }
202:
203: public void addDropListener(Component dragComponent,
204: DropListener listener) {
205: dei.addListener(dragComponent, listener);
206: }
207:
208: public void addDropListener(Component[] dragComponents,
209: DropListener listener) {
210: dei.addListener(dragComponents, listener);
211: }
212:
213: public void removeDropListener(DropListener listener) {
214: dei.removeListener(listener);
215: }
216:
217: public void fireDrop(DropEvent ev) {
218: dei.fireDrop(ev);
219: }
220:
221: public void fireDrop(Component dragComponent) {
222: fireDrop(new DropEvent(this , dragComponent));
223: }
224:
225: public void fireDrop(Component dragComponent, Object dragObject) {
226: fireDrop(new DropEvent(this , null, dragComponent, dragObject));
227: }
228:
229: public void addKeyPressListener(String keyPressCombo,
230: KeyPressListener listener) {
231: kpei.addListener(keyPressCombo, listener);
232: }
233:
234: public void addKeyPressListener(String[] keyPressCombos,
235: KeyPressListener listener) {
236: kpei.addListener(keyPressCombos, listener);
237: }
238:
239: public void removeKeyPressListener(KeyPressListener listener) {
240: kpei.removeListener(listener);
241: }
242:
243: public void fireKeyPress(KeyPressEvent ev) {
244: kpei.fireKeyPress(ev);
245: }
246:
247: public void fireKeyPress(String keyPressCombo) {
248: fireKeyPress(new KeyPressEvent(keyPressCombo, this ));
249: }
250:
251: public Object getParent() {
252: return parent;
253: }
254:
255: void setParent(Object parent) {
256: this .parent = parent;
257: }
258:
259: public Container getContainer() {
260: Container c = null;
261: Object o = this .getParent();
262:
263: while (o != null) {
264: if (o instanceof Container) {
265: c = (Container) o;
266: break;
267: } else if (o instanceof Component) {
268: o = ((Component) o).getParent();
269: } else if (o instanceof GridBox.Row) {
270: o = ((GridBox.Row) o).getParent();
271: } else {
272: throw new IllegalStateException(
273: "No known method of getting the parent for class '"
274: + o.getClass() + "'");
275: }
276: }
277:
278: return c;
279: }
280:
281: public Label getLabel() {
282: return label;
283: }
284:
285: void setLabel(Label label) {
286: this .label = label;
287: }
288:
289: public Object getUserObject() {
290: return userObject;
291: }
292:
293: public void setUserObject(Object userObject) {
294: Object oldUserObject = this .userObject;
295: this .userObject = userObject;
296: firePropertyChange(this , PROPERTY_USER_OBJECT, oldUserObject,
297: userObject);
298: }
299:
300: public boolean isEnabled() {
301: return this .enabled;
302: }
303:
304: public void setEnabled(boolean enabled) {
305: boolean oldEnabled = this .enabled;
306: this .enabled = enabled;
307: firePropertyChange(this , PROPERTY_ENABLED, oldEnabled, enabled);
308: }
309:
310: public boolean isFocusCapable() {
311: return focusCapable;
312: }
313:
314: public void setFocusCapable(boolean focusCapable) {
315: boolean oldFocusCapable = this .focusCapable;
316: this .focusCapable = focusCapable;
317: firePropertyChange(this , PROPERTY_FOCUS_CAPABLE,
318: oldFocusCapable, focusCapable);
319: }
320:
321: public final boolean isFocus() {
322: return focus;
323: }
324:
325: public void setFocus(boolean focus) {
326: if (!this .isFocusCapable())
327: throw new IllegalStateException(this .getClass()
328: .getSimpleName()
329: + ": !this.isFocusCapable()");
330:
331: if (parent instanceof Container || parent == null) {
332: if (this .focus == focus)
333: return;
334:
335: if (focus) {
336:
337: // Determine if the component is a new container (a container that has just been given focus by application code
338: // or has a component thet has focus, but hasn't yet been rendered)
339: boolean newContainer = false;
340: if (this instanceof Container) {
341: Container cont = (Container) this ;
342: Component cwf = cont.getChildWithFocus();
343:
344: while (cwf != null && cwf instanceof Container)
345: cwf = ((Container) cwf).getChildWithFocus();
346: if (cwf == null
347: || !cwf
348: .equals(cont
349: .getComponentWithFocus()))
350: newContainer = true;
351: }
352:
353: if ((parent != null && (!(this instanceof Container) || newContainer))
354: || (this instanceof Dialog && newContainer)) {
355: Container container = parent != null ? (Container) parent
356: : app.getFrame();
357: Component childWithFocus = container
358: .getChildWithFocus();
359:
360: while (childWithFocus == null) {
361: container = (Container) container.getParent();
362: if (container == null)
363: break;
364: childWithFocus = container.getChildWithFocus();
365: }
366:
367: if (childWithFocus != null)
368: childWithFocus.setFocus(false);
369: }
370:
371: firePropertyChange(this , PROPERTY_FOCUS, this .focus,
372: this .focus = true);
373:
374: if (parent != null || this instanceof Dialog) {
375: AbstractContainer container = parent != null ? (AbstractContainer) parent
376: : app.getFrame();
377: container.setChildWithFocus(this );
378: if (app == null
379: || !container.equals(app.getFrame()))
380: container.setFocus(true);
381: }
382: } else {
383: app.setPriorFocus(this );
384: // We need to walk down the containment hierarchy nulling out the childWithFocus property
385: // and setting each component's focus property to false, until we reach the final component
386: if (this instanceof Container) {
387: Component childWithFocus = ((Container) this )
388: .getChildWithFocus();
389: if (childWithFocus != null) {
390: ((AbstractContainer) this )
391: .setChildWithFocus(null);
392: childWithFocus.setFocus(false);
393: }
394: } else if (parent != null) {
395: AbstractContainer container = (AbstractContainer) parent;
396: Component childWithFocus = container
397: .getChildWithFocus();
398: if (this .equals(childWithFocus))
399: container.setChildWithFocus(null);
400: }
401:
402: firePropertyChange(this , PROPERTY_FOCUS, this .focus,
403: this .focus = false);
404: }
405: } else
406: throw new UnsupportedOperationException(
407: "the property 'focus' is not supported by "
408: + this .getClass());
409: }
410:
411: public Style getStyle() {
412: return style;
413: }
414:
415: private void rangeCheck(String propertyName, int value, int min,
416: int max) {
417: if (value < min || value >= max)
418: throw new IllegalArgumentException(propertyName + " < "
419: + min + " || " + propertyName + " >= " + max);
420: }
421:
422: public int getX() {
423: return x;
424: }
425:
426: public void setX(int x) {
427: rangeCheck(PROPERTY_X, x, Short.MIN_VALUE, Short.MAX_VALUE);
428: int oldX = this .x;
429: this .x = x;
430: firePropertyChange(this , PROPERTY_X, oldX, x);
431: }
432:
433: public int getY() {
434: return y;
435: }
436:
437: public void setY(int y) {
438: rangeCheck(PROPERTY_Y, y, Short.MIN_VALUE, Short.MAX_VALUE);
439: int oldY = this .y;
440: this .y = y;
441: firePropertyChange(this , PROPERTY_Y, oldY, y);
442: }
443:
444: public Component setPosition(int x, int y) {
445: rangeCheck(PROPERTY_X, x, Short.MIN_VALUE, Short.MAX_VALUE);
446: rangeCheck(PROPERTY_Y, y, Short.MIN_VALUE, Short.MAX_VALUE);
447: int oX = -1, oY = -1;
448: boolean error = false;
449:
450: try {
451: oX = getX();
452: oY = getY();
453: ignoreFirePropertyChange = true;
454: setX(x);
455: setY(y);
456: } catch (RuntimeException e) {
457: error = true;
458: throw e;
459: } finally {
460: if (error) {
461: if (oX != -1 && oY != -1) {
462: setX(oX);
463: setY(oY);
464: }
465:
466: ignoreFirePropertyChange = false;
467: } else {
468: ignoreFirePropertyChange = false;
469: firePropertyChange(this , PROPERTY_X, oX, x);
470: firePropertyChange(this , PROPERTY_Y, oY, y);
471: }
472: }
473:
474: return this ;
475: }
476:
477: public int getWidth() {
478: return width;
479: }
480:
481: public void setWidth(int width) {
482: rangeCheck(PROPERTY_WIDTH, width, 0, Short.MAX_VALUE);
483: int oldWidth = this .width;
484: this .width = width;
485: firePropertyChange(this , PROPERTY_WIDTH, oldWidth, width);
486: }
487:
488: public int getHeight() {
489: return height;
490: }
491:
492: public void setHeight(int height) {
493: rangeCheck(PROPERTY_HEIGHT, height, 0, Short.MAX_VALUE);
494: int oldHeight = this .height;
495: this .height = height;
496: firePropertyChange(this , PROPERTY_HEIGHT, oldHeight, height);
497: }
498:
499: public Component setSize(int width, int height) {
500: rangeCheck(PROPERTY_WIDTH, width, 0, Short.MAX_VALUE);
501: rangeCheck(PROPERTY_HEIGHT, height, 0, Short.MAX_VALUE);
502: int oWidth = -1, oHeight = -1;
503: boolean error = false;
504:
505: try {
506: oWidth = getWidth();
507: oHeight = getHeight();
508: ignoreFirePropertyChange = true;
509: setWidth(width);
510: setHeight(height);
511: } catch (RuntimeException e) {
512: error = true;
513: throw e;
514: } finally {
515: if (error) {
516: if (oWidth != -1 && oHeight != -1) {
517: setWidth(oWidth);
518: setHeight(oHeight);
519: }
520:
521: ignoreFirePropertyChange = false;
522: } else {
523: ignoreFirePropertyChange = false;
524: firePropertyChange(this , PROPERTY_WIDTH, oWidth, width);
525: firePropertyChange(this , PROPERTY_HEIGHT, oHeight,
526: height);
527: }
528: }
529:
530: return this ;
531: }
532:
533: public Component setBounds(int x, int y, int width, int height) {
534: rangeCheck(PROPERTY_X, x, Short.MIN_VALUE, Short.MAX_VALUE);
535: rangeCheck(PROPERTY_Y, y, Short.MIN_VALUE, Short.MAX_VALUE);
536: rangeCheck(PROPERTY_WIDTH, width, 0, Short.MAX_VALUE);
537: rangeCheck(PROPERTY_HEIGHT, height, 0, Short.MAX_VALUE);
538: int oX = -1, oY = -1, oWidth = -1, oHeight = -1;
539: boolean error = false;
540:
541: try {
542: oX = getX();
543: oY = getY();
544: oWidth = getWidth();
545: oHeight = getHeight();
546: ignoreFirePropertyChange = true;
547: setX(x);
548: setY(y);
549: setWidth(width);
550: setHeight(height);
551: } catch (RuntimeException e) {
552: error = true;
553: throw e;
554: } finally {
555: if (error) {
556: if (oX != -1 && oY != -1 && oWidth != -1
557: && oHeight != -1) {
558: setX(oX);
559: setY(oY);
560: setWidth(oWidth);
561: setHeight(oHeight);
562: }
563:
564: ignoreFirePropertyChange = false;
565: } else {
566: ignoreFirePropertyChange = false;
567: firePropertyChange(this , PROPERTY_X, oX, x);
568: firePropertyChange(this , PROPERTY_Y, oY, y);
569: firePropertyChange(this , PROPERTY_WIDTH, oWidth, width);
570: firePropertyChange(this , PROPERTY_HEIGHT, oHeight,
571: height);
572: }
573: }
574: return this ;
575: }
576:
577: public Object getLimit() {
578: return limit;
579: }
580:
581: public Component setLimit(Object limit) {
582: Object oldLimit = this .limit;
583: this .limit = limit;
584: firePropertyChange(this , PROPERTY_LIMIT, oldLimit, limit);
585: return this ;
586: }
587:
588: public boolean isVisible() {
589: return visible;
590: }
591:
592: public void setVisible(boolean visible) {
593: boolean oldVisible = this.visible;
594: this.visible = visible;
595: firePropertyChange(this, PROPERTY_VISIBLE, oldVisible, visible);
596: }
597: }
|