]> source.dussan.org Git - vaadin-framework.git/commitdiff
Removed SortableColumnHeaderRenderer #13334
authorJohn Ahlroos <john@vaadin.com>
Thu, 7 Aug 2014 13:04:17 +0000 (16:04 +0300)
committerJohn Ahlroos <john@vaadin.com>
Tue, 19 Aug 2014 07:37:58 +0000 (10:37 +0300)
Change-Id: I3f15765228428049febfe3a8d5966c3631d010a9

client/src/com/vaadin/client/ui/grid/Grid.java
client/src/com/vaadin/client/ui/grid/GridHeader.java
client/src/com/vaadin/client/ui/grid/GridStaticSection.java
shared/src/com/vaadin/shared/ui/grid/GridConstants.java

index aae7f046b6864f8c7d8c38dffcc130924c7a7ac8..a407038917c9b236204825bc2579b47e863fee44 100644 (file)
@@ -30,6 +30,7 @@ import com.google.gwt.dom.client.BrowserEvents;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.EventTarget;
 import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.dom.client.TableCellElement;
 import com.google.gwt.dom.client.Touch;
 import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.event.shared.HandlerRegistration;
@@ -463,6 +464,83 @@ public class Grid<T> extends Composite implements
         }
     }
 
+    /**
+     * Class for sorting at a later time
+     */
+    private class LazySorter extends Timer {
+
+        private Cell cell;
+
+        private boolean multisort;
+
+        @Override
+        public void run() {
+            SortOrder sortingOrder = getSortOrder(getColumnFromVisibleIndex(cell
+                    .getColumn()));
+            if (sortingOrder == null) {
+                /*
+                 * No previous sorting, sort Ascending
+                 */
+                sort(cell, SortDirection.ASCENDING, multisort);
+
+            } else {
+                // Toggle sorting
+                SortDirection direction = sortingOrder.getDirection();
+                if (direction == SortDirection.ASCENDING) {
+                    sort(cell, SortDirection.DESCENDING, multisort);
+                } else {
+                    sort(cell, SortDirection.ASCENDING, multisort);
+                }
+            }
+        }
+
+        /**
+         * Set the cell reference to the primary cell that sorting should be
+         * done for.
+         * 
+         * @param cell
+         * 
+         */
+        public void setCellReference(Cell cell) {
+            this.cell = cell;
+        }
+
+        /**
+         * Is multiple column sorting is enabled/disabled
+         * 
+         * @param multisort
+         *            true if multiple column sorting is enabled
+         */
+        public void setMultisort(boolean multisort) {
+            this.multisort = multisort;
+        }
+
+        /**
+         * Sorts the column in a direction
+         */
+        private void sort(Cell cell, SortDirection direction, boolean multisort) {
+            TableCellElement th = TableCellElement.as(cell.getElement());
+
+            // Apply primary sorting on clicked column
+            GridColumn<?, ?> columnInstance = getColumnFromVisibleIndex(cell
+                    .getColumn());
+            Sort sorting = Sort.by(columnInstance, direction);
+
+            // Re-apply old sorting to the sort order
+            if (multisort) {
+                for (SortOrder order : getSortOrder()) {
+                    if (order.getColumn() != columnInstance) {
+                        sorting = sorting.then(order.getColumn(),
+                                order.getDirection());
+                    }
+                }
+            }
+
+            // Perform sorting
+            Grid.this.sort(sorting);
+        }
+    }
+
     /**
      * Escalator used internally by grid to render the rows
      */
@@ -511,6 +589,8 @@ public class Grid<T> extends Composite implements
 
     private final ActiveCellHandler activeCellHandler;
 
+    private final LazySorter lazySorter = new LazySorter();
+
     /**
      * Enumeration for easy setting of selection mode.
      */
@@ -552,13 +632,6 @@ public class Grid<T> extends Composite implements
         protected abstract <T> SelectionModel<T> createModel();
     }
 
-    class SortableColumnHeaderRenderer extends
-            AbstractGridColumn.SortableColumnHeaderRenderer {
-        SortableColumnHeaderRenderer(Renderer<String> cellRenderer) {
-            super(Grid.this, cellRenderer);
-        }
-    }
-
     /**
      * Base class for grid columns internally used by the Grid. The user should
      * use {@link GridColumn} when creating new columns.
@@ -572,274 +645,7 @@ public class Grid<T> extends Composite implements
     static abstract class AbstractGridColumn<C, T> implements HasVisibility {
 
         /**
-         * Renderer for columns which are sortable
-         * 
-         * FIXME Currently assumes multisorting
-         */
-        static class SortableColumnHeaderRenderer extends
-                ComplexRenderer<String> {
-
-            private Grid<?> grid;
-
-            /**
-             * Delay before a long tap action is triggered. Number in
-             * milliseconds.
-             */
-            private static final int LONG_TAP_DELAY = 500;
-
-            /**
-             * The threshold in pixels a finger can move while long tapping.
-             */
-            private static final int LONG_TAP_THRESHOLD = 3;
-
-            /**
-             * Class for sorting at a later time
-             */
-            private class LazySorter extends Timer {
-
-                private Cell cell;
-
-                private boolean multisort;
-
-                @Override
-                public void run() {
-                    SortOrder sortingOrder = getSortingOrder(grid
-                            .getColumnFromVisibleIndex(cell.getColumn()));
-                    if (sortingOrder == null) {
-                        /*
-                         * No previous sorting, sort Ascending
-                         */
-                        sort(cell, SortDirection.ASCENDING, multisort);
-
-                    } else {
-                        // Toggle sorting
-                        SortDirection direction = sortingOrder.getDirection();
-                        if (direction == SortDirection.ASCENDING) {
-                            sort(cell, SortDirection.DESCENDING, multisort);
-                        } else {
-                            sort(cell, SortDirection.ASCENDING, multisort);
-                        }
-                    }
-                }
-
-                public void setCurrentCell(Cell cell) {
-                    this.cell = cell;
-                }
-
-                public void setMultisort(boolean multisort) {
-                    this.multisort = multisort;
-                }
-            }
-
-            private final LazySorter lazySorter = new LazySorter();
-
-            private Renderer<String> cellRenderer;
-
-            private Point touchStartPoint;
-
-            /**
-             * Creates column renderer with sort indicators
-             * 
-             * @param cellRenderer
-             *            The actual cell renderer
-             */
-            public SortableColumnHeaderRenderer(Grid<?> grid,
-                    Renderer<String> cellRenderer) {
-                this.grid = grid;
-                this.cellRenderer = cellRenderer;
-            }
-
-            @Override
-            public void render(FlyweightCell cell, String data) {
-
-                // Render cell
-                this.cellRenderer.render(cell, data);
-
-                /*
-                 * FIXME This grid null check is needed since Grid.addColumns()
-                 * is invoking Escalator.insertColumn() before the grid instance
-                 * for the column is set resulting in the first render() being
-                 * done without a grid instance. Remove the if statement when
-                 * this is fixed.
-                 */
-                if (grid != null) {
-                    GridColumn<?, ?> column = grid
-                            .getColumnFromVisibleIndex(cell.getColumn());
-                    SortOrder sortingOrder = getSortingOrder(column);
-                    Element cellElement = cell.getElement();
-                    if (column.isSortable()) {
-                        if (sortingOrder != null) {
-                            if (SortDirection.ASCENDING == sortingOrder
-                                    .getDirection()) {
-                                cellElement.replaceClassName("sort-desc",
-                                        "sort-asc");
-                            } else {
-                                cellElement.replaceClassName("sort-asc",
-                                        "sort-desc");
-                            }
-
-                            int sortIndex = grid.getSortOrder().indexOf(
-                                    sortingOrder);
-                            if (sortIndex > -1
-                                    && grid.getSortOrder().size() > 1) {
-                                // Show sort order indicator if column is sorted
-                                // and other sorted columns also exists.
-                                cellElement.setAttribute("sort-order",
-                                        String.valueOf(sortIndex + 1));
-
-                            } else {
-                                cellElement.removeAttribute("sort-order");
-                            }
-                        } else {
-                            cleanup(cell);
-                        }
-                    } else {
-                        cleanup(cell);
-                    }
-                }
-            }
-
-            private void cleanup(FlyweightCell cell) {
-                Element cellElement = cell.getElement();
-                cellElement.removeAttribute("sort-order");
-                cellElement.removeClassName("sort-desc");
-                cellElement.removeClassName("sort-asc");
-            }
-
-            @Override
-            public Collection<String> getConsumedEvents() {
-                return Arrays.asList(BrowserEvents.TOUCHSTART,
-                        BrowserEvents.TOUCHMOVE, BrowserEvents.TOUCHEND,
-                        BrowserEvents.TOUCHCANCEL, BrowserEvents.CLICK);
-            }
-
-            @Override
-            public boolean onBrowserEvent(final Cell cell, NativeEvent event) {
-
-                // Handle sorting events if column is sortable
-                if (grid.getColumn(cell.getColumn()).isSortable()) {
-
-                    if (BrowserEvents.TOUCHSTART.equals(event.getType())) {
-                        if (event.getTouches().length() > 1) {
-                            return false;
-                        }
-
-                        event.preventDefault();
-
-                        Touch touch = event.getChangedTouches().get(0);
-                        touchStartPoint = new Point(touch.getClientX(),
-                                touch.getClientY());
-
-                        lazySorter.setCurrentCell(cell);
-                        lazySorter.setMultisort(true);
-                        lazySorter.schedule(LONG_TAP_DELAY);
-
-                    } else if (BrowserEvents.TOUCHMOVE.equals(event.getType())) {
-                        if (event.getTouches().length() > 1) {
-                            return false;
-                        }
-
-                        event.preventDefault();
-
-                        Touch touch = event.getChangedTouches().get(0);
-                        double diffX = Math.abs(touch.getClientX()
-                                - touchStartPoint.getX());
-                        double diffY = Math.abs(touch.getClientY()
-                                - touchStartPoint.getY());
-
-                        // Cancel long tap if finger strays too far from
-                        // starting point
-                        if (diffX > LONG_TAP_THRESHOLD
-                                || diffY > LONG_TAP_THRESHOLD) {
-                            lazySorter.cancel();
-                        }
-
-                    } else if (BrowserEvents.TOUCHEND.equals(event.getType())) {
-                        if (event.getTouches().length() > 0) {
-                            return false;
-                        }
-
-                        if (lazySorter.isRunning()) {
-                            // Not a long tap yet, perform single sort
-                            lazySorter.cancel();
-                            lazySorter.setMultisort(false);
-                            lazySorter.run();
-                        }
-
-                    } else if (BrowserEvents.TOUCHCANCEL
-                            .equals(event.getType())) {
-                        if (event.getChangedTouches().length() > 1) {
-                            return false;
-                        }
-
-                        lazySorter.cancel();
-
-                    } else if (BrowserEvents.CLICK.equals(event.getType())) {
-                        lazySorter.setCurrentCell(cell);
-                        lazySorter.setMultisort(event.getShiftKey());
-                        lazySorter.run();
-
-                        // Active cell handling is also monitoring the click
-                        // event so we allow event to propagate for it
-                        return false;
-                    }
-                    return true;
-                }
-                return false;
-
-            }
-
-            protected void removeFromRow(HeaderRow row) {
-                row.setRenderer(new Renderer<String>() {
-                    @Override
-                    public void render(FlyweightCell cell, String data) {
-                        cleanup(cell);
-                    }
-                });
-                grid.refreshHeader();
-                row.setRenderer(cellRenderer);
-                grid.refreshHeader();
-            }
-
-            /**
-             * Sorts the column in a direction
-             */
-            private void sort(Cell cell, SortDirection direction,
-                    boolean multisort) {
-                // Apply primary sorting on clicked column
-                GridColumn<?, ?> columnInstance = grid
-                        .getColumnFromVisibleIndex(cell.getColumn());
-                Sort sorting = Sort.by(columnInstance, direction);
-
-                // Re-apply old sorting to the sort order
-                if (multisort) {
-                    for (SortOrder order : grid.getSortOrder()) {
-                        if (order.getColumn() != columnInstance) {
-                            sorting = sorting.then(order.getColumn(),
-                                    order.getDirection());
-                        }
-                    }
-                }
-
-                // Perform sorting
-                grid.sort(sorting);
-            }
-
-            /**
-             * Finds the sorting order for this column
-             */
-            private SortOrder getSortingOrder(GridColumn<?, ?> column) {
-                for (SortOrder order : grid.getSortOrder()) {
-                    if (order.getColumn() == column) {
-                        return order;
-                    }
-                }
-                return null;
-            }
-        }
-
-        /**
-         * The grid the column is associated with
+         * the column is associated with
          */
         private Grid<T> grid;
 
@@ -1187,13 +993,14 @@ public class Grid<T> extends Composite implements
                 int index = columnIndices.get(cell.getColumn());
                 final StaticCell metadata = staticRow.getCell(index);
 
+                // Decorate default row with sorting indicators
+                if (staticRow instanceof HeaderRow) {
+                    addSortingIndicatorsToHeaderRow((HeaderRow) staticRow, cell);
+                }
+
                 // Assign colspan to cell before rendering
                 cell.setColSpan(metadata.getColspan());
 
-                // Decorates cell with possible indicators onto the cell.
-                // Actual content is rendered below.
-                staticRow.getRenderer().render(cell, null);
-
                 switch (metadata.getType()) {
                 case TEXT:
                     cell.getElement().setInnerText(metadata.getText());
@@ -1212,6 +1019,57 @@ public class Grid<T> extends Composite implements
             }
         }
 
+        private void addSortingIndicatorsToHeaderRow(HeaderRow headerRow,
+                FlyweightCell cell) {
+
+            cleanup(cell);
+
+            GridColumn<?, ?> column = getColumnFromVisibleIndex(cell
+                    .getColumn());
+            SortOrder sortingOrder = getSortOrder(column);
+            if (!headerRow.isDefault() || !column.isSortable()
+                    || sortingOrder == null) {
+                // Only apply sorting indicators to sortable header columns in
+                // the default header row
+                return;
+            }
+
+            Element cellElement = cell.getElement();
+
+            if (SortDirection.ASCENDING == sortingOrder.getDirection()) {
+                cellElement.addClassName("sort-asc");
+            } else {
+                cellElement.addClassName("sort-desc");
+            }
+
+            int sortIndex = Grid.this.getSortOrder().indexOf(sortingOrder);
+            if (sortIndex > -1 && Grid.this.getSortOrder().size() > 1) {
+                // Show sort order indicator if column is
+                // sorted and other sorted columns also exists.
+                cellElement.setAttribute("sort-order",
+                        String.valueOf(sortIndex + 1));
+            }
+        }
+
+        /**
+         * Finds the sort order for this column
+         */
+        private SortOrder getSortOrder(GridColumn<?, ?> column) {
+            for (SortOrder order : Grid.this.getSortOrder()) {
+                if (order.getColumn() == column) {
+                    return order;
+                }
+            }
+            return null;
+        }
+
+        private void cleanup(FlyweightCell cell) {
+            Element cellElement = cell.getElement();
+            cellElement.removeAttribute("sort-order");
+            cellElement.removeClassName("sort-desc");
+            cellElement.removeClassName("sort-asc");
+        }
+
         @Override
         public void preAttach(Row row, Iterable<FlyweightCell> cellsToAttach) {
         }
@@ -1333,6 +1191,9 @@ public class Grid<T> extends Composite implements
                 refreshBody();
             }
         });
+
+        // Sink header events
+        sinkEvents(getHeader().getConsumedEvents());
     }
 
     @Override
@@ -1371,7 +1232,7 @@ public class Grid<T> extends Composite implements
      * The updater is invoked when body rows or columns are added or removed,
      * the content of body cells is changed, or the body is scrolled to expose
      * previously hidden content.
-     *
+     * 
      * @return the new body updater instance
      */
     protected EscalatorUpdater createBodyUpdater() {
@@ -1997,17 +1858,15 @@ public class Grid<T> extends Composite implements
                     // FIXME getFromVisibleIndex???
                     GridColumn<?, T> gridColumn = columns.get(cell.getColumn());
 
-                    Renderer<?> renderer;
                     if (container == escalator.getHeader()) {
-                        renderer = header.getRow(cell.getRow()).getRenderer();
+                        if (getHeader().getRow(cell.getRow()).isDefault()) {
+                            handleDefaultRowEvent(cell, event);
+                        }
                     } else if (container == escalator.getFooter()) {
-                        renderer = footer.getRow(cell.getRow()).getRenderer();
-                    } else {
-                        renderer = gridColumn.getRenderer();
-                    }
-
-                    if (renderer instanceof ComplexRenderer) {
-                        ComplexRenderer<?> cplxRenderer = (ComplexRenderer<?>) renderer;
+                        // NOP
+                    } else if (gridColumn.getRenderer() instanceof ComplexRenderer) {
+                        ComplexRenderer<?> cplxRenderer = (ComplexRenderer<?>) gridColumn
+                                .getRenderer();
                         if (cplxRenderer.getConsumedEvents().contains(
                                 event.getType())) {
                             if (cplxRenderer.onBrowserEvent(cell, event)) {
@@ -2027,6 +1886,81 @@ public class Grid<T> extends Composite implements
         }
     }
 
+    private Point rowEventTouchStartingPoint;
+
+    private boolean handleDefaultRowEvent(final Cell cell, NativeEvent event) {
+        if (!getColumn(cell.getColumn()).isSortable()) {
+            // Only handle sorting events if the column is sortable
+            return false;
+        }
+
+        if (BrowserEvents.TOUCHSTART.equals(event.getType())) {
+            if (event.getTouches().length() > 1) {
+                return false;
+            }
+
+            event.preventDefault();
+
+            Touch touch = event.getChangedTouches().get(0);
+            rowEventTouchStartingPoint = new Point(touch.getClientX(),
+                    touch.getClientY());
+
+            lazySorter.setCellReference(cell);
+            lazySorter.setMultisort(true);
+            lazySorter.schedule(GridConstants.LONG_TAP_DELAY);
+
+        } else if (BrowserEvents.TOUCHMOVE.equals(event.getType())) {
+            if (event.getTouches().length() > 1) {
+                return false;
+            }
+
+            event.preventDefault();
+
+            Touch touch = event.getChangedTouches().get(0);
+            double diffX = Math.abs(touch.getClientX()
+                    - rowEventTouchStartingPoint.getX());
+            double diffY = Math.abs(touch.getClientY()
+                    - rowEventTouchStartingPoint.getY());
+
+            // Cancel long tap if finger strays too far from
+            // starting point
+            if (diffX > GridConstants.LONG_TAP_THRESHOLD
+                    || diffY > GridConstants.LONG_TAP_THRESHOLD) {
+                lazySorter.cancel();
+            }
+
+        } else if (BrowserEvents.TOUCHEND.equals(event.getType())) {
+            if (event.getTouches().length() > 0) {
+                return false;
+            }
+
+            if (lazySorter.isRunning()) {
+                // Not a long tap yet, perform single sort
+                lazySorter.cancel();
+                lazySorter.setMultisort(false);
+                lazySorter.run();
+            }
+
+        } else if (BrowserEvents.TOUCHCANCEL.equals(event.getType())) {
+            if (event.getChangedTouches().length() > 1) {
+                return false;
+            }
+
+            lazySorter.cancel();
+
+        } else if (BrowserEvents.CLICK.equals(event.getType())) {
+            lazySorter.setCellReference(cell);
+            lazySorter.setMultisort(event.getShiftKey());
+            lazySorter.run();
+
+            // Active cell handling is also monitoring the click
+            // event so we allow event to propagate for it
+            return false;
+        }
+
+        return true;
+    }
+
     @Override
     public com.google.gwt.user.client.Element getSubPartElement(String subPart) {
         // Parse SubPart string to type and indices
@@ -2358,6 +2292,18 @@ public class Grid<T> extends Composite implements
         return Collections.unmodifiableList(sortOrder);
     }
 
+    /**
+     * Finds the sorting order for this column
+     */
+    private SortOrder getSortOrder(GridColumn<?, ?> column) {
+        for (SortOrder order : getSortOrder()) {
+            if (order.getColumn() == column) {
+                return order;
+            }
+        }
+        return null;
+    }
+
     /**
      * Register a GWT event handler for a sorting event. This handler gets
      * called whenever this Grid needs its data source to provide data sorted in
index f7148486180aae4eb759a226a63c89778cfbc651..2867ae4d1ce300ed994c2330a3a2286feb1d4a01 100644 (file)
  */
 package com.vaadin.client.ui.grid;
 
+import java.util.Arrays;
+import java.util.Collection;
+
 import com.google.gwt.core.client.Scheduler;
-import com.vaadin.client.ui.grid.Grid.AbstractGridColumn.SortableColumnHeaderRenderer;
+import com.google.gwt.dom.client.BrowserEvents;
 
 /**
  * Represents the header section of a Grid. A header consists of a single header
@@ -89,21 +92,9 @@ public class GridHeader extends GridStaticSection<GridHeader.HeaderRow> {
                     "Cannot set a default row that does not exist in the container");
         }
         if (defaultRow != null) {
-            assert defaultRow.getRenderer() instanceof SortableColumnHeaderRenderer;
-
-            // Eclipse is wrong about this warning - javac does not accept the
-            // parameterized version
-            ((Grid.SortableColumnHeaderRenderer) defaultRow.getRenderer())
-                    .removeFromRow(defaultRow);
-
             defaultRow.setDefault(false);
         }
         if (row != null) {
-            assert !(row.getRenderer() instanceof SortableColumnHeaderRenderer);
-
-            row.setRenderer(getGrid().new SortableColumnHeaderRenderer(row
-                    .getRenderer()));
-
             row.setDefault(true);
         }
         defaultRow = row;
@@ -145,4 +136,15 @@ public class GridHeader extends GridStaticSection<GridHeader.HeaderRow> {
             }
         });
     }
+
+    /**
+     * Returns the events consumed by the header
+     * 
+     * @return a collection of BrowserEvents
+     */
+    public Collection<String> getConsumedEvents() {
+        return Arrays.asList(BrowserEvents.TOUCHSTART, BrowserEvents.TOUCHMOVE,
+                BrowserEvents.TOUCHEND, BrowserEvents.TOUCHCANCEL,
+                BrowserEvents.CLICK);
+    }
 }
index 1be0a92b8f6c5814c2c13e745a637fbb2f9feba1..8c9ada46d0c3a7839a68b780701a4e0050987ec1 100644 (file)
@@ -187,17 +187,6 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
 
         private List<CELLTYPE> cells = new ArrayList<CELLTYPE>();
 
-        private Renderer<String> renderer = new Renderer<String>() {
-
-            @Override
-            public void render(FlyweightCell cell, String data) {
-                /*
-                 * The rendering into the cell is done directly from the updater
-                 * since it needs to handle multiple types of data.
-                 */
-            }
-        };
-
         private GridStaticSection<?> section;
 
         private Collection<List<CELLTYPE>> cellGroups = new HashSet<List<CELLTYPE>>();
@@ -359,14 +348,6 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
             cells.remove(index);
         }
 
-        protected void setRenderer(Renderer<String> renderer) {
-            this.renderer = renderer;
-        }
-
-        protected Renderer<String> getRenderer() {
-            return renderer;
-        }
-
         protected abstract CELLTYPE createCell();
 
         protected GridStaticSection<?> getSection() {
index 346e85b994be59e23f7bf5a3db6f9714c2be9a19..1ee79a5d376c67bce7e326c524a07853ccd68010 100644 (file)
@@ -31,4 +31,14 @@ public final class GridConstants implements Serializable {
      * explicitly defined padding value.
      */
     public static final int DEFAULT_PADDING = 0;
+
+    /**
+     * Delay before a long tap action is triggered. Number in milliseconds.
+     */
+    public static final int LONG_TAP_DELAY = 500;
+
+    /**
+     * The threshold in pixels a finger can move while long tapping.
+     */
+    public static final int LONG_TAP_THRESHOLD = 3;
 }