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.RenderStateEvent;
031: import thinwire.render.RenderStateListener;
032: import thinwire.render.web.WebApplication;
033: import thinwire.ui.event.PropertyChangeEvent;
034: import thinwire.ui.event.PropertyChangeListener;
035: import thinwire.ui.style.Background;
036: import thinwire.ui.style.Border;
037: import thinwire.ui.style.Color;
038: import thinwire.ui.style.FX;
039: import thinwire.ui.style.Font;
040: import thinwire.ui.style.Style;
041:
042: /**
043: * The generic <code>DropDown</code> component allows you to place an
044: * arbitrary component in a <code>DropDown</code>. In order to implement
045: * this, the developer must implement a <code>DropDown.View</code> (or extend
046: * <code>AbstractView</code>) for the <code>Component</code> they are
047: * placing in the <code>DropDown</code>.
048: *
049: * @see thinwire.ui.DropDownDateBox
050: * @see thinwire.ui.DropDownGridBox
051: * @author Joshua J. Gertzen
052: * @author Ted C. Howard
053: */
054: public class DropDown<T extends Component> extends
055: AbstractMaskEditorComponent {
056: public static final String PROPERTY_EDIT_ALLOWED = "editAllowed";
057: public static final String PROPERTY_VIEW = "view";
058: public static final String PROPERTY_COMPONENT = "component";
059:
060: private static final String[] STYLE_PROPERTIES = {
061: Font.PROPERTY_FONT_BOLD, Font.PROPERTY_FONT_COLOR,
062: Font.PROPERTY_FONT_FAMILY, Font.PROPERTY_FONT_ITALIC,
063: Font.PROPERTY_FONT_SIZE, Font.PROPERTY_FONT_UNDERLINE,
064: Font.PROPERTY_FONT_STRIKE };
065:
066: static void copyDropDownStyle(Component parent, Component child,
067: boolean copyBackground) {
068: Style cs = child.getStyle();
069: Style ps = parent.getStyle();
070: Border csb = cs.getBorder();
071: Border dcsb = Application.getDefaultStyle(child.getClass())
072: .getBorder();
073: if (csb.getColor().equals(dcsb.getColor()))
074: csb.setColor(Color.WINDOWFRAME);
075: if (csb.getType().equals(dcsb.getType()))
076: csb.setType(Border.Type.SOLID);
077: if (csb.getSize() == dcsb.getSize())
078: csb.setSize(1);
079: if (copyBackground)
080: cs.getBackground().copy(ps.getBackground(), true);
081: cs.getFont().copy(ps.getFont(), true);
082: }
083:
084: public static interface View<T extends Component> {
085: DropDown<T> getDropDown();
086:
087: Object getValue();
088:
089: void setValue(Object value);
090:
091: int getOptimalWidth();
092:
093: int getOptimalHeight();
094:
095: void setComponent(T comp);
096: }
097:
098: public static abstract class AbstractView<T extends Component>
099: implements View<T> {
100:
101: protected DropDown<T> dd;
102: protected T ddc;
103:
104: protected void init(DropDown<T> dropDown, T comp) {
105: dd = dropDown;
106: ddc = comp;
107:
108: if (dd != null) {
109: String oldValue = dd.getText();
110: if (oldValue.length() > 0)
111: setValue(oldValue);
112: }
113: }
114:
115: protected void addCloseComponent(final Component comp) {
116: if (dd == null)
117: throw new IllegalStateException("dd == null");
118:
119: final WebApplication app = (WebApplication) Application
120: .current();
121:
122: if (app != null) {
123: app.addRenderStateListener(comp,
124: new RenderStateListener() {
125: public void renderStateChange(
126: RenderStateEvent ev) {
127: app.clientSideMethodCall(app
128: .getComponentId(dd),
129: "addCloseComponent", app
130: .getComponentId(comp));
131: }
132: });
133: }
134: }
135:
136: public int getOptimalWidth() {
137: return dd.getWidth();
138: }
139:
140: public void setComponent(T comp) {
141: init(dd, comp);
142: }
143:
144: }
145:
146: private boolean editAllowed = true;
147: private DropDown.View<T> view;
148: private T comp;
149:
150: protected DropDown(DropDown.View<T> view, T comp) {
151: if (view == null)
152: throw new IllegalArgumentException("view == null");
153: if (comp == null)
154: throw new IllegalArgumentException("comp == null");
155: setView(view);
156: setComponent(comp);
157:
158: addPropertyChangeListener(STYLE_PROPERTIES,
159: new PropertyChangeListener() {
160: public void propertyChange(PropertyChangeEvent ev) {
161: String propertyName = ev.getPropertyName();
162: Style s = getComponent().getStyle();
163: Object o = ev.getNewValue();
164: s.setProperty(propertyName, o);
165: }
166: });
167:
168: addPropertyChangeListener(PROPERTY_WIDTH,
169: new PropertyChangeListener() {
170: public void propertyChange(PropertyChangeEvent ev) {
171: if (DropDown.this .comp != null)
172: DropDown.this .comp.setWidth(getView()
173: .getOptimalWidth());
174: }
175: });
176: }
177:
178: public void setText(String text) {
179: formattedText = text = text == null ? "" : text;
180: getView().setValue(text);
181: super .setText(getUnformattedText(text));
182: }
183:
184: public View<T> getView() {
185: return view;
186: }
187:
188: public void setView(View<T> view) {
189: if (view == null)
190: throw new IllegalArgumentException("view == null");
191: View<T> oldView = this .view;
192: this .view = view;
193: firePropertyChange(this , PROPERTY_VIEW, oldView, view);
194: }
195:
196: /**
197: * Returns the component that is displayed upon clicking the drop down button.
198: * @return the component that is displayed upon clicking the drop down button.
199: */
200: public T getComponent() {
201: return comp;
202: }
203:
204: /**
205: * Assigns the component that is displayed upon clicking the drop down button.
206: * @param comp the component to display upon clicking the drop down button.
207: */
208: public void setComponent(T comp) {
209: if (comp == null)
210: throw new IllegalArgumentException("comp == null");
211: if (comp.getParent() != null)
212: throw new IllegalStateException("comp.getParent() != null");
213: T oldComp = getComponent();
214: if (oldComp != null)
215: ((AbstractComponent) oldComp).setParent(null);
216: this .comp = comp;
217: ((AbstractComponent) comp).setParent(this );
218: copyDropDownStyle(this , comp, false);
219: if (getView().getDropDown() != null)
220: getView().setComponent(comp);
221: firePropertyChange(this , PROPERTY_COMPONENT, oldComp, comp);
222: }
223:
224: /**
225: * Returns whether you can type in the text field.
226: * @return true if the field is editable (Default = true)
227: */
228: public boolean isEditAllowed() {
229: return editAllowed;
230: }
231:
232: /**
233: * Toggles a boolean variable that determines if the text field will be active (editable).
234: * @param editAllowed If true the field will be editable. (Default = true)
235: */
236: public void setEditAllowed(boolean editAllowed) {
237: boolean oldEditAllowed = this.editAllowed;
238: this.editAllowed = editAllowed;
239: firePropertyChange(this, PROPERTY_EDIT_ALLOWED, oldEditAllowed,
240: editAllowed);
241: }
242: }
|