]> source.dussan.org Git - vaadin-framework.git/commitdiff
Add SubPartAware interface to Grid client side (#13334)
authorTeemu Suo-Anttila <teemusa@vaadin.com>
Wed, 28 May 2014 08:11:35 +0000 (11:11 +0300)
committerVaadin Code Review <review@vaadin.com>
Thu, 29 May 2014 11:38:56 +0000 (11:38 +0000)
Change-Id: I067f2a248a84076531b0b0b18b4e39c493db457f

client/src/com/vaadin/client/ui/grid/Escalator.java
client/src/com/vaadin/client/ui/grid/Grid.java
client/src/com/vaadin/client/ui/grid/RowContainer.java

index cc3ee55182c1fac90234f9fae9681847abaacd78..53c70bbb701a285edf5ac89d50eda9fb29944055 100644 (file)
@@ -1090,6 +1090,11 @@ public class Escalator extends Widget {
             root = rowContainerElement;
         }
 
+        @Override
+        public Element getElement() {
+            return root;
+        }
+
         /**
          * Gets the tag name of an element to represent a cell in a row.
          * <p>
@@ -1375,6 +1380,11 @@ public class Escalator extends Widget {
             return cellElem;
         }
 
+        @Override
+        public Element getRowElement(int index) {
+            return getTrByVisualIndex(index);
+        }
+
         /**
          * Gets the child element that is visually at a certain index
          * 
@@ -1384,7 +1394,7 @@ public class Escalator extends Widget {
          * @throws IndexOutOfBoundsException
          *             if {@code index} is not valid within {@link #root}
          */
-        abstract protected Element getTrByVisualIndex(int index)
+        protected abstract Element getTrByVisualIndex(int index)
                 throws IndexOutOfBoundsException;
 
         protected void paintRemoveColumns(final int offset,
@@ -3041,6 +3051,22 @@ public class Escalator extends Widget {
             }
         }
 
+        @Override
+        public Element getRowElement(int index) {
+            if (index < 0 || index >= getRowCount()) {
+                throw new IndexOutOfBoundsException("No such logical index: "
+                        + index);
+            }
+            int visualIndex = index
+                    - getLogicalRowIndex(visualRowOrder.getFirst());
+            if (visualIndex >= 0 && visualIndex < visualRowOrder.size()) {
+                return super.getRowElement(visualIndex);
+            } else {
+                throw new IllegalStateException("Row with logical index "
+                        + index + " is currently not available in the DOM");
+            }
+        }
+
         private void setBodyScrollPosition(final double scrollLeft,
                 final double scrollTop) {
             tBodyScrollLeft = scrollLeft;
@@ -4215,7 +4241,6 @@ public class Escalator extends Widget {
                     .getLast()) + 1;
 
             int visibleRowCount = visibleRangeEnd - visibleRangeStart;
-
             fireEvent(new RowVisibilityChangeEvent(visibleRangeStart,
                     visibleRowCount));
         } else {
@@ -4223,6 +4248,17 @@ public class Escalator extends Widget {
         }
     }
 
+    /**
+     * Gets the range of currently visible rows
+     * 
+     * @return range of visible rows
+     */
+    public Range getVisibleRowRange() {
+        return Range.between(
+                body.getLogicalRowIndex(body.visualRowOrder.getFirst()),
+                body.getLogicalRowIndex(body.visualRowOrder.getLast()) + 1);
+    }
+
     /**
      * Accesses the package private method Widget#setParent()
      * 
index 25186ae80a3e69f0b0e98f19855be1f3c6ca7732..c5eb76c6ad273004c32a6be84873e59b3d3fdf8b 100644 (file)
 package com.vaadin.client.ui.grid;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import com.google.gwt.core.shared.GWT;
@@ -28,15 +30,18 @@ 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.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.HasVisibility;
 import com.vaadin.client.data.DataChangeHandler;
 import com.vaadin.client.data.DataSource;
+import com.vaadin.client.ui.SubPartAware;
 import com.vaadin.client.ui.grid.renderers.ComplexRenderer;
 import com.vaadin.client.ui.grid.renderers.TextRenderer;
 import com.vaadin.shared.ui.grid.GridConstants;
 import com.vaadin.shared.ui.grid.HeightMode;
+import com.vaadin.shared.ui.grid.Range;
 import com.vaadin.shared.ui.grid.ScrollDestination;
 import com.vaadin.shared.util.SharedUtil;
 
@@ -72,7 +77,7 @@ import com.vaadin.shared.util.SharedUtil;
  * @since 7.4
  * @author Vaadin Ltd
  */
-public class Grid<T> extends Composite {
+public class Grid<T> extends Composite implements SubPartAware {
 
     /**
      * Escalator used internally by grid to render the rows
@@ -1485,4 +1490,95 @@ public class Grid<T> extends Composite {
             }
         }
     }
+
+    @Override
+    public com.google.gwt.user.client.Element getSubPartElement(String subPart) {
+        // Parse SubPart string to type and indices
+        String[] splitArgs = subPart.split("\\[");
+
+        String type = splitArgs[0];
+        int[] indices = new int[splitArgs.length - 1];
+        for (int i = 0; i < indices.length; ++i) {
+            String tmp = splitArgs[i + 1];
+            indices[i] = Integer.parseInt(tmp.substring(0, tmp.length() - 1));
+        }
+
+        // Get correct RowContainer for type from Escalator
+        RowContainer container = null;
+        if (type.equalsIgnoreCase("header")) {
+            container = escalator.getHeader();
+        } else if (type.equalsIgnoreCase("cell")) {
+            // If wanted row is not visible, we need to scroll there.
+            Range visibleRowRange = escalator.getVisibleRowRange();
+            if (!visibleRowRange.contains(indices[0])) {
+                try {
+                    scrollToRow(indices[0]);
+                } catch (IllegalArgumentException e) {
+                    getLogger().log(Level.SEVERE, e.getMessage());
+                }
+                // Scrolling causes a lazy loading event. No element can
+                // currently be retrieved.
+                return null;
+            }
+            container = escalator.getBody();
+        } else if (type.equalsIgnoreCase("footer")) {
+            container = escalator.getFooter();
+        }
+
+        if (null != container) {
+            if (indices.length == 0) {
+                // No indexing. Just return the wanted container element
+                return DOM.asOld(container.getElement());
+            } else {
+                try {
+                    return DOM.asOld(getSubPart(container, indices));
+                } catch (Exception e) {
+                    getLogger().log(Level.SEVERE, e.getMessage());
+                }
+            }
+        }
+        return null;
+    }
+
+    private Element getSubPart(RowContainer container, int[] indices) {
+        // Scroll wanted column to view if able
+        if (indices.length > 1
+                && escalator.getColumnConfiguration().getFrozenColumnCount() <= indices[1]) {
+            escalator.scrollToColumn(indices[1], ScrollDestination.ANY, 0);
+        }
+
+        Element targetElement = container.getRowElement(indices[0]);
+        for (int i = 1; i < indices.length && targetElement != null; ++i) {
+            targetElement = (Element) targetElement.getChild(indices[i]);
+        }
+        return targetElement;
+    }
+
+    @Override
+    public String getSubPartName(com.google.gwt.user.client.Element subElement) {
+        // Containers and matching SubPart types
+        List<RowContainer> containers = Arrays.asList(escalator.getHeader(),
+                escalator.getBody(), escalator.getFooter());
+        List<String> containerType = Arrays.asList("header", "cell", "footer");
+
+        for (int i = 0; i < containers.size(); ++i) {
+            RowContainer container = containers.get(i);
+            boolean containerRow = (subElement.getTagName().equalsIgnoreCase(
+                    "tr") && subElement.getParentElement() == container
+                    .getElement());
+            if (containerRow) {
+                // Wanted SubPart is row that is a child of containers root
+                // To get indices, we use a cell that is a child of this row
+                subElement = DOM.asOld(subElement.getFirstChildElement());
+            }
+
+            Cell cell = container.getCell(subElement);
+            if (cell != null) {
+                // Skip the column index if subElement was a child of root
+                return containerType.get(i) + "[" + cell.getRow()
+                        + (containerRow ? "]" : "][" + cell.getColumn() + "]");
+            }
+        }
+        return null;
+    }
 }
index 9cf5d0274213150e6dc020096fc5b45d1ccee4e6..b0b580d6651a2cc8c60a976dce93726770803c5c 100644 (file)
@@ -169,4 +169,26 @@ public interface RowContainer {
      */
     public Cell getCell(Element element);
 
+    /**
+     * Gets the row element with given logical index. For lazy loaded containers
+     * such as Escalators BodyRowContainer visibility should be checked before
+     * calling this function. See {@link Escalator#getVisibleRowRange()}.
+     * 
+     * @param index
+     *            the logical index of the element to retrieve
+     * @return the element at position {@code index}
+     * @throws IndexOutOfBoundsException
+     *             if {@code index} is not valid within container
+     * @throws IllegalStateException
+     *             if {@code index} is currently not available in the DOM
+     */
+    public Element getRowElement(int index) throws IndexOutOfBoundsException,
+            IllegalStateException;
+
+    /**
+     * Returns the root element of RowContainer
+     * 
+     * @return RowContainer root element
+     */
+    public Element getElement();
 }