KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > wings > SAbstractButton


1 /*
2  * $Id: SAbstractButton.java,v 1.13 2005/05/26 13:18:08 neurolabs Exp $
3  * Copyright 2000,2005 wingS development team.
4  *
5  * This file is part of wingS (http://www.j-wings.org).
6  *
7  * wingS is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2.1
10  * of the License, or (at your option) any later version.
11  *
12  * Please see COPYING for the complete licence.
13  */

14 package org.wings;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.wings.plaf.ButtonCG;
19
20 import javax.swing.*;
21 import java.awt.event.ActionEvent JavaDoc;
22 import java.awt.event.ActionListener JavaDoc;
23 import java.beans.PropertyChangeEvent JavaDoc;
24 import java.beans.PropertyChangeListener JavaDoc;
25
26 /**
27  * This is the base class for all components which have a button
28  * functionality. This class handles ActionListener notification.
29  *
30  * @author <a HREF="mailto:armin.haaf@mercatis.de">Armin Haaf</a>
31  * @version $Revision: 1.13 $
32  */

33 public abstract class SAbstractButton
34         extends SAbstractIconTextCompound
35         implements LowLevelEventListener {
36     private final transient static Log log = LogFactory.getLog(SAbstractButton.class);
37
38     public static final String JavaDoc SUBMIT_BUTTON = "submit";
39     public static final String JavaDoc RESET_BUTTON = "reset";
40     public static final String JavaDoc IMAGE_BUTTON = "image";
41     public static final String JavaDoc CHECKBOX = "checkbox";
42     public static final String JavaDoc RADIOBUTTON = "radio";
43
44     private String JavaDoc type = SUBMIT_BUTTON;
45
46     private SButtonGroup buttonGroup;
47
48     protected String JavaDoc actionCommand;
49
50     private String JavaDoc eventTarget;
51
52     private Action action;
53
54     private PropertyChangeListener JavaDoc actionPropertyChangeListener;
55
56     private String JavaDoc mnemonic;
57
58     /** @see LowLevelEventListener#isEpochCheckEnabled() */
59     private boolean epochCheckEnabled = true;
60
61     /**
62      * Create a button with given text.
63      *
64      * @param text the button text
65      */

66     public SAbstractButton(String JavaDoc text) {
67         super(text);
68     }
69
70     public SAbstractButton(Action action) {
71         setAction(action);
72     }
73
74     /**
75      * Creates a new Button with the given Text and the given Type.
76      *
77      * @param text the button text
78      * @param type the button type
79      * @see #setType
80      */

81     public SAbstractButton(String JavaDoc text, String JavaDoc type) {
82         this(text);
83         setType(type);
84     }
85
86     /**
87      * Creates a new submit button
88      */

89     public SAbstractButton() {
90     }
91
92     /**
93      * Sets the action command for this button.
94      *
95      * @param ac the action command for this button
96      */

97     public void setActionCommand(String JavaDoc ac) {
98         actionCommand = ac;
99     }
100
101     /**
102      * Returns the action command for this button.
103      *
104      * @return the action command for this button
105      */

106     public final String JavaDoc getActionCommand() {
107         return actionCommand;
108     }
109
110
111     /**
112      * TODO: Return the Button group where this button lies in
113      *
114      * @return Button Group or null if not in a group
115      */

116     public final SButtonGroup getGroup() {
117         return buttonGroup;
118     }
119
120     protected void setParentFrame(SFrame f) {
121         if (buttonGroup != null && getDispatcher() != null) {
122             getDispatcher().removeLowLevelEventListener(this, buttonGroup.getComponentId());
123         } // end of if ()
124

125         super.setParentFrame(f);
126
127         if (buttonGroup != null && getDispatcher() != null) {
128             getDispatcher().addLowLevelEventListener(this, buttonGroup.getComponentId());
129         } // end of if ()
130
}
131
132     /**
133      * Add this button to a button group. This influences the event-prefix
134      * this button reports to the request dispatcher: it will change to
135      * the button group's prefix.
136      */

137     protected void setGroup(SButtonGroup g) {
138         if (isDifferent(buttonGroup, g)) {
139             if (buttonGroup != null && getDispatcher() != null) {
140                 getDispatcher().removeLowLevelEventListener(this, buttonGroup.getComponentId());
141             } // end of if ()
142
buttonGroup = g;
143             if (buttonGroup != null && getDispatcher() != null) {
144                 getDispatcher().removeLowLevelEventListener(this, buttonGroup.getComponentId());
145             } // end of if ()
146
reload();
147         }
148     }
149
150     /**
151      * Adds an ActionListener to the button.
152      *
153      * @param listener the ActionListener to be added
154      */

155     public void addActionListener(ActionListener JavaDoc listener) {
156         addEventListener(ActionListener JavaDoc.class, listener);
157     }
158
159     /**
160      * Removes the supplied Listener from teh listener list
161      */

162     public void removeActionListener(ActionListener JavaDoc listener) {
163         removeEventListener(ActionListener JavaDoc.class, listener);
164     }
165
166     /**
167      * Returns an array of all the <code>ActionListener</code>s added
168      * to this AbstractButton with addActionListener().
169      *
170      * @return all of the <code>ActionListener</code>s added or an empty
171      * array if no listeners have been added
172      */

173     public ActionListener JavaDoc[] getActionListeners() {
174         return (ActionListener JavaDoc[]) (getListeners(ActionListener JavaDoc.class));
175     }
176
177     /**
178      * Fire an ActionEvent at each registered listener.
179      *
180      * @param event supplied ActionEvent
181      */

182     protected void fireActionPerformed(ActionEvent JavaDoc event) {
183         // Guaranteed to return a non-null array
184
Object JavaDoc[] listeners = getListenerList();
185         ActionEvent JavaDoc e = null;
186         // Process the listeners last to first, notifying
187
// those that are interested in this event
188
for (int i = listeners.length - 2; i >= 0; i -= 2) {
189             if (listeners[i] == ActionListener JavaDoc.class) {
190                 if (e == null) {
191                     String JavaDoc actionCommand = event.getActionCommand();
192                     if (actionCommand == null) {
193                         actionCommand = getActionCommand();
194                     }
195                     e = new ActionEvent JavaDoc(SAbstractButton.this,
196                             ActionEvent.ACTION_PERFORMED,
197                             actionCommand,
198                             event.getWhen(),
199                             event.getModifiers());
200                 }
201                 ((ActionListener JavaDoc) listeners[i + 1]).actionPerformed(e);
202             }
203         }
204     }
205
206
207     /**
208      * Sets the button type. Use one of the following types:
209      * <UL>
210      * <LI> {@link #SUBMIT_BUTTON}
211      * <LI> {@link #RESET_BUTTON}
212      * <LI> {@link #CHECKBOX}
213      * <LI> {@link #RADIOBUTTON}
214      * </UL>
215      */

216     public void setType(String JavaDoc t) {
217         if (isDifferent(type, t)) {
218             type = t;
219             reload();
220         }
221     }
222
223     /**
224      * Delifers the Button Type
225      *
226      * @return Button Type
227      */

228     public final String JavaDoc getType() {
229         return type;
230     }
231
232     /**
233      * Simulates an click on the Button
234      */

235     public void doClick() {
236         setSelected(!isSelected());
237
238         fireActionPerformed(new ActionEvent JavaDoc(this, ActionEvent.ACTION_PERFORMED, getActionCommand()));
239     }
240
241     /**
242      * Sets the state of the button. *
243      *
244      * @param b true if the button is selected, otherwise false
245      */

246     public void setSelected(boolean b) {
247         if (isSelected() != b) {
248             if (buttonGroup != null) {
249                 buttonGroup.setSelected(this, b);
250             }
251             super.setSelected(b);
252         }
253     }
254
255     public void processLowLevelEvent(String JavaDoc action, String JavaDoc[] values) {
256         processKeyEvents(values);
257
258         boolean requestSelection = isSelected();
259
260         int eventCount = 0;
261
262         if (buttonGroup != null) {
263             // button group prefix is shared, so maybe more than one value is
264
// delivered in a form
265
for (int i = 0; i < values.length; i++) {
266
267                 // with button group the value has a special encoding...
268
// this is because in a form the name of a parameter for
269
// buttons in a buttongroup must be the same...
270
String JavaDoc value = values[i];
271         
272                 // illegal format
273
if (value.length() < 3) { continue; }
274         
275                 // no uid DIVIDER
276
// value.charAt(value.length()-2)!=UID_DIVIDER ) { break; }
277

278                 // not for me
279
if (!value.startsWith(super.getLowLevelEventId())) { continue; }
280         
281                 // last character is indicator, if button should be
282
// selected or not
283
switch (value.charAt(value.length() - 1)) {
284                     case '1':
285                         requestSelection = true;
286                         ++eventCount;
287                         break;
288                     case '0':
289                         requestSelection = false;
290                         ++eventCount;
291                         break;
292                 }
293             }
294         } else {
295             for (int i = 0; i < values.length; i++) {
296                 requestSelection = parseSelectionToggle(values[0]);
297                 ++eventCount;
298             }
299         }
300     
301         /*
302          * Checkboxes in HTML-forms write two form components:
303          * one hidden input, containing the deselect-command (value='0'),
304          * and one <input type="checkbox".. value="1">.
305          * This is, because browsers send the checkbox-variable
306          * only if it is set, not if it is not set.
307          * So, if we get two events with the same name, then the checkbox
308          * actually got selected; if we only got one event (from the hidden
309          * input), then it was a deselect-event (select event value = '1',
310          * deselect value = '0').
311          * This is just in case, the browser sends the both events
312          * in the wrong order (select and then deselect).
313          */

314         if (eventCount == 2) {
315             requestSelection = true;
316         }
317
318         if (isSelected() != requestSelection) {
319             delayEvents(true);
320             if (buttonGroup != null) {
321                 buttonGroup.setDelayEvents(true);
322                 setSelected(requestSelection);
323                 buttonGroup.setDelayEvents(false);
324             } else {
325                 setSelected(requestSelection);
326             }
327
328             SForm.addArmedComponent(this);
329         }
330     }
331
332     public void fireIntermediateEvents() {
333         super.fireIntermediateEvents();
334         if (buttonGroup != null) {
335             buttonGroup.fireDelayedIntermediateEvents();
336         }
337     }
338
339     public void fireFinalEvents() {
340         requestFocus();
341         super.fireFinalEvents();
342         fireActionPerformed(new ActionEvent JavaDoc(this, ActionEvent.ACTION_PERFORMED, getActionCommand()));
343         if (buttonGroup != null)
344             buttonGroup.fireDelayedFinalEvents();
345     }
346
347     public final String JavaDoc getEventTarget() {
348         return eventTarget;
349     }
350
351
352     public void setEventTarget(String JavaDoc target) {
353         if (isDifferent(eventTarget, target)) {
354             eventTarget = target;
355             reload();
356         }
357     }
358
359     protected boolean parseSelectionToggle(String JavaDoc toggleParameter) {
360         if ("1".equals(toggleParameter))
361             return true;
362         else if ("0".equals(toggleParameter))
363             return false;
364     
365         // don't change...
366
return isSelected();
367     }
368
369     public String JavaDoc getToggleSelectionParameter() {
370         return isSelected() ? getDeselectionParameter() : getSelectionParameter();
371     }
372
373     public String JavaDoc getSelectionParameter() {
374         return "1";
375     }
376
377     public String JavaDoc getDeselectionParameter() {
378         return "0";
379     }
380
381
382     /**
383      * Sets the action for the ActionEvent source.
384      * the new action code will replace the old one but not the one bound to the actionListener
385      *
386      * @param a the Action for the AbstractButton,
387      */

388
389     public void setAction(Action a) {
390         Action oldValue = getAction();
391         if (action == null || !action.equals(a)) {
392             action = a;
393             if (oldValue != null) {
394                 removeActionListener(oldValue);
395                 oldValue.removePropertyChangeListener(actionPropertyChangeListener);
396                 actionPropertyChangeListener = null;
397             }
398             configurePropertiesFromAction(action);
399             if (action != null) {
400                 // Don't add if it is already a listener
401
if (!isListener(ActionListener JavaDoc.class, action)) {
402                     addActionListener(action);
403                 }
404                 // Reverse linkage:
405
actionPropertyChangeListener = createActionPropertyChangeListener(action);
406                 action.addPropertyChangeListener(actionPropertyChangeListener);
407             }
408             reload();
409         }
410     }
411
412     private boolean isListener(Class JavaDoc c, ActionListener JavaDoc a) {
413         boolean isListener = false;
414         Object JavaDoc[] listeners = getListenerList();
415         for (int i = listeners.length - 2; i >= 0; i -= 2) {
416             if (listeners[i] == c && listeners[i + 1] == a) {
417                 isListener = true;
418             }
419         }
420         return isListener;
421     }
422
423     /**
424      * Returns the action for this ActionEvent source, or <code>null</code>
425      * if no <code>Action</code> is set.
426      *
427      * @return the <code>Action</code> for this <code>ActionEvent</code>
428      * source, or <code>null</code>
429      */

430     public Action getAction() {
431         return action;
432     }
433
434     public void setCG(ButtonCG cg) {
435         super.setCG(cg);
436     }
437
438     protected void configurePropertiesFromAction(Action a) {
439         // uncomment if compiled against < jdk 1.3
440
// setActionCommand((a != null
441
// ? (String)a.getValue(Action.ACTION_COMMAND_KEY)
442
// : null));
443
setText((a != null ? (String JavaDoc) a.getValue(Action.NAME) : null));
444         setIcon((a != null ? (SIcon) a.getValue(Action.SMALL_ICON) : null));
445         setEnabled((a != null ? a.isEnabled() : true));
446         setToolTipText((a != null ? (String JavaDoc) a.getValue(Action.SHORT_DESCRIPTION) : null));
447     }
448
449     protected PropertyChangeListener JavaDoc createActionPropertyChangeListener(Action a) {
450         return new ButtonActionPropertyChangeListener(this, a);
451     }
452
453     private static class ButtonActionPropertyChangeListener
454             extends AbstractActionPropertyChangeListener {
455         ButtonActionPropertyChangeListener(SAbstractButton b, Action a) {
456             super(b, a);
457         }
458
459         public void propertyChange(PropertyChangeEvent JavaDoc e) {
460             String JavaDoc propertyName = e.getPropertyName();
461             SAbstractButton button = (SAbstractButton) getTarget();
462             if (button == null) {
463                 Action action = (Action) e.getSource();
464                 action.removePropertyChangeListener(this);
465             } else {
466                 if (e.getPropertyName().equals(Action.NAME)) {
467                     String JavaDoc text = (String JavaDoc) e.getNewValue();
468                     button.setText(text);
469                 } else if (e.getPropertyName().equals(Action.SHORT_DESCRIPTION)) {
470                     String JavaDoc text = (String JavaDoc) e.getNewValue();
471                     button.setToolTipText(text);
472                 } else if (propertyName.equals("enabled")) {
473                     Boolean JavaDoc enabled = (Boolean JavaDoc) e.getNewValue();
474                     button.setEnabled(enabled.booleanValue());
475                 } else if (e.getPropertyName().equals(Action.SMALL_ICON)) {
476                     SIcon icon = (SIcon) e.getNewValue();
477                     button.setIcon(icon);
478                 }
479                 // uncomment if compiled against jdk < 1.3
480
/* else if (e.getPropertyName().equals(Action.ACTION_COMMAND_KEY)) {
481                                   String actionCommand = (String)e.getNewValue();
482                                   button.setActionCommand(actionCommand);
483                                   }*/

484             }
485         }
486     }
487
488     public void setMnemonic(String JavaDoc mnemonic) {
489         reloadIfChange(this.mnemonic, mnemonic);
490         this.mnemonic = mnemonic;
491     }
492
493     public String JavaDoc getMnemonic() {
494         return mnemonic;
495     }
496
497     /** @see LowLevelEventListener#isEpochCheckEnabled() */
498     public boolean isEpochCheckEnabled() {
499         return epochCheckEnabled;
500     }
501
502     /** @see LowLevelEventListener#isEpochCheckEnabled() */
503     public void setEpochCheckEnabled(boolean epochCheckEnabled) {
504         this.epochCheckEnabled = epochCheckEnabled;
505     }
506 }
507
Popular Tags