Example usage for com.google.gwt.safehtml.shared SafeHtmlBuilder appendHtmlConstant

List of usage examples for com.google.gwt.safehtml.shared SafeHtmlBuilder appendHtmlConstant

Introduction

In this page you can find the example usage for com.google.gwt.safehtml.shared SafeHtmlBuilder appendHtmlConstant.

Prototype

public SafeHtmlBuilder appendHtmlConstant(String html) 

Source Link

Document

Appends a compile-time-constant string, which will not be escaped.

Usage

From source file:com.sencha.gxt.widget.core.client.grid.editing.GridInlineEditing.java

License:sencha.com license

@Override
protected SafeHtml getErrorHtml() {
    SafeHtmlBuilder sb = new SafeHtmlBuilder();
    sb.appendHtmlConstant("<ul>");
    ColumnConfig<M, ?> c = columnModel.getColumn(activeCell.getCol());
    IsField<?> f = getEditor(c);/*from   w ww. j  av a  2 s.c o m*/

    getErrorMessage(f, sb, c.getHeader());

    sb.appendHtmlConstant("</ul>");
    return sb.toSafeHtml();
}

From source file:com.sencha.gxt.widget.core.client.grid.editing.GridRowEditing.java

License:sencha.com license

@Override
protected SafeHtml getErrorHtml() {
    SafeHtmlBuilder sb = new SafeHtmlBuilder();
    sb.appendHtmlConstant("<ul>");

    ColumnModel<M> cm = getEditableGrid().getColumnModel();

    for (int i = 0; i < cm.getColumnCount(); i++) {
        ColumnConfig<M, ?> columnConfig = cm.getColumn(i);

        IsField<?> f = (IsField<?>) getEditor(columnConfig);
        ;//from w  w w.  j  av a2s .  c o  m

        if (f == null) {
            continue;
        }

        getErrorMessage(f, sb, columnConfig.getHeader());
    }

    sb.appendHtmlConstant("</ul>");
    return sb.toSafeHtml();
}

From source file:com.sencha.gxt.widget.core.client.grid.GridView.java

License:sencha.com license

/**
 * Renders the grid view into safe HTML.
 *
 * @param cs the column attributes required for rendering
 * @param rows the data models for the rows to be rendered
 * @param startRow the index of the first row in <code>rows</code>
 *///w w  w  .  java 2 s  .  c  o  m
protected SafeHtml doRender(List<ColumnData> cs, List<M> rows, int startRow) {
    final int colCount = cm.getColumnCount();
    final int last = colCount - 1;

    int[] columnWidths = getColumnWidths();

    // root builder
    SafeHtmlBuilder buf = new SafeHtmlBuilder();

    final SafeStyles rowStyles = SafeStylesUtils.fromTrustedString("width: " + getTotalWidth() + "px;");

    final String unselectableClass = unselectable;
    final String rowAltClass = styles.rowAlt();
    final String rowDirtyClass = styles.rowDirty();

    final String cellClass = styles.cell() + " " + states.cell();
    final String cellInnerClass = styles.cellInner() + " " + states.cellInner();
    final String cellFirstClass = "x-grid-cell-first";
    final String cellLastClass = "x-grid-cell-last";
    final String cellDirty = styles.cellDirty();

    final String rowWrap = styles.rowWrap() + " " + states.rowWrap();
    final String rowBody = styles.rowBody() + " " + states.rowBody();
    final String rowBodyRow = states.rowBodyRow();

    // loop over all rows
    for (int j = 0; j < rows.size(); j++) {
        M model = rows.get(j);

        ListStore<M>.Record r = ds.hasRecord(model) ? ds.getRecord(model) : null;

        int rowBodyColSpanCount = colCount;
        if (enableRowBody) {
            for (ColumnConfig<M, ?> c : cm.getColumns()) {
                if (c instanceof RowExpander) {
                    rowBodyColSpanCount--;
                }
            }
        }

        int rowIndex = (j + startRow);

        String rowClasses = styles.row() + " " + states.row();

        if (!selectable) {
            rowClasses += " " + unselectableClass;
        }
        if (isStripeRows() && ((rowIndex + 1) % 2 == 0)) {
            rowClasses += " " + rowAltClass;
        }

        if (showDirtyCells && r != null && r.isDirty()) {
            rowClasses += " " + rowDirtyClass;
        }

        if (viewConfig != null) {
            rowClasses += " " + viewConfig.getRowStyle(model, rowIndex);
        }

        SafeHtmlBuilder trBuilder = new SafeHtmlBuilder();

        // loop each cell per row
        for (int i = 0; i < colCount; i++) {
            SafeHtml rv = getRenderedValue(rowIndex, i, model, r);
            ColumnConfig<M, ?> columnConfig = cm.getColumn(i);
            ColumnData columnData = cs.get(i);

            String cellClasses = cellClass;
            if (i == 0) {
                cellClasses += " " + cellFirstClass;
            } else if (i == last) {
                cellClasses += " " + cellLastClass;
            }

            String cellInnerClasses = cellInnerClass;
            if (columnConfig.getColumnTextClassName() != null) {
                cellInnerClasses += " " + columnConfig.getColumnTextClassName();
            }
            if (!columnConfig.isCellPadding()) {
                cellInnerClasses += " " + styles.noPadding();
            }

            if (columnData.getClassNames() != null) {
                cellClasses += " " + columnData.getClassNames();
            }

            if (columnConfig.getCellClassName() != null) {
                cellClasses += " " + columnConfig.getCellClassName();
            }

            if (showDirtyCells && r != null && r.getChange(columnConfig.getValueProvider()) != null) {
                cellClasses += " " + cellDirty;
            }

            if (viewConfig != null) {
                cellClasses += " " + viewConfig.getColStyle(model, cm.getValueProvider(i), rowIndex, i);
            }

            final SafeStyles cellStyles = columnData.getStyles();

            final SafeHtml tdContent;
            if (enableRowBody && i == 0) {
                tdContent = tpls.tdRowSpan(i, cellClasses, cellStyles, rowBodyRowSpan, cellInnerClasses, rv);
            } else {
                if (!selectable && GXT.isIE()) {
                    tdContent = tpls.tdUnselectable(i, cellClasses, cellStyles, cellInnerClasses,
                            columnConfig.getColumnTextStyle(), rv);
                } else {
                    tdContent = tpls.td(i, cellClasses, cellStyles, cellInnerClasses,
                            columnConfig.getColumnTextStyle(), rv);
                }

            }
            trBuilder.append(tdContent);
        }

        if (enableRowBody) {
            String cls = styles.dataTable() + " x-grid-resizer";

            SafeHtmlBuilder sb = new SafeHtmlBuilder();
            sb.append(tpls.tr("", trBuilder.toSafeHtml()));
            sb.appendHtmlConstant("<tr class='" + rowBodyRow + "'><td colspan=" + rowBodyColSpanCount
                    + "><div class='" + rowBody + "'></div></td></tr>");

            SafeHtml tdWrap = null;
            if (!selectable && GXT.isIE()) {
                tdWrap = tpls.tdWrapUnselectable(colCount, "", rowWrap,
                        tpls.table(cls, rowStyles, sb.toSafeHtml(), renderHiddenHeaders(columnWidths)));
            } else {
                tdWrap = tpls.tdWrap(colCount, "", rowWrap,
                        tpls.table(cls, rowStyles, sb.toSafeHtml(), renderHiddenHeaders(columnWidths)));
            }
            buf.append(tpls.tr(rowClasses, tdWrap));

        } else {
            buf.append(tpls.tr(rowClasses, trBuilder.toSafeHtml()));
        }

    }
    // end row loop
    return buf.toSafeHtml();

}

From source file:com.sencha.gxt.widget.core.client.grid.LiveGridView.java

License:sencha.com license

private void updateScrollerHeight() {
    int height = totalCount * getRowHeight();
    // 1000000 as browser maxheight hack
    int count = height / 1000000;
    int h = 0;//  ww w  .ja v  a  2s .  c  o m

    SafeHtmlBuilder sb = new SafeHtmlBuilder();

    if (count > 0) {
        h = height / count;

        for (int i = 0; i < count; i++) {
            sb.appendHtmlConstant(
                    "<div style=\"width: " + barWidth + "px; height: " + h + "px;\">&#160;</div>");
        }
    }
    int diff = height - count * h;
    if (diff != 0) {
        sb.appendHtmlConstant("<div style=\"width: " + barWidth + "px; height: " + diff + "px;\"></div>");
    }
    liveScroller.setInnerSafeHtml(sb.toSafeHtml());
}

From source file:com.sencha.gxt.widget.core.client.ListView.java

License:sencha.com license

/**
 * Is called before a load when a {@link #setLoader(Loader) and {@link #setLoadingIndicator(SafeHtml) or
 * {@link #setLoadingIndicator(String)} are used the list will display the loading HTML.
 * <p/>/*from ww  w  .  j  a v  a  2 s. c  om*/
 * <ul>
 * <li>The {@link #setLoader(Loader)} has to be set for this to be called.
 * <li>The css class name 'loading-indicator' can style the loading HTML or text.
 * </ul>
 */
protected void onBeforeLoad() {
    if (loadingIndicator != SafeHtmlUtils.EMPTY_SAFE_HTML) {
        SafeHtmlBuilder sb = new SafeHtmlBuilder();
        sb.appendHtmlConstant("<div class='loading-indicator'>");
        sb.append(loadingIndicator);
        sb.appendHtmlConstant("</div>");
        getElement().setInnerSafeHtml(sb.toSafeHtml());
        all.removeAll();
    }
}

From source file:com.sencha.gxt.widget.core.client.ListViewCustomAppearance.java

License:sencha.com license

@Override
public void render(SafeHtmlBuilder builder) {
    builder.appendHtmlConstant("<div class='" + ListView.getStandardResources().css().view() + "'></div>");
}

From source file:com.tasktop.c2c.server.common.profile.web.client.TextAreaInputCell.java

License:Open Source License

@Override
public void render(Context context, String value, SafeHtmlBuilder sb) {
    // Get the view data.
    ViewData viewData = getViewData(context.getKey());
    if (viewData != null && viewData.getCurrentValue().equals(value)) {
        clearViewData(context.getKey());
        viewData = null;/*  w w  w .j a  v a  2  s  .  c om*/
    }

    String s = (viewData != null) ? viewData.getCurrentValue() : value;
    if (s != null) {
        SafeHtml html = renderer.render(s);
        // Note: template will not treat SafeHtml specially
        sb.append(template.input(html.asString()));
    } else {
        sb.appendHtmlConstant("<textarea tabindex=\"-1\"></textarea>");
    }
}

From source file:com.tasktop.c2c.server.common.profile.web.client.ValidatingTextAreaInputCell.java

License:Open Source License

private void renderError(Context context, String value, SafeHtmlBuilder sb) {

    // Tack on our surrounding highlight.
    sb.appendHtmlConstant("<div class=\"errorLabelWrapper\">");

    super.render(context, value, sb);

    // Also add in a space for our validation failure message.
    sb.appendHtmlConstant("<div class=\"errorLabel\">");
    sb.appendEscaped(ValidationUtils.getErrorMessage(context.getKey(), fieldName, errorMap));
    sb.appendHtmlConstant("</div></div>");
}

From source file:com.tasktop.c2c.server.tasks.client.widgets.admin.customfields.CustomFieldValuesEditor.java

License:Open Source License

private void initTableColumns() {

    DelegateCell<String> moveUpCell = new DelegateCell<String>(new DelegateCell.RenderDelegate<String>() {
        @Override// w  w  w. j  a v a2 s.  co  m
        public SafeHtml render(Cell.Context context, String value, SafeHtmlBuilder sb) {
            return SafeHtmlUtils.fromSafeConstant("<span class=\"order-control\"><a class=\"up\"/></span>");
        }
    }, new DelegateCell.ActionDelegate<String>() {
        @Override
        public void execute(Cell.Context object) {
            int index = object.getIndex();
            if (index > 0) {
                dataProvider.getList().get(index).setSortkey((short) (index - 1));
                dataProvider.getList().get(index - 1).setSortkey((short) index);
                Collections.sort(dataProvider.getList());
                refreshDisplays();
            }
        }
    });

    Column<CustomFieldValue, String> moveUpColumn = new Column<CustomFieldValue, String>(moveUpCell) {

        @Override
        public String getValue(CustomFieldValue object) {
            return null;
        }

        @Override
        public void render(Cell.Context context, CustomFieldValue object, SafeHtmlBuilder sb) {
            if (context.getIndex() != 0) {
                super.render(context, object, sb);
            }
        }
    };
    cellTable.addColumn(moveUpColumn);
    cellTable.setColumnWidth(moveUpColumn, 22, Unit.PX);

    DelegateCell<String> moveDownCell = new DelegateCell<String>(new DelegateCell.RenderDelegate<String>() {
        @Override
        public SafeHtml render(Cell.Context context, String value, SafeHtmlBuilder sb) {
            return SafeHtmlUtils.fromSafeConstant("<span class=\"order-control\"><a class=\"down\"/></span>");
        }
    }, new DelegateCell.ActionDelegate<String>() {
        @Override
        public void execute(Cell.Context object) {
            Short index = (short) object.getIndex();
            if (index < dataProvider.getList().size() - 1) {
                dataProvider.getList().get(index).setSortkey((short) (index + 1));
                dataProvider.getList().get(index + 1).setSortkey((short) index);
                Collections.sort(dataProvider.getList());
                refreshDisplays();
            }
        }
    });

    Column<CustomFieldValue, String> moveDownColumn = new Column<CustomFieldValue, String>(moveDownCell) {

        @Override
        public String getValue(CustomFieldValue object) {
            return null;
        }

        @Override
        public void render(Cell.Context context, CustomFieldValue object, SafeHtmlBuilder sb) {
            if (context.getIndex() != dataProvider.getList().size() - 1) {
                super.render(context, object, sb);
            }
        }
    };
    cellTable.addColumn(moveDownColumn);
    cellTable.setColumnWidth(moveDownColumn, 22, Unit.PX);

    Column<CustomFieldValue, String> nameColumn = new Column<CustomFieldValue, String>(new TextInputCell()) {

        @Override
        public String getValue(CustomFieldValue value) {
            return value.getValue();
        }
    };
    nameColumn.setFieldUpdater(new FieldUpdater<CustomFieldValue, String>() {

        @Override
        public void update(int index, CustomFieldValue customFieldValue, String value) {

            customFieldValue.setValue(value);
        }
    });
    cellTable.addColumn(nameColumn);

    DelegateCell<String> removeCell = new DelegateCell<String>(new DelegateCell.RenderDelegate<String>() {
        @Override
        public SafeHtml render(Cell.Context context, String value, SafeHtmlBuilder sb) {
            final CustomFieldValue referenced = dataProvider.getList().get(context.getIndex());
            if (referenced != null && "---".equals(referenced.getValue())) {
                return SafeHtmlUtils.fromSafeConstant("<a class=\"delete-disabled\"><span/></a>");
            }
            return SafeHtmlUtils.fromSafeConstant("<a class=\"misc-icon cancel\"><span/></a>");
        }
    }, new DelegateCell.ActionDelegate<String>() {
        @Override
        public void execute(final Cell.Context object) {
            final CustomFieldValue toRemove = dataProvider.getList().get(object.getIndex());
            if (toRemove == null) {
                return;
            }
            if ("---".equals(toRemove.getValue())) {
                return;
            }
            dataProvider.getList().remove(toRemove);

        }
    });
    Column<CustomFieldValue, String> removeColumn = new Column<CustomFieldValue, String>(removeCell) {

        @Override
        public String getValue(CustomFieldValue object) {
            return null;
        }

        @Override
        public void render(Cell.Context context, CustomFieldValue object, SafeHtmlBuilder sb) {
            if (dataProvider.getList().size() == 1) {
                sb.appendHtmlConstant("<a><span/></a>");
            } else {
                super.render(context, object, sb);
            }
        }
    };
    cellTable.addColumn(removeColumn);
    cellTable.setColumnWidth(removeColumn, 30, Unit.PX);

    DelegateCell<String> addCell = new DelegateCell<String>(new DelegateCell.RenderDelegate<String>() {
        @Override
        public SafeHtml render(Cell.Context context, String value, SafeHtmlBuilder sb) {
            return SafeHtmlUtils.fromSafeConstant("<a class=\"misc-icon add right\"><span/></a>");
        }
    }, new DelegateCell.ActionDelegate<String>() {
        @Override
        public void execute(Cell.Context object) {
            addNewValue();
        }
    });
    Column<CustomFieldValue, String> addColumn = new Column<CustomFieldValue, String>(addCell) {
        @Override
        public String getValue(CustomFieldValue object) {
            return null;
        }

        @Override
        public void render(Cell.Context context, CustomFieldValue object, SafeHtmlBuilder sb) {
            if (context.getIndex() == dataProvider.getList().size() - 1) {
                super.render(context, object, sb);
            } else {
                sb.appendHtmlConstant("<a><span/></a>");
            }
        }
    };
    cellTable.addColumn(addColumn);
    cellTable.setColumnWidth(addColumn, 30, Unit.PX);
}

From source file:com.tasktop.c2c.server.tasks.client.widgets.admin.products.ProjectAdminTasksEditView.java

License:Open Source License

private void createReleasesTable() {
    milestoneTable = new CellTable<Milestone>(10, resources);
    milestoneTable.setWidth("320px", true);
    DelegateCell<String> moveReleaseUpCell = new DelegateCell<String>(
            new DelegateCell.RenderDelegate<String>() {
                @Override//from  ww  w.  j a  v a  2 s.  c o  m
                public SafeHtml render(Cell.Context context, String value, SafeHtmlBuilder sb) {
                    return SafeHtmlUtils
                            .fromSafeConstant("<span class=\"order-control\"><a class=\"up\"/></span>");
                }
            }, new DelegateCell.ActionDelegate<String>() {
                @Override
                public void execute(Cell.Context object) {
                    int index = object.getIndex();
                    if (index > 0) {
                        milestonesEditor.getList().get(index).setSortkey((short) (index - 1));
                        milestonesEditor.getList().get(index - 1).setSortkey((short) index);
                        Collections.sort(milestonesEditor.getList());
                        milestoneTable.setRowData(milestonesEditor.getList());
                    }
                }
            });
    Column<Milestone, String> moveReleaseUpColumn = new Column<Milestone, String>(moveReleaseUpCell) {

        @Override
        public String getValue(Milestone object) {
            return null;
        }

        @Override
        public void render(Cell.Context context, Milestone object, SafeHtmlBuilder sb) {
            if (context.getIndex() != 0) {
                super.render(context, object, sb);
            }
        }
    };
    milestoneTable.addColumn(moveReleaseUpColumn);
    milestoneTable.setColumnWidth(moveReleaseUpColumn, 22, Unit.PX);

    DelegateCell<String> moveReleaseDownCell = new DelegateCell<String>(
            new DelegateCell.RenderDelegate<String>() {
                @Override
                public SafeHtml render(Cell.Context context, String value, SafeHtmlBuilder sb) {
                    return SafeHtmlUtils
                            .fromSafeConstant("<span class=\"order-control\"><a class=\"down\"/></span>");
                }
            }, new DelegateCell.ActionDelegate<String>() {
                @Override
                public void execute(Cell.Context object) {
                    Short index = (short) object.getIndex();
                    if (index < milestonesEditor.getList().size() - 1) {
                        milestonesEditor.getList().get(index).setSortkey((short) (index + 1));
                        milestonesEditor.getList().get(index + 1).setSortkey(index);
                        Collections.sort(milestonesEditor.getList());
                        milestoneTable.setRowData(milestonesEditor.getList());
                    }
                }
            });
    Column<Milestone, String> moveReleaseDownColumn = new Column<Milestone, String>(moveReleaseDownCell) {

        @Override
        public String getValue(Milestone object) {
            return null;
        }

        @Override
        public void render(Cell.Context context, Milestone object, SafeHtmlBuilder sb) {
            if (context.getIndex() != milestonesEditor.getList().size() - 1) {
                super.render(context, object, sb);
            }
        }
    };
    milestoneTable.addColumn(moveReleaseDownColumn);
    milestoneTable.setColumnWidth(moveReleaseDownColumn, 22, Unit.PX);

    DelegateCell<String> moveReleaseToTopCell = new DelegateCell<String>(
            new DelegateCell.RenderDelegate<String>() {
                @Override
                public SafeHtml render(Cell.Context context, String value, SafeHtmlBuilder sb) {
                    return SafeHtmlUtils
                            .fromSafeConstant("<span class=\"order-control\"><a class=\"top\"/></span>");
                }
            }, new DelegateCell.ActionDelegate<String>() {
                @Override
                public void execute(Cell.Context object) {
                    int index = object.getIndex();
                    Milestone topRelease = milestonesEditor.getList().get(index);
                    milestonesEditor.getList().remove(topRelease);
                    milestonesEditor.getList().add(0, topRelease);
                    int i = 0;
                    for (Milestone milestone : milestonesEditor.getList()) {
                        milestone.setSortkey((short) i);
                        i++;
                    }
                    Collections.sort(milestonesEditor.getList());
                    milestoneTable.setRowData(milestonesEditor.getList());
                }
            });
    Column<Milestone, String> moveReleaseToTopColumn = new Column<Milestone, String>(moveReleaseToTopCell) {

        @Override
        public String getValue(Milestone object) {
            return null;
        }

        @Override
        public void render(Cell.Context context, Milestone object, SafeHtmlBuilder sb) {
            if (context.getIndex() != 0) {
                super.render(context, object, sb);
            }
        }
    };
    milestoneTable.addColumn(moveReleaseToTopColumn);
    milestoneTable.setColumnWidth(moveReleaseToTopColumn, 22, Unit.PX);

    Column<Milestone, String> releaseVersionColumn = addColumn(
            new TextBoxCell(new TextBoxCell.TemplateDelegate() {
                @Override
                public SafeHtml getHtml(Context context, String string) {
                    SafeHtml releaseVerHtml = template.releaseVersion(tasksMessages.releaseVersion(), string);
                    String fieldName = "value";

                    if (ValidationUtils.hasError(context.getKey(), fieldName, errorTable)) {
                        String errorMsg = ValidationUtils.getErrorMessage(context.getKey(), fieldName,
                                errorTable);

                        return template.errorWrapper(releaseVerHtml, SafeHtmlUtils.fromString(errorMsg));
                    } else {
                        return releaseVerHtml;
                    }
                }
            }), new GetValue<Milestone, String>() {
                @Override
                public String getValue(Milestone object) {
                    return milestonesEditor.getEditors()
                            .get(milestonesEditor.getList().indexOf(object)).valueEditor.getValue();
                }
            });
    releaseVersionColumn.setFieldUpdater(new FieldUpdater<Milestone, String>() {
        @Override
        public void update(int index, Milestone object, String value) {
            Milestone currentDefaultMilestone = productDefaultRelease.getValue();
            for (Milestone milestone : presenter.getProduct().getMilestones()) {
                if (milestone.getId().equals(object.getId())) {
                    milestone.setValue(value);
                    break;
                }
            }
            for (Milestone milestone : presenter.getProduct().getMilestones()) {
                if (milestone.getId().equals(currentDefaultMilestone.getId())) {
                    productDefaultRelease.asEditor().getValue().setValue(value);
                    break;
                }
            }

            milestonesEditor.getEditors().get(index).valueEditor.setValue(value);
            productDefaultRelease.setAcceptableValues(presenter.getProduct().getMilestones());
        }
    });
    milestoneTable.addColumn(releaseVersionColumn);
    milestoneTable.setColumnWidth(releaseVersionColumn, 250, Unit.PX);

    DelegateCell<String> removeReleaseCell = new DelegateCell<String>(
            new DelegateCell.RenderDelegate<String>() {
                @Override
                public SafeHtml render(Cell.Context context, String value, SafeHtmlBuilder sb) {
                    final Milestone referenced = milestonesEditor.getList().get(context.getIndex());
                    if (referenced != null && "---".equals(referenced.getValue())) {
                        return SafeHtmlUtils.fromSafeConstant("<a class=\"delete-disabled\"><span/></a>");
                    }
                    return SafeHtmlUtils.fromSafeConstant("<a class=\"misc-icon cancel\"><span/></a>");
                }
            }, new DelegateCell.ActionDelegate<String>() {
                @Override
                public void execute(final Cell.Context object) {
                    final Milestone toRemove = milestonesEditor.getList().get(object.getIndex());
                    if (toRemove == null) {
                        return;
                    }
                    if ("---".equals(toRemove.getValue())) {
                        return;
                    }
                    presenter.deleteMilestone(toRemove.getId(), new ClientCallback<Void>() {
                        @Override
                        public void onReturn(Void aVoid) {
                            for (Milestone milestone : presenter.getProduct().getMilestones()) {
                                if (milestone.getId().equals(toRemove.getId())) {
                                    presenter.getProduct().getMilestones().remove(milestone);
                                    break;
                                }
                            }
                            productDefaultRelease.setAcceptableValues(presenter.getProduct().getMilestones());
                            milestonesEditor.getList().remove(toRemove);
                            milestoneTable.setRowData(milestonesEditor.getList());
                        }
                    });
                }
            });
    Column<Milestone, String> removeReleaseColumn = new Column<Milestone, String>(removeReleaseCell) {

        @Override
        public String getValue(Milestone object) {
            return null;
        }

        @Override
        public void render(Cell.Context context, Milestone object, SafeHtmlBuilder sb) {
            if (milestoneTable.getRowCount() == 1) {
                sb.appendHtmlConstant("<a><span/></a>");
            } else {
                super.render(context, object, sb);
            }
        }
    };
    milestoneTable.addColumn(removeReleaseColumn);
    milestoneTable.setColumnWidth(removeReleaseColumn, 30, Unit.PX);

    DelegateCell<String> addReleaseCell = new DelegateCell<String>(new DelegateCell.RenderDelegate<String>() {
        @Override
        public SafeHtml render(Cell.Context context, String value, SafeHtmlBuilder sb) {
            return SafeHtmlUtils.fromSafeConstant("<a class=\"misc-icon add right\"><span/></a>");
        }
    }, new DelegateCell.ActionDelegate<String>() {
        @Override
        public void execute(Cell.Context object) {
            Milestone newMilestone = presenter.createNewTransientMilestone(milestonesEditor.getList());
            milestonesEditor.getList().add(newMilestone);
            milestoneTable.setRowData(milestonesEditor.getList());
            presenter.getProduct().getMilestones().add(ProjectAdminTasksUtil.duplicateMilestone(newMilestone));
            productDefaultRelease.setAcceptableValues(presenter.getProduct().getMilestones());
        }
    });
    Column<Milestone, String> addReleaseColumn = new Column<Milestone, String>(addReleaseCell) {
        @Override
        public String getValue(Milestone object) {
            return null;
        }

        @Override
        public void render(Cell.Context context, Milestone object, SafeHtmlBuilder sb) {
            if (context.getIndex() == milestoneTable.getRowCount() - 1) {
                super.render(context, object, sb);
            } else {
                sb.appendHtmlConstant("<a><span/></a>");
            }
        }
    };
    milestoneTable.addColumn(addReleaseColumn);
    milestoneTable.setColumnWidth(addReleaseColumn, 30, Unit.PX);
}