001/**
002*   Please feel free to use any fragment of the code in this file that you need
003*   in your own work. As far as I am concerned, it's in the public domain. No
004*   permission is necessary or required. Credit is always appreciated if you
005*   use a large chunk or base a significant product on one of my examples,
006*   but that's not required either.
007*
008*   This code is distributed in the hope that it will be useful,
009*   but WITHOUT ANY WARRANTY; without even the implied warranty of
010*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
011*
012*      --- Joseph A. Huwaldt
013**/
014package jahuwaldt.swing;
015
016import java.util.*;
017
018import javax.swing.*;
019
020
021/**
022 * Extends
023 * <code>javax.swing.ButtonGroup</code> to provide methods that allow working
024 * with button references instead of button models.
025 *
026 * Modified by Joseph A. Huwaldt, Date: September 16, 2012
027 *
028 * @author Daniel Tofan
029 * @version 1.0 April 2003
030 * @see ButtonGroup
031 */
032@SuppressWarnings("serial")
033public class JButtonGroup extends ButtonGroup {
034
035    /**
036     * Stores a reference to the currently selected button in the group
037     */
038    private AbstractButton selectedButton;
039    /**
040     * Previously selected button.
041         *
042     */
043    private AbstractButton prevSelectedButton;
044
045    /**
046     * Creates an empty
047     * <code>JButtonGroup</code>
048     */
049    public JButtonGroup() {
050        super();
051    }
052
053    /**
054     * Creates a
055     * <code>JButtonGroup</code> object from an array of buttons and adds the
056     * buttons to the group No button will be selected initially.
057     *
058     * @param buttons an array of
059     * <code>AbstractButton</code>s
060     */
061    public JButtonGroup(AbstractButton[] buttons) {
062        add(buttons);
063    }
064
065    /**
066     * Adds a button to the group
067     *
068     * @param button an
069     * <code>AbstractButton</code> reference
070     */
071    @Override
072    public void add(AbstractButton button) {
073        if (button == null || buttons.contains(button)) {
074            return;
075        }
076        super.add(button);
077        if (getSelection() == button.getModel()) {
078            selectedButton = button;
079        }
080    }
081
082    /**
083     * Adds an array of buttons to the group
084     *
085     * @param buttons an array of
086     * <code>AbstractButton</code>s
087     */
088    public final void add(AbstractButton[] buttons) {
089        if (buttons == null) {
090            return;
091        }
092        for (int i = 0; i < buttons.length; i++) {
093            add(buttons[i]);
094        }
095    }
096
097    /**
098     * Removes a button from the group
099     *
100     * @param button the button to be removed
101     */
102    @Override
103    public void remove(AbstractButton button) {
104        if (button != null) {
105            if (selectedButton == button) {
106                selectedButton = null;
107            }
108            if (prevSelectedButton == button) {
109                prevSelectedButton = null;
110            }
111            super.remove(button);
112        }
113    }
114
115    /**
116     * Removes all the buttons in the array from the group
117     *
118     * @param buttons an array of
119     * <code>AbstractButton</code>s
120     */
121    public void remove(AbstractButton[] buttons) {
122        if (buttons == null) {
123            return;
124        }
125        for (int i = 0; i < buttons.length; i++) {
126            remove(buttons[i]);
127        }
128    }
129
130    /**
131     * Sets the selected button in the group Only one button in the group can be
132     * selected
133     *
134     * @param button an
135     * <code>AbstractButton</code> reference
136     * @param selected an
137     * <code>boolean</code> representing the selection state of the button
138     */
139    public void setSelected(AbstractButton button, boolean selected) {
140        if (button != null && buttons.contains(button)) {
141            setSelected(button.getModel(), selected);
142            if (getSelection() == button.getModel()) {
143                selectedButton = button;
144            }
145        }
146    }
147
148    /**
149     * Sets the selected button model in the group
150     *
151     * @param model a
152     * <code>ButtonModel</code> reference
153     * @param selected an
154     * <code>boolean</code> representing the selection state of the button
155     */
156    @Override
157    public void setSelected(ButtonModel model, boolean selected) {
158        AbstractButton button = getButton(model);
159        if (buttons.contains(button)) {
160            prevSelectedButton = getSelected();
161            super.setSelected(model, selected);
162            selectedButton = button;
163        }
164    }
165
166    /**
167     * Returns the
168     * <code>AbstractButton</code> whose
169     * <code>ButtonModel</code> is given. If the model does not belong to a
170     * button in the group, returns null.
171     *
172     * @param model a
173     * <code>ButtonModel</code> that should belong to a button in the group
174     * @return an
175     * <code>AbstractButton</code> reference whose model is
176     * <code>model</code> if the button belongs to the group,
177     * <code>null</code>otherwise
178     */
179    public AbstractButton getButton(ButtonModel model) {
180        for (AbstractButton ab : buttons) {
181            if (ab.getModel() == model) {
182                return ab;
183            }
184        }
185        return null;
186    }
187
188    /**
189     * Returns the selected button in the group.
190     *
191     * @return a reference to the currently selected button in the group or
192     * <code>null</code> if no button is selected
193     */
194    public AbstractButton getSelected() {
195        return selectedButton;
196    }
197
198    /**
199     * Returns the button that was selected prior to the currently selected
200     * button in the group.
201     *
202     * @return a reference to the button selected prior to the currently
203     * selected button in the group or
204     * <code>null</code> if no button was selected prior to the currently
205     * selected button.
206     */
207    public AbstractButton getPreviousSelected() {
208        return prevSelectedButton;
209    }
210
211    /**
212     * Returns whether the button is selected
213     *
214     * @param button an
215     * <code>AbstractButton</code> reference
216     * @return
217     * <code>true</code> if the button is selected,
218     * <code>false</code> otherwise
219     */
220    public boolean isSelected(AbstractButton button) {
221        return button == selectedButton;
222    }
223
224    /**
225     * Returns the buttons in the group as a
226     * <code>List</code>
227     *
228     * @return a
229     * <code>List</code> containing the buttons in the group, in the order they
230     * were added to the group
231     */
232    public List<AbstractButton> getButtons() {
233        return Collections.unmodifiableList(buttons);
234    }
235
236    /**
237     * Checks whether the group contains the given button
238     *
239     * @return
240     * <code>true</code> if the button is contained in the group,
241     * <code>false</code> otherwise
242     */
243    public boolean contains(AbstractButton button) {
244        return buttons.contains(button);
245    }
246
247    /**
248     * Enables or disables all the buttons in this button group.
249     */
250    public void setEnabled(boolean flag) {
251        List<AbstractButton> btns = getButtons();
252        for (AbstractButton button : btns) {
253            button.setEnabled(flag);
254        }
255    }
256
257    /**
258     * Returns true if any button in this button group is enabled.
259     */
260    public boolean isEnabled() {
261        List<AbstractButton> btns = getButtons();
262        for (AbstractButton button : btns) {
263            if (button.isEnabled()) {
264                return true;
265            }
266        }
267        return false;
268    }
269}