001package org.gwtbootstrap3.client.ui.base; 002 003/* 004 * #%L 005 * GwtBootstrap3 006 * %% 007 * Copyright (C) 2015 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 java.text.ParseException; 024import java.util.HashMap; 025import java.util.HashSet; 026import java.util.List; 027import java.util.Map; 028import java.util.Set; 029 030import org.gwtbootstrap3.client.ui.Radio; 031import org.gwtbootstrap3.client.ui.base.mixin.BlankValidatorMixin; 032import org.gwtbootstrap3.client.ui.base.mixin.ErrorHandlerMixin; 033import org.gwtbootstrap3.client.ui.form.error.ErrorHandler; 034import org.gwtbootstrap3.client.ui.form.error.ErrorHandlerType; 035import org.gwtbootstrap3.client.ui.form.error.HasErrorHandler; 036import org.gwtbootstrap3.client.ui.form.validator.HasBlankValidator; 037import org.gwtbootstrap3.client.ui.form.validator.HasValidators; 038import org.gwtbootstrap3.client.ui.form.validator.RadioGroupBlankValidatorMixin; 039import org.gwtbootstrap3.client.ui.form.validator.ValidationChangedEvent.ValidationChangedHandler; 040import org.gwtbootstrap3.client.ui.form.validator.Validator; 041import org.gwtbootstrap3.client.ui.gwt.FlowPanel; 042 043import com.google.gwt.editor.client.EditorError; 044import com.google.gwt.editor.client.HasEditorErrors; 045import com.google.gwt.editor.client.LeafValueEditor; 046import com.google.gwt.event.logical.shared.ValueChangeEvent; 047import com.google.gwt.event.logical.shared.ValueChangeHandler; 048import com.google.gwt.text.shared.Parser; 049import com.google.gwt.user.client.ui.HasName; 050import com.google.gwt.user.client.ui.HasOneWidget; 051import com.google.gwt.user.client.ui.HasValue; 052import com.google.gwt.user.client.ui.HasWidgets; 053import com.google.gwt.user.client.ui.IsWidget; 054import com.google.gwt.user.client.ui.Widget; 055import com.google.web.bindery.event.shared.HandlerRegistration; 056 057/** 058 * Contains a group of radio input elements. 059 * 060 * @param <T> the return value type of the radio group. 061 * @author Steven Jardine 062 */ 063public class RadioGroupBase<T> extends FlowPanel implements HasName, HasValue<T>, LeafValueEditor<T>, 064 HasEditorErrors<T>, HasErrorHandler, HasValidators<T>, HasBlankValidator<T> { 065 066 private final ErrorHandlerMixin<T> errorHandlerMixin = new ErrorHandlerMixin<T>(this); 067 068 private String name = null; 069 070 private final Parser<T> parser; 071 072 private final BlankValidatorMixin<RadioGroupBase<T>, T> validatorMixin = new RadioGroupBlankValidatorMixin<RadioGroupBase<T>, T>( 073 this, errorHandlerMixin.getErrorHandler()); 074 075 private final Map<Radio, HandlerRegistration> valueChangedRegistrations = new HashMap<Radio, HandlerRegistration>(); 076 077 /** 078 * Constructor. 079 * 080 * @param name the name 081 * @param parser the parser 082 */ 083 public RadioGroupBase(final String name, final Parser<T> parser) { 084 super(); 085 this.name = name; 086 this.parser = parser; 087 } 088 089 /** {@inheritDoc} */ 090 @Override 091 public void add(final Widget w) { 092 super.add(w); 093 updateChildren(); 094 } 095 096 @Override 097 public HandlerRegistration addValidationChangedHandler(final ValidationChangedHandler handler) { 098 return validatorMixin.addValidationChangedHandler(handler); 099 } 100 101 @Override 102 public void addValidator(final Validator<T> validator) { 103 validatorMixin.addValidator(validator); 104 } 105 106 /** {@inheritDoc} */ 107 @Override 108 public com.google.gwt.event.shared.HandlerRegistration addValueChangeHandler(final ValueChangeHandler<T> handler) { 109 return addHandler(handler, ValueChangeEvent.getType()); 110 } 111 112 /** {@inheritDoc} */ 113 @Override 114 public void clear() { 115 super.clear(); 116 updateChildren(); 117 } 118 119 @Override 120 public boolean getAllowBlank() { 121 return validatorMixin.getAllowBlank(); 122 } 123 124 /** {@inheritDoc} */ 125 @Override 126 public ErrorHandler getErrorHandler() { 127 return errorHandlerMixin.getErrorHandler(); 128 } 129 130 /** {@inheritDoc} */ 131 @Override 132 public ErrorHandlerType getErrorHandlerType() { 133 return errorHandlerMixin.getErrorHandlerType(); 134 } 135 136 /** {@inheritDoc} */ 137 @Override 138 public String getName() { 139 return name; 140 } 141 142 /** 143 * @return the radio children 144 */ 145 public Set<Radio> getRadioChildren() { 146 return getRadioChildren(this, null); 147 } 148 149 /** 150 * Gets the radio children. 151 * 152 * @param widget the widget 153 * @param c the current children 154 * @return the radio children 155 */ 156 protected Set<Radio> getRadioChildren(final Widget widget, final Set<Radio> c) { 157 Set<Radio> children = c; 158 if (children == null) { 159 children = new HashSet<Radio>(); 160 } 161 if (widget instanceof Radio) { 162 children.add((Radio) widget); 163 } else if (widget instanceof HasOneWidget) { 164 children = getRadioChildren(((HasOneWidget) widget).getWidget(), children); 165 } else if (widget instanceof HasWidgets) { 166 for (Widget w : (HasWidgets) widget) { 167 if (w instanceof Radio) { 168 children.add((Radio) w); 169 } else { 170 children = getRadioChildren(w, children); 171 } 172 } 173 } 174 return children; 175 } 176 177 /** {@inheritDoc} */ 178 @Override 179 public boolean getValidateOnBlur() { 180 return validatorMixin.getValidateOnBlur(); 181 } 182 183 /** {@inheritDoc} */ 184 @Override 185 public T getValue() { 186 for (Radio child : getRadioChildren()) { 187 if (child.getValue()) { 188 try { 189 return parser.parse(child.getFormValue()); 190 } catch (ParseException e) { 191 } 192 } 193 } 194 return null; 195 } 196 197 /** {@inheritDoc} */ 198 @Override 199 public void insert(final IsWidget w, final int beforeIndex) { 200 super.insert(w, beforeIndex); 201 updateChildren(); 202 } 203 204 /** {@inheritDoc} */ 205 @Override 206 public void insert(final Widget w, final int beforeIndex) { 207 super.insert(w, beforeIndex); 208 updateChildren(); 209 } 210 211 /** {@inheritDoc} */ 212 @Override 213 public boolean removeValidator(final Validator<T> validator) { 214 return validatorMixin.removeValidator(validator); 215 } 216 217 /** {@inheritDoc} */ 218 @Override 219 public void reset() { 220 setValue(null); 221 validatorMixin.reset(); 222 } 223 224 /** {@inheritDoc} */ 225 @Override 226 public void setAllowBlank(final boolean allowBlank) { 227 validatorMixin.setAllowBlank(allowBlank); 228 } 229 230 /** {@inheritDoc} */ 231 @Override 232 public void setErrorHandler(final ErrorHandler handler) { 233 errorHandlerMixin.setErrorHandler(handler); 234 validatorMixin.setErrorHandler(handler); 235 } 236 237 /** {@inheritDoc} */ 238 @Override 239 public void setErrorHandlerType(final ErrorHandlerType type) { 240 errorHandlerMixin.setErrorHandlerType(type); 241 } 242 243 /** {@inheritDoc} */ 244 @Override 245 public void setName(final String name) { 246 this.name = name; 247 } 248 249 @Override 250 public void setValidateOnBlur(final boolean validateOnBlur) { 251 validatorMixin.setValidateOnBlur(validateOnBlur); 252 } 253 254 @Override 255 public void setValidators(@SuppressWarnings("unchecked") final Validator<T>... validators) { 256 validatorMixin.setValidators(validators); 257 } 258 259 /** {@inheritDoc} */ 260 @Override 261 public void setValue(final T value) { 262 setValue(value, false); 263 } 264 265 /** {@inheritDoc} */ 266 @Override 267 public void setValue(final T value, final boolean fireEvents) { 268 for (Radio child : getRadioChildren()) { 269 try { 270 if (value != null && value.equals(parser.parse(child.getFormValue()))) { 271 child.setValue(true, fireEvents); 272 } 273 } catch (ParseException e) { 274 } 275 } 276 } 277 278 /** {@inheritDoc} */ 279 @Override 280 public void showErrors(final List<EditorError> errors) { 281 errorHandlerMixin.showErrors(errors); 282 } 283 284 private ValueChangeHandler<Boolean> changeHandler = new ValueChangeHandler<Boolean>() { 285 @Override 286 public void onValueChange(ValueChangeEvent<Boolean> event) { 287 ValueChangeEvent.fire(RadioGroupBase.this, getValue()); 288 } 289 }; 290 291 /** 292 * Update the radio children names. 293 */ 294 protected void updateChildren() { 295 for (Radio child : getRadioChildren()) { 296 HandlerRegistration reg = valueChangedRegistrations.get(child); 297 if (reg == null) { 298 valueChangedRegistrations.put(child, child.addValueChangeHandler(changeHandler)); 299 } 300 child.setName(name); 301 } 302 } 303 304 /** {@inheritDoc} */ 305 @Override 306 public boolean validate() { 307 return validatorMixin.validate(); 308 } 309 310 /** {@inheritDoc} */ 311 @Override 312 public boolean validate(final boolean show) { 313 return validatorMixin.validate(show); 314 } 315 316 /** {@inheritDoc} */ 317 @Override 318 public boolean remove(Widget w) { 319 return super.remove(w); 320 } 321 322}