package org.gwtbootstrap3.client.ui.base;
/*
* #%L
* GwtBootstrap3
* %%
* Copyright (C) 2015 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 java.text.ParseException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.gwtbootstrap3.client.ui.Radio;
import org.gwtbootstrap3.client.ui.base.mixin.BlankValidatorMixin;
import org.gwtbootstrap3.client.ui.base.mixin.ErrorHandlerMixin;
import org.gwtbootstrap3.client.ui.form.error.ErrorHandler;
import org.gwtbootstrap3.client.ui.form.error.ErrorHandlerType;
import org.gwtbootstrap3.client.ui.form.error.HasErrorHandler;
import org.gwtbootstrap3.client.ui.form.validator.HasBlankValidator;
import org.gwtbootstrap3.client.ui.form.validator.HasValidators;
import org.gwtbootstrap3.client.ui.form.validator.RadioGroupBlankValidatorMixin;
import org.gwtbootstrap3.client.ui.form.validator.ValidationChangedEvent.ValidationChangedHandler;
import org.gwtbootstrap3.client.ui.form.validator.Validator;
import org.gwtbootstrap3.client.ui.gwt.FlowPanel;
import com.google.gwt.editor.client.EditorError;
import com.google.gwt.editor.client.HasEditorErrors;
import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.text.shared.Parser;
import com.google.gwt.user.client.ui.HasName;
import com.google.gwt.user.client.ui.HasOneWidget;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.HandlerRegistration;
/**
* Contains a group of radio input elements.
*
* @param <T> the return value type of the radio group.
* @author Steven Jardine
*/
public class RadioGroupBase<T> extends FlowPanel implements HasName, HasValue<T>, LeafValueEditor<T>,
HasEditorErrors<T>, HasErrorHandler, HasValidators<T>, HasBlankValidator<T> {
private final ErrorHandlerMixin<T> errorHandlerMixin = new ErrorHandlerMixin<T>(this);
private String name = null;
private final Parser<T> parser;
private final BlankValidatorMixin<RadioGroupBase<T>, T> validatorMixin = new RadioGroupBlankValidatorMixin<RadioGroupBase<T>, T>(
this, errorHandlerMixin.getErrorHandler());
private final Map<Radio, HandlerRegistration> valueChangedRegistrations = new HashMap<Radio, HandlerRegistration>();
/**
* Constructor.
*
* @param name the name
* @param parser the parser
*/
public RadioGroupBase(final String name, final Parser<T> parser) {
super();
this.name = name;
this.parser = parser;
}
/** {@inheritDoc} */
@Override
public void add(final Widget w) {
super.add(w);
updateChildren();
}
@Override
public HandlerRegistration addValidationChangedHandler(final ValidationChangedHandler handler) {
return validatorMixin.addValidationChangedHandler(handler);
}
@Override
public void addValidator(final Validator<T> validator) {
validatorMixin.addValidator(validator);
}
/** {@inheritDoc} */
@Override
public com.google.gwt.event.shared.HandlerRegistration addValueChangeHandler(final ValueChangeHandler<T> handler) {
return addHandler(handler, ValueChangeEvent.getType());
}
/** {@inheritDoc} */
@Override
public void clear() {
super.clear();
updateChildren();
}
@Override
public boolean getAllowBlank() {
return validatorMixin.getAllowBlank();
}
/** {@inheritDoc} */
@Override
public ErrorHandler getErrorHandler() {
return errorHandlerMixin.getErrorHandler();
}
/** {@inheritDoc} */
@Override
public ErrorHandlerType getErrorHandlerType() {
return errorHandlerMixin.getErrorHandlerType();
}
/** {@inheritDoc} */
@Override
public String getName() {
return name;
}
/**
* @return the radio children
*/
public Set<Radio> getRadioChildren() {
return getRadioChildren(this, null);
}
/**
* Gets the radio children.
*
* @param widget the widget
* @param c the current children
* @return the radio children
*/
protected Set<Radio> getRadioChildren(final Widget widget, final Set<Radio> c) {
Set<Radio> children = c;
if (children == null) {
children = new HashSet<Radio>();
}
if (widget instanceof Radio) {
children.add((Radio) widget);
} else if (widget instanceof HasOneWidget) {
children = getRadioChildren(((HasOneWidget) widget).getWidget(), children);
} else if (widget instanceof HasWidgets) {
for (Widget w : (HasWidgets) widget) {
if (w instanceof Radio) {
children.add((Radio) w);
} else {
children = getRadioChildren(w, children);
}
}
}
return children;
}
/** {@inheritDoc} */
@Override
public boolean getValidateOnBlur() {
return validatorMixin.getValidateOnBlur();
}
/** {@inheritDoc} */
@Override
public T getValue() {
for (Radio child : getRadioChildren()) {
if (child.getValue()) {
try {
return parser.parse(child.getFormValue());
} catch (ParseException e) {
}
}
}
return null;
}
/** {@inheritDoc} */
@Override
public void insert(final IsWidget w, final int beforeIndex) {
super.insert(w, beforeIndex);
updateChildren();
}
/** {@inheritDoc} */
@Override
public void insert(final Widget w, final int beforeIndex) {
super.insert(w, beforeIndex);
updateChildren();
}
/** {@inheritDoc} */
@Override
public boolean removeValidator(final Validator<T> validator) {
return validatorMixin.removeValidator(validator);
}
/** {@inheritDoc} */
@Override
public void reset() {
setValue(null);
validatorMixin.reset();
}
/** {@inheritDoc} */
@Override
public void setAllowBlank(final boolean allowBlank) {
validatorMixin.setAllowBlank(allowBlank);
}
/** {@inheritDoc} */
@Override
public void setErrorHandler(final ErrorHandler handler) {
errorHandlerMixin.setErrorHandler(handler);
validatorMixin.setErrorHandler(handler);
}
/** {@inheritDoc} */
@Override
public void setErrorHandlerType(final ErrorHandlerType type) {
errorHandlerMixin.setErrorHandlerType(type);
}
/** {@inheritDoc} */
@Override
public void setName(final String name) {
this.name = name;
}
@Override
public void setValidateOnBlur(final boolean validateOnBlur) {
validatorMixin.setValidateOnBlur(validateOnBlur);
}
@Override
public void setValidators(@SuppressWarnings("unchecked") final Validator<T>... validators) {
validatorMixin.setValidators(validators);
}
/** {@inheritDoc} */
@Override
public void setValue(final T value) {
setValue(value, false);
}
/** {@inheritDoc} */
@Override
public void setValue(final T value, final boolean fireEvents) {
for (Radio child : getRadioChildren()) {
try {
if (value != null && value.equals(parser.parse(child.getFormValue()))) {
child.setValue(true, fireEvents);
}
} catch (ParseException e) {
}
}
}
/** {@inheritDoc} */
@Override
public void showErrors(final List<EditorError> errors) {
errorHandlerMixin.showErrors(errors);
}
private ValueChangeHandler<Boolean> changeHandler = new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
ValueChangeEvent.fire(RadioGroupBase.this, getValue());
}
};
/**
* Update the radio children names.
*/
protected void updateChildren() {
for (Radio child : getRadioChildren()) {
HandlerRegistration reg = valueChangedRegistrations.get(child);
if (reg == null) {
valueChangedRegistrations.put(child, child.addValueChangeHandler(changeHandler));
}
child.setName(name);
}
}
/** {@inheritDoc} */
@Override
public boolean validate() {
return validatorMixin.validate();
}
/** {@inheritDoc} */
@Override
public boolean validate(final boolean show) {
return validatorMixin.validate(show);
}
/** {@inheritDoc} */
@Override
public boolean remove(Widget w) {
return super.remove(w);
}
}