package org.gwtbootstrap3.client.ui;
/*
* #%L
* GwtBootstrap3
* %%
* Copyright (C) 2013 GwtBootstrap3
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import org.gwtbootstrap3.client.ui.base.HasActive;
import org.gwtbootstrap3.client.ui.base.HasIcon;
import org.gwtbootstrap3.client.ui.base.HasIconPosition;
import org.gwtbootstrap3.client.ui.base.HasSize;
import org.gwtbootstrap3.client.ui.base.HasType;
import org.gwtbootstrap3.client.ui.base.helper.StyleHelper;
import org.gwtbootstrap3.client.ui.base.mixin.ActiveMixin;
import org.gwtbootstrap3.client.ui.constants.ButtonSize;
import org.gwtbootstrap3.client.ui.constants.ButtonType;
import org.gwtbootstrap3.client.ui.constants.IconFlip;
import org.gwtbootstrap3.client.ui.constants.IconPosition;
import org.gwtbootstrap3.client.ui.constants.IconRotate;
import org.gwtbootstrap3.client.ui.constants.IconSize;
import org.gwtbootstrap3.client.ui.constants.IconType;
import org.gwtbootstrap3.client.ui.constants.Styles;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.i18n.client.HasDirection.Direction;
import com.google.gwt.i18n.shared.DirectionEstimator;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.uibinder.client.UiConstructor;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
/**
* Button representing a radio button used within a {@link ButtonGroup} that has
* toggle set to {@code Toogle.BUTTONS}.
* <p/>
* If you are looking for a classic radio button see {@link RadioButton}.
*
* @author Sven Jacobs
*/
public class RadioButton extends Radio implements HasActive,
HasType<ButtonType>, HasSize<ButtonSize>, HasIcon, HasIconPosition {
private final ActiveMixin<RadioButton> activeMixin = new ActiveMixin<RadioButton>(this);
private IconPosition iconPosition = IconPosition.LEFT;
private Icon icon;
/**
* Creates a new radio associated with a particular group, and initialized
* with the given HTML label. All radio buttons associated with the same
* group name belong to a mutually-exclusive set.
*
* Radio buttons are grouped by their name attribute, so changing their name
* using the setName() method will also change their associated group.
*
* @param name
* the group name with which to associate the radio button
* @param label
* this radio button's html label
*/
public RadioButton(String name, SafeHtml label) {
this(name, label.asString(), true);
}
/**
* @see #RadioButtonToggle(String, SafeHtml)
*
* @param name
* the group name with which to associate the radio button
* @param label
* this radio button's html label
* @param dir
* the text's direction. Note that {@code DEFAULT} means
* direction should be inherited from the widget's parent
* element.
*/
public RadioButton(String name, SafeHtml label, Direction dir) {
this(name);
setHTML(label, dir);
}
/**
* @see #RadioButtonToggle(String, SafeHtml)
*
* @param name
* the group name with which to associate the radio button
* @param label
* this radio button's html label
* @param directionEstimator
* A DirectionEstimator object used for automatic direction
* adjustment. For convenience,
* {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
*/
public RadioButton(String name, SafeHtml label, DirectionEstimator directionEstimator) {
this(name);
setDirectionEstimator(directionEstimator);
setHTML(label.asString());
}
/**
* Creates a new radio associated with a particular group, and initialized
* with the given HTML label. All radio buttons associated with the same
* group name belong to a mutually-exclusive set.
*
* Radio buttons are grouped by their name attribute, so changing their name
* using the setName() method will also change their associated group.
*
* @param name
* the group name with which to associate the radio button
* @param label
* this radio button's label
*/
public RadioButton(String name, String label) {
this(name);
setText(label);
}
/**
* @see #RadioButtonToggle(String, SafeHtml)
*
* @param name
* the group name with which to associate the radio button
* @param label
* this radio button's label
* @param dir
* the text's direction. Note that {@code DEFAULT} means
* direction should be inherited from the widget's parent
* element.
*/
public RadioButton(String name, String label, Direction dir) {
this(name);
setText(label, dir);
}
/**
* @see #RadioButtonToggle(String, SafeHtml)
*
* @param name
* the group name with which to associate the radio button
* @param label
* this radio button's label
* @param directionEstimator
* A DirectionEstimator object used for automatic direction
* adjustment. For convenience,
* {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
*/
public RadioButton(String name, String label, DirectionEstimator directionEstimator) {
this(name);
setDirectionEstimator(directionEstimator);
setText(label);
}
/**
* Creates a new radio button associated with a particular group, and
* initialized with the given label (optionally treated as HTML). All radio
* buttons associated with the same group name belong to a
* mutually-exclusive set.
*
* Radio buttons are grouped by their name attribute, so changing their name
* using the setName() method will also change their associated group.
*
* @param name
* name the group with which to associate the radio button
* @param label
* this radio button's label
* @param asHTML
* <code>true</code> to treat the specified label as HTML
*/
public RadioButton(String name, String label, boolean asHTML) {
this(name);
if (asHTML) {
setHTML(label);
} else {
setText(label);
}
}
@UiConstructor
public RadioButton(String name) {
this(Document.get().createRadioInputElement(name));
}
protected RadioButton(InputElement element) {
super(DOM.createLabel(), element);
setStyleName(Styles.BTN);
setType(ButtonType.DEFAULT);
getElement().appendChild(inputElem);
getElement().appendChild(Document.get().createTextNode(" "));
getElement().appendChild(labelElem);
getElement().appendChild(Document.get().createTextNode(" "));
}
@Override
protected void ensureDomEventHandlers() {
// Use a ClickHandler since Bootstrap's jQuery does not trigger native
// change events:
// http://learn.jquery.com/events/triggering-event-handlers/
addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
final boolean oldValue = getValue();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
ValueChangeEvent.fireIfNotEqual(RadioButton.this,
oldValue, getValue());
}
});
}
});
}
@Override
public void sinkEvents(int eventBitsToAdd) {
// Sink on the actual element because that's what gets clicked
if (isOrWasAttached()) {
Event.sinkEvents(getElement(),
eventBitsToAdd | Event.getEventsSunk(getElement()));
} else {
super.sinkEvents(eventBitsToAdd);
}
}
@Override
public void setSize(ButtonSize size) {
StyleHelper.addUniqueEnumStyleName(this, ButtonSize.class, size);
}
@Override
public ButtonSize getSize() {
return ButtonSize.fromStyleName(getStyleName());
}
@Override
public void setType(ButtonType type) {
StyleHelper.addUniqueEnumStyleName(this, ButtonType.class, type);
}
@Override
public ButtonType getType() {
return ButtonType.fromStyleName(getStyleName());
}
@Override
public void setActive(boolean active) {
setValue(active);
activeMixin.setActive(active);
}
@Override
public boolean isActive() {
return activeMixin.isActive();
}
@Override
public void setIconPosition(IconPosition iconPosition) {
this.iconPosition = iconPosition;
render();
}
@Override
public IconPosition getIconPosition() {
return iconPosition;
}
@Override
public void setIcon(IconType iconType) {
getActualIcon().setType(iconType);
}
@Override
public IconType getIcon() {
return getActualIcon().getType();
}
@Override
public void setIconSize(IconSize iconSize) {
getActualIcon().setSize(iconSize);
}
@Override
public IconSize getIconSize() {
return getActualIcon().getSize();
}
@Override
public void setIconFlip(IconFlip iconFlip) {
getActualIcon().setFlip(iconFlip);
}
@Override
public IconFlip getIconFlip() {
return getActualIcon().getFlip();
}
@Override
public void setIconRotate(IconRotate iconRotate) {
getActualIcon().setRotate(iconRotate);
}
@Override
public IconRotate getIconRotate() {
return getActualIcon().getRotate();
}
@Override
public void setIconBordered(boolean iconBordered) {
getActualIcon().setBorder(iconBordered);
}
@Override
public boolean isIconBordered() {
return getActualIcon().isBorder();
}
/** {@inheritDoc} */
@Override
public void setIconInverse(final boolean iconInverse) {
getActualIcon().setInverse(iconInverse);
}
/** {@inheritDoc} */
@Override
public boolean isIconInverse() {
return getActualIcon().isInverse();
}
@Override
public void setIconSpin(boolean iconSpin) {
getActualIcon().setSpin(iconSpin);
}
@Override
public boolean isIconSpin() {
return getActualIcon().isSpin();
}
@Override
public void setIconPulse(boolean iconPulse) {
getActualIcon().setPulse(iconPulse);
}
@Override
public boolean isIconPulse() {
return getActualIcon().isPulse();
}
@Override
public void setIconFixedWidth(boolean iconFixedWidth) {
getActualIcon().setFixedWidth(iconFixedWidth);
}
@Override
public boolean isIconFixedWidth() {
return getActualIcon().isFixedWidth();
}
private Icon getActualIcon() {
if (icon == null) {
icon = new Icon();
render();
}
return icon;
}
private void render() {
if (iconPosition == IconPosition.LEFT) {
getElement().insertAfter(icon.getElement(), inputElem);
} else {
getElement().insertAfter(icon.getElement(), null);
}
}
@Override
public void setIconColor(String iconColor) {
getActualIcon().setColor(iconColor);
}
}