package org.ovirt.engine.ui.common.widget.table.cell;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.ovirt.engine.ui.uicommonweb.models.EntityModel;
import org.ovirt.engine.ui.uicommonweb.models.ListModel;
import com.google.gwt.cell.client.SelectionCell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.text.shared.Renderer;
import com.google.gwt.view.client.CellPreviewEvent;
/**
* This class may be used to display a ListBox, backed by a ListModel, in cell widgets. It mimics the behaviour of a
* SelectionCell by passing on rendering requests and browser events to a member delegate. The SelectionCell options are
* set by rendering the items of a ListModel using the renderer passed to the constructor. Additional functionality
* includes enabling/disabling the ListBox according to the IsChangeable state of the ListModel.
* </p>
* <p>
* Supports tooltips.
* </p>
*
* @param <T>
* the ListModel item type.
*/
public class ListModelListBoxCell<T> extends AbstractInputCell<ListModel, String> implements EventHandlingCell {
private static final String PATTERN_SELECT = "<select"; //$NON-NLS-1$
private static final String REPLACEMENT_SELECT = "<select disabled"; //$NON-NLS-1$
private SelectionCell delegate;
private Map<String, T> entityByName;
private final Renderer<T> renderer;
public ListModelListBoxCell(final Renderer<T> renderer) {
this.renderer = renderer;
delegate = new SelectionCell(new ArrayList<String>()); // just to avoid null pointer in setSelection()
}
@Override
public Set<String> getConsumedEvents() {
Set<String> set = new HashSet<>(super.getConsumedEvents());
set.add(BrowserEvents.CHANGE);
return set;
}
@SuppressWarnings("unchecked")
private void setOptions(ListModel model) {
Iterable<T> items = model.getItems();
if (items == null) {
items = new ArrayList<>();
}
entityByName = new HashMap<>();
List<String> options = new ArrayList<>();
for (T entity : items) {
String entityName = renderer.render(entity);
entityByName.put(entityName, entity);
options.add(entityName);
}
delegate = new SelectionCell(options);
}
@SuppressWarnings("unchecked")
@Override
public void render(Context context, ListModel value, SafeHtmlBuilder sb, String id) {
setOptions(value);
SafeHtmlBuilder sbDelegate = new SafeHtmlBuilder();
delegate.render(context, renderer.render((T) value.getSelectedItem()), sbDelegate);
String select = sbDelegate.toSafeHtml().asString();
select = select.replaceFirst(PATTERN_SELECT, PATTERN_SELECT + " id=\"" + id + "\""); //$NON-NLS-1$ //$NON-NLS-2$
if (value.getIsChangable()) {
sb.append(SafeHtmlUtils.fromTrustedString(select));
} else {
sb.appendHtmlConstant(select.replaceFirst(PATTERN_SELECT, REPLACEMENT_SELECT));
}
}
@SuppressWarnings("unchecked")
@Override
public void onBrowserEvent(Context context,
Element parent,
final ListModel model,
NativeEvent event,
ValueUpdater<ListModel> valueUpdater) {
delegate.onBrowserEvent(context,
parent,
renderer.render((T) model.getSelectedItem()),
event,
value -> {
if (value != null) {
model.setSelectedItem(entityByName.get(value));
}
});
}
@Override
public boolean handlesEvent(CellPreviewEvent<EntityModel> event) {
return EventHandlingCellMixin.selectOptionHandlesClick(event);
}
}