package org.ovirt.engine.ui.common.widget.editor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.gwtbootstrap3.client.ui.constants.Styles; import org.ovirt.engine.ui.common.css.OvirtCss; import org.ovirt.engine.ui.common.widget.label.EnableableFormLabel; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.safehtml.client.SafeHtmlTemplates; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.text.shared.Renderer; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; /** * A {@code ListBox} widget that displays the list in a grouped fashion. The groups are created by using the * OptionGroup tag. How the items are grouped is determined by the group label associated with each model object. * * @param <T> The type of the model to use in the list box. */ public abstract class GroupedListModelListBox<T> extends ListModelListBox<T> { interface HeaderItemTemplate extends SafeHtmlTemplates { @Template("<span class=\"text\">{0}</span>") SafeHtml headerListItem(String text); } FlowPanel groupLabelContainer; EnableableFormLabel groupLabel; private final HeaderItemTemplate headerItemTemplate = GWT.create(HeaderItemTemplate.class); public GroupedListModelListBox(Renderer<T> renderer) { super(renderer); addValueChangeHandler(event -> updateGroupLabel(event.getValue())); groupLabelContainer = new FlowPanel(); groupLabelContainer.addStyleName(style.labelContainer()); groupLabel = new EnableableFormLabel(); groupLabel.addStyleName(style.label()); groupLabelContainer.add(groupLabel); container.add(groupLabelContainer); } protected UnorderedListPanel getListPanel() { return new GroupedUnorderedListPanel(); } /** * Set the value, do nothing if the value is null. */ public void setValue(T value) { if (value != null) { super.setValue(value, true); } } @Override protected Widget getWidget() { return container.getWidget(0); } /** * Set the acceptable values. */ @Override public void setAcceptableValues(Collection<T> newValues) { if (newValues instanceof List) { List<T> sortedValues = (List<T>) newValues; Collections.sort(sortedValues, getComparator()); super.setAcceptableValues(sortedValues); } } protected boolean ignoreChanging() { return true; } /** * Get the label that represents the model passed in. * @param model The model to get the label for. * @return The label as a {@code String} usually the name of the model. */ public abstract String getModelLabel(T model); /** * Get the group label of the group this model is associated with. * @param model The model to get the group label for. * @return The label as a {@code String} */ public abstract String getGroupLabel(T model); public abstract Comparator<T> getComparator(); @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); final String oldStyleName = enabled ? OvirtCss.LABEL_DISABLED : OvirtCss.LABEL_ENABLED; final String newStyleName = enabled ? OvirtCss.LABEL_ENABLED : OvirtCss.LABEL_DISABLED; groupLabel.getElement().replaceClassName(oldStyleName, newStyleName); } private void updateGroupLabel(T value) { groupLabel.setText(getGroupLabel(value)); } protected class GroupedUnorderedListPanel extends UnorderedListPanel { final List<String> shownGroupLabels = new ArrayList<>(); void addListItem(String text, T value) { String groupLabel = getGroupLabel(value); if (!shownGroupLabels.contains(groupLabel)) { addGroupHeaderListItem(groupLabel); shownGroupLabels.add(groupLabel); } super.addListItem(text, value); } protected void addGroupHeaderListItem(String text) { add(new GroupHeaderListItem(text), getElement()); } protected ListModelListBox<T>.ListItem getListItem(String text, T value) { return new ListItem(text, value); } @Override public void clear() { super.clear(); shownGroupLabels.clear(); } } protected class GroupHeaderListItem extends ComplexPanel { public GroupHeaderListItem(String text) { Element li = Document.get().createLIElement(); li.addClassName(Styles.DROPDOWN_HEADER); li.setInnerHTML(headerItemTemplate.headerListItem(text).asString()); setElement(li); } } }