001: /*
002: * This file is part of the Echo Web Application Framework (hereinafter "Echo").
003: * Copyright (C) 2002-2005 NextApp, Inc.
004: *
005: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
006: *
007: * The contents of this file are subject to the Mozilla Public License Version
008: * 1.1 (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: * http://www.mozilla.org/MPL/
011: *
012: * Software distributed under the License is distributed on an "AS IS" basis,
013: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
014: * for the specific language governing rights and limitations under the
015: * License.
016: *
017: * Alternatively, the contents of this file may be used under the terms of
018: * either the GNU General Public License Version 2 or later (the "GPL"), or
019: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
020: * in which case the provisions of the GPL or the LGPL are applicable instead
021: * of those above. If you wish to allow use of your version of this file only
022: * under the terms of either the GPL or the LGPL, and not to allow others to
023: * use your version of this file under the terms of the MPL, indicate your
024: * decision by deleting the provisions above and replace them with the notice
025: * and other provisions required by the GPL or the LGPL. If you do not delete
026: * the provisions above, a recipient may use your version of this file under
027: * the terms of any one of the MPL, the GPL or the LGPL.
028: */
029:
030: package nextapp.echo2.app.button;
031:
032: import java.util.EventListener;
033:
034: import nextapp.echo2.app.Alignment;
035: import nextapp.echo2.app.Extent;
036: import nextapp.echo2.app.ImageReference;
037: import nextapp.echo2.app.event.ChangeEvent;
038: import nextapp.echo2.app.event.ChangeListener;
039:
040: /**
041: * An abstract base class for 'two state' buttons.
042: */
043: public abstract class ToggleButton extends AbstractButton {
044:
045: public static final String PROPERTY_PRESSED_STATE_ICON = "pressedStateIcon";
046: public static final String PROPERTY_PRESSED_SELECTED_STATE_ICON = "pressedSelectedStateIcon";
047: public static final String PROPERTY_ROLLOVER_STATE_ICON = "rolloverStateIcon";
048: public static final String PROPERTY_ROLLOVER_SELECTED_STATE_ICON = "rolloverSelectedStateIcon";
049: public static final String PROPERTY_STATE_ALIGNMENT = "stateAlignment";
050: public static final String PROPERTY_STATE_ICON = "stateIcon";
051: public static final String PROPERTY_STATE_MARGIN = "stateMargin";
052: public static final String PROPERTY_STATE_POSITION = "statePosition";
053: public static final String PROPERTY_SELECTED_STATE_ICON = "selectedStateIcon";
054:
055: public static final String SELECTED_CHANGED_PROPERTY = "selected";
056:
057: /**
058: * Forwards events generated by the model to listeners registered with the
059: * component instance.
060: */
061: private ChangeListener changeForwarder = new ChangeListener() {
062:
063: /**
064: * @see nextapp.echo2.app.event.ChangeListener#stateChanged(nextapp.echo2.app.event.ChangeEvent)
065: */
066: public void stateChanged(ChangeEvent e) {
067: fireStateChanged();
068: if (isSelected()) {
069: firePropertyChange(SELECTED_CHANGED_PROPERTY,
070: Boolean.FALSE, Boolean.TRUE);
071: } else {
072: firePropertyChange(SELECTED_CHANGED_PROPERTY,
073: Boolean.TRUE, Boolean.FALSE);
074: }
075: }
076: };
077:
078: /**
079: * Adds a <code>ChangeListener</code> to receive notification of state
080: * changes, i.e., to the selected state of a <code>ToggleButton</code>.
081: *
082: * @param l the listener to add
083: */
084: public void addChangeListener(ChangeListener l) {
085: getEventListenerList().addListener(ChangeListener.class, l);
086: }
087:
088: /**
089: * Notifies all listeners that have registered for this event type.
090: */
091: public void fireStateChanged() {
092: EventListener[] listeners = getEventListenerList()
093: .getListeners(ChangeListener.class);
094: ChangeEvent e = new ChangeEvent(this );
095: for (int index = 0; index < listeners.length; ++index) {
096: ((ChangeListener) listeners[index]).stateChanged(e);
097: }
098: }
099:
100: /**
101: * Returns the selected state icon displayed when the
102: * button is being pressed.
103: *
104: * @return the icon
105: */
106: public ImageReference getPressedSelectedStateIcon() {
107: return (ImageReference) getProperty(PROPERTY_PRESSED_SELECTED_STATE_ICON);
108: }
109:
110: /**
111: * Returns the default (non-selected) state icon displayed when the
112: * button is being pressed.
113: *
114: * @return the icon
115: */
116: public ImageReference getPressedStateIcon() {
117: return (ImageReference) getProperty(PROPERTY_PRESSED_STATE_ICON);
118: }
119:
120: /**
121: * Returns the selected state icon displayed when the mouse
122: * cursor is inside the bounds of the button.
123: *
124: * @return the icon
125: */
126: public ImageReference getRolloverSelectedStateIcon() {
127: return (ImageReference) getProperty(PROPERTY_ROLLOVER_SELECTED_STATE_ICON);
128: }
129:
130: /**
131: * Returns the default (non-selected) state icon displayed when the mouse
132: * cursor is inside the bounds of the button.
133: *
134: * @return the icon
135: */
136: public ImageReference getRolloverStateIcon() {
137: return (ImageReference) getProperty(PROPERTY_ROLLOVER_STATE_ICON);
138: }
139:
140: /**
141: * Returns the selected state icon.
142: *
143: * @return the icon
144: */
145: public ImageReference getSelectedStateIcon() {
146: return (ImageReference) getProperty(PROPERTY_SELECTED_STATE_ICON);
147: }
148:
149: /**
150: * Returns the alignment of the state icon relative to the button's
151: * text/icon.
152: *
153: * @return the state alignment
154: */
155: public Alignment getStateAlignment() {
156: return (Alignment) getProperty(PROPERTY_STATE_ALIGNMENT);
157: }
158:
159: /**
160: * Returns the default (non-selected) state icon.
161: *
162: * @return the icon
163: */
164: public ImageReference getStateIcon() {
165: return (ImageReference) getProperty(PROPERTY_STATE_ICON);
166: }
167:
168: /**
169: * Returns the margin size between the state icon and the
170: * toggle button's icon and/or text. The margin will only
171: * be displayed in the case where icon and/or text are
172: * present.
173: * This property only supports <code>Extent</code>s with
174: * fixed (i.e., not percent) units.
175: *
176: * @return the margin size
177: */
178: public Extent getStateMargin() {
179: return (Extent) getProperty(PROPERTY_STATE_MARGIN);
180: }
181:
182: /**
183: * Returns the position of the state icon relative to the button's
184: * text/icon.
185: *
186: * @return the state position
187: */
188: public Alignment getStatePosition() {
189: return (Alignment) getProperty(PROPERTY_STATE_POSITION);
190: }
191:
192: /**
193: * Determines the selection state.
194: *
195: * @return the selection state
196: */
197: public boolean isSelected() {
198: return ((ToggleButtonModel) getModel()).isSelected();
199: }
200:
201: /**
202: * @see nextapp.echo2.app.Component#processInput(java.lang.String, java.lang.Object)
203: */
204: public void processInput(String name, Object value) {
205: super .processInput(name, value);
206: if (SELECTED_CHANGED_PROPERTY.equals(name)) {
207: setSelected(((Boolean) value).booleanValue());
208: }
209: }
210:
211: /**
212: * Removes a <code>ChangeListener</code> from being notified of state
213: * changes, i.e., to the selected state of a <code>ToggleButton</code>.
214: *
215: * @param l the listener to remove
216: */
217: public void removeChangeListener(ChangeListener l) {
218: getEventListenerList().removeListener(ChangeListener.class, l);
219: }
220:
221: /**
222: * @see nextapp.echo2.app.button.AbstractButton#setModel(nextapp.echo2.app.button.ButtonModel)
223: */
224: public void setModel(ButtonModel newValue) {
225: if (!(newValue instanceof ToggleButtonModel)) {
226: throw new IllegalArgumentException(
227: "Model is not a ToggleButtonModel.");
228: }
229:
230: ToggleButtonModel oldValue = (ToggleButtonModel) getModel();
231:
232: if (oldValue != null) {
233: oldValue.removeChangeListener(changeForwarder);
234: }
235:
236: super .setModel(newValue);
237:
238: ((ToggleButtonModel) newValue)
239: .addChangeListener(changeForwarder);
240: }
241:
242: /**
243: * Sets the selected state icon displayed when the
244: * button is being pressed.
245: *
246: * @param newValue the new icon
247: */
248: public void setPressedSelectedStateIcon(ImageReference newValue) {
249: setProperty(PROPERTY_PRESSED_SELECTED_STATE_ICON, newValue);
250: }
251:
252: /**
253: * Sets the default (non-selected) state icon displayed when the
254: * button is being pressed.
255: *
256: * @param newValue the new icon
257: */
258: public void setPressedStateIcon(ImageReference newValue) {
259: setProperty(PROPERTY_PRESSED_STATE_ICON, newValue);
260: }
261:
262: /**
263: * Sets the selected state icon displayed when the mouse
264: * cursor is inside the bounds of the button.
265: *
266: * @param newValue the new icon
267: */
268: public void setRolloverSelectedStateIcon(ImageReference newValue) {
269: setProperty(PROPERTY_ROLLOVER_SELECTED_STATE_ICON, newValue);
270: }
271:
272: /**
273: * Sets the default (non-selected) state icon displayed when the mouse
274: * cursor is inside the bounds of the button.
275: *
276: * @param newValue the new icon
277: */
278: public void setRolloverStateIcon(ImageReference newValue) {
279: setProperty(PROPERTY_ROLLOVER_STATE_ICON, newValue);
280: }
281:
282: /**
283: * Sets the selected state icon.
284: *
285: * @param newValue the new icon
286: */
287: public void setSelectedStateIcon(ImageReference newValue) {
288: setProperty(PROPERTY_SELECTED_STATE_ICON, newValue);
289: }
290:
291: /**
292: * Sets the selection state.
293: *
294: * @param newValue the new selection state
295: */
296: public void setSelected(boolean newValue) {
297: ((ToggleButtonModel) getModel()).setSelected(newValue);
298: }
299:
300: /**
301: * Sets the alignment of the state icon relative to the text/icon
302: * of the button.
303: * Note that only one of the provided <code>Alignment</code>'s
304: * settings should be non-default.
305: *
306: * @param newValue the new state alignment
307: */
308: public void setStateAlignment(Alignment newValue) {
309: setProperty(PROPERTY_STATE_ALIGNMENT, newValue);
310: }
311:
312: /**
313: * Sets the default (non-selected) state icon.
314: *
315: * @param newValue the new icon
316: */
317: public void setStateIcon(ImageReference newValue) {
318: setProperty(PROPERTY_STATE_ICON, newValue);
319: }
320:
321: /**
322: * Sets the margin size between the state icon and the
323: * toggle button's icon and/or text. The margin will only
324: * be displayed in the case where icon and/or text are
325: * present.
326: * This property only supports <code>Extent</code>s with
327: * fixed (i.e., not percent) units.
328: *
329: * @param newValue the new margin size
330: */
331: public void setStateMargin(Extent newValue) {
332: setProperty(PROPERTY_STATE_MARGIN, newValue);
333: }
334:
335: /**
336: * Sets the position of the state icon relative to the text/icon
337: * of the button.
338: * Note that only one of the provided <code>Alignment</code>'s
339: * settings should be non-default.
340: *
341: * @param newValue the new state position
342: */
343: public void setStatePosition(Alignment newValue) {
344: setProperty(PROPERTY_STATE_POSITION, newValue);
345: }
346: }
|