package xapi.polymer.pickers; import static xapi.components.impl.JsSupport.newElement; import static xapi.components.impl.JsSupport.setAttr; import java.util.function.Consumer; import com.google.gwt.core.client.js.JsProperty; import com.google.gwt.core.client.js.JsType; import elemental.dom.Element; import elemental.html.InputElement; import xapi.components.api.IsWebComponent; import xapi.components.api.OnWebComponentAttributeChanged; import xapi.components.api.ToStringIsName; import xapi.components.api.WebComponent; import xapi.components.api.WebComponentMethod; import xapi.components.impl.JsFunctionSupport; @JsType @WebComponent(tagName=EnumPickerElement.TAG_NAME) public interface EnumPickerElement <E extends Enum<E>> extends IsWebComponent<Element>, AbstractPickerElement<Element>, OnWebComponentAttributeChanged { String TAG_NAME = "xapi-enum-picker"; // This type does not have a default factory, since we want to let subinterfaces define specific factories @JsProperty @WebComponentMethod(mapToAttribute = true) E getValue(); @JsProperty @WebComponentMethod(mapToAttribute = true) void setValue(E property); @Override default void onCreated(Element e) { initializePolymer("paper-radio-group"); } @SuppressWarnings("unchecked") @WebComponentMethod(useJsniWildcard=true) default void render(E selected, E ... all) { Element group = getPolymer().element(); for (E item : all) { // element is not actually an <input/>, but javascript doesn't care // and neither do we, since we can treat it just like an input InputElement radio = newElement("paper-radio-button"); radio.setAttribute("name", item instanceof ToStringIsName ? item.toString() : item.name()); radio.setAttribute("label", item.name()); setAttr(radio, "toggles"); group.appendChild(radio); radio.addEventListener("core-change", e-> maybeUpdate(radio, item), false); } setValue(selected);// Initialized the provided value } @WebComponentMethod(useJsniWildcard=true) default void maybeUpdate(InputElement radio, E item) { if (radio.isChecked()) { setValue(item); } else if (item == getValue()) { setValue(null); } } default void addAttributeChangeHandler(Consumer<E> handler) { Consumer<E> existing = getAttributeChangeHandler(); if (existing == null) { setAttributeChangeHandler(handler); } else { setAttributeChangeHandler(JsFunctionSupport.mergeConsumer(existing, handler)); } } @JsProperty Consumer<E> getAttributeChangeHandler(); @JsProperty void setAttributeChangeHandler(Consumer<E> listener); @Override default void onAttributeChanged(String name, String oldVal, String newVal) { // Used when the user manually sets <xapi-enum-picker>.value="newVal" // This will also be called whenever the radio group is updated via clicks, // however, this has no effect as the selected variable already equals newVal switch (name) { case "value": getPolymer().element().setAttribute("selected", newVal); Consumer<E> handler = getAttributeChangeHandler(); if (handler != null) { handler.accept(getValue()); } break; } } }