From 8aaa602c776f70458c81fbba2721468fd3cda8d3 Mon Sep 17 00:00:00 2001 From: Jonatan Kronqvist Date: Wed, 27 Apr 2011 11:05:51 +0000 Subject: [PATCH] Fix for #6697 - Resizing a table column no longer affects the size of other columns svn changeset:18492/svn branch:6.6 --- .../terminal/gwt/client/ui/VScrollTable.java | 80 +++++++--- src/com/vaadin/ui/Table.java | 151 ++++++++++++------ 2 files changed, 162 insertions(+), 69 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 94896c645f..09f3101825 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -102,6 +102,7 @@ import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation; public class VScrollTable extends FlowPanel implements Table, ScrollHandler, VHasDropHandler, FocusHandler, BlurHandler, Focusable, ActionOwner { + private static final String ROW_HEADER_COLUMN_KEY = "0"; public static final String CLASSNAME = "v-table"; public static final String CLASSNAME_SELECTION_FOCUS = CLASSNAME + "-focus"; @@ -502,6 +503,24 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } + /** + * Non-immediate variable update of column resize events for a bunch of + * columns. + * + * @param columns + * the columns to trigger the events for. + */ + private void enqueueColumnResizeEventsForColumns( + Collection columns) { + String[] newSizes = new String[columns.size()]; + int ix = 0; + for (HeaderCell cell : columns) { + newSizes[ix++] = cell.getColKey() + ":" + cell.getWidth(); + } + client.updateVariable(paintableId, "columnResizeEvents", newSizes, + false); + } + /** * Moves the focus one step down * @@ -1162,14 +1181,14 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, int visibleCols = strings.length; int colIndex = 0; if (showRowHeaders) { - tHead.enableColumn("0", colIndex); + tHead.enableColumn(ROW_HEADER_COLUMN_KEY, colIndex); visibleCols++; visibleColOrder = new String[visibleCols]; - visibleColOrder[colIndex] = "0"; + visibleColOrder[colIndex] = ROW_HEADER_COLUMN_KEY; colIndex++; } else { visibleColOrder = new String[visibleCols]; - tHead.removeCell("0"); + tHead.removeCell(ROW_HEADER_COLUMN_KEY); } int i; @@ -1201,10 +1220,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, // Add dummy column if row headers are present int colIndex = 0; if (showRowHeaders) { - tFoot.enableColumn("0", colIndex); + tFoot.enableColumn(ROW_HEADER_COLUMN_KEY, colIndex); colIndex++; } else { - tFoot.removeCell("0"); + tFoot.removeCell(ROW_HEADER_COLUMN_KEY); } int i; @@ -1267,7 +1286,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, */ private int getColIndexByKey(String colKey) { // return 0 if asked for rowHeaders - if ("0".equals(colKey)) { + if (ROW_HEADER_COLUMN_KEY.equals(colKey)) { return 0; } for (int i = 0; i < visibleColOrder.length; i++) { @@ -1978,6 +1997,11 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, setAlign(ALIGN_LEFT); } + public void disableAutoWidthCalculation() { + definedWidth = true; + expandRatio = 0; + } + public void setWidth(int w, boolean ensureDefinedWidth) { if (ensureDefinedWidth) { definedWidth = true; @@ -2276,9 +2300,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, case Event.ONMOUSEUP: isResizing = false; DOM.releaseCapture(getElement()); - // readjust undefined width columns - lazyAdjustColumnWidths.cancel(); - lazyAdjustColumnWidths.schedule(1); + tHead.disableAutoColumnWidthCalculation(this); fireColumnResizeEvent(cid, originalWidth, getColWidth(cid)); break; case Event.ONMOUSEMOVE: @@ -2403,7 +2425,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, public class RowHeadersHeaderCell extends HeaderCell { RowHeadersHeaderCell() { - super("0", ""); + super(ROW_HEADER_COLUMN_KEY, ""); this.setStyleName(CLASSNAME + "-header-cell-rowheader"); } @@ -2459,7 +2481,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, DOM.sinkEvents(columnSelector, Event.ONCLICK); - availableCells.put("0", new RowHeadersHeaderCell()); + availableCells.put(ROW_HEADER_COLUMN_KEY, + new RowHeadersHeaderCell()); } @Override @@ -2468,13 +2491,13 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, removeCell(cid); } availableCells.clear(); - availableCells.put("0", new RowHeadersHeaderCell()); + availableCells.put(ROW_HEADER_COLUMN_KEY, + new RowHeadersHeaderCell()); } public void updateCellsFromUIDL(UIDL uidl) { Iterator it = uidl.getChildIterator(); HashSet updated = new HashSet(); - updated.add("0"); while (it.hasNext()) { final UIDL col = (UIDL) it.next(); final String cid = col.getStringAttribute("cid"); @@ -2828,6 +2851,22 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } return aligns; } + + /** + * Disables the automatic calculation of all column widths by forcing + * the widths to be "defined" thus turning off expand ratios and such. + */ + public void disableAutoColumnWidthCalculation(HeaderCell source) { + for (HeaderCell cell : availableCells.values()) { + cell.disableAutoWidthCalculation(); + } + // fire column resize events for all columns but the source of the + // resize action, since an event will fire separately for this. + ArrayList columns = new ArrayList( + availableCells.values()); + columns.remove(source); + enqueueColumnResizeEventsForColumns(columns); + } } /** @@ -3136,7 +3175,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, public class RowHeadersFooterCell extends FooterCell { RowHeadersFooterCell() { - super("0", ""); + super(ROW_HEADER_COLUMN_KEY, ""); } @Override @@ -3178,7 +3217,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, setStyleName(CLASSNAME + "-footer-wrap"); - availableCells.put("0", new RowHeadersFooterCell()); + availableCells.put(ROW_HEADER_COLUMN_KEY, + new RowHeadersFooterCell()); } @Override @@ -3187,7 +3227,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, removeCell(cid); } availableCells.clear(); - availableCells.put("0", new RowHeadersFooterCell()); + availableCells.put(ROW_HEADER_COLUMN_KEY, + new RowHeadersFooterCell()); } /* @@ -3253,13 +3294,13 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, public void updateCellsFromUIDL(UIDL uidl) { Iterator columnIterator = uidl.getChildIterator(); HashSet updated = new HashSet(); - 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"); + String caption = col.hasAttribute("fcaption") ? col + .getStringAttribute("fcaption") : ""; FooterCell c = getFooterCell(cid); if (c == null) { c = new FooterCell(cid, caption); @@ -5117,7 +5158,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, * @return html snippet containing possibly an icon + caption text */ protected String buildCaptionHtmlSnippet(UIDL uidl) { - String s = uidl.getStringAttribute("caption"); + String s = uidl.hasAttribute("caption") ? uidl + .getStringAttribute("caption") : ""; if (uidl.hasAttribute("icon")) { s = " - * If terminal implementation supports re-sizeable columns the column - * becomes fixed width column if users resizes the column. + * If terminal implementation supports re-sizable columns the column becomes + * fixed width column if users resizes the column. * - * @param columnId - * colunmns property id + * @param propertyId + * columns property id * @param expandRatio * the expandRatio used to divide excess space for this column */ - public void setColumnExpandRatio(Object columnId, float expandRatio) { + public void setColumnExpandRatio(Object propertyId, float expandRatio) { if (expandRatio < 0) { - columnWidths.remove(columnId); + columnWidths.remove(propertyId); } else { - columnWidths.put(columnId, new Float(expandRatio)); + columnWidths.put(propertyId, new Float(expandRatio)); } } @@ -794,9 +802,14 @@ public class Table extends AbstractSelect implements Action.Container, * Gets the pixel width of column * * @param propertyId - * @return width of colun or -1 when value not set + * @return width of column or -1 when value not set */ public int getColumnWidth(Object propertyId) { + if (propertyId == null) { + // Since propertyId is null, this is the row header. Use the magic + // id to retrieve the width of the row header. + propertyId = MAGIC_ROW_HEADER_ID; + } final Object width = columnWidths.get(propertyId); if (width == null || !(width instanceof Integer)) { return -1; @@ -1029,7 +1042,7 @@ public class Table extends AbstractSelect implements Action.Container, * Sets the column header for the specified column; * * @param propertyId - * the propertyId indentifying the column. + * the propertyId identifying the column. * @param header * the header to set. */ @@ -1985,7 +1998,7 @@ public class Table extends AbstractSelect implements Action.Container, handleClickEvent(variables); - handleColumnResizeEvent(variables); + handleColumnResizeEvents(variables); disableContentRefreshing(); @@ -2215,38 +2228,62 @@ public class Table extends AbstractSelect implements Action.Container, * * @param variables */ - private void handleColumnResizeEvent(Map variables) { + private void handleColumnResizeEvents(Map variables) { + if (variables.containsKey("columnResizeEvents")) { + handleMultipleColumnResizeEvents(variables); + } if (variables.containsKey("columnResizeEventColumn")) { - Object cid = variables.get("columnResizeEventColumn"); - Object propertyId = null; - if (cid != null) { - propertyId = columnIdMap.get(cid.toString()); - } + handleSingleColumnResizeEvent(variables); + } + } - Object prev = variables.get("columnResizeEventPrev"); - int previousWidth = -1; - if (prev != null) { - previousWidth = Integer.valueOf(prev.toString()); - } + private void handleSingleColumnResizeEvent(Map variables) { + Object cid = variables.get("columnResizeEventColumn"); + Object propertyId = null; + if (cid != null) { + propertyId = columnIdMap.get(cid.toString()); + } - Object curr = variables.get("columnResizeEventCurr"); - int currentWidth = -1; - if (curr != null) { - currentWidth = Integer.valueOf(curr.toString()); - } + Object prev = variables.get("columnResizeEventPrev"); + int previousWidth = -1; + if (prev != null) { + previousWidth = Integer.valueOf(prev.toString()); + } - /* - * Update the sizes on the server side. If a column previously had a - * expand ratio and the user resized the column then the expand - * ratio will be turned into a static pixel size. - */ - setColumnWidth(propertyId, currentWidth); + Object curr = variables.get("columnResizeEventCurr"); + int currentWidth = -1; + if (curr != null) { + currentWidth = Integer.valueOf(curr.toString()); + } + + fireColumnResizeEvent(propertyId, previousWidth, currentWidth); + } + + private void handleMultipleColumnResizeEvents(Map variables) { + String[] events = (String[]) variables.get("columnResizeEvents"); + for (String str : events) { + String[] eventDetails = str.split(":"); + Object propertyId = columnIdMap.get(eventDetails[0]); + int curWidth = Integer.valueOf(eventDetails[1]); + int prevWidth = getColumnWidth(propertyId); - fireEvent(new ColumnResizeEvent(this, propertyId, previousWidth, - currentWidth)); + fireColumnResizeEvent(propertyId, prevWidth, curWidth); } } + private void fireColumnResizeEvent(Object propertyId, int previousWidth, + int currentWidth) { + /* + * Update the sizes on the server side. If a column previously had a + * expand ratio and the user resized the column then the expand ratio + * will be turned into a static pixel size. + */ + setColumnWidth(propertyId, currentWidth); + + fireEvent(new ColumnResizeEvent(this, propertyId, previousWidth, + currentWidth)); + } + /** * Go to mode where content updates are not done. This is due we want to * bypass expensive content for some reason (like when we know we may have @@ -2377,7 +2414,7 @@ public class Table extends AbstractSelect implements Action.Container, if (colheads) { target.addAttribute("colheaders", true); } - if (getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN) { + if (rowHeadersAreEnabled()) { target.addAttribute("rowheaders", true); } @@ -2540,6 +2577,12 @@ public class Table extends AbstractSelect implements Action.Container, target.addVariable(this, "collapsedcolumns", collapsedkeys); } target.startTag("visiblecolumns"); + if (rowHeadersAreEnabled()) { + target.startTag("column"); + target.addAttribute("cid", ROW_HEADER_COLUMN_ID); + paintColumnWidth(target, MAGIC_ROW_HEADER_ID); + target.endTag("column"); + } int i = 0; for (final Iterator it = visibleColumns.iterator(); it .hasNext(); i++) { @@ -2565,15 +2608,7 @@ public class Table extends AbstractSelect implements Action.Container, if (!ALIGN_LEFT.equals(getColumnAlignment(columnId))) { target.addAttribute("align", getColumnAlignment(columnId)); } - if (columnWidths.containsKey(columnId)) { - if (getColumnWidth(columnId) > -1) { - target.addAttribute("width", - String.valueOf(getColumnWidth(columnId))); - } else { - target.addAttribute("er", - getColumnExpandRatio(columnId)); - } - } + paintColumnWidth(target, columnId); target.endTag("column"); } } @@ -2584,6 +2619,22 @@ public class Table extends AbstractSelect implements Action.Container, } } + private void paintColumnWidth(PaintTarget target, final Object columnId) + throws PaintException { + if (columnWidths.containsKey(columnId)) { + if (getColumnWidth(columnId) > -1) { + target.addAttribute("width", + String.valueOf(getColumnWidth(columnId))); + } else { + target.addAttribute("er", getColumnExpandRatio(columnId)); + } + } + } + + private boolean rowHeadersAreEnabled() { + return getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN; + } + private void paintRow(PaintTarget target, final Object[][] cells, final boolean iseditable, final Set actionSet, final boolean[] iscomponent, int indexInRowbuffer, @@ -2677,7 +2728,7 @@ public class Table extends AbstractSelect implements Action.Container, protected void paintRowHeader(PaintTarget target, Object[][] cells, int indexInRowbuffer) throws PaintException { - if (getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN) { + if (rowHeadersAreEnabled()) { if (cells[CELL_HEADER][indexInRowbuffer] != null) { target.addAttribute("caption", (String) cells[CELL_HEADER][indexInRowbuffer]); @@ -2688,7 +2739,7 @@ public class Table extends AbstractSelect implements Action.Container, protected void paintRowIcon(PaintTarget target, final Object[][] cells, int indexInRowbuffer) throws PaintException { - if (getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN + if (rowHeadersAreEnabled() && cells[CELL_ICON][indexInRowbuffer] != null) { target.addAttribute("icon", (Resource) cells[CELL_ICON][indexInRowbuffer]); -- 2.39.5