diff options
author | Jonatan Kronqvist <jonatan.kronqvist@itmill.com> | 2011-08-17 10:20:39 +0000 |
---|---|---|
committer | Jonatan Kronqvist <jonatan.kronqvist@itmill.com> | 2011-08-17 10:20:39 +0000 |
commit | 63411e8a5478aef8316cd270f045d82c83caee68 (patch) | |
tree | 5daf8fde17cfcebfbdb535751dab687391bda533 /src | |
parent | aade55ae17d4e40b0ad64ae8d3c2a2205897f6ff (diff) | |
download | vaadin-framework-63411e8a5478aef8316cd270f045d82c83caee68.tar.gz vaadin-framework-63411e8a5478aef8316cd270f045d82c83caee68.zip |
Optional expand and collapse animations for TreeTable (#6723)
svn changeset:20445/svn branch:6.7
Diffstat (limited to 'src')
-rw-r--r-- | src/com/vaadin/terminal/gwt/client/ComputedStyle.java | 178 | ||||
-rw-r--r-- | src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java | 43 | ||||
-rw-r--r-- | src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java | 338 | ||||
-rw-r--r-- | src/com/vaadin/ui/Table.java | 77 | ||||
-rw-r--r-- | src/com/vaadin/ui/TreeTable.java | 22 |
5 files changed, 614 insertions, 44 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/ComputedStyle.java b/src/com/vaadin/terminal/gwt/client/ComputedStyle.java new file mode 100644 index 0000000000..5aac2caf47 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ComputedStyle.java @@ -0,0 +1,178 @@ +package com.vaadin.terminal.gwt.client; + +import com.google.gwt.core.client.JavaScriptObject; +import com.google.gwt.user.client.Element; + +public class ComputedStyle { + + protected final JavaScriptObject computedStyle; + private final Element elem; + + /** + * Gets this element's computed style object which can be used to gather + * information about the current state of the rendered node. + * <p> + * Note that this method is expensive. Wherever possible, reuse the returned + * object. + * + * @param elem + * the element + * @return the computed style + */ + public ComputedStyle(Element elem) { + computedStyle = getComputedStyle(elem); + this.elem = elem; + } + + private static native JavaScriptObject getComputedStyle(Element elem) + /*-{ + if(elem.nodeType != 1) { + return {}; + } + + if($wnd.document.defaultView && $wnd.document.defaultView.getComputedStyle) { + return $wnd.document.defaultView.getComputedStyle(elem, null); + } + + if(elem.currentStyle) { + return elem.currentStyle; + } + }-*/; + + /** + * + * @param name + * name of the CSS property in camelCase + * @return the value of the property, normalized for across browsers (each + * browser returns pixel values whenever possible). + */ + public final native String getProperty(String name) + /*-{ + var cs = this.@com.vaadin.terminal.gwt.client.ComputedStyle::computedStyle; + var elem = this.@com.vaadin.terminal.gwt.client.ComputedStyle::elem; + + // Border values need to be checked separately. The width might have a + // meaningful value even if the border style is "none". In that case the + // value should be 0. + if(name.indexOf("border") > -1 && name.indexOf("Width") > -1) { + var borderStyleProp = name.substring(0,name.length-5) + "Style"; + if(cs.getPropertyValue) + var borderStyle = cs.getPropertyValue(borderStyleProp); + else // IE + var borderStyle = cs[borderStyleProp]; + if(borderStyle == "none") + return "0px"; + } + + if(cs.getPropertyValue) { + + // Convert name to dashed format + name = name.replace(/([A-Z])/g, "-$1").toLowerCase(); + var ret = cs.getPropertyValue(name); + + } else { + + var ret = cs[name]; + var style = elem.style; + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { + // Remember the original values + var left = style.left, rsLeft = elem.runtimeStyle.left; + + // Put in the new values to get a computed value out + elem.runtimeStyle.left = this.left; + style.left = ret || 0; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + elem.runtimeStyle.left = rsLeft; + } + + } + + // Normalize margin values. This is not totally valid, but in most cases + // it is what the user wants to know. + if(name.indexOf("margin") > -1 && ret == "auto") { + return "0px"; + } + + // Some browsers return undefined width and height values as "auto", so + // we need to retrieve those ourselves. + if (name == "width" && ret == "auto") { + ret = elem.clientWidth + "px"; + } else if (name == "height" && ret == "auto") { + ret = elem.clientHeight + "px"; + } + + return ret; + + }-*/; + + public final int getIntProperty(String name) { + return parseInt(getProperty(name)).intValue(); + } + + /** + * Get current margin values from the DOM. The array order is the default + * CSS order: top, right, bottom, left. + */ + public final int[] getMargin() { + int[] margin = { 0, 0, 0, 0 }; + margin[0] = getIntProperty("marginTop"); + margin[1] = getIntProperty("marginRight"); + margin[2] = getIntProperty("marginBottom"); + margin[3] = getIntProperty("marginLeft"); + return margin; + } + + /** + * Get current padding values from the DOM. The array order is the default + * CSS order: top, right, bottom, left. + */ + public final int[] getPadding() { + int[] padding = { 0, 0, 0, 0 }; + padding[0] = getIntProperty("paddingTop"); + padding[1] = getIntProperty("paddingRight"); + padding[2] = getIntProperty("paddingBottom"); + padding[3] = getIntProperty("paddingLeft"); + return padding; + } + + /** + * Get current border values from the DOM. The array order is the default + * CSS order: top, right, bottom, left. + */ + public final int[] getBorder() { + int[] border = { 0, 0, 0, 0 }; + border[0] = getIntProperty("borderTopWidth"); + border[1] = getIntProperty("borderRightWidth"); + border[2] = getIntProperty("borderBottomWidth"); + border[3] = getIntProperty("borderLeftWidth"); + return border; + } + + /** + * Takes a String value e.g. "12px" and parses that to int 12. + * + * @param String + * a value starting with a number + * @return int the value from the string before any non-numeric characters. + * If the value cannot be parsed to a number, returns + * <code>null</code>. + */ + public static native Integer parseInt(final String value) + /*-{ + var number = parseInt(value, 10); + if (isNaN(number)) + return null; + else + return @java.lang.Integer::valueOf(I)(number); + }-*/; + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index ad69d8a751..fb51919b10 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -876,7 +876,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, UIDL partialRowUpdates = uidl.getChildByTagName("urows"); if (partialRowUpdates != null || partialRowAdditions != null) { updateRowsInBody(partialRowUpdates); - addRowsToBody(partialRowAdditions); + addAndRemoveRows(partialRowAdditions); } else { UIDL rowData = uidl.getChildByTagName("rows"); if (rowData != null) { @@ -1355,7 +1355,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, scrollBody.renderRows(uidl, firstRow, reqRows); - updateCache(); + discardRowsOutsideCacheWindow(); } private void updateRowsInBody(UIDL partialRowUpdates) { @@ -1367,10 +1367,14 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, scrollBody.unlinkRows(firstRowIx, count); scrollBody.insertRows(partialRowUpdates, firstRowIx, count); - updateCache(); + discardRowsOutsideCacheWindow(); } - private void updateCache() { + /** + * Updates the internal cache by unlinking rows that fall outside of the + * caching window. + */ + protected void discardRowsOutsideCacheWindow() { final int optimalFirstRow = (int) (firstRowInViewPort - pageLength * cache_rate); boolean cont = true; @@ -1391,7 +1395,14 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, scrollBody.restoreRowVisibility(); } - private void addRowsToBody(UIDL partialRowAdditions) { + /** + * Inserts rows in the table body or removes them from the table body based + * on the commands in the UIDL. + * + * @param partialRowAdditions + * the UIDL containing row updates. + */ + protected void addAndRemoveRows(UIDL partialRowAdditions) { if (partialRowAdditions == null) { return; } @@ -1412,7 +1423,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } } - updateCache(); + discardRowsOutsideCacheWindow(); } /** @@ -3890,14 +3901,26 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } } - protected void insertRows(UIDL rowData, int firstIndex, int rows) { + /** + * Inserts rows as provided in the rowData starting at firstIndex. + * + * @param rowData + * @param firstIndex + * @param rows + * the number of rows + * @return a list of the rows added. + */ + protected List<VScrollTableRow> insertRows(UIDL rowData, + int firstIndex, int rows) { aligns = tHead.getColumnAlignments(); final Iterator<?> it = rowData.getChildIterator(); + List<VScrollTableRow> insertedRows = new ArrayList<VScrollTableRow>(); if (firstIndex == lastRendered + 1) { while (it.hasNext()) { final VScrollTableRow row = prepareRow((UIDL) it.next()); addRow(row); + insertedRows.add(row); lastRendered++; } fixSpacers(); @@ -3910,18 +3933,22 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } for (i = 0; i < rows; i++) { addRowBeforeFirstRendered(rowArray[i]); + insertedRows.add(rowArray[i]); firstRendered--; } } else { // insert in the middle int realIx = firstIndex - firstRendered; while (it.hasNext()) { - insertRowAt(prepareRow((UIDL) it.next()), realIx); + VScrollTableRow row = prepareRow((UIDL) it.next()); + insertRowAt(row, realIx); + insertedRows.add(row); lastRendered++; realIx++; } fixSpacers(); } + return insertedRows; } protected void insertRowsDeleteBelow(UIDL rowData, int firstIndex, diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java index 15ebcde35e..a3b7008e77 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java @@ -4,17 +4,25 @@ package com.vaadin.terminal.gwt.client.ui; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; +import com.google.gwt.animation.client.Animation; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.ImageElement; import com.google.gwt.dom.client.SpanElement; +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.event.dom.client.KeyCodes; +import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.BrowserInfo; +import com.vaadin.terminal.gwt.client.ComputedStyle; import com.vaadin.terminal.gwt.client.RenderSpace; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.VConsole; @@ -29,6 +37,7 @@ public class VTreeTable extends VScrollTable { private int colIndexOfHierarchy; private String collapsedRowKey; private VTreeTableScrollBody scrollBody; + private boolean animationsEnabled; @Override public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { @@ -38,6 +47,7 @@ public class VTreeTable extends VScrollTable { widget = (FocusableScrollPanel) getWidget(1); scrollPosition = widget.getScrollPosition(); } + animationsEnabled = uidl.getBooleanAttribute("animate"); colIndexOfHierarchy = uidl .hasAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) ? uidl .getIntAttribute(ATTRIBUTE_HIERARCHY_COLUMN_INDEX) : 0; @@ -73,6 +83,36 @@ public class VTreeTable extends VScrollTable { return scrollBody; } + /* + * Overridden to allow animation of expands and collapses of nodes. + */ + @Override + protected void addAndRemoveRows(UIDL partialRowAdditions) { + if (partialRowAdditions == null) { + return; + } + + if (animationsEnabled && browserSupportsAnimation()) { + if (partialRowAdditions.hasAttribute("hide")) { + scrollBody.unlinkRowsAnimatedAndUpdateCacheWhenFinished( + partialRowAdditions.getIntAttribute("firstprowix"), + partialRowAdditions.getIntAttribute("numprows")); + } else { + scrollBody.insertRowsAnimated(partialRowAdditions, + partialRowAdditions.getIntAttribute("firstprowix"), + partialRowAdditions.getIntAttribute("numprows")); + discardRowsOutsideCacheWindow(); + } + } else { + super.addAndRemoveRows(partialRowAdditions); + } + } + + private boolean browserSupportsAnimation() { + BrowserInfo bi = BrowserInfo.get(); + return !(bi.isIE6() || bi.isIE7() || bi.isSafari4()); + } + class VTreeTableScrollBody extends VScrollTable.VScrollTableBody { private int identWidth = -1; @@ -241,6 +281,304 @@ public class VTreeTable extends VScrollTable { next.setIdent(); } } + + protected void unlinkRowsAnimatedAndUpdateCacheWhenFinished( + final int firstIndex, final int rows) { + List<VScrollTableRow> rowsToDelete = new ArrayList<VScrollTableRow>(); + for (int ix = firstIndex; ix < firstIndex + rows; ix++) { + VScrollTableRow row = getRowByRowIndex(ix); + if (row != null) { + rowsToDelete.add(row); + } + } + RowCollapseAnimation anim = new RowCollapseAnimation(rowsToDelete) { + @Override + protected void onComplete() { + super.onComplete(); + // Actually unlink the rows and update the cache after the + // animation is done. + unlinkRows(firstIndex, rows); + discardRowsOutsideCacheWindow(); + ensureCacheFilled(); + } + }; + anim.run(150); + } + + protected List<VScrollTableRow> insertRowsAnimated(UIDL rowData, + int firstIndex, int rows) { + List<VScrollTableRow> insertedRows = insertRows(rowData, + firstIndex, rows); + RowExpandAnimation anim = new RowExpandAnimation(insertedRows); + anim.run(150); + return insertedRows; + } + + /** + * Prepares the table for animation by copying the background colors of + * all TR elements to their respective TD elements if the TD element is + * transparent. This is needed, since if TDs have transparent + * backgrounds, the rows sliding behind them are visible. + */ + private class AnimationPreparator { + private final int lastItemIx; + + public AnimationPreparator(int lastItemIx) { + this.lastItemIx = lastItemIx; + } + + public void prepareTableForAnimation() { + int ix = lastItemIx; + VScrollTableRow row = null; + while ((row = getRowByRowIndex(ix)) != null) { + copyTRBackgroundsToTDs(row); + --ix; + } + } + + private void copyTRBackgroundsToTDs(VScrollTableRow row) { + Element tr = row.getElement(); + ComputedStyle cs = new ComputedStyle(tr); + String backgroundAttachment = cs + .getProperty("backgroundAttachment"); + String backgroundClip = cs.getProperty("backgroundClip"); + String backgroundColor = cs.getProperty("backgroundColor"); + String backgroundImage = cs.getProperty("backgroundImage"); + String backgroundOrigin = cs.getProperty("backgroundOrigin"); + for (int ix = 0; ix < tr.getChildCount(); ix++) { + Element td = tr.getChild(ix).cast(); + if (!elementHasBackground(td)) { + td.getStyle().setProperty("backgroundAttachment", + backgroundAttachment); + td.getStyle().setProperty("backgroundClip", + backgroundClip); + td.getStyle().setProperty("backgroundColor", + backgroundColor); + td.getStyle().setProperty("backgroundImage", + backgroundImage); + td.getStyle().setProperty("backgroundOrigin", + backgroundOrigin); + } + } + } + + private boolean elementHasBackground(Element element) { + ComputedStyle cs = new ComputedStyle(element); + String clr = cs.getProperty("backgroundColor"); + String img = cs.getProperty("backgroundImage"); + return !("rgba(0, 0, 0, 0)".equals(clr.trim()) + || "transparent".equals(clr.trim()) || img == null); + } + + public void restoreTableAfterAnimation() { + int ix = lastItemIx; + VScrollTableRow row = null; + while ((row = getRowByRowIndex(ix)) != null) { + restoreStyleForTDsInRow(row); + + --ix; + } + } + + private void restoreStyleForTDsInRow(VScrollTableRow row) { + Element tr = row.getElement(); + for (int ix = 0; ix < tr.getChildCount(); ix++) { + Element td = tr.getChild(ix).cast(); + td.getStyle().clearProperty("backgroundAttachment"); + td.getStyle().clearProperty("backgroundClip"); + td.getStyle().clearProperty("backgroundColor"); + td.getStyle().clearProperty("backgroundImage"); + td.getStyle().clearProperty("backgroundOrigin"); + } + } + } + + /** + * Animates row expansion using the GWT animation framework. + * + * The idea is as follows: + * + * 1. Insert all rows normally + * + * 2. Insert a newly created DIV containing a new TABLE element below + * the DIV containing the actual scroll table body. + * + * 3. Clone the rows that were inserted in step 1 and attach the clones + * to the new TABLE element created in step 2. + * + * 4. The new DIV from step 2 is absolutely positioned so that the last + * inserted row is just behind the row that was expanded. + * + * 5. Hide the contents of the originally inserted rows by setting the + * DIV.v-table-cell-wrapper to display:none;. + * + * 6. Set the height of the originally inserted rows to 0. + * + * 7. The animation loop slides the DIV from step 2 downwards, while at + * the same pace growing the height of each of the inserted rows from 0 + * to full height. The first inserted row grows from 0 to full and after + * this the second row grows from 0 to full, etc until all rows are full + * height. + * + * 8. Remove the DIV from step 2 + * + * 9. Restore display:block; to the DIV.v-table-cell-wrapper elements. + * + * 10. DONE + */ + private class RowExpandAnimation extends Animation { + + private final List<VScrollTableRow> rows; + private Element cloneDiv; + private Element cloneTable; + private AnimationPreparator preparator; + + public RowExpandAnimation(List<VScrollTableRow> rows) { + this.rows = rows; + buildAndInsertAnimatingDiv(); + preparator = new AnimationPreparator(rows.get(0).getIndex() - 1); + preparator.prepareTableForAnimation(); + for (VScrollTableRow row : rows) { + cloneAndAppendRow(row); + row.addStyleName("v-table-row-animating"); + setCellWrapperDivsToDisplayNone(row); + row.setHeight(getInitialHeight()); + } + } + + protected String getInitialHeight() { + return "0px"; + } + + private void cloneAndAppendRow(VScrollTableRow row) { + Element clonedTR = null; + clonedTR = row.getElement().cloneNode(true).cast(); + clonedTR.getStyle().setVisibility(Visibility.VISIBLE); + cloneTable.appendChild(clonedTR); + } + + protected double getBaseOffset() { + return rows.get(0).getAbsoluteTop() + - rows.get(0).getParent().getAbsoluteTop() + - rows.size() * getRowHeight(); + } + + private void buildAndInsertAnimatingDiv() { + cloneDiv = DOM.createDiv(); + cloneDiv.addClassName("v-treetable-animation-clone-wrapper"); + cloneTable = DOM.createTable(); + cloneTable.addClassName("v-treetable-animation-clone"); + cloneDiv.appendChild(cloneTable); + insertAnimatingDiv(); + } + + private void insertAnimatingDiv() { + Element tableBody = getElement().cast(); + Element tableBodyParent = tableBody.getParentElement().cast(); + tableBodyParent.insertAfter(cloneDiv, tableBody); + } + + @Override + protected void onUpdate(double progress) { + animateDiv(progress); + animateRowHeights(progress); + } + + private void animateDiv(double progress) { + double offset = calculateDivOffset(progress, getRowHeight()); + + cloneDiv.getStyle().setTop(getBaseOffset() + offset, Unit.PX); + } + + private void animateRowHeights(double progress) { + double rh = getRowHeight(); + double vlh = calculateHeightOfAllVisibleLines(progress, rh); + int ix = 0; + + while (ix < rows.size()) { + double height = vlh < rh ? vlh : rh; + rows.get(ix).setHeight(height + "px"); + vlh -= height; + ix++; + } + } + + protected double calculateHeightOfAllVisibleLines(double progress, + double rh) { + return rows.size() * rh * progress; + } + + protected double calculateDivOffset(double progress, double rh) { + return progress * rows.size() * rh; + } + + @Override + protected void onComplete() { + preparator.restoreTableAfterAnimation(); + for (VScrollTableRow row : rows) { + resetCellWrapperDivsDisplayProperty(row); + row.removeStyleName("v-table-row-animating"); + } + Element tableBodyParent = (Element) getElement() + .getParentElement(); + tableBodyParent.removeChild(cloneDiv); + } + + private void setCellWrapperDivsToDisplayNone(VScrollTableRow row) { + Element tr = row.getElement(); + for (int ix = 0; ix < tr.getChildCount(); ix++) { + getWrapperDiv(tr, ix).getStyle().setDisplay(Display.NONE); + } + } + + private Element getWrapperDiv(Element tr, int tdIx) { + Element td = tr.getChild(tdIx).cast(); + return td.getChild(0).cast(); + } + + private void resetCellWrapperDivsDisplayProperty(VScrollTableRow row) { + Element tr = row.getElement(); + for (int ix = 0; ix < tr.getChildCount(); ix++) { + getWrapperDiv(tr, ix).getStyle().clearProperty("display"); + } + } + + } + + /** + * This is the inverse of the RowExpandAnimation and is implemented by + * extending it and overriding the calculation of offsets and heights. + */ + private class RowCollapseAnimation extends RowExpandAnimation { + + private final List<VScrollTableRow> rows; + + public RowCollapseAnimation(List<VScrollTableRow> rows) { + super(rows); + this.rows = rows; + } + + @Override + protected String getInitialHeight() { + return getRowHeight() + "px"; + } + + @Override + protected double getBaseOffset() { + return getRowHeight(); + } + + @Override + protected double calculateHeightOfAllVisibleLines(double progress, + double rh) { + return rows.size() * rh * (1 - progress); + } + + @Override + protected double calculateDivOffset(double progress, double rh) { + return -super.calculateDivOffset(progress, rh); + } + } } /** diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index fd18bf0fd7..5f0fd07277 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -378,7 +378,7 @@ public class Table extends AbstractSelect implements Action.Container, * Table cell specific style generator */ private CellStyleGenerator cellStyleGenerator = null; - + /** * Table cell specific tooltip generator */ @@ -2867,8 +2867,8 @@ public class Table extends AbstractSelect implements Action.Container, target.addAttribute("style-" + columnIdMap.key(columnId), cellStyle); } - } - + } + if ((iscomponent[currentColumn] || iseditable) && Component.class.isInstance(cells[CELL_FIRSTCOL + currentColumn][indexInRowbuffer])) { @@ -2881,29 +2881,34 @@ public class Table extends AbstractSelect implements Action.Container, c.paint(target); } } else { - target.addText((String) cells[CELL_FIRSTCOL + currentColumn][indexInRowbuffer]); - paintCellTooltips(target, itemId, columnId); + target.addText((String) cells[CELL_FIRSTCOL + currentColumn][indexInRowbuffer]); + paintCellTooltips(target, itemId, columnId); } } target.endTag("tr"); } - - private void paintCellTooltips(PaintTarget target, Object itemId, Object columnId) throws PaintException { - if(itemDescriptionGenerator != null) { - String itemDescription = itemDescriptionGenerator.generateDescription(this, itemId, columnId); - if(itemDescription != null && !itemDescription.equals("")) { - target.addAttribute("descr-" + columnIdMap.key(columnId), itemDescription); - } - } + + private void paintCellTooltips(PaintTarget target, Object itemId, + Object columnId) throws PaintException { + if (itemDescriptionGenerator != null) { + String itemDescription = itemDescriptionGenerator + .generateDescription(this, itemId, columnId); + if (itemDescription != null && !itemDescription.equals("")) { + target.addAttribute("descr-" + columnIdMap.key(columnId), + itemDescription); + } + } } - - private void paintRowTooltips(PaintTarget target, Object itemId ) throws PaintException { - if(itemDescriptionGenerator != null) { - String rowDescription = itemDescriptionGenerator.generateDescription(this, itemId, null); - if(rowDescription != null && !rowDescription.equals("")){ - target.addAttribute("rowdescr", rowDescription); - } + + private void paintRowTooltips(PaintTarget target, Object itemId) + throws PaintException { + if (itemDescriptionGenerator != null) { + String rowDescription = itemDescriptionGenerator + .generateDescription(this, itemId, null); + if (rowDescription != null && !rowDescription.equals("")) { + target.addAttribute("rowdescr", rowDescription); + } } } @@ -2947,11 +2952,11 @@ public class Table extends AbstractSelect implements Action.Container, if (rowStyle != null && !rowStyle.equals("")) { target.addAttribute("rowstyle", rowStyle); } - } - - paintRowTooltips(target, itemId); - - paintRowAttributes(target, itemId); + } + + paintRowTooltips(target, itemId); + + paintRowAttributes(target, itemId); } protected void paintRowHeader(PaintTarget target, Object[][] cells, @@ -3895,7 +3900,7 @@ public class Table extends AbstractSelect implements Action.Container, */ public void setCellStyleGenerator(CellStyleGenerator cellStyleGenerator) { this.cellStyleGenerator = cellStyleGenerator; - requestRepaint(); + refreshRenderedCells(); } /** @@ -4576,27 +4581,27 @@ public class Table extends AbstractSelect implements Action.Container, removeListener(VScrollTable.COLUMN_REORDER_EVENT_ID, ColumnReorderEvent.class, listener); } - + /** - * Set the item description generator which generates tooltips - * for cells and rows in the Table + * Set the item description generator which generates tooltips for cells and + * rows in the Table * * @param generator - * The generator to use or null to disable + * The generator to use or null to disable */ - public void setItemDescriptionGenerator(ItemDescriptionGenerator generator){ + public void setItemDescriptionGenerator(ItemDescriptionGenerator generator) { if (generator != itemDescriptionGenerator) { itemDescriptionGenerator = generator; refreshRenderedCells(); } } - + /** - * Get the item description generator which generates tooltips - * for cells and rows in the Table. + * Get the item description generator which generates tooltips for cells and + * rows in the Table. */ - public ItemDescriptionGenerator getItemDescriptionGenerator(){ - return itemDescriptionGenerator; + public ItemDescriptionGenerator getItemDescriptionGenerator() { + return itemDescriptionGenerator; } } diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java index 987e3a9bfd..f64c818313 100644 --- a/src/com/vaadin/ui/TreeTable.java +++ b/src/com/vaadin/ui/TreeTable.java @@ -309,6 +309,7 @@ public class TreeTable extends Table implements Hierarchical { private Object focusedRowId = null; private Object hierarchyColumnId; private Object toggledItemId; + private boolean animationsEnabled; private ContainerStrategy getContainerStrategy() { if (cStrategy == null) { @@ -408,6 +409,7 @@ public class TreeTable extends Table implements Hierarchical { target.addAttribute("focusedRow", itemIdMapper.key(focusedRowId)); focusedRowId = null; } + target.addAttribute("animate", animationsEnabled); if (hierarchyColumnId != null) { Object[] visibleColumns2 = getVisibleColumns(); for (int i = 0; i < visibleColumns2.length; i++) { @@ -704,4 +706,24 @@ public class TreeTable extends Table implements Hierarchical { fireEvent(new CollapseEvent(this, itemId)); } + /** + * @return true if animations are enabled + */ + public boolean isAnimationsEnabled() { + return animationsEnabled; + } + + /** + * Animations can be enabled by passing true to this method. Currently + * expanding rows slide in from the top and collapsing rows slide out the + * same way. NOTE! not supported in Internet Explorer 6 or 7. + * + * @param animationsEnabled + * true or false whether to enable animations or not. + */ + public void setAnimationsEnabled(boolean animationsEnabled) { + this.animationsEnabled = animationsEnabled; + requestRepaint(); + } + } |