All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dominokit.domino.ui.forms.Radio Maven / Gradle / Ivy

There is a newer version: 2.0.4
Show newest version
/*
 * Copyright © 2019 Dominokit
 *
 * 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.
 */
package org.dominokit.domino.ui.forms;

import static java.util.Objects.nonNull;
import static org.jboss.elemento.Elements.*;

import elemental2.dom.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.dominokit.domino.ui.grid.flex.FlexItem;
import org.dominokit.domino.ui.style.Color;
import org.dominokit.domino.ui.style.Style;
import org.dominokit.domino.ui.utils.*;
import org.gwtproject.editor.client.TakesValue;
import org.gwtproject.safehtml.shared.SafeHtml;
import org.jboss.elemento.IsElement;

/**
 * A component that represent a single option in a {@link RadioGroup}
 *
 * @param  The type fo the radio value
 */
public class Radio extends BaseDominoElement>
    implements HasName>,
        HasValue, T>,
        HasLabel>,
        Switchable>,
        Checkable>,
        TakesValue,
        HasHelperText>,
        HasInputElement {

  private FlexItem container = FlexItem.create().addCss("radio-option");
  private HTMLLabelElement labelElement = label().element();
  private HTMLInputElement inputElement = input("radio").element();
  private DominoElement helperTextElement = DominoElement.of(p());
  private List> changeHandlers;
  private Color color;
  private boolean checked = false;
  private RadioGroup radioGroup;
  private T value;

  /**
   * Creates an instance for the specified value with a label
   *
   * @param value T
   * @param label String
   */
  public Radio(T value, String label) {
    changeHandlers = new ArrayList<>();
    linkLabelToField();
    container.appendChild(labelElement);
    container.appendChild(inputElement);
    setLabel(label);
    value(value);
    container.addEventListener(
        "click",
        evt -> {
          if (isEnabled() && !isChecked()) check();
        });
    inputElement.addEventListener("change", evt -> onCheck());
    init(this);
  }

  /**
   * Creates an instance for the specified value without a label, the label will be the
   * String.valueOf(value)
   *
   * @param value T
   */
  public Radio(T value) {
    this(value, String.valueOf(value));
  }

  /**
   * Creates an instance for the specified value with a label
   *
   * @param value T
   * @param label String
   * @param  the type of the value
   * @return new Radio instance
   */
  public static  Radio create(E value, String label) {
    return new Radio<>(value, label);
  }

  /**
   * Creates an instance for the specified value without a label, the label will be the
   * String.valueOf(value)
   *
   * @param value T
   * @param  the type of value
   * @return new Radio instance
   */
  public static  Radio create(E value) {
    return new Radio<>(value);
  }

  private void linkLabelToField() {
    DominoElement asDominoElement = DominoElement.of(inputElement);
    if (!asDominoElement.hasAttribute("id")) {
      inputElement.setAttribute("id", asDominoElement.getDominoId());
    }
    labelElement.setAttribute("for", asDominoElement.getAttribute("id"));
  }

  /** {@inheritDoc} */
  @Override
  public Radio check() {
    return check(false);
  }

  /** {@inheritDoc} */
  @Override
  public Radio uncheck() {
    return uncheck(false);
  }

  /** {@inheritDoc} */
  @Override
  public Radio check(boolean silent) {
    if (nonNull(radioGroup)) {
      if (!radioGroup.isReadOnly()) {
        radioGroup.getRadios().forEach(radio -> radio.setChecked(false));
        setChecked(true);
        if (!silent) onCheck();
      }
    } else {
      setChecked(true);
      if (!silent) onCheck();
    }
    return this;
  }

  /** {@inheritDoc} */
  @Override
  public Radio uncheck(boolean silent) {
    if (nonNull(radioGroup)) {
      if (!radioGroup.isReadOnly()) {
        setChecked(false);
        if (!silent) onCheck();
      }
    } else {
      setChecked(false);
      if (!silent) onCheck();
    }

    return this;
  }

  /** {@inheritDoc} */
  @Override
  public Radio addChangeHandler(ChangeHandler changeHandler) {
    changeHandlers.add(changeHandler);
    return this;
  }

  private void setChecked(boolean value) {
    inputElement.checked = value;
    this.checked = value;
    if (this.checked) {
      element.css("checked");
    } else {
      element.removeCss("checked");
    }
  }

  /** {@inheritDoc} */
  @Override
  public Radio removeChangeHandler(ChangeHandler changeHandler) {
    if (changeHandler != null) changeHandlers.remove(changeHandler);
    return this;
  }

  /** {@inheritDoc} */
  @Override
  public boolean hasChangeHandler(ChangeHandler changeHandler) {
    return changeHandlers.contains(changeHandler);
  }

  private void onCheck() {
    for (ChangeHandler checkHandler : changeHandlers)
      checkHandler.onValueChanged(isChecked());
  }

  /** {@inheritDoc} */
  @Override
  public boolean isChecked() {
    return this.checked;
  }

  /**
   * Introduce a small white gap between the radio border and its check mark filling
   *
   * @return same Radio instance
   */
  public Radio withGap() {
    Style.of(inputElement).addCss("with-gap");
    element.css("with-gap");
    return this;
  }

  /**
   * Removesthe small white gap between the radio border and its check mark filling
   *
   * @return same Radio instance
   */
  public Radio withoutGap() {
    Style.of(inputElement).removeCss("with-gap");
    element.removeCss("with-gap");
    return this;
  }

  /**
   * Sets the color of the radio border and filling
   *
   * @param color {@link Color}
   * @return same Radio instance
   */
  public Radio setColor(Color color) {
    if (this.color != null) {
      element.removeCss(this.color.getStyle());
    }
    element.css(color.getStyle());
    this.color = color;
    return this;
  }

  /** {@inheritDoc} */
  @Override
  public HTMLDivElement element() {
    return container.element();
  }

  /** {@inheritDoc} */
  @Override
  public String getName() {
    return inputElement.name;
  }

  /** {@inheritDoc} */
  @Override
  public Radio setName(String name) {
    inputElement.name = name;
    return this;
  }

  /** {@inheritDoc} */
  @Override
  public Radio value(T value) {
    return value(value, false);
  }

  /** {@inheritDoc} */
  @Override
  public Radio value(T value, boolean silent) {
    setValue(value);
    return this;
  }

  /** {@inheritDoc} */
  @Override
  public void setValue(T value) {
    this.value = value;
  }

  /** {@inheritDoc} */
  @Override
  public T getValue() {
    return this.value;
  }

  /** {@inheritDoc} */
  @Override
  public Radio setLabel(String label) {
    labelElement.textContent = label;
    return this;
  }

  /** @param safeHtml {@link SafeHtml} to be used as a label */
  public Radio setLabel(SafeHtml safeHtml) {
    labelElement.innerHTML = safeHtml.asString();
    return this;
  }

  /** @param node {@link Node} to be used as a label */
  public Radio setLabel(Node node) {
    DominoElement.of(labelElement).clearElement().appendChild(node);
    return this;
  }

  /** @param element {@link IsElement} to be used as a label */
  public Radio setLabel(IsElement element) {
    return setLabel(element.element());
  }

  /** {@inheritDoc} */
  @Override
  public Optional getLabel() {
    return Optional.of(labelElement.textContent);
  }

  /** {@inheritDoc} */
  @Override
  public Radio enable() {
    inputElement.disabled = false;
    element.removeCss("disabled");
    return this;
  }

  /** {@inheritDoc} */
  @Override
  public Radio disable() {
    inputElement.disabled = true;
    element.css("disabled");
    return this;
  }

  /** {@inheritDoc} */
  @Override
  public String getHelperText() {
    return helperTextElement.getTextContent();
  }

  /** {@inheritDoc} */
  @Override
  public Radio setHelperText(String text) {
    helperTextElement.setTextContent(text);
    if (!DominoElement.of(labelElement).contains(helperTextElement.element())) {
      labelElement.appendChild(helperTextElement.element());
    }
    return this;
  }

  /** {@inheritDoc} */
  @Override
  public boolean isEnabled() {
    return !inputElement.disabled;
  }

  /** @param radioGroup {@link RadioGroup} this radio belongs to */
  void setGroup(RadioGroup radioGroup) {
    this.radioGroup = radioGroup;
  }

  /** {@inheritDoc} */
  @Override
  public DominoElement getInputElement() {
    return DominoElement.of(inputElement);
  }

  /** {@inheritDoc} */
  @Override
  public String getStringValue() {
    return String.valueOf(getValue());
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy