]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fix for #6697 - Resizing a table column no longer affects the size of other columns
authorJonatan Kronqvist <jonatan.kronqvist@itmill.com>
Wed, 27 Apr 2011 11:05:51 +0000 (11:05 +0000)
committerJonatan Kronqvist <jonatan.kronqvist@itmill.com>
Wed, 27 Apr 2011 11:05:51 +0000 (11:05 +0000)
svn changeset:18492/svn branch:6.6

src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
src/com/vaadin/ui/Table.java

index 94896c645f0b0ee19f94aa7c507eeb3507989800..09f3101825be7bc788a1a851ed0aa6fc05bec705 100644 (file)
@@ -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<HeaderCell> 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<String> updated = new HashSet<String>();
-            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<HeaderCell> columns = new ArrayList<HeaderCell>(
+                    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<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");
+                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 = "<img src=\""
                     + client.translateVaadinUri(uidl.getStringAttribute("icon"))
index cb956e25a9fcdc8e9c33164501f9f4617dc87041..f0416a20590dcc1dd400d858de55df88df817a24 100644 (file)
@@ -202,6 +202,9 @@ public class Table extends AbstractSelect implements Action.Container,
      */
     private static final double CACHE_RATE_DEFAULT = 2;
 
+    private static final String ROW_HEADER_COLUMN_ID = "0";
+    private static final Object MAGIC_ROW_HEADER_ID = new Object();
+
     /* Private table extensions to Select */
 
     /**
@@ -723,17 +726,22 @@ public class Table extends AbstractSelect implements Action.Container,
      * Column can either have a fixed width or expand ratio. The latter one set
      * is used. See @link {@link #setColumnExpandRatio(Object, float)}.
      * 
-     * @param columnId
+     * @param propertyId
      *            colunmns property id
      * @param width
      *            width to be reserved for colunmns content
      * @since 4.0.3
      */
-    public void setColumnWidth(Object columnId, int width) {
+    public void setColumnWidth(Object propertyId, int width) {
+        if (propertyId == null) {
+            // Since propertyId is null, this is the row header. Use the magic
+            // id to store the width of the row header.
+            propertyId = MAGIC_ROW_HEADER_ID;
+        }
         if (width < 0) {
-            columnWidths.remove(columnId);
+            columnWidths.remove(propertyId);
         } else {
-            columnWidths.put(columnId, Integer.valueOf(width));
+            columnWidths.put(propertyId, Integer.valueOf(width));
         }
     }
 
@@ -764,19 +772,19 @@ public class Table extends AbstractSelect implements Action.Container,
      * implementation.
      * 
      * <p>
-     * 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<String, Object> variables) {
+    private void handleColumnResizeEvents(Map<String, Object> 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<String, Object> 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<String, Object> 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<Object> 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<Action> 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]);