I created this class to expand strings in GWT. It requires a column that you want to expand, and replaces it with a place holder, which can have 2 states.
I use it as follows:
PlaceHolderColumn<Notification, SafeHtml> placeholder = new PlaceHolderColumn<Notification, SafeHtml>(new SafeHtmlCell()) { @Override public SafeHtml getValue(Notification object) { return SafeHtmlUtils.fromSafeConstant(getSelected() ? "<i class=\"glyphicon glyphicon-chevron-down\"></i>" : "<i class=\"glyphicon glyphicon-chevron-right\"></i>"); } }; notificationsTable.setTableBuilder(new ExpandableCellTableBuilder<Notification, SafeHtml>(notificationsTable, columnBody, placeholder));
I have access to the glyphicon, so I use them instead of the default placeholder column, which is +/-
<Image here ... but due to lack of reputation :(>
columnBody in the above code example is the standard column that will span the width of the table. The seat holder will be displayed in its place in any columnBody position on which it was sitting.
Hope this helps someone :)
public class ExpandableCellTableBuilder<T, U> extends AbstractCellTableBuilder<T> { private Column<T, U> expandColumn = null; private PlaceHolderColumn<T, ?> placeholderColumn = null; private final String evenRowStyle; private final String oddRowStyle; private final String selectedRowStyle; private final String cellStyle; private final String evenCellStyle; private final String oddCellStyle; private final String firstColumnStyle; private final String lastColumnStyle; private final String selectedCellStyle; public static class ExpandMultiSelectionModel<T> extends AbstractSelectionModel<T> { Map<Object, T> selected = new HashMap<Object, T>(); public ExpandMultiSelectionModel(ProvidesKey<T> keyProvider) { super(keyProvider); } @Override public boolean isSelected(T object) { return isKeySelected(getKey(object)); } protected boolean isKeySelected(Object key) { return selected.get(key) != null; } @Override public void setSelected(T object, boolean selected) { Object key = getKey(object); if (isKeySelected(key)) { this.selected.remove(key); } else { this.selected.put(key, object); } scheduleSelectionChangeEvent(); } } public static abstract class PlaceHolderColumn<T, C> extends Column<T, C> { private boolean isSelected; public PlaceHolderColumn(Cell<C> cell) { super(cell); } protected boolean getSelected() { return isSelected; } } private int expandColumnIndex; public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> expandColumn) { this(cellTable, expandColumn, new ExpandMultiSelectionModel<T>(cellTable.getKeyProvider()), null); } public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> exandColumn, SelectionModel<T> selectionModel) { this(cellTable, exandColumn, selectionModel, null); } public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> exandColumn, PlaceHolderColumn<T, ?> placeHolder) { this(cellTable, exandColumn, new ExpandMultiSelectionModel<T>(cellTable.getKeyProvider()), placeHolder); } public ExpandableCellTableBuilder(AbstractCellTable<T> cellTable, Column<T, U> expandColumn, SelectionModel<T> selectionModel, PlaceHolderColumn<T, ?> placeHolder) { super(cellTable); this.expandColumn = expandColumn; this.cellTable.setSelectionModel(selectionModel); if (placeHolder == null) { this.placeholderColumn = new PlaceHolderColumn<T, String>(new TextCell()) { @Override public String getValue(T object) { return getSelected() ? "-" : "+"; } }; } else { this.placeholderColumn = placeHolder; }