package org.ovirt.engine.ui.common.widget.editor;
import java.util.List;
import org.ovirt.engine.ui.common.widget.AbstractValidatedWidgetWithLabel;
import org.ovirt.engine.ui.common.widget.VisibilityRenderer;
import org.ovirt.engine.ui.common.widget.renderer.NullSafeRenderer;
import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.text.shared.Renderer;
/**
* The editor associated with a ListBox that allows multiple selections.
* Due to the {@code EditorContext} setInModel single object limit we have to be a little creative in how we pass
* multiple values around. If we set the type to be {@code List<T>} instead of T, we have the ability to pass around
* multiple values in the list. However due to the generics the {@code Renderer} is now passed a List instead of a
* single object. As an example of an EnumRenderer:
* <pre>
* <code>
* editor = new ListModelMultipleSelectListBoxEditor<T>(new AbstractRenderer<List<T>>() {
* {@literal}@Override
* public String render(List<T> object) {
* //Get the first element of the list, as we are assuming this is a single item list.
* return EnumTranslator.getInstance().translate(object.get(0));
* }
* }, new ModeSwitchingVisibilityRenderer());
* </code>
* </pre>
*
* Notice that the Renderer takes a List<T> parameter instead of a straight <T>, but that the type
* of the {@code ListModelMultipleSelectListBoxEditor} takes a straight <T><br>
* <br>
* The definition of the editor looks something like this:
* <pre>
* <code>
* {@literal}@UiField(provided = true)
* {@literal}@Path(value = "type.selectedItems")
* {@literal}@WithElementId("type")
* public ListModelMultipleSelectListBoxEditor<T> editor;
* </code>
* </pre>
* Notice that the type of variable is a straight {@code <T>}. Also note the path value is selectedItems (plural). So
* the ListModels setSelectedItems is used instead of the usual setSelectedItem.
*
* Usage in a ui binder xml file is the same as normal.<br>
* <pre>
* {@code <e:ListModelMultipleSelectListBoxEditor ui:field="editor" />}
* </pre>
* @param <T> The type of the object to use in the list box.
*/
public class ListModelMultipleSelectListBoxEditor<T>
extends AbstractValidatedWidgetWithLabel<List<T>, ListModelMultipleSelectListBox<T>>
implements IsEditor<WidgetWithLabelEditor<List<T>, ListModelMultipleSelectListBoxEditor<T>>> {
private static class SingletonListRendererAdapter<T> extends NullSafeRenderer<List<T>> {
private final Renderer<T> renderer;
public SingletonListRendererAdapter(Renderer<T> renderer) {
this.renderer = renderer;
}
@Override
protected String renderNullSafe(List<T> list) {
return list.isEmpty() ? "" : renderer.render(list.get(0));
}
}
private final WidgetWithLabelEditor<List<T>, ListModelMultipleSelectListBoxEditor<T>> editor;
public ListModelMultipleSelectListBoxEditor(Renderer<T> renderer, VisibilityRenderer visibilityRenderer) {
super(new ListModelMultipleSelectListBox<>(new SingletonListRendererAdapter<>(renderer)), visibilityRenderer);
this.editor = WidgetWithLabelEditor.of(getContentWidget().asEditor(), this);
}
@Override
public WidgetWithLabelEditor<List<T>, ListModelMultipleSelectListBoxEditor<T>> asEditor() {
return editor;
}
}