001 package org.gwtbootstrap3.client.ui;
002
003 /*
004 * #%L
005 * GwtBootstrap3
006 * %%
007 * Copyright (C) 2013 GwtBootstrap3
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 * http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023 import org.gwtbootstrap3.client.ui.constants.Styles;
024 import org.gwtbootstrap3.client.ui.impl.RadioImpl;
025
026 import com.google.gwt.core.shared.GWT;
027 import com.google.gwt.dom.client.Document;
028 import com.google.gwt.dom.client.Element;
029 import com.google.gwt.dom.client.InputElement;
030 import com.google.gwt.dom.client.LabelElement;
031 import com.google.gwt.event.logical.shared.ValueChangeEvent;
032 import com.google.gwt.i18n.client.HasDirection.Direction;
033 import com.google.gwt.i18n.shared.DirectionEstimator;
034 import com.google.gwt.safehtml.shared.SafeHtml;
035 import com.google.gwt.uibinder.client.UiConstructor;
036 import com.google.gwt.user.client.DOM;
037
038 /**
039 * A mutually-exclusive selection radio button widget. Fires
040 * {@link com.google.gwt.event.dom.client.ClickEvent ClickEvents} when the radio
041 * button is clicked, and {@link ValueChangeEvent ValueChangeEvents} when the
042 * button becomes checked. Note, however, that browser limitations prevent
043 * ValueChangeEvents from being sent when the radio button is cleared as a side
044 * effect of another in the group being clicked.
045 *
046 * <p>
047 * <h3>Built-in Bidi Text Support</h3>
048 * This widget is capable of automatically adjusting its direction according to
049 * its content. This feature is controlled by {@link #setDirectionEstimator} or
050 * passing a DirectionEstimator parameter to the constructor, and is off by
051 * default.
052 * </p>
053 *
054 * @author Sven Jacobs
055 */
056 public class Radio extends CheckBox {
057
058 private static final RadioImpl impl = GWT.create(RadioImpl.class);
059
060 /**
061 * Creates a new radio associated with a particular group, and initialized
062 * with the given HTML label. All radio buttons associated with the same
063 * group name belong to a mutually-exclusive set.
064 *
065 * Radio buttons are grouped by their name attribute, so changing their name
066 * using the setName() method will also change their associated group.
067 *
068 * @param name
069 * the group name with which to associate the radio button
070 * @param label
071 * this radio button's html label
072 */
073 public Radio(String name, SafeHtml label) {
074 this(name, label.asString(), true);
075 }
076
077 /**
078 * @see #RadioButton(String, SafeHtml)
079 *
080 * @param name
081 * the group name with which to associate the radio button
082 * @param label
083 * this radio button's html label
084 * @param dir
085 * the text's direction. Note that {@code DEFAULT} means
086 * direction should be inherited from the widget's parent
087 * element.
088 */
089 public Radio(String name, SafeHtml label, Direction dir) {
090 this(name);
091 setHTML(label, dir);
092 }
093
094 /**
095 * @see #RadioButton(String, SafeHtml)
096 *
097 * @param name
098 * the group name with which to associate the radio button
099 * @param label
100 * this radio button's html label
101 * @param directionEstimator
102 * A DirectionEstimator object used for automatic direction
103 * adjustment. For convenience,
104 * {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
105 */
106 public Radio(String name, SafeHtml label, DirectionEstimator directionEstimator) {
107 this(name);
108 setDirectionEstimator(directionEstimator);
109 setHTML(label.asString());
110 }
111
112 /**
113 * Creates a new radio associated with a particular group, and initialized
114 * with the given HTML label. All radio buttons associated with the same
115 * group name belong to a mutually-exclusive set.
116 *
117 * Radio buttons are grouped by their name attribute, so changing their name
118 * using the setName() method will also change their associated group.
119 *
120 * @param name
121 * the group name with which to associate the radio button
122 * @param label
123 * this radio button's label
124 */
125 public Radio(String name, String label) {
126 this(name);
127 setText(label);
128 }
129
130 /**
131 * @see #RadioButton(String, SafeHtml)
132 *
133 * @param name
134 * the group name with which to associate the radio button
135 * @param label
136 * this radio button's label
137 * @param dir
138 * the text's direction. Note that {@code DEFAULT} means
139 * direction should be inherited from the widget's parent
140 * element.
141 */
142 public Radio(String name, String label, Direction dir) {
143 this(name);
144 setText(label, dir);
145 }
146
147 /**
148 * @see #RadioButton(String, SafeHtml)
149 *
150 * @param name
151 * the group name with which to associate the radio button
152 * @param label
153 * this radio button's label
154 * @param directionEstimator
155 * A DirectionEstimator object used for automatic direction
156 * adjustment. For convenience,
157 * {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
158 */
159 public Radio(String name, String label, DirectionEstimator directionEstimator) {
160 this(name);
161 setDirectionEstimator(directionEstimator);
162 setText(label);
163 }
164
165 /**
166 * Creates a new radio button associated with a particular group, and
167 * initialized with the given label (optionally treated as HTML). All radio
168 * buttons associated with the same group name belong to a
169 * mutually-exclusive set.
170 *
171 * Radio buttons are grouped by their name attribute, so changing their name
172 * using the setName() method will also change their associated group.
173 *
174 * @param name
175 * name the group with which to associate the radio button
176 * @param label
177 * this radio button's label
178 * @param asHTML
179 * <code>true</code> to treat the specified label as HTML
180 */
181 public Radio(String name, String label, boolean asHTML) {
182 this(name);
183 if (asHTML) {
184 setHTML(label);
185 } else {
186 setText(label);
187 }
188 }
189
190 /**
191 * Creates a new radio associated with a particular group name. All radio
192 * buttons associated with the same group name belong to a
193 * mutually-exclusive set.
194 *
195 * Radio buttons are grouped by their name attribute, so changing their name
196 * using the setName() method will also change their associated group.
197 *
198 * @param name
199 * the group name with which to associate the radio button
200 */
201 @UiConstructor
202 public Radio(String name) {
203 super(DOM.createDiv(), Document.get().createRadioInputElement(name));
204 setStyleName(Styles.RADIO);
205
206 LabelElement label = Document.get().createLabelElement();
207 label.appendChild(inputElem);
208 label.appendChild(labelElem);
209
210 getElement().appendChild(label);
211 }
212
213 protected Radio(Element elem, InputElement inputElement) {
214 super(elem, inputElement);
215 }
216
217 /**
218 * Change the group name of this radio button.
219 *
220 * Radio buttons are grouped by their name attribute, so changing their name
221 * using the setName() method will also change their associated group.
222 *
223 * If changing this group name results in a new radio group with multiple
224 * radio buttons selected, this radio button will remain selected and the
225 * other radio buttons will be unselected.
226 *
227 * @param name
228 * name the group with which to associate the radio button
229 */
230 @Override
231 public void setName(String name) {
232 super.setName(name);
233 }
234
235 @Override
236 protected void ensureDomEventHandlers() {
237 impl.ensureDomEventHandlers(this);
238 }
239
240 @Override
241 public void sinkEvents(int eventBitsToAdd) {
242 if (isOrWasAttached()) {
243 impl.sinkEvents(eventBitsToAdd, inputElem, labelElem);
244 } else {
245 super.sinkEvents(eventBitsToAdd);
246 }
247 }
248
249 }