summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorHenrik Paul <henrik@vaadin.com>2015-02-17 11:51:11 +0200
committerHenrik Paul <henrik@vaadin.com>2015-02-17 14:40:44 +0000
commitadd05e15fcd82d73f4c46245dbe6d0999437cdec (patch)
tree861a19b9a37fe0da141950450917451bb487d061 /client
parentf5f699e61cd42f5c4ff1bc9b63ec2db8d446e316 (diff)
downloadvaadin-framework-add05e15fcd82d73f4c46245dbe6d0999437cdec.tar.gz
vaadin-framework-add05e15fcd82d73f4c46245dbe6d0999437cdec.zip
Modifies GridElement to support details (#16644)
Grid's SubPartAware logic was refactored, splitting it into both Grid and Escalator. Also adds tests for grid details rows. Change-Id: I4876a8a9a397eea35526e15f7e447c69b0d96983
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/widgets/Escalator.java240
-rw-r--r--client/src/com/vaadin/client/widgets/Grid.java169
2 files changed, 286 insertions, 123 deletions
diff --git a/client/src/com/vaadin/client/widgets/Escalator.java b/client/src/com/vaadin/client/widgets/Escalator.java
index 6c6998277f..567262c6b2 100644
--- a/client/src/com/vaadin/client/widgets/Escalator.java
+++ b/client/src/com/vaadin/client/widgets/Escalator.java
@@ -16,6 +16,7 @@
package com.vaadin.client.widgets;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
@@ -57,6 +58,7 @@ import com.vaadin.client.BrowserInfo;
import com.vaadin.client.DeferredWorker;
import com.vaadin.client.Profiler;
import com.vaadin.client.WidgetUtil;
+import com.vaadin.client.ui.SubPartAware;
import com.vaadin.client.widget.escalator.Cell;
import com.vaadin.client.widget.escalator.ColumnConfiguration;
import com.vaadin.client.widget.escalator.EscalatorUpdater;
@@ -267,7 +269,8 @@ abstract class JsniWorkaround {
* @since 7.4
* @author Vaadin Ltd
*/
-public class Escalator extends Widget implements RequiresResize, DeferredWorker {
+public class Escalator extends Widget implements RequiresResize,
+ DeferredWorker, SubPartAware {
// todo comments legend
/*
@@ -4319,6 +4322,26 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
assert getElement().isOrHasChild(spacer.getRootElement()) : "Spacer's root element somehow got detached from Escalator during attaching";
assert getElement().isOrHasChild(spacer.getElement()) : "Spacer element somehow got detached from Escalator during attaching";
}
+
+ public String getSubPartName(Element subElement) {
+ for (SpacerImpl spacer : rowIndexToSpacer.values()) {
+ if (spacer.getRootElement().isOrHasChild(subElement)) {
+ return "spacer[" + spacer.getRow() + "]";
+ }
+ }
+ return null;
+ }
+
+ public Element getSubPartElement(int index) {
+ getLogger().warning("SpacerContainer.getSubPartElement " + index);
+
+ SpacerImpl spacer = rowIndexToSpacer.get(Integer.valueOf(index));
+ if (spacer != null) {
+ return spacer.getElement();
+ } else {
+ return null;
+ }
+ }
}
private class ElementPositionBookkeeper {
@@ -4347,6 +4370,50 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
}
}
+ public static class SubPartArguments {
+ private String type;
+ private int[] indices;
+
+ private SubPartArguments(String type, int[] indices) {
+ /*
+ * The constructor is private so that no third party would by
+ * mistake start using this parsing scheme, since it's not official
+ * by TestBench (yet?).
+ */
+
+ this.type = type;
+ this.indices = indices;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public int getIndicesLength() {
+ return indices.length;
+ }
+
+ public int getIndex(int i) {
+ return indices[i];
+ }
+
+ public int[] getIndices() {
+ return Arrays.copyOf(indices, indices.length);
+ }
+
+ static SubPartArguments create(String subPart) {
+ 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));
+ }
+ return new SubPartArguments(type, indices);
+ }
+ }
+
// abs(atan(y/x))*(180/PI) = n deg, x = 1, solve y
/**
* The solution to
@@ -5295,4 +5362,175 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
int to = (int) Math.ceil(body.heightOfSection);
return Range.between(from, to);
}
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public com.google.gwt.user.client.Element getSubPartElement(String subPart) {
+ SubPartArguments args = parseSubPartArguments(subPart);
+
+ Element tableStructureElement = getSubPartElementTableStructure(args);
+ if (tableStructureElement != null) {
+ return DOM.asOld(tableStructureElement);
+ }
+
+ Element spacerElement = getSubPartElementSpacer(args);
+ if (spacerElement != null) {
+ return DOM.asOld(spacerElement);
+ }
+
+ return null;
+ }
+
+ private Element getSubPartElementTableStructure(SubPartArguments args) {
+
+ String type = args.getType();
+ int[] indices = args.getIndices();
+
+ // Get correct RowContainer for type from Escalator
+ RowContainer container = null;
+ if (type.equalsIgnoreCase("header")) {
+ container = getHeader();
+ } else if (type.equalsIgnoreCase("cell")) {
+ // If wanted row is not visible, we need to scroll there.
+ Range visibleRowRange = getVisibleRowRange();
+ if (indices.length > 0 && !visibleRowRange.contains(indices[0])) {
+ try {
+ scrollToRow(indices[0], ScrollDestination.ANY, 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 = getBody();
+ } else if (type.equalsIgnoreCase("footer")) {
+ container = getFooter();
+ }
+
+ if (null != container) {
+ if (indices.length == 0) {
+ // No indexing. Just return the wanted container element
+ return container.getElement();
+ } else {
+ try {
+ return getSubPart(container, indices);
+ } catch (Exception e) {
+ getLogger().log(Level.SEVERE, e.getMessage());
+ }
+ }
+ }
+ return null;
+ }
+
+ private Element getSubPart(RowContainer container, int[] indices) {
+ Element targetElement = container.getRowElement(indices[0]);
+
+ // Scroll wanted column to view if able
+ if (indices.length > 1 && targetElement != null) {
+ if (getColumnConfiguration().getFrozenColumnCount() <= indices[1]) {
+ scrollToColumn(indices[1], ScrollDestination.ANY, 0);
+ }
+
+ targetElement = getCellFromRow(TableRowElement.as(targetElement),
+ indices[1]);
+
+ for (int i = 2; i < indices.length && targetElement != null; ++i) {
+ targetElement = (Element) targetElement.getChild(indices[i]);
+ }
+ }
+
+ return targetElement;
+ }
+
+ private static Element getCellFromRow(TableRowElement rowElement, int index) {
+ int childCount = rowElement.getCells().getLength();
+ if (index < 0 || index >= childCount) {
+ return null;
+ }
+
+ TableCellElement currentCell = null;
+ boolean indexInColspan = false;
+ int i = 0;
+
+ while (!indexInColspan) {
+ currentCell = rowElement.getCells().getItem(i);
+
+ // Calculate if this is the cell we are looking for
+ int colSpan = currentCell.getColSpan();
+ indexInColspan = index < colSpan + i;
+
+ // Increment by colspan to skip over hidden cells
+ i += colSpan;
+ }
+ return currentCell;
+ }
+
+ private Element getSubPartElementSpacer(SubPartArguments args) {
+ if ("spacer".equals(args.getType()) && args.getIndicesLength() == 1) {
+ return body.spacerContainer.getSubPartElement(args.getIndex(0));
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public String getSubPartName(com.google.gwt.user.client.Element subElement) {
+
+ /*
+ * The spacer check needs to be before table structure check, because
+ * (for now) the table structure will take spacer elements into account
+ * as well, when it shouldn't.
+ */
+
+ String spacer = getSubPartNameSpacer(subElement);
+ if (spacer != null) {
+ return spacer;
+ }
+
+ String tableStructure = getSubPartNameTableStructure(subElement);
+ if (tableStructure != null) {
+ return tableStructure;
+ }
+
+ return null;
+ }
+
+ private String getSubPartNameTableStructure(Element subElement) {
+
+ List<RowContainer> containers = Arrays.asList(getHeader(), getBody(),
+ 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 = 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;
+ }
+
+ private String getSubPartNameSpacer(Element subElement) {
+ return body.spacerContainer.getSubPartName(subElement);
+ }
+
+ public static SubPartArguments parseSubPartArguments(String subPart) {
+ return SubPartArguments.create(subPart);
+ }
}
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java
index 31984f7d5b..7890b13904 100644
--- a/client/src/com/vaadin/client/widgets/Grid.java
+++ b/client/src/com/vaadin/client/widgets/Grid.java
@@ -130,6 +130,7 @@ import com.vaadin.client.widget.grid.sort.SortEvent;
import com.vaadin.client.widget.grid.sort.SortHandler;
import com.vaadin.client.widget.grid.sort.SortOrder;
import com.vaadin.client.widgets.Escalator.AbstractRowContainer;
+import com.vaadin.client.widgets.Escalator.SubPartArguments;
import com.vaadin.client.widgets.Grid.Editor.State;
import com.vaadin.shared.data.sort.SortDirection;
import com.vaadin.shared.ui.grid.GridConstants;
@@ -5250,153 +5251,77 @@ public class Grid<T> extends ResizeComposite implements
}
@Override
+ @SuppressWarnings("deprecation")
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 (indices.length > 0 && !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();
- } else if (type.equalsIgnoreCase("editor")) {
- if (editor.getState() != State.ACTIVE) {
- // Editor is not there.
- return null;
- }
- if (indices.length == 0) {
- return DOM.asOld(editor.editorOverlay);
- } else if (indices.length == 1 && indices[0] < columns.size()) {
- escalator.scrollToColumn(indices[0], ScrollDestination.ANY, 0);
- return editor.getWidget(columns.get(indices[0])).getElement();
- } else {
- return null;
- }
+ Element subPartElement = escalator.getSubPartElement(subPart
+ .replaceFirst("^details\\[", "spacer["));
+ if (subPartElement != null) {
+ return DOM.asOld(subPartElement);
}
- 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());
- }
- }
+ SubPartArguments args = Escalator.parseSubPartArguments(subPart);
+
+ Element editor = getSubPartElementEditor(args);
+ if (editor != null) {
+ return DOM.asOld(editor);
}
+
return null;
}
- private Element getSubPart(RowContainer container, int[] indices) {
- Element targetElement = container.getRowElement(indices[0]);
-
- // Scroll wanted column to view if able
- if (indices.length > 1 && targetElement != null) {
- if (escalator.getColumnConfiguration().getFrozenColumnCount() <= indices[1]) {
- escalator.scrollToColumn(indices[1], ScrollDestination.ANY, 0);
- }
+ private Element getSubPartElementEditor(SubPartArguments args) {
- targetElement = getCellFromRow(TableRowElement.as(targetElement),
- indices[1]);
-
- for (int i = 2; i < indices.length && targetElement != null; ++i) {
- targetElement = (Element) targetElement.getChild(indices[i]);
- }
+ if (!args.getType().equalsIgnoreCase("editor")
+ || editor.getState() != State.ACTIVE) {
+ return null;
}
- return targetElement;
- }
-
- private Element getCellFromRow(TableRowElement rowElement, int index) {
- int childCount = rowElement.getCells().getLength();
- if (index < 0 || index >= childCount) {
- return null;
+ if (args.getIndicesLength() == 0) {
+ return editor.editorOverlay;
+ } else if (args.getIndicesLength() == 1
+ && args.getIndex(0) < columns.size()) {
+ escalator
+ .scrollToColumn(args.getIndex(0), ScrollDestination.ANY, 0);
+ return editor.getWidget(columns.get(args.getIndex(0))).getElement();
}
- TableCellElement currentCell = null;
- boolean indexInColspan = false;
- int i = 0;
+ return null;
+ }
- while (!indexInColspan) {
- currentCell = rowElement.getCells().getItem(i);
+ @Override
+ @SuppressWarnings("deprecation")
+ public String getSubPartName(com.google.gwt.user.client.Element subElement) {
- // Calculate if this is the cell we are looking for
- int colSpan = currentCell.getColSpan();
- indexInColspan = index < colSpan + i;
+ String escalatorStructureName = escalator.getSubPartName(subElement);
+ if (escalatorStructureName != null) {
+ return escalatorStructureName.replaceFirst("^spacer", "details");
+ }
- // Increment by colspan to skip over hidden cells
- i += colSpan;
+ String editorName = getSubPartNameEditor(subElement);
+ if (editorName != null) {
+ return editorName;
}
- return currentCell;
- }
- @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");
+ return null;
+ }
- 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());
- }
+ private String getSubPartNameEditor(Element subElement) {
- 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() + "]");
- }
+ if (editor.getState() != State.ACTIVE
+ || !editor.editorOverlay.isOrHasChild(subElement)) {
+ return null;
}
- // Check if subelement is part of editor.
- if (editor.getState() == State.ACTIVE) {
- if (editor.editorOverlay.isOrHasChild(subElement)) {
- int i = 0;
- for (Column<?, T> column : columns) {
- if (editor.getWidget(column).getElement()
- .isOrHasChild(subElement)) {
- return "editor[" + i + "]";
- }
- ++i;
- }
- return "editor";
+ int i = 0;
+ for (Column<?, T> column : columns) {
+ if (editor.getWidget(column).getElement().isOrHasChild(subElement)) {
+ return "editor[" + i + "]";
}
+ ++i;
}
- return null;
+ return "editor";
}
private void setSelectColumnRenderer(