cursor: pointer;
}
+.v-table-generated-row {
+ background: #efefef;
+}
+
.v-table-body-noselection .v-table-row,
.v-table-body-noselection .v-table-row-odd {
cursor: default;
margin: 0;
}
+.v-table-generated-row {
+ background: #c9c9c9;
+ }
+
+
div.v-table-focus-slot-right {
background: transparent;
border-right: 2px solid #b3b3b3;
background: #eef0f2;
}
+.v-table-generated-row {
+ color: #336699;
+ font-weight: bold;
+ font-size: 11px;
+ padding-left: 0px;
+ padding-top: 6px;
+ background: #c0c2c5;
+}
+
.v-table .v-selected {
background-color: #5B677D;
color: #FFF;
.v-table-row-odd {
background: #eff0f1;
}
+.v-table-generated-row {
+ background: #dcdee0;
+ text-transform: uppercase;
+ font-size: 10px;
+ font-weight: bold;
+ color: #222;
+ text-shadow: #f3f5f8 0 1px 0;
+ line-height: normal;
+}
.v-table-cell-content:last-child {
border-right-color: transparent;
}
.v-table-body-noselection .v-table-row-odd:hover {
background-color: #f6f7f7;
}
+.v-table-generated-row {
+ color: #393a3c;
+ font-size: 15px;
+ padding: 9px 2px 9px 0;
+ text-shadow: #ffffff 0 1px 0;
+ background: #e7e9ea;
+}
.v-table tr.v-selected {
background: #57a7ed;
color: #fff;
/**
* Run only once when component is attached and received its initial
- * content. This function : * Syncs headers and bodys "natural widths and
- * saves the values. * Sets proper width and height * Makes deferred request
- * to get some cache rows
+ * content. This function:
+ *
+ * * Syncs headers and bodys "natural widths and saves the values.
+ *
+ * * Sets proper width and height
+ *
+ * * Makes deferred request to get some cache rows
*/
private void sizeInit() {
/*
*/
private VScrollTableRow prepareRow(UIDL uidl) {
final VScrollTableRow row = createRow(uidl, aligns);
- final int cells = DOM.getChildCount(row.getElement());
- for (int i = 0; i < cells; i++) {
- final Element cell = DOM.getChild(row.getElement(), i);
- int w = VScrollTable.this.getColWidth(getColKeyByIndex(i));
- if (w < 0) {
- w = 0;
- }
- cell.getFirstChildElement().getStyle()
- .setPropertyPx("width", w);
- cell.getStyle().setPropertyPx("width", w);
- }
+ row.initCellWidths();
return row;
}
protected VScrollTableRow createRow(UIDL uidl, char[] aligns2) {
- return new VScrollTableRow(uidl, aligns);
+ if (uidl.hasAttribute("gen_html")) {
+ // This is a generated row.
+ return new VScrollTableGeneratedRow(uidl, aligns2);
+ }
+ return new VScrollTableRow(uidl, aligns2);
}
private void addRowBeforeFirstRendered(VScrollTableRow row) {
*/
public int getColWidth(int columnIndex) {
if (tBodyMeasurementsDone) {
- NodeList<TableRowElement> rows = tBodyElement.getRows();
- if (rows.getLength() == 0) {
+ if (renderedRows.isEmpty()) {
// no rows yet rendered
return 0;
- } else {
- com.google.gwt.dom.client.Element wrapperdiv = rows
- .getItem(0).getCells().getItem(columnIndex)
- .getFirstChildElement();
- return wrapperdiv.getOffsetWidth();
}
+ for (Widget row : renderedRows) {
+ if (!(row instanceof VScrollTableGeneratedRow)) {
+ TableRowElement tr = row.getElement().cast();
+ Element wrapperdiv = tr.getCells().getItem(columnIndex)
+ .getFirstChildElement().cast();
+ return wrapperdiv.getOffsetWidth();
+ }
+ }
+ return 0;
} else {
return 0;
}
* @param w
*/
public void setColWidth(int colIndex, int w) {
- NodeList<TableRowElement> rows2 = tBodyElement.getRows();
- final int rows = rows2.getLength();
- for (int i = 0; i < rows; i++) {
- TableRowElement row = rows2.getItem(i);
- TableCellElement cell = row.getCells().getItem(colIndex);
- cell.getFirstChildElement().getStyle()
- .setPropertyPx("width", w);
- cell.getStyle().setPropertyPx("width", w);
+ for (Widget row : renderedRows) {
+ TableRowElement tr = row.getElement().cast();
+ TableCellElement cell = tr.getCells().getItem(colIndex);
+ boolean spanned = false;
+ if (row instanceof VScrollTableGeneratedRow) {
+ spanned = ((VScrollTableGeneratedRow) row).isSpanColumns();
+ }
+ if (!spanned) {
+ cell.getFirstChildElement().getStyle()
+ .setPropertyPx("width", w);
+ cell.getStyle().setPropertyPx("width", w);
+ } else if (colIndex == 0) {
+ cell.getFirstChildElement().getStyle()
+ .clearProperty("width");
+ cell.getStyle().clearProperty("width");
+ }
}
}
protected final int rowKey;
private List<UIDL> pendingComponentPaints;
- private String[] actionKeys = null;
- private final TableRowElement rowElement;
+ protected String[] actionKeys = null;
+ protected final TableRowElement rowElement;
private boolean mDown;
private int index;
private Event touchStart;
| Event.ONCONTEXTMENU | VTooltip.TOOLTIP_EVENTS);
}
+ public VScrollTableRow(UIDL uidl, char[] aligns) {
+ this(uidl.getIntAttribute("key"));
+
+ /*
+ * Rendering the rows as hidden improves Firefox and Safari
+ * performance drastically.
+ */
+ getElement().getStyle().setProperty("visibility", "hidden");
+
+ String rowStyle = uidl.getStringAttribute("rowstyle");
+ if (rowStyle != null) {
+ addStyleName(CLASSNAME + "-row-" + rowStyle);
+ }
+
+ String rowDescription = uidl.getStringAttribute("rowdescr");
+ if (rowDescription != null && !rowDescription.equals("")) {
+ TooltipInfo info = new TooltipInfo(rowDescription);
+ client.registerTooltip(VScrollTable.this, rowElement, info);
+ } else {
+ // Remove possibly previously set tooltip
+ client.registerTooltip(VScrollTable.this, rowElement, null);
+ }
+
+ tHead.getColumnAlignments();
+ int col = 0;
+ int visibleColumnIndex = -1;
+
+ // row header
+ if (showRowHeaders) {
+ boolean sorted = tHead.getHeaderCell(col).isSorted();
+ addCell(uidl, buildCaptionHtmlSnippet(uidl), aligns[col++],
+ "rowheader", true, sorted);
+ visibleColumnIndex++;
+ }
+
+ if (uidl.hasAttribute("al")) {
+ actionKeys = uidl.getStringArrayAttribute("al");
+ }
+
+ addCellsFromUIDL(uidl, aligns, col, visibleColumnIndex);
+
+ if (uidl.hasAttribute("selected") && !isSelected()) {
+ toggleSelection();
+ }
+ }
+
+ /**
+ * Add a dummy row, used for measurements if Table is empty.
+ */
+ public VScrollTableRow() {
+ this(0);
+ addStyleName(CLASSNAME + "-row");
+ addCell(null, "_", 'b', "", true, false);
+ }
+
+ protected void initCellWidths() {
+ final int cells = DOM.getChildCount(getElement());
+ for (int i = 0; i < cells; i++) {
+ final Element cell = DOM.getChild(getElement(), i);
+ int w = VScrollTable.this.getColWidth(getColKeyByIndex(i));
+ if (w < 0) {
+ w = 0;
+ }
+ cell.getFirstChildElement().getStyle()
+ .setPropertyPx("width", w);
+ cell.getStyle().setPropertyPx("width", w);
+ }
+ }
+
+ protected void addCellsFromUIDL(UIDL uidl, char[] aligns, int col,
+ int visibleColumnIndex) {
+ final Iterator<?> cells = uidl.getChildIterator();
+ while (cells.hasNext()) {
+ final Object cell = cells.next();
+ visibleColumnIndex++;
+
+ String columnId = visibleColOrder[visibleColumnIndex];
+
+ String style = "";
+ if (uidl.hasAttribute("style-" + columnId)) {
+ style = uidl.getStringAttribute("style-" + columnId);
+ }
+
+ String description = null;
+ if (uidl.hasAttribute("descr-" + columnId)) {
+ description = uidl.getStringAttribute("descr-"
+ + columnId);
+ }
+
+ boolean sorted = tHead.getHeaderCell(col).isSorted();
+ if (cell instanceof String) {
+ addCell(uidl, cell.toString(), aligns[col++], style,
+ isRenderCellsAsHtml(), sorted, description);
+ } else {
+ final Paintable cellContent = client
+ .getPaintable((UIDL) cell);
+
+ addCell(uidl, (Widget) cellContent, aligns[col++],
+ style, sorted);
+ paintComponent(cellContent, (UIDL) cell);
+ }
+ }
+ }
+
+ /**
+ * Overriding this and returning true causes all text cells to be
+ * rendered as HTML.
+ *
+ * @return always returns false in the default implementation
+ */
+ protected boolean isRenderCellsAsHtml() {
+ return false;
+ }
+
/**
* Detects whether row is visible in tables viewport.
*
return index;
}
- private void paintComponent(Paintable p, UIDL uidl) {
+ protected void paintComponent(Paintable p, UIDL uidl) {
if (isAttached()) {
p.updateFromUIDL(uidl, client);
} else {
return String.valueOf(rowKey);
}
- public VScrollTableRow(UIDL uidl, char[] aligns) {
- this(uidl.getIntAttribute("key"));
-
- /*
- * Rendering the rows as hidden improves Firefox and Safari
- * performance drastically.
- */
- getElement().getStyle().setProperty("visibility", "hidden");
-
- String rowStyle = uidl.getStringAttribute("rowstyle");
- if (rowStyle != null) {
- addStyleName(CLASSNAME + "-row-" + rowStyle);
- }
-
- String rowDescription = uidl.getStringAttribute("rowdescr");
- if (rowDescription != null && !rowDescription.equals("")) {
- TooltipInfo info = new TooltipInfo(rowDescription);
- client.registerTooltip(VScrollTable.this, rowElement, info);
- } else {
- // Remove possibly previously set tooltip
- client.registerTooltip(VScrollTable.this, rowElement, null);
- }
-
- tHead.getColumnAlignments();
- int col = 0;
- int visibleColumnIndex = -1;
-
- // row header
- if (showRowHeaders) {
- boolean sorted = tHead.getHeaderCell(col).isSorted();
- addCell(uidl, buildCaptionHtmlSnippet(uidl), aligns[col++],
- "rowheader", true, sorted);
- visibleColumnIndex++;
- }
-
- if (uidl.hasAttribute("al")) {
- actionKeys = uidl.getStringArrayAttribute("al");
- }
-
- final Iterator<?> cells = uidl.getChildIterator();
- while (cells.hasNext()) {
- final Object cell = cells.next();
- visibleColumnIndex++;
-
- String columnId = visibleColOrder[visibleColumnIndex];
-
- String style = "";
- if (uidl.hasAttribute("style-" + columnId)) {
- style = uidl.getStringAttribute("style-" + columnId);
- }
-
- String description = null;
- if (uidl.hasAttribute("descr-" + columnId)) {
- description = uidl.getStringAttribute("descr-"
- + columnId);
- }
-
- boolean sorted = tHead.getHeaderCell(col).isSorted();
- if (cell instanceof String) {
- addCell(uidl, cell.toString(), aligns[col++], style,
- false, sorted, description);
- } else {
- final Paintable cellContent = client
- .getPaintable((UIDL) cell);
-
- addCell(uidl, (Widget) cellContent, aligns[col++],
- style, sorted);
- paintComponent(cellContent, (UIDL) cell);
- }
- }
- if (uidl.hasAttribute("selected") && !isSelected()) {
- toggleSelection();
- }
- }
-
- /**
- * Add a dummy row, used for measurements if Table is empty.
- */
- public VScrollTableRow() {
- this(0);
- addStyleName(CLASSNAME + "-row");
- addCell(null, "_", 'b', "", true, false);
- }
-
public void addCell(UIDL rowUidl, String text, char align,
String style, boolean textIsHTML, boolean sorted) {
addCell(rowUidl, text, align, style, textIsHTML, sorted, null);
String style, boolean textIsHTML, boolean sorted,
String description) {
// String only content is optimized by not using Label widget
- final Element td = DOM.createTD();
+ final TableCellElement td = DOM.createTD().cast();
+ initCellWithText(text, align, style, textIsHTML, sorted,
+ description, td);
+ }
+
+ protected void initCellWithText(String text, char align,
+ String style, boolean textIsHTML, boolean sorted,
+ String description, final TableCellElement td) {
final Element container = DOM.createDiv();
String className = CLASSNAME + "-cell-content";
if (style != null && !style.equals("")) {
public void addCell(UIDL rowUidl, Widget w, char align,
String style, boolean sorted) {
- final Element td = DOM.createTD();
+ final TableCellElement td = DOM.createTD().cast();
+ initCellWithWidget(w, align, style, sorted, td);
+ }
+
+ protected void initCellWithWidget(Widget w, char align,
+ String style, boolean sorted, final TableCellElement td) {
final Element container = DOM.createDiv();
String className = CLASSNAME + "-cell-content";
if (style != null && !style.equals("")) {
};
}
- private int getColIndexOf(Widget child) {
+ protected int getColIndexOf(Widget child) {
com.google.gwt.dom.client.Element widgetCell = child
.getElement().getParentElement().getParentElement();
NodeList<TableCellElement> cells = rowElement.getCells();
}
}
+ protected class VScrollTableGeneratedRow extends VScrollTableRow {
+
+ private boolean spanColumns;
+ private boolean renderAsHtml;
+
+ public VScrollTableGeneratedRow(UIDL uidl, char[] aligns) {
+ super(uidl, aligns);
+ addStyleName("v-table-generated-row");
+ }
+
+ @Override
+ protected void initCellWidths() {
+ if (!spanColumns) {
+ super.initCellWidths();
+ }
+ }
+
+ public boolean isSpanColumns() {
+ return spanColumns;
+ }
+
+ @Override
+ protected boolean isRenderCellsAsHtml() {
+ return renderAsHtml;
+ }
+
+ @Override
+ protected void addCellsFromUIDL(UIDL uidl, char[] aligns, int col,
+ int visibleColumnIndex) {
+ renderAsHtml = uidl.getBooleanAttribute("gen_html");
+ spanColumns = uidl.getBooleanAttribute("gen_span");
+
+ final Iterator<?> cells = uidl.getChildIterator();
+ if (spanColumns) {
+ int colCount = uidl.getChildCount();
+ if (cells.hasNext()) {
+ final Object cell = cells.next();
+ if (cell instanceof String) {
+ addSpannedCell(uidl, cell.toString(), aligns[0],
+ "", renderAsHtml, false, null, colCount);
+ } else {
+ addSpannedCell(uidl, (Widget) cell, aligns[0], "",
+ false, colCount);
+ }
+ }
+ } else {
+ super.addCellsFromUIDL(uidl, aligns, col,
+ visibleColumnIndex);
+ }
+ }
+
+ private void addSpannedCell(UIDL rowUidl, Widget w, char align,
+ String style, boolean sorted, int colCount) {
+ TableCellElement td = DOM.createTD().cast();
+ td.setColSpan(colCount);
+ initCellWithWidget(w, align, style, sorted, td);
+ }
+
+ private void addSpannedCell(UIDL rowUidl, String text, char align,
+ String style, boolean textIsHTML, boolean sorted,
+ String description, int colCount) {
+ // String only content is optimized by not using Label widget
+ final TableCellElement td = DOM.createTD().cast();
+ td.setColSpan(colCount);
+ initCellWithText(text, align, style, textIsHTML, sorted,
+ description, td);
+ }
+ }
+
/**
* Ensure the component has a focus.
*
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.Visibility;
+import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
@Override
protected VScrollTableRow createRow(UIDL uidl, char[] aligns2) {
+ if (uidl.hasAttribute("gen_html")) {
+ // This is a generated row.
+ return new VTreeTableGeneratedRow(uidl, aligns2);
+ }
return new VTreeTableRow(uidl, aligns2);
}
private boolean open;
private int depth;
private boolean canHaveChildren;
- private Widget widgetInHierarchyColumn;
+ protected Widget widgetInHierarchyColumn;
public VTreeTableRow(UIDL uidl, char[] aligns2) {
super(uidl, aligns2);
addTreeSpacer(rowUidl);
}
- private boolean addTreeSpacer(UIDL rowUidl) {
+ protected boolean addTreeSpacer(UIDL rowUidl) {
if (cellShowsTreeHierarchy(getElement().getChildCount() - 1)) {
Element container = (Element) getElement().getLastChild()
.getFirstChild();
}
+ protected class VTreeTableGeneratedRow extends VTreeTableRow {
+
+ private boolean spanColumns;
+ private boolean renderAsHtml;
+
+ public VTreeTableGeneratedRow(UIDL uidl, char[] aligns) {
+ super(uidl, aligns);
+ addStyleName("v-table-generated-row");
+ }
+
+ @Override
+ protected void initCellWidths() {
+ if (!spanColumns) {
+ super.initCellWidths();
+ }
+ }
+
+ public boolean isSpanColumns() {
+ return spanColumns;
+ }
+
+ @Override
+ protected boolean isRenderCellsAsHtml() {
+ return renderAsHtml;
+ }
+
+ @Override
+ protected void addCellsFromUIDL(UIDL uidl, char[] aligns, int col,
+ int visibleColumnIndex) {
+ renderAsHtml = uidl.getBooleanAttribute("gen_html");
+ spanColumns = uidl.getBooleanAttribute("gen_span");
+
+ final Iterator<?> cells = uidl.getChildIterator();
+ if (spanColumns) {
+ int colCount = uidl.getChildCount();
+ if (cells.hasNext()) {
+ final Object cell = cells.next();
+ if (cell instanceof String) {
+ addSpannedCell(uidl, cell.toString(), aligns[0],
+ "", renderAsHtml, false, null, colCount);
+ } else {
+ addSpannedCell(uidl, (Widget) cell, aligns[0], "",
+ false, colCount);
+ }
+ }
+ } else {
+ super.addCellsFromUIDL(uidl, aligns, col,
+ visibleColumnIndex);
+ }
+ }
+
+ private void addSpannedCell(UIDL rowUidl, Widget w, char align,
+ String style, boolean sorted, int colCount) {
+ TableCellElement td = DOM.createTD().cast();
+ td.setColSpan(colCount);
+ initCellWithWidget(w, align, style, sorted, td);
+ if (addTreeSpacer(rowUidl)) {
+ widgetInHierarchyColumn = w;
+ }
+ }
+
+ private void addSpannedCell(UIDL rowUidl, String text, char align,
+ String style, boolean textIsHTML, boolean sorted,
+ String description, int colCount) {
+ // String only content is optimized by not using Label widget
+ final TableCellElement td = DOM.createTD().cast();
+ td.setColSpan(colCount);
+ initCellWithText(text, align, style, textIsHTML, sorted,
+ description, td);
+ addTreeSpacer(rowUidl);
+ }
+ }
+
private int getIdentWidth() {
return identWidth;
}
protected static final int CELL_ITEMID = 3;
- protected static final int CELL_FIRSTCOL = 4;
+ protected static final int CELL_GENERATED_ROW = 4;
+
+ protected static final int CELL_FIRSTCOL = 5;
/**
* Left column alignment. <b>This is the default behaviour. </b>
private boolean rowCacheInvalidated;
+ private RowGenerator rowGenerator = null;
+
/* Table constructors */
/**
cells[CELL_ICON][i] = getItemIcon(id);
}
+ GeneratedRow generatedRow = rowGenerator != null ? rowGenerator
+ .generateRow(this, id) : null;
+ cells[CELL_GENERATED_ROW][i] = generatedRow;
+
for (int j = 0; j < cols; j++) {
if (isColumnCollapsed(colids[j])) {
continue;
}
Property p = null;
Object value = "";
- boolean isGenerated = columnGenerators.containsKey(colids[j]);
+ boolean isGeneratedRow = generatedRow != null;
+ boolean isGeneratedColumn = columnGenerators
+ .containsKey(colids[j]);
+ boolean isGenerated = isGeneratedRow || isGeneratedColumn;
if (!isGenerated) {
p = getContainerProperty(id, colids[j]);
}
- // check in current pageBuffer already has row
- int index = firstIndex + i;
- if (p != null || isGenerated) {
- if (index < firstIndexNotInCache
- && index >= pageBufferFirstIndex) {
- // we have data already in our cache,
- // recycle it instead of fetching it via
- // getValue/getPropertyValue
+ if (isGeneratedRow) {
+ if (generatedRow.isSpanColumns() && j > 0) {
+ value = null;
+ } else if (generatedRow.getText().length > j) {
+ value = generatedRow.getText()[j];
+ }
+ } else {
+ // check in current pageBuffer already has row
+ int index = firstIndex + i;
+ if (p != null || isGenerated) {
int indexInOldBuffer = index - pageBufferFirstIndex;
- value = pageBuffer[CELL_FIRSTCOL + j][indexInOldBuffer];
- if (!isGenerated && iscomponent[j]
- || !(value instanceof Component)) {
- listenProperty(p, oldListenedProperties);
- }
- } else {
- if (isGenerated) {
- ColumnGenerator cg = columnGenerators
- .get(colids[j]);
- value = cg.generateCell(this, id, colids[j]);
- if (value != null && !(value instanceof Component)
- && !(value instanceof String)) {
- // Avoid errors if a generator returns something
- // other than a Component or a String
- value = value.toString();
- }
- } else if (iscomponent[j]) {
- value = p.getValue();
- listenProperty(p, oldListenedProperties);
- } else if (p != null) {
- value = getPropertyValue(id, colids[j], p);
- /*
- * If returned value is Component (via fieldfactory
- * or overridden getPropertyValue) we excpect it to
- * listen property value changes. Otherwise if
- * property emits value change events, table will
- * start to listen them and refresh content when
- * needed.
- */
- if (!(value instanceof Component)) {
+ if (index < firstIndexNotInCache
+ && index >= pageBufferFirstIndex
+ && pageBuffer[CELL_GENERATED_ROW][indexInOldBuffer] == null) {
+ // we have data already in our cache,
+ // recycle it instead of fetching it via
+ // getValue/getPropertyValue
+ value = pageBuffer[CELL_FIRSTCOL + j][indexInOldBuffer];
+ if (!isGeneratedColumn && iscomponent[j]
+ || !(value instanceof Component)) {
listenProperty(p, oldListenedProperties);
}
} else {
- value = getPropertyValue(id, colids[j], null);
+ if (isGeneratedColumn) {
+ ColumnGenerator cg = columnGenerators
+ .get(colids[j]);
+ value = cg.generateCell(this, id, colids[j]);
+ if (value != null
+ && !(value instanceof Component)
+ && !(value instanceof String)) {
+ // Avoid errors if a generator returns
+ // something
+ // other than a Component or a String
+ value = value.toString();
+ }
+ } else if (iscomponent[j]) {
+ value = p.getValue();
+ listenProperty(p, oldListenedProperties);
+ } else if (p != null) {
+ value = getPropertyValue(id, colids[j], p);
+ /*
+ * If returned value is Component (via
+ * fieldfactory or overridden getPropertyValue)
+ * we excpect it to listen property value
+ * changes. Otherwise if property emits value
+ * change events, table will start to listen
+ * them and refresh content when needed.
+ */
+ if (!(value instanceof Component)) {
+ listenProperty(p, oldListenedProperties);
+ }
+ } else {
+ value = getPropertyValue(id, colids[j], null);
+ }
}
}
}
paintRowIcon(target, cells, indexInRowbuffer);
paintRowHeader(target, cells, indexInRowbuffer);
+ paintGeneratedRowInfo(target, cells, indexInRowbuffer);
target.addAttribute("key",
Integer.parseInt(cells[CELL_KEY][indexInRowbuffer].toString()));
paintRowAttributes(target, itemId);
}
+ private void paintGeneratedRowInfo(PaintTarget target, Object[][] cells,
+ int indexInRowBuffer) throws PaintException {
+ GeneratedRow generatedRow = (GeneratedRow) cells[CELL_GENERATED_ROW][indexInRowBuffer];
+ if (generatedRow != null) {
+ target.addAttribute("gen_html", generatedRow.isRenderAsHtml());
+ target.addAttribute("gen_span", generatedRow.isSpanColumns());
+ }
+ }
+
protected void paintRowHeader(PaintTarget target, Object[][] cells,
int indexInRowbuffer) throws PaintException {
if (rowHeadersAreEnabled()) {
return itemDescriptionGenerator;
}
+ public interface RowGenerator {
+ /**
+ * Called for every row that is painted in the Table. Returning a
+ * GeneratedRow object will cause the row to be painted based on the
+ * contents of the GeneratedRow. A generated row is by default styled
+ * similarly to a header or footer row.
+ * <p>
+ * The GeneratedRow data object contains the text that should be
+ * rendered in the row. The itemId in the container thus works only as a
+ * placeholder.
+ * <p>
+ * If GeneratedRow.setSpanColumns(true) is used, there will be one
+ * String spanning all columns (use setText("Spanning text")). Otherwise
+ * you can define one String per visible column.
+ * <p>
+ * If GeneratedRow.setRenderAsHtml(true) is used, the strings can
+ * contain HTML markup, otherwise all strings will be rendered as text
+ * (the default).
+ * <p>
+ * A "v-table-generated-row" CSS class is added to all generated rows.
+ * For custom styling of a generated row you can combine a RowGenerator
+ * with a CellStyleGenerator.
+ * <p>
+ *
+ * @param table
+ * The Table that is being painted
+ * @param itemId
+ * The itemId for the row
+ * @return A GeneratedRow describing how the row should be painted or
+ * null to paint the row with the contents from the container
+ */
+ public GeneratedRow generateRow(Table table, Object itemId);
+ }
+
+ public static class GeneratedRow {
+ private boolean renderAsHtml = false;
+ private boolean spanColumns = false;
+ private String[] text = null;
+
+ /**
+ * Creates a new generated row. If only one string is passed in, columns
+ * are automatically spanned.
+ *
+ * @param text
+ */
+ public GeneratedRow(String... text) {
+ setRenderAsHtml(false);
+ setSpanColumns(text.length == 1);
+ setText(text);
+ }
+
+ /**
+ * Pass one String if spanColumns is used, one String for each visible
+ * column otherwise
+ */
+ public void setText(String... text) {
+ this.text = text;
+ }
+
+ protected String[] getText() {
+ return text;
+ }
+
+ protected boolean isRenderAsHtml() {
+ return renderAsHtml;
+ }
+
+ /**
+ * If set to true, all strings passed to {@link #setText(String...)}
+ * will be rendered as HTML.
+ *
+ * @param renderAsHtml
+ */
+ public void setRenderAsHtml(boolean renderAsHtml) {
+ this.renderAsHtml = renderAsHtml;
+ }
+
+ protected boolean isSpanColumns() {
+ return spanColumns;
+ }
+
+ /**
+ * If set to true, only one string will be rendered, spanning the entire
+ * row.
+ *
+ * @param spanColumns
+ */
+ public void setSpanColumns(boolean spanColumns) {
+ this.spanColumns = spanColumns;
+ }
+ }
+
+ /**
+ * Assigns a row generator to the table. The row generator will be able to
+ * replace rows in the table when it is rendered.
+ *
+ * @param generator
+ * the new row generator
+ */
+ public void setRowGenerator(RowGenerator generator) {
+ rowGenerator = generator;
+ refreshRenderedCells();
+ }
+
+ /**
+ * @return the current row generator
+ */
+ public RowGenerator getRowGenerator() {
+ return rowGenerator;
+ }
}
--- /dev/null
+package com.vaadin.tests.components.table;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Item;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Table.GeneratedRow;
+import com.vaadin.ui.Table.RowGenerator;
+
+public class RowGenerators extends TestBase implements RowGenerator {
+
+ @Override
+ protected void setup() {
+ Table table = new Table();
+ table.setContainerDataSource(filledContainer());
+ table.setRowGenerator(this);
+ addComponent(table);
+ }
+
+ private Container filledContainer() {
+ IndexedContainer c = new IndexedContainer();
+ c.addContainerProperty("Property 1", String.class, "");
+ c.addContainerProperty("Property 2", String.class, "");
+ c.addContainerProperty("Property 3", String.class, "");
+ c.addContainerProperty("Property 4", String.class, "");
+ for (int ix = 0; ix < 500; ix++) {
+ Item i = c.addItem(ix);
+ i.getItemProperty("Property 1").setValue("Item " + ix + ",1");
+ i.getItemProperty("Property 2").setValue("Item " + ix + ",2");
+ i.getItemProperty("Property 3").setValue("Item " + ix + ",3");
+ i.getItemProperty("Property 4").setValue("Item " + ix + ",4");
+ }
+ return c;
+ }
+
+ public GeneratedRow generateRow(Table table, Object itemId) {
+ if ((Integer) itemId % 5 == 0) {
+ if ((Integer) itemId % 10 == 0) {
+ return new GeneratedRow(
+ "foobarbazoof very extremely long, most definitely will span.");
+ } else {
+ return new GeneratedRow("foo", "bar", "baz", "oof");
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Row generators should replace every fifth row in the table";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 6720;
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.table.Tables?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item0</td>
+ <td>46,13</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[0]/VMenuBar[0]#item8</td>
+ <td>42,5</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[1]/VMenuBar[0]#item6</td>
+ <td>82,3</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[2]/VMenuBar[0]#item1</td>
+ <td>56,4</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item0</td>
+ <td>29,3</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>spanned</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item0</td>
+ <td>30,5</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item0</td>
+ <td>27,4</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[0]/VMenuBar[0]#item8</td>
+ <td>47,13</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[1]/VMenuBar[0]#item6</td>
+ <td>80,2</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[2]/VMenuBar[0]#item2</td>
+ <td>80,8</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>nospan</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::PID_Smenu#item0</td>
+ <td>36,12</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[0]/VMenuBar[0]#item8</td>
+ <td>47,5</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[1]/VMenuBar[0]#item6</td>
+ <td>95,7</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTables::Root/VOverlay[2]/VMenuBar[0]#item3</td>
+ <td>67,12</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>html</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
import com.vaadin.ui.Table.ColumnResizeListener;\r
import com.vaadin.ui.Table.FooterClickEvent;\r
import com.vaadin.ui.Table.FooterClickListener;\r
+import com.vaadin.ui.Table.GeneratedRow;\r
import com.vaadin.ui.Table.HeaderClickEvent;\r
import com.vaadin.ui.Table.HeaderClickListener;\r
+import com.vaadin.ui.Table.RowGenerator;\r
\r
public class Tables<T extends Table> extends AbstractSelectTestCase<T>\r
implements ItemClickListener, HeaderClickListener, FooterClickListener,\r
}\r
};\r
\r
+ private class GeneratedRowInfo {\r
+\r
+ private final int nth;\r
+ private final String[] text;\r
+ private final boolean isHtml;\r
+\r
+ public GeneratedRowInfo(int nth, boolean isHtml, String... text) {\r
+ this.nth = nth;\r
+ this.isHtml = isHtml;\r
+ this.text = text;\r
+ }\r
+\r
+ public boolean appliesTo(Object itemId) {\r
+ int ix = Integer.valueOf(itemId.toString().substring(5));\r
+ return ix % nth == 0;\r
+ }\r
+ }\r
+\r
+ private Command<T, GeneratedRowInfo> rowGeneratorCommand = new Command<T, GeneratedRowInfo>() {\r
+\r
+ public void execute(T c, final GeneratedRowInfo generatedRowInfo,\r
+ Object data) {\r
+ if (generatedRowInfo == null) {\r
+ c.setRowGenerator(null);\r
+ } else {\r
+ c.setRowGenerator(new RowGenerator() {\r
+\r
+ public GeneratedRow generateRow(Table table, Object itemId) {\r
+ if (generatedRowInfo.appliesTo(itemId)) {\r
+ GeneratedRow generatedRow = new GeneratedRow(\r
+ generatedRowInfo.text);\r
+ generatedRow\r
+ .setRenderAsHtml(generatedRowInfo.isHtml);\r
+ return generatedRow;\r
+ }\r
+ return null;\r
+ }\r
+ });\r
+ }\r
+ }\r
+ };\r
+\r
private Command<T, Boolean> setSortEnabledCommand = new Command<T, Boolean>() {\r
\r
public void execute(T c, Boolean value, Object data) {\r
createColumnHeaderMode(CATEGORY_FEATURES);\r
createAddGeneratedColumnAction(CATEGORY_FEATURES);\r
createCellStyleAction(CATEGORY_FEATURES);\r
+ createGeneratedRowAction(CATEGORY_FEATURES);\r
\r
createBooleanAction("Sort enabled", CATEGORY_FEATURES, true,\r
setSortEnabledCommand);\r
"None", cellStyleCommand, true);\r
}\r
\r
+ private void createGeneratedRowAction(String categoryFeatures) {\r
+ LinkedHashMap<String, GeneratedRowInfo> options = new LinkedHashMap<String, GeneratedRowInfo>();\r
+ options.put("None", null);\r
+ options.put("Every fifth row, spanned", new GeneratedRowInfo(5, false,\r
+ "foobarbaz this is a long one that should span."));\r
+ int props = getComponent().getContainerPropertyIds().size();\r
+ String[] text = new String[props];\r
+ for (int ix = 0; ix < props; ix++) {\r
+ text[ix] = "foo" + ix;\r
+ }\r
+ options.put("Every tenth row, no spanning", new GeneratedRowInfo(10,\r
+ false, text));\r
+ options.put(\r
+ "Every eight row, spanned, html formatted",\r
+ new GeneratedRowInfo(8, true,\r
+ "<b>foo</b> <i>bar</i> <span style='color:red;text-size:0.5em;'>baz</span>"));\r
+ createSelectAction("Row generator", categoryFeatures, options, "None",\r
+ rowGeneratorCommand, true);\r
+ }\r
+\r
private void createColumnHeaderMode(String category) {\r
LinkedHashMap<String, Integer> columnHeaderModeOptions = new LinkedHashMap<String, Integer>();\r
columnHeaderModeOptions.put("Hidden", Table.COLUMN_HEADER_MODE_HIDDEN);\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.treetable.TreeTableTest?restartApplication=</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_Smenu#item0</td>
+ <td>30,7</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[0]/VMenuBar[0]#item5</td>
+ <td>36,4</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[1]/VMenuBar[0]#item1</td>
+ <td>75,6</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[2]/VMenuBar[0]#item13</td>
+ <td>34,10</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_Smenu#item0</td>
+ <td>39,9</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[0]/VMenuBar[0]#item5</td>
+ <td>43,2</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[1]/VMenuBar[0]#item3</td>
+ <td>45,4</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[2]/VMenuBar[0]#item10</td>
+ <td>41,8</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_Smenu#item0</td>
+ <td>10,9</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[0]/VMenuBar[0]#item2</td>
+ <td>35,7</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[1]/VMenuBar[0]#item2</td>
+ <td>32,8</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[2]/VMenuBar[0]#item3</td>
+ <td>54,7</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_Smenu#item0</td>
+ <td>20,4</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[0]/VMenuBar[0]#item8</td>
+ <td>42,5</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[1]/VMenuBar[0]#item6</td>
+ <td>92,5</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[2]/VMenuBar[0]#item1</td>
+ <td>65,8</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[4]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>12,8</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>spanned</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[4]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>12,4</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_Smenu#item0</td>
+ <td>22,2</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[0]/VMenuBar[0]#item8</td>
+ <td>44,0</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[1]/VMenuBar[0]#item6</td>
+ <td>87,3</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[2]/VMenuBar[0]#item2</td>
+ <td>68,12</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[9]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>11,6</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>nospan</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[9]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>11,6</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_Smenu#item0</td>
+ <td>7,12</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[0]/VMenuBar[0]#item8</td>
+ <td>24,1</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[1]/VMenuBar[0]#item6</td>
+ <td>93,8</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[2]/VMenuBar[0]#item3</td>
+ <td>61,6</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[7]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>12,7</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>html</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>