1 /*
2 * Copyright 2006-2016 The JGUIraffe Team.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package net.sf.jguiraffe.gui.platform.swing.builder.components;
17
18 import java.util.Enumeration;
19
20 import javax.swing.AbstractButton;
21 import javax.swing.ButtonGroup;
22
23 import net.sf.jguiraffe.gui.builder.components.Color;
24 import net.sf.jguiraffe.gui.builder.components.WidgetHandler;
25
26 import org.apache.commons.lang.ObjectUtils;
27
28 /**
29 * <p>
30 * A specialized {@link WidgetHandler} implementation for Swing radio groups.
31 * </p>
32 * <p>
33 * A radio group in Swing is somewhat special. It is not a graphical component
34 * on its own, but it merely refers to the actual radio button components.
35 * However, in the <em>JGUIraffe</em> library radio groups are more or less
36 * treated like regular components, and their properties can be accessed through
37 * the {@link WidgetHandler} interface.
38 * </p>
39 * <p>
40 * Because of this a special implementation is needed for radio buttons. This
41 * implementations acts like a typical composite. Set operations are delegated
42 * to all components in the group. For get operations there are some
43 * limitations: Unless noted otherwise for a specific operation, the group widget
44 * handler expects that all radio buttons in the group share the same properties
45 * (e.g. colors or visible state). Therefore it simply returns the corresponding
46 * property of the first button in the group.
47 * </p>
48 * <p>
49 * Implementation notes: This class is not thread-safe. It should be accessed
50 * from the <em>event dispatch thread</em> only. The {@code ButtonGroup} must
51 * not be changed after it was passed to the constructor.
52 * </p>
53 *
54 * @author Oliver Heger
55 * @version $Id: SwingRadioGroupWidgetHandler.java 205 2012-01-29 18:29:57Z oheger $
56 */
57 class SwingRadioGroupWidgetHandler implements WidgetHandler
58 {
59 /** Constant for the tool tip separator. */
60 private static final String TIP_SEPARATOR = "\n";
61
62 /** Stores the underlying button group. */
63 private final ButtonGroup buttonGroup;
64
65 /** An array for easy access to the buttons in the group. */
66 private final AbstractButton[] buttons;
67
68 /** An array with the original tool tips of the radio buttons. */
69 private final String[] buttonTips;
70
71 /** The tool tip of the whole radio group. */
72 private String groupTip;
73
74 /**
75 * Creates a new instance of {@code SwingRadioGroupWidgetHandler} and
76 * initializes it with the underlying {@code ButtonGroup}.
77 *
78 * @param group the {@code ButtonGroup}
79 */
80 public SwingRadioGroupWidgetHandler(ButtonGroup group)
81 {
82 assert group != null : "Null ButtonGroup passed in!";
83 buttonGroup = group;
84
85 buttons = new AbstractButton[group.getButtonCount()];
86 int idx = 0;
87 for (Enumeration<AbstractButton> en = group.getElements(); en
88 .hasMoreElements();)
89 {
90 buttons[idx++] = en.nextElement();
91 }
92 assert buttons.length > 0 : "Group is empty!";
93
94 buttonTips = new String[buttons.length];
95 }
96
97 /**
98 * Returns a reference to the underlying {@code ButtonGroup} object.
99 *
100 * @return the {@code ButtonGroup}
101 */
102 public ButtonGroup getButtonGroup()
103 {
104 return buttonGroup;
105 }
106
107 /**
108 * Returns the background color of this radio button group. This
109 * implementation assumes that all radio buttons in the group have the same
110 * color. So it returns the color of the first radio button.
111 *
112 * @return the background color of this radio button group
113 */
114 public Color getBackgroundColor()
115 {
116 return SwingComponentUtils.getBackgroundColor(buttons[0]);
117 }
118
119 /**
120 * Returns the foreground color of this radio button group. This
121 * implementation assumes that all radio buttons in the group have the same
122 * color. So it returns the color of the first radio button.
123 *
124 * @return the foreground color of this radio button group
125 */
126 public Color getForegroundColor()
127 {
128 return SwingComponentUtils.getForegroundColor(buttons[0]);
129 }
130
131 /**
132 * Returns the tool tip of this radio group. The tool tip for the whole
133 * group is independent of the tips of single radio buttons. So this
134 * implementation just returns the string that was set using
135 * {@link #setToolTip(String)}.
136 *
137 * @return the tool tip of this radio group
138 */
139 public String getToolTip()
140 {
141 return groupTip;
142 }
143
144 /**
145 * Returns the widget wrapped by this handler. This implementation returns
146 * the underlying {@code ButtonGroup} object, which is not a real graphical
147 * widget.
148 *
149 * @return the wrapped widget
150 */
151 public Object getWidget()
152 {
153 return getButtonGroup();
154 }
155
156 /**
157 * Returns the visible state of this radio group. This implementation
158 * expects that all buttons in the group have the same visible state. So
159 * only the first button is checked.
160 *
161 * @return the visible state of this group
162 */
163 public boolean isVisible()
164 {
165 return buttons[0].isVisible();
166 }
167
168 /**
169 * Sets the background color of this radio button group. This implementation
170 * passes the color to all radio buttons in the group. If the color is
171 * <b>null</b>, this method has no effect.
172 *
173 * @param c the new background color
174 */
175 public void setBackgroundColor(Color c)
176 {
177 if (c != null)
178 {
179 for (AbstractButton b : buttons)
180 {
181 SwingComponentUtils.setBackgroundColor(b, c);
182 }
183 }
184 }
185
186 /**
187 * Sets the foreground color of this radio button group. This implementation
188 * passes the color to all radio buttons in the group. If the color is
189 * <b>null</b>, this method has no effect.
190 *
191 * @param c the new foreground color
192 */
193 public void setForegroundColor(Color c)
194 {
195 if (c != null)
196 {
197 for (AbstractButton b : buttons)
198 {
199 SwingComponentUtils.setForegroundColor(b, c);
200 }
201 }
202 }
203
204 /**
205 * Sets the tool tip of this radio group. This implementation sets the
206 * overall tool tip, and it changes the tool tips of the radio buttons that
207 * belong to this group. The tool tips of the radio buttons are generated by
208 * their original tool tip, a separator, plus the group's tool tip.
209 *
210 * @param tip the new tool tip for the whole group
211 */
212 public void setToolTip(String tip)
213 {
214 for (int i = 0; i < buttons.length; i++)
215 {
216 String expectedTip = SwingComponentUtils.combineToolTips(
217 buttonTips[i], groupTip, TIP_SEPARATOR);
218 String currentTip = SwingComponentUtils.getToolTip(buttons[i]);
219 if (!ObjectUtils.equals(expectedTip, currentTip))
220 {
221 // the tip of the button has changed in the mean time
222 buttonTips[i] = currentTip;
223 }
224
225 SwingComponentUtils.setToolTip(buttons[i], buttonTips[i], tip,
226 TIP_SEPARATOR);
227 }
228
229 groupTip = tip;
230 }
231
232 /**
233 * Sets the visible state of this radio group. This implementation sets the
234 * visible state for all radio buttons in the group.
235 *
236 * @param f the new visible state
237 */
238 public void setVisible(boolean f)
239 {
240 for (AbstractButton b : buttons)
241 {
242 b.setVisible(f);
243 }
244 }
245
246 /**
247 * Returns the font of this radio group. This implementation returns the
248 * font of the first button.
249 *
250 * @return the font of this widget
251 */
252 public Object getFont()
253 {
254 return SwingComponentUtils.getFont(buttons[0]);
255 }
256
257 /**
258 * Sets the font for this radio group. This implementation sets the font for
259 * all buttons in the group.
260 *
261 * @param font the font to be set
262 */
263 public void setFont(Object font)
264 {
265 for (AbstractButton b : buttons)
266 {
267 SwingComponentUtils.setFont(b, font);
268 }
269 }
270 }