001package 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
023import org.gwtbootstrap3.client.ui.constants.Styles;
024import org.gwtbootstrap3.client.ui.impl.RadioImpl;
025
026import com.google.gwt.core.shared.GWT;
027import com.google.gwt.dom.client.Document;
028import com.google.gwt.dom.client.Element;
029import com.google.gwt.dom.client.InputElement;
030import com.google.gwt.dom.client.LabelElement;
031import com.google.gwt.event.logical.shared.ValueChangeEvent;
032import com.google.gwt.i18n.client.HasDirection.Direction;
033import com.google.gwt.i18n.shared.DirectionEstimator;
034import com.google.gwt.safehtml.shared.SafeHtml;
035import com.google.gwt.uibinder.client.UiConstructor;
036import 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 */
056public 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}