summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Alhroos <john.ahlroos@itmill.com>2010-04-16 14:29:22 +0000
committerJohn Alhroos <john.ahlroos@itmill.com>2010-04-16 14:29:22 +0000
commit1ee5d432f434938201c16701432f19f8889b8ce5 (patch)
treef90fed01620f8553b49268211a395719fdb84ebe
parentab798fddd8df7ae3d0e8f31691088914b26889a1 (diff)
downloadvaadin-framework-1ee5d432f434938201c16701432f19f8889b8ce5.tar.gz
vaadin-framework-1ee5d432f434938201c16701432f19f8889b8ce5.zip
Added footer to Table #1553
svn changeset:12613/svn branch:6.4
-rw-r--r--WebContent/VAADIN/themes/base/styles.css33
-rw-r--r--WebContent/VAADIN/themes/base/table/table.css29
-rw-r--r--WebContent/VAADIN/themes/reindeer/styles.css50
-rw-r--r--WebContent/VAADIN/themes/reindeer/table/table.css17
-rw-r--r--WebContent/VAADIN/themes/runo/styles.css33
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java491
-rw-r--r--src/com/vaadin/ui/Table.java73
7 files changed, 714 insertions, 12 deletions
diff --git a/WebContent/VAADIN/themes/base/styles.css b/WebContent/VAADIN/themes/base/styles.css
index aa9c1afdb9..b1dc7f5c0f 100644
--- a/WebContent/VAADIN/themes/base/styles.css
+++ b/WebContent/VAADIN/themes/base/styles.css
@@ -1,5 +1,5 @@
-.v-theme-version:after {content:"6_4_0_dev-20100415";}
-.v-theme-version-6_4_0_dev-20100415 {display: none;}
+.v-theme-version:after {content:"6_4_0_dev-20100416";}
+.v-theme-version-6_4_0_dev-20100416 {display: none;}
/* Automatically compiled css file from subdirectories. */
.v-absolutelayout-wrapper {
@@ -1445,6 +1445,35 @@ div.v-progressindicator-indeterminate-disabled {
.v-table-header-cell-desc {
cursor: pointer;
}
+
+.v-table-footer-wrap {
+ overflow: hidden;
+ border: 1px solid #aaa;
+ border-top: none;
+ background: #efefef;
+}
+.v-table-footer table,
+.v-table-table {
+ border-spacing: 0;
+ border-collapse: separate;
+ margin: 0;
+ padding: 0;
+ border: 0;
+}
+.v-table-footer td {
+ padding: 0;
+ border-right: 1px solid #aaa;
+}
+.v-table-footer-cell,
+.v-table-footer-cell-asc,
+.v-table-footer-cell-desc {
+ cursor: pointer;
+}
+.v-table-footer-container{
+ padding-left:6px;
+ padding-right:6px;
+ overfow: hidden;
+}
.v-table-resizer {
display: block;
height: 1.2em;
diff --git a/WebContent/VAADIN/themes/base/table/table.css b/WebContent/VAADIN/themes/base/table/table.css
index 498d1bfe80..269bd5b684 100644
--- a/WebContent/VAADIN/themes/base/table/table.css
+++ b/WebContent/VAADIN/themes/base/table/table.css
@@ -51,6 +51,35 @@
.v-table-header-cell-desc {
cursor: pointer;
}
+
+.v-table-footer-wrap {
+ overflow: hidden;
+ border: 1px solid #aaa;
+ border-top: none;
+ background: #efefef;
+}
+.v-table-footer table,
+.v-table-table {
+ border-spacing: 0;
+ border-collapse: separate;
+ margin: 0;
+ padding: 0;
+ border: 0;
+}
+.v-table-footer td {
+ padding: 0;
+ border-right: 1px solid #aaa;
+}
+.v-table-footer-cell,
+.v-table-footer-cell-asc,
+.v-table-footer-cell-desc {
+ cursor: pointer;
+}
+.v-table-footer-container{
+ padding-left:6px;
+ padding-right:6px;
+ overfow: hidden;
+}
.v-table-resizer {
display: block;
height: 1.2em;
diff --git a/WebContent/VAADIN/themes/reindeer/styles.css b/WebContent/VAADIN/themes/reindeer/styles.css
index 788c4aaf1a..3cace6f837 100644
--- a/WebContent/VAADIN/themes/reindeer/styles.css
+++ b/WebContent/VAADIN/themes/reindeer/styles.css
@@ -1,5 +1,5 @@
-.v-theme-version:after {content:"9_9_9_INTERNAL-DEBUG-BUILD";}
-.v-theme-version-9_9_9_INTERNAL-DEBUG-BUILD {display: none;}
+.v-theme-version:after {content:"6_4_0_dev-20100416";}
+.v-theme-version-6_4_0_dev-20100416 {display: none;}
/* Automatically compiled css file from subdirectories. */
.v-absolutelayout-wrapper {
@@ -1445,6 +1445,35 @@ div.v-progressindicator-indeterminate-disabled {
.v-table-header-cell-desc {
cursor: pointer;
}
+
+.v-table-footer-wrap {
+ overflow: hidden;
+ border: 1px solid #aaa;
+ border-top: none;
+ background: #efefef;
+}
+.v-table-footer table,
+.v-table-table {
+ border-spacing: 0;
+ border-collapse: separate;
+ margin: 0;
+ padding: 0;
+ border: 0;
+}
+.v-table-footer td {
+ padding: 0;
+ border-right: 1px solid #aaa;
+}
+.v-table-footer-cell,
+.v-table-footer-cell-asc,
+.v-table-footer-cell-desc {
+ cursor: pointer;
+}
+.v-table-footer-container{
+ padding-left:6px;
+ padding-right:6px;
+ overfow: hidden;
+}
.v-table-resizer {
display: block;
height: 1.2em;
@@ -4112,9 +4141,23 @@ td.v-datefield-calendarpanel-nextyear {
text-shadow: #fff 0 1px 0;
line-height: normal;
}
+
+.v-table-footer-wrap,
+.white .v-table-footer-wrap{
+ border-color: #c2c3c4;
+ background: transparent repeat-x;
+ background-image: url(table/img/header-bg-light.png);
+ height: 20px;
+}
+
.v-table-header {
height: 20px;
}
+.v-table-footer,
+.v-table-footer table {
+ height: 20px;
+}
+
.v-table-caption-container {
heigth: 16px;
padding-top: 4px;
@@ -4128,6 +4171,9 @@ td.v-datefield-calendarpanel-nextyear {
.v-ie .v-table-caption-container .v-icon {
margin-top: -3px;
}
+.v-table-footer-container {
+ heigth: 16px;
+}
.v-table-resizer {
height: 20px;
width: 2px;
diff --git a/WebContent/VAADIN/themes/reindeer/table/table.css b/WebContent/VAADIN/themes/reindeer/table/table.css
index 3c237d1393..b6052424bb 100644
--- a/WebContent/VAADIN/themes/reindeer/table/table.css
+++ b/WebContent/VAADIN/themes/reindeer/table/table.css
@@ -21,9 +21,23 @@
text-shadow: #fff 0 1px 0;
line-height: normal;
}
+
+.v-table-footer-wrap,
+.white .v-table-footer-wrap{
+ border-color: #c2c3c4;
+ background: transparent repeat-x;
+ background-image: url(img/header-bg-light.png);
+ height: 20px;
+}
+
.v-table-header {
height: 20px;
}
+.v-table-footer,
+.v-table-footer table {
+ height: 20px;
+}
+
.v-table-caption-container {
heigth: 16px;
padding-top: 4px;
@@ -37,6 +51,9 @@
.v-ie .v-table-caption-container .v-icon {
margin-top: -3px;
}
+.v-table-footer-container {
+ heigth: 16px;
+}
.v-table-resizer {
height: 20px;
width: 2px;
diff --git a/WebContent/VAADIN/themes/runo/styles.css b/WebContent/VAADIN/themes/runo/styles.css
index 490248ad2f..09ca23bf5d 100644
--- a/WebContent/VAADIN/themes/runo/styles.css
+++ b/WebContent/VAADIN/themes/runo/styles.css
@@ -1,5 +1,5 @@
-.v-theme-version:after {content:"9_9_9_INTERNAL-DEBUG-BUILD";}
-.v-theme-version-9_9_9_INTERNAL-DEBUG-BUILD {display: none;}
+.v-theme-version:after {content:"6_4_0_dev-20100416";}
+.v-theme-version-6_4_0_dev-20100416 {display: none;}
/* Automatically compiled css file from subdirectories. */
.v-absolutelayout-wrapper {
@@ -1445,6 +1445,35 @@ div.v-progressindicator-indeterminate-disabled {
.v-table-header-cell-desc {
cursor: pointer;
}
+
+.v-table-footer-wrap {
+ overflow: hidden;
+ border: 1px solid #aaa;
+ border-top: none;
+ background: #efefef;
+}
+.v-table-footer table,
+.v-table-table {
+ border-spacing: 0;
+ border-collapse: separate;
+ margin: 0;
+ padding: 0;
+ border: 0;
+}
+.v-table-footer td {
+ padding: 0;
+ border-right: 1px solid #aaa;
+}
+.v-table-footer-cell,
+.v-table-footer-cell-asc,
+.v-table-footer-cell-desc {
+ cursor: pointer;
+}
+.v-table-footer-container{
+ padding-left:6px;
+ padding-right:6px;
+ overfow: hidden;
+}
.v-table-resizer {
display: block;
height: 1.2em;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
index 416a8b67d2..841e210b63 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
@@ -135,6 +135,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
private final TableHead tHead = new TableHead();
+ private final TableFooter tFoot = new TableFooter();
+
private final ScrollPanel bodyContainer = new ScrollPanel();
private int totalRows;
@@ -158,6 +160,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
private Element scrollPositionElement;
private boolean enabled;
private boolean showColHeaders;
+ private boolean showColFooters;
/** flag to indicate that table body has changed */
private boolean isNewBody = true;
@@ -185,14 +188,23 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
setStyleName(CLASSNAME);
add(tHead);
add(bodyContainer);
+ add(tFoot);
rowRequestHandler = new RowRequestHandler();
-
}
@SuppressWarnings("unchecked")
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
rendering = true;
+
+ /*
+ * We need to do this before updateComponent since updateComponent calls
+ * this.setHeight() which will calculate a new body height depending on
+ * the space available.
+ */
+ showColFooters = uidl.getBooleanAttribute("colfooters");
+ tFoot.setVisible(showColFooters);
+
if (client.updateComponent(this, uidl, true)) {
rendering = false;
return;
@@ -211,6 +223,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
if (scrollBody != null) {
if (totalRows == 0) {
tHead.clear();
+ tFoot.clear();
}
initializedAndAttached = false;
initialContentReceived = false;
@@ -231,6 +244,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
recalcWidths = uidl.hasAttribute("recalcWidths");
if (recalcWidths) {
tHead.clear();
+ tFoot.clear();
}
if (uidl.hasAttribute("pagelength")) {
@@ -300,6 +314,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
updateActionMap(c);
} else if (c.getTag().equals("visiblecolumns")) {
tHead.updateCellsFromUIDL(c);
+ tFoot.updateCellsFromUIDL(c);
} else if (c.getTag().equals("-ac")) {
ac = c;
}
@@ -317,6 +332,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
updateHeader(uidl.getStringArrayAttribute("vcolorder"));
+ updateFooter(uidl.getStringArrayAttribute("vcolorder"));
+
if (!recalcWidths && initializedAndAttached) {
updateBody(rowData, uidl.getIntAttribute("firstrow"), uidl
.getIntAttribute("rows"));
@@ -437,6 +454,30 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
/**
+ * Updates footers.
+ * <p>
+ * Update headers whould be called before this method is called!
+ * </p>
+ *
+ * @param strings
+ */
+ private void updateFooter(String[] strings) {
+ if (strings == null) {
+ return;
+ }
+
+ int i;
+ int colIndex = 0;
+ for (i = 0; i < strings.length; i++) {
+ final String cid = strings[i];
+ tFoot.enableColumn(cid, colIndex);
+ colIndex++;
+ }
+
+ tFoot.setVisible(showColFooters);
+ }
+
+ /**
* @param uidl
* which contains row data
* @param firstRow
@@ -512,9 +553,18 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
private void setColWidth(int colIndex, int w, boolean isDefinedWidth) {
- final HeaderCell cell = tHead.getHeaderCell(colIndex);
- cell.setWidth(w, isDefinedWidth);
+ // Set header column width
+ final HeaderCell hcell = tHead.getHeaderCell(colIndex);
+ hcell.setWidth(w, isDefinedWidth);
+
+ // Set body column width
scrollBody.setColWidth(colIndex, w);
+
+ // Set footer column width
+ final FooterCell fcell = tFoot.getFooterCell(colIndex);
+ if (fcell != null) {
+ fcell.setWidth(w, isDefinedWidth);
+ }
}
private int getColWidth(String colKey) {
@@ -543,6 +593,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
// Change body order
scrollBody.moveCol(oldIndex, newIndex);
+ // Change footer order
+ tFoot.moveCell(oldIndex, newIndex);
+
/*
* Build new columnOrder and update it to server Note that columnOrder
* also contains collapsed columns so we cannot directly build it from
@@ -636,6 +689,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
final int[] widths = new int[tHead.visibleCells.size()];
tHead.enableBrowserIntelligence();
+ tFoot.enableBrowserIntelligence();
+
// first loop: collect natural widths
while (headCells.hasNext()) {
final HeaderCell hCell = (HeaderCell) headCells.next();
@@ -661,6 +716,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
tHead.disableBrowserIntelligence();
+ tFoot.disableBrowserIntelligence();
boolean willHaveScrollbarz = willHaveScrollbars();
@@ -1532,8 +1588,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
headerChangedDuringUpdate = true;
}
}
-
}
+
// check for orphaned header cells
for (Iterator<String> cit = availableCells.keySet().iterator(); cit
.hasNext();) {
@@ -1543,7 +1599,6 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
cit.remove();
}
}
-
}
public void enableColumn(String cid, int index) {
@@ -1825,6 +1880,425 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
}
/**
+ * A cell in the footer
+ */
+ public class FooterCell extends Widget {
+ private Element td = DOM.createTD();
+ private Element captionContainer = DOM.createDiv();
+ private char align = ALIGN_LEFT;
+ private int width = -1;
+ private float expandRatio = 0;
+
+ public FooterCell(String colId, String headerText) {
+ setText(headerText);
+
+ DOM.setElementProperty(captionContainer, "className", CLASSNAME
+ + "-footer-container");
+
+ // ensure no clipping initially (problem on column additions)
+ DOM.setStyleAttribute(captionContainer, "overflow", "visible");
+
+ DOM.appendChild(td, captionContainer);
+
+ setElement(td);
+ }
+
+ /**
+ * Sets the text of the footer
+ *
+ * @param footerText
+ * The text in the footer
+ */
+ public void setText(String footerText) {
+ DOM.setInnerHTML(captionContainer, footerText);
+ }
+
+ /**
+ * Set alignment of the text in the cell
+ *
+ * @param c
+ * The alignment which can be ALIGN_CENTER, ALIGN_LEFT,
+ * ALIGN_RIGHT
+ */
+ public void setAlign(char c) {
+ if (align != c) {
+ switch (c) {
+ case ALIGN_CENTER:
+ DOM.setStyleAttribute(captionContainer, "textAlign",
+ "center");
+ break;
+ case ALIGN_RIGHT:
+ DOM.setStyleAttribute(captionContainer, "textAlign",
+ "right");
+ break;
+ default:
+ DOM.setStyleAttribute(captionContainer, "textAlign", "");
+ break;
+ }
+ }
+ align = c;
+ }
+
+ /**
+ * Get the alignment of the text int the cell
+ *
+ * @return Returns either ALIGN_CENTER, ALIGN_LEFT or ALIGN_RIGHT
+ */
+ public char getAlign() {
+ return align;
+ }
+
+ /**
+ * Sets the width of the cell
+ *
+ * @param w
+ * The width of the cell
+ * @param ensureDefinedWidth
+ * Ensures the the given width is not recalculated
+ */
+ public void setWidth(int w, boolean ensureDefinedWidth) {
+
+ // Account for 1px right border
+ w--;
+
+ if (ensureDefinedWidth) {
+ // on column resize expand ratio becomes zero
+ expandRatio = 0;
+ }
+ if (width == w) {
+ return;
+ }
+ if (width == -1) {
+ // go to default mode, clip content if necessary
+ DOM.setStyleAttribute(captionContainer, "overflow", "");
+ }
+ width = w;
+ if (w == -1) {
+ DOM.setStyleAttribute(captionContainer, "width", "");
+ setWidth("");
+ } else {
+
+ captionContainer.getStyle().setPropertyPx("width", w);
+
+ /*
+ * if we already have tBody, set the header width properly, if
+ * not defer it. IE will fail with complex float in table header
+ * unless TD width is not explicitly set.
+ */
+ if (scrollBody != null) {
+ int tdWidth = width + scrollBody.getCellExtraWidth();
+ setWidth(tdWidth + "px");
+ } else {
+ DeferredCommand.addCommand(new Command() {
+ public void execute() {
+ int tdWidth = width
+ + scrollBody.getCellExtraWidth();
+ setWidth(tdWidth + "px");
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Sets the width to undefined
+ */
+ public void setUndefinedWidth() {
+ setWidth(-1, false);
+ }
+
+ /**
+ * Sets the expand ratio of the cell
+ *
+ * @param floatAttribute
+ * The expand ratio
+ */
+ public void setExpandRatio(float floatAttribute) {
+ expandRatio = floatAttribute;
+ }
+
+ /**
+ * Returns the expand ration of the cell
+ *
+ * @return The expand ratio
+ */
+ public float getExpandRatio() {
+ return expandRatio;
+ }
+
+ /**
+ * Is the cell enabled?
+ *
+ * @return True if enabled else False
+ */
+ public boolean isEnabled() {
+ return getParent() != null;
+ }
+
+ }
+
+ /**
+ * The footer of the table which can be seen in the bottom of the Table.
+ */
+ public class TableFooter extends Panel {
+
+ private static final int WRAPPER_WIDTH = 9000;
+
+ ArrayList<Widget> visibleCells = new ArrayList<Widget>();
+ HashMap<String, FooterCell> availableCells = new HashMap<String, FooterCell>();
+
+ Element div = DOM.createDiv();
+ Element hTableWrapper = DOM.createDiv();
+ Element hTableContainer = DOM.createDiv();
+ Element table = DOM.createTable();
+ Element headerTableBody = DOM.createTBody();
+ Element tr = DOM.createTR();
+
+ public TableFooter() {
+
+ DOM.setStyleAttribute(hTableWrapper, "overflow", "hidden");
+ DOM.setElementProperty(hTableWrapper, "className", CLASSNAME
+ + "-footer");
+
+ DOM.appendChild(table, headerTableBody);
+ DOM.appendChild(headerTableBody, tr);
+ DOM.appendChild(hTableContainer, table);
+ DOM.appendChild(hTableWrapper, hTableContainer);
+ DOM.appendChild(div, hTableWrapper);
+ setElement(div);
+
+ setStyleName(CLASSNAME + "-footer-wrap");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.google.gwt.user.client.ui.Panel#remove(com.google.gwt.user.client
+ * .ui.Widget)
+ */
+ @Override
+ public boolean remove(Widget w) {
+ if (visibleCells.contains(w)) {
+ visibleCells.remove(w);
+ orphan(w);
+ DOM.removeChild(DOM.getParent(w.getElement()), w.getElement());
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.google.gwt.user.client.ui.HasWidgets#iterator()
+ */
+ @Override
+ public Iterator<Widget> iterator() {
+ return visibleCells.iterator();
+ }
+
+ /**
+ * Gets a footer cell which represents the given columnId
+ *
+ * @param cid
+ * The columnId
+ *
+ * @return The cell
+ */
+ public FooterCell getFooterCell(String cid) {
+ return availableCells.get(cid);
+ }
+
+ /**
+ * Gets a footer cell by using a column index
+ *
+ * @param index
+ * The index of the column
+ * @return The Cell
+ */
+ public FooterCell getFooterCell(int index) {
+ if (index < visibleCells.size()) {
+ return (FooterCell) visibleCells.get(index);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Updates the cells contents when updateUIDL request is received
+ *
+ * @param uidl
+ * The UIDL
+ */
+ public void updateCellsFromUIDL(UIDL uidl) {
+ Iterator<?> columnIterator = uidl.getChildIterator();
+ HashSet<String> updated = new HashSet<String>();
+ updated.add("0");
+ while (columnIterator.hasNext()) {
+ final UIDL col = (UIDL) columnIterator.next();
+ final String cid = col.getStringAttribute("cid");
+ updated.add(cid);
+
+ String caption = col.getStringAttribute("fcaption");
+ FooterCell c = getFooterCell(cid);
+ if (c == null) {
+ c = new FooterCell(cid, caption);
+ availableCells.put(cid, c);
+ if (initializedAndAttached) {
+ // we will need a column width recalculation
+ initializedAndAttached = false;
+ initialContentReceived = false;
+ isNewBody = true;
+ }
+ } else {
+ c.setText(caption);
+ }
+
+ if (col.hasAttribute("align")) {
+ c.setAlign(col.getStringAttribute("align").charAt(0));
+ }
+ if (col.hasAttribute("width")) {
+ final String width = col.getStringAttribute("width");
+ c.setWidth(Integer.parseInt(width), true);
+ } else if (recalcWidths) {
+ c.setUndefinedWidth();
+ }
+ if (col.hasAttribute("er")) {
+ c.setExpandRatio(col.getFloatAttribute("er"));
+ }
+ if (col.hasAttribute("collapsed")) {
+ // ensure header is properly removed from parent (case when
+ // collapsing happens via servers side api)
+ if (c.isAttached()) {
+ c.removeFromParent();
+ headerChangedDuringUpdate = true;
+ }
+ }
+ }
+
+ // check for orphaned header cells
+ for (Iterator<String> cit = availableCells.keySet().iterator(); cit
+ .hasNext();) {
+ String cid = cit.next();
+ if (!updated.contains(cid)) {
+ removeCell(cid);
+ cit.remove();
+ }
+ }
+ }
+
+ /**
+ * Set a footer cell for a specified column index
+ *
+ * @param index
+ * The index
+ * @param cell
+ * The footer cell
+ */
+ public void setFooterCell(int index, FooterCell cell) {
+ if (cell.isEnabled()) {
+ // we're moving the cell
+ DOM.removeChild(tr, cell.getElement());
+ orphan(cell);
+ }
+ if (index < visibleCells.size()) {
+ // insert to right slot
+ DOM.insertChild(tr, cell.getElement(), index);
+ adopt(cell);
+ visibleCells.add(index, cell);
+ } else if (index == visibleCells.size()) {
+ // simply append
+ DOM.appendChild(tr, cell.getElement());
+ adopt(cell);
+ visibleCells.add(cell);
+ } else {
+ throw new RuntimeException(
+ "Header cells must be appended in order");
+ }
+ }
+
+ /**
+ * Remove a cell by using the columnId
+ *
+ * @param colKey
+ * The columnId to remove
+ */
+ public void removeCell(String colKey) {
+ final FooterCell c = getFooterCell(colKey);
+ remove(c);
+ }
+
+ /**
+ * Enable a column (Sets the footer cell)
+ *
+ * @param cid
+ * The columnId
+ * @param index
+ * The index of the column
+ */
+ public void enableColumn(String cid, int index) {
+ final FooterCell c = getFooterCell(cid);
+ if (!c.isEnabled() || getFooterCell(index) != c) {
+ setFooterCell(index, c);
+ if (initializedAndAttached) {
+ headerChangedDuringUpdate = true;
+ }
+ }
+ }
+
+ /**
+ * Disable browser measurement of the table width
+ */
+ public void disableBrowserIntelligence() {
+ DOM.setStyleAttribute(hTableContainer, "width", WRAPPER_WIDTH
+ + "px");
+ }
+
+ /**
+ * Enable browser measurement of the table width
+ */
+ public void enableBrowserIntelligence() {
+ DOM.setStyleAttribute(hTableContainer, "width", "");
+ }
+
+ /**
+ * Set the horizontal position in the cell in the footer. This is done
+ * when a horizontal scrollbar is present.
+ *
+ * @param scrollLeft
+ * The value of the leftScroll
+ */
+ public void setHorizontalScrollPosition(int scrollLeft) {
+ if (BrowserInfo.get().isIE6()) {
+ hTableWrapper.getStyle().setProperty("position", "relative");
+ hTableWrapper.getStyle().setPropertyPx("left", -scrollLeft);
+ } else {
+ hTableWrapper.setScrollLeft(scrollLeft);
+ }
+ }
+
+ /**
+ * Swap cells when the column are dragged
+ *
+ * @param oldIndex
+ * The old index of the cell
+ * @param newIndex
+ * The new index of the cell
+ */
+ public void moveCell(int oldIndex, int newIndex) {
+ final FooterCell hCell = getFooterCell(oldIndex);
+ final Element cell = hCell.getElement();
+
+ visibleCells.remove(oldIndex);
+ DOM.removeChild(tr, cell);
+
+ DOM.insertChild(tr, cell, newIndex);
+ visibleCells.add(newIndex, hCell);
+ }
+ }
+
+ /**
* This Panel can only contain VScrollTableRow type of widgets. This
* "simulates" very large table, keeping spacers which take room of
* unrendered rows.
@@ -3096,6 +3570,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
private void setContentWidth(int pixels) {
tHead.setWidth(pixels + "px");
bodyContainer.setWidth(pixels + "px");
+ tFoot.setWidth(pixels + "px");
}
private int borderWidth = -1;
@@ -3120,7 +3595,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
*/
private void setContainerHeight() {
if (height != null && !"".equals(height)) {
- int contentH = getOffsetHeight() - tHead.getOffsetHeight();
+ int contentH = getOffsetHeight() - tHead.getOffsetHeight()
+ - tFoot.getOffsetHeight();
contentH -= getContentAreaBorderHeight();
if (contentH < 0) {
contentH = 0;
@@ -3248,6 +3724,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
// fix headers horizontal scrolling
tHead.setHorizontalScrollPosition(scrollLeft);
+ // fix footers horizontal scrolling
+ tFoot.setHorizontalScrollPosition(scrollLeft);
+
firstRowInViewPort = (int) Math.ceil(scrollTop
/ scrollBody.getRowHeight());
if (firstRowInViewPort > totalRows - pageLength) {
diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java
index 69b619054c..19ffaae2b9 100644
--- a/src/com/vaadin/ui/Table.java
+++ b/src/com/vaadin/ui/Table.java
@@ -242,6 +242,11 @@ public class Table extends AbstractSelect implements Action.Container,
private final HashMap<Object, String> columnHeaders = new HashMap<Object, String>();
/**
+ * Holds footers for visible columns (by propertyId).
+ */
+ private final HashMap<Object, String> columnFooters = new HashMap<Object, String>();
+
+ /**
* Holds icons for visible columns (by propertyId).
*/
private final HashMap<Object, Resource> columnIcons = new HashMap<Object, Resource>();
@@ -288,6 +293,11 @@ public class Table extends AbstractSelect implements Action.Container,
private int columnHeaderMode = COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID;
/**
+ * Should the Table footer be visible?
+ */
+ private boolean columnFootersVisible = false;
+
+ /**
* True iff the row captions are hidden.
*/
private boolean rowCaptionsAreHidden = true;
@@ -2184,6 +2194,9 @@ public class Table extends AbstractSelect implements Action.Container,
if (rowheads) {
target.addAttribute("rowheaders", true);
}
+ if (columnFootersVisible) {
+ target.addAttribute("colfooters", true);
+ }
// Visible column order
final Collection sortables = getSortableContainerPropertyIds();
@@ -2418,6 +2431,8 @@ public class Table extends AbstractSelect implements Action.Container,
target.addAttribute("cid", columnIdMap.key(columnId));
final String head = getColumnHeader(columnId);
target.addAttribute("caption", (head != null ? head : ""));
+ final String foot = getColumnFooter(columnId);
+ target.addAttribute("fcaption", (foot != null ? foot : ""));
if (isColumnCollapsed(columnId)) {
target.addAttribute("collapsed", true);
}
@@ -2679,6 +2694,7 @@ public class Table extends AbstractSelect implements Action.Container,
columnAlignments.remove(propertyId);
columnIcons.remove(propertyId);
columnHeaders.remove(propertyId);
+ columnFooters.remove(propertyId);
return super.removeContainerProperty(propertyId);
}
@@ -3703,4 +3719,61 @@ public class Table extends AbstractSelect implements Action.Container,
public HeaderClickHandler getHeaderClickHandler() {
return headerClickHandler;
}
+
+ /**
+ * Gets the footer caption beneath the rows
+ *
+ * @param propertyId
+ * The propertyId of the column *
+ * @return The caption of the footer or NULL if not set
+ */
+ public String getColumnFooter(Object propertyId) {
+ return columnFooters.get(propertyId);
+ }
+
+ /**
+ * Sets the column footer caption. The column footer caption is the text
+ * displayed beneath the column if footers have been set visible.
+ *
+ * @param propertyId
+ * The properyId of the column
+ *
+ * @param footer
+ * The caption of the footer
+ */
+ public void setColumnFooter(Object propertyId, String footer) {
+ if (footer == null) {
+ columnFooters.remove(propertyId);
+ return;
+ }
+ columnFooters.put(propertyId, footer);
+
+ requestRepaint();
+ }
+
+ /**
+ * Sets the footer visible in the bottom of the table.
+ * <p>
+ * The footer can be used to add column related data like sums to the bottom
+ * of the Table using setColumnFooter(Object propertyId, String footer).
+ * </p>
+ *
+ * @param visible
+ * Should the footer be visible
+ */
+ public void setFooterVisible(boolean visible){
+ columnFootersVisible = visible;
+
+ // Assures the visual refresh
+ refreshRenderedCells();
+ }
+
+ /**
+ * Is the footer currently visible?
+ *
+ * @return Returns true if visible else false
+ */
+ public boolean isFooterVisible() {
+ return columnFootersVisible;
+ }
}