package org.ovirt.engine.ui.webadmin.widget.table.column; import java.util.ArrayList; import java.util.List; import org.ovirt.engine.ui.common.widget.table.column.AbstractSafeHtmlColumn; import org.ovirt.engine.ui.webadmin.ApplicationTemplates; import org.ovirt.engine.ui.webadmin.gin.AssetProvider; import com.google.gwt.cell.client.ActionCell; import com.google.gwt.cell.client.ActionCell.Delegate; import com.google.gwt.cell.client.Cell; import com.google.gwt.cell.client.CompositeCell; import com.google.gwt.cell.client.HasCell; import com.google.gwt.cell.client.ValueUpdater; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlBuilder; import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.cellview.client.IdentityColumn; /** * A Column that shows one Text Cell, and one or more Action Cells * * @param <T> * The Column Type */ public class ActionColumn<T> extends IdentityColumn<T> { /** * The delegate that is used when the Action Cell is rendered/clicked.<BR> * An Implementation must provide either a Button Text or a Button Image for the Action Cell.<BR> * {@link #showAction(Object)} can be overwritten to decide whether to show the action button. * * @param <C> * The Action Column Type */ public abstract static class ActionCellDelegate<C> implements Delegate<C> { @Override public final void execute(C object) { // not used }; public abstract void execute(C object, NativeEvent event); /** * Gets the Button Image<BR> * Default implementation returns <code>null</code> * * @param object * the object which is the target for this Action Cell */ public ImageResource getButtonImage(C object) { return null; } /** * Gets the Button Text<BR> * Default implementation returns <code>null</code> * * @param object * the object which is the target for this Action Cell */ public String getButtonText(C object) { return null; } /** * Whether to show the Button for the specified object * * @param object * the object which is the target for this Action Cell */ public boolean showAction(C object) { return true; } } /** * Gets string values for text cells * * @param <C> * The Column Type */ public interface ValueGetter<C> { /** * Get String the value for the Text Cell */ public SafeHtml getValue(C object); } /** * An Action Cell the is left floated, and uses an {@link ActionCellDelegate} * * @param <C> * The Action Cell Type */ private static class FloatingActionCell<C> extends ActionCell<C> { private final ActionCellDelegate<C> delegate; private static final ApplicationTemplates templates = AssetProvider.getTemplates(); public FloatingActionCell(ActionCellDelegate<C> delegate) { super("", delegate); //$NON-NLS-1$ this.delegate = delegate; } @Override public void render(Context context, C value, SafeHtmlBuilder sb) { // show cell? if (delegate.showAction(value)) { String buttonText = delegate.getButtonText(value); ImageResource buttonImage = delegate.getButtonImage(value); // use text or image if (buttonText != null) { sb.append(templates.actionButtonText(buttonText)); } else if (buttonImage != null) { sb.append(templates.actionButtonImage(buttonImage.getURL())); } else { throw new IllegalArgumentException("Either getButtonText() or getButtonImage() must return non-null values"); //$NON-NLS-1$ } } }; @Override protected void onEnterKeyDown(Cell.Context context, Element parent, C value, NativeEvent event, ValueUpdater<C> valueUpdater) { delegate.execute(value, event); } } /** * Create the Column Cells from a single delegate */ private static <S> List<HasCell<S, ?>> createCells(ValueGetter<S> getter, ActionCellDelegate<S> delegate) { List<ActionCellDelegate<S>> delegates = new ArrayList<>(); delegates.add(delegate); return createCells(getter, delegates); } /** * Create the Column Cells from a a list of delegates */ private static <S> List<HasCell<S, ?>> createCells(final ValueGetter<S> getter, List<ActionCellDelegate<S>> delegates) { List<HasCell<S, ?>> cells = new ArrayList<>(); // text cell AbstractSafeHtmlColumn<S> textColumn = new AbstractSafeHtmlColumn<S>() { @Override public SafeHtml getValue(S object) { return getter.getValue(object); } }; cells.add(textColumn); // action cells for (ActionCellDelegate<S> delegate : delegates) { Column<S, S> actionColumn = new IdentityColumn<>(new FloatingActionCell<>(delegate)); cells.add(actionColumn); } return cells; } /** * Create an Action Column with the specified getter and delegate * * @param getter * The getter for the Text Cell * @param delegate * The delegate for the Action Cell */ public ActionColumn(ValueGetter<T> getter, ActionCellDelegate<T> delegate) { super(new CompositeCell<>(createCells(getter, delegate))); } /** * Create an Action Column with the specified getter and list of delegates * * @param getter * The getter for the Text Cell * @param delegate * The list of delegates for the Action Cells */ public ActionColumn(ValueGetter<T> getter, List<ActionCellDelegate<T>> delegates) { super(new CompositeCell<>(createCells(getter, delegates))); } }