001: /* *************************************************************************
002:
003: Millstone(TM)
004: Open Sourced User Interface Library for
005: Internet Development with Java
006:
007: Millstone is a registered trademark of IT Mill Ltd
008: Copyright (C) 2000-2005 IT Mill Ltd
009:
010: *************************************************************************
011:
012: This library is free software; you can redistribute it and/or
013: modify it under the terms of the GNU Lesser General Public
014: license version 2.1 as published by the Free Software Foundation.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: *************************************************************************
026:
027: For more information, contact:
028:
029: IT Mill Ltd phone: +358 2 4802 7180
030: Ruukinkatu 2-4 fax: +358 2 4802 7181
031: 20540, Turku email: info@itmill.com
032: Finland company www: www.itmill.com
033:
034: Primary source for MillStone information and releases: www.millstone.org
035:
036: ********************************************************************** */
037:
038: package org.millstone.base.ui;
039:
040: import java.util.Map;
041: import java.lang.reflect.Method;
042:
043: import org.millstone.base.data.Property;
044: import org.millstone.base.terminal.PaintTarget;
045: import org.millstone.base.terminal.PaintException;
046:
047: /** A generic button component.
048: *
049: * @author IT Mill Ltd.
050: * @version 3.1.1
051: * @since 3.0
052: */
053: public class Button extends AbstractField {
054:
055: /* Final members *************************************************** */
056:
057: /** strings to be catched at adatapter (transformer) */
058: private static final String BUTTON_VAR_NAME = "clicked";
059:
060: /* Private members ************************************************* */
061:
062: boolean switchMode = false;
063:
064: /** Creates a new push button.
065: *
066: * The value of the push button is allways false and they are
067: * immediate by default.
068: *
069: */
070: public Button() {
071: setSwitchMode(false);
072: }
073:
074: /** Creates a new push button.
075: *
076: * The value of the push button is allways false and they are
077: * immediate by default.
078: *
079: * @param caption Button caption
080: */
081: public Button(String caption) {
082: setCaption(caption);
083: setSwitchMode(false);
084: }
085:
086: /** Creates a new push button with click listener.
087: * @param caption Button caption
088: * @param listener Button click listener
089: */
090: public Button(String caption, ClickListener listener) {
091: this (caption);
092: addListener(listener);
093: }
094:
095: /** Creates a new push button with a method listening button clicks.
096: * The method must have either no parameters, or only one parameter of
097: * Button.ClickEvent type.
098: * @param caption Button caption
099: * @param target Object having the method for listening button clicks
100: * @param methodName The name of the method in target object, that
101: * receives button click events.
102: */
103: public Button(String caption, Object target, String methodName) {
104: this (caption);
105: addListener(ClickEvent.class, target, methodName);
106: }
107:
108: /** Creates new switch button with initial value.
109: * @param state Initial state of the switch-button.
110: */
111: public Button(String caption, boolean initialState) {
112: setCaption(caption);
113: setValue(new Boolean(initialState));
114: setSwitchMode(true);
115: }
116:
117: /** Creates new switch button that is connected to a boolean property.
118: * @param state Initial state of the switch-button.
119: */
120: public Button(String caption, Property dataSource) {
121: setCaption(caption);
122: setSwitchMode(true);
123: setPropertyDataSource(dataSource);
124: }
125:
126: /** Get component UIDL tag.
127: * @return Component UIDL tag as string.
128: */
129: public String getTag() {
130: return "button";
131: }
132:
133: /** Paint the content of this component.
134: * @param event PaintEvent.
135: * @throws IOException Passed from the UIDLStream.
136: * @throws PaintException The paint operation failed.
137: */
138: public void paintContent(PaintTarget target) throws PaintException {
139: super .paintContent(target);
140:
141: if (isSwitchMode())
142: target.addAttribute("type", "switch");
143: boolean state;
144: try {
145: state = ((Boolean) getValue()).booleanValue();
146: } catch (NullPointerException e) {
147: state = false;
148: }
149: target.addVariable(this , "state", state);
150: }
151:
152: /** Invoked when the value of a variable has changed. Button
153: * listeners are notified if the button is clicked.
154: * @param event Variable change event.
155: */
156: public void changeVariables(Object source, Map variables) {
157: if (variables.containsKey("state")) {
158: // Get the new and old button states
159: Boolean newValue = (Boolean) variables.get("state");
160: Boolean oldValue = (Boolean) getValue();
161:
162: if (isSwitchMode()) {
163:
164: // For switch button, the event is only sent if the
165: // switch state is changed
166: if (newValue != null && !newValue.equals(oldValue)
167: && !isReadOnly()) {
168: setValue(newValue);
169: fireClick();
170: }
171: } else {
172:
173: // Only send click event if the button is pushed
174: if (newValue.booleanValue())
175: fireClick();
176:
177: // If the button is true for some reason, release it
178: if (oldValue.booleanValue())
179: setValue(new Boolean(false));
180: }
181: }
182: }
183:
184: /**
185: * Returns the switchMode.
186: * @return boolean
187: */
188: public boolean isSwitchMode() {
189: return switchMode;
190: }
191:
192: /**
193: * Sets the switchMode.
194: * @param switchMode The switchMode to set
195: */
196: public void setSwitchMode(boolean switchMode) {
197: this .switchMode = switchMode;
198: if (!switchMode) {
199: setImmediate(true);
200: setValue(new Boolean(false));
201: }
202: }
203:
204: /** Set immediate mode.
205: * @see org.millstone.base.ui.AbstractComponent#setImmediate(boolean)
206: *
207: * Push buttons can not be set in non-immediate mode.
208: */
209: public void setImmediate(boolean immediate) {
210: // Push buttons are allways immediate
211: super .setImmediate(!isSwitchMode() || immediate);
212: }
213:
214: /** The type of the button as a property.
215: * @see org.millstone.base.data.Property#getType()
216: */
217: public Class getType() {
218: return Boolean.class;
219: }
220:
221: /* Click event ************************************************ */
222:
223: private static final Method BUTTON_CLICK_METHOD;
224: static {
225: try {
226: BUTTON_CLICK_METHOD = ClickListener.class
227: .getDeclaredMethod("buttonClick",
228: new Class[] { ClickEvent.class });
229: } catch (java.lang.NoSuchMethodException e) {
230: // This should never happen
231: throw new java.lang.RuntimeException();
232: }
233: }
234:
235: /** Click event. This event is thrown, when the button is clicked.
236: * @author IT Mill Ltd.
237: * @version 3.1.1
238: * @since 3.0
239: */
240: public class ClickEvent extends Component.Event {
241:
242: /**
243: * Serial generated by eclipse.
244: */
245: private static final long serialVersionUID = 3546647602931118393L;
246:
247: /** New instance of text change event
248: * @param source Source of the event.
249: */
250: public ClickEvent(Component source) {
251: super (source);
252: }
253:
254: /** Button where the event occurred
255: * @return Source of the event.
256: */
257: public Button getButton() {
258: return (Button) getSource();
259: }
260: }
261:
262: /** Button click listener
263: * @author IT Mill Ltd.
264: * @version 3.1.1
265: * @since 3.0
266: */
267: public interface ClickListener {
268:
269: /** Button has been pressed.
270: * @param event Button click event.
271: */
272: public void buttonClick(ClickEvent event);
273: }
274:
275: /** Add button click listener
276: * @param listener Listener to be added.
277: */
278: public void addListener(ClickListener listener) {
279: addListener(ClickEvent.class, listener, BUTTON_CLICK_METHOD);
280: }
281:
282: /** Remove button click listener
283: * @param listener Listener to be removed.
284: */
285: public void removeListener(ClickListener listener) {
286: removeListener(ClickEvent.class, listener, BUTTON_CLICK_METHOD);
287: }
288:
289: /** Emit options change event. */
290: protected void fireClick() {
291: fireEvent(new Button.ClickEvent(this));
292: }
293: }
|