aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonatan Kronqvist <jonatan@vaadin.com>2013-09-09 15:52:23 +0300
committerJonatan Kronqvist <jonatan@vaadin.com>2013-09-16 10:01:42 +0300
commitdc14ea4ca1cec8a4fc1ac23c07151e11cd2ac72b (patch)
tree2b9d705fcd841d7aa1b3a6a01da674ed4e65c54d
parent72db2044ea2844c5c7a49a704a507f32af5755ed (diff)
downloadvaadin-framework-dc14ea4ca1cec8a4fc1ac23c07151e11cd2ac72b.tar.gz
vaadin-framework-dc14ea4ca1cec8a4fc1ac23c07151e11cd2ac72b.zip
Implemented SubPartAware in VScrollTable #12514
This allows for "//VScrollTable#row[n]/col[m]" -style locator strings. Change-Id: I65bea31ab0eaa59fcd5a566ea3d1a43465ef298f
-rw-r--r--client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java55
-rw-r--r--client/src/com/vaadin/client/ui/VScrollTable.java108
2 files changed, 151 insertions, 12 deletions
diff --git a/client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java b/client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java
index f597003b60..3516aa3e93 100644
--- a/client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java
+++ b/client/src/com/vaadin/client/componentlocator/VaadinFinderLocatorStrategy.java
@@ -28,6 +28,7 @@ import com.vaadin.client.metadata.NoDataException;
import com.vaadin.client.metadata.Property;
import com.vaadin.client.ui.AbstractConnector;
import com.vaadin.client.ui.AbstractHasComponentsConnector;
+import com.vaadin.client.ui.SubPartAware;
import com.vaadin.client.ui.VNotification;
import com.vaadin.shared.AbstractComponentState;
@@ -50,6 +51,7 @@ import com.vaadin.shared.AbstractComponentState;
*/
public class VaadinFinderLocatorStrategy implements LocatorStrategy {
+ private static final String SUBPART_SEPARATOR = "#";
private ComponentLocator componentLocator;
public VaadinFinderLocatorStrategy(ComponentLocator componentLocator) {
@@ -76,8 +78,8 @@ public class VaadinFinderLocatorStrategy implements LocatorStrategy {
if (path.startsWith("//VNotification")) {
return findNotificationByPath(path);
}
- return findElementByPath(path, componentLocator.getClient()
- .getUIConnector());
+ return getElementByPathStartingAtConnector(path, componentLocator
+ .getClient().getUIConnector());
}
/**
@@ -110,23 +112,54 @@ public class VaadinFinderLocatorStrategy implements LocatorStrategy {
*/
@Override
public Element getElementByPathStartingAt(String path, Element root) {
- return findElementByPath(path,
+ return getElementByPathStartingAtConnector(path,
Util.findPaintable(componentLocator.getClient(), root));
}
/**
- * Recursively finds an element identified by the provided path by
- * traversing the connector hierarchy starting from the {@code parent}
- * connector.
+ * Finds an element by the specified path, starting traversal of the
+ * connector hierarchy from the specified root.
+ *
+ * @param path
+ * the locator path
+ * @param root
+ * the root connector
+ * @return the element identified by path or null if not found.
+ */
+ private Element getElementByPathStartingAtConnector(String path,
+ ComponentConnector root) {
+ String[] pathComponents = path.split(SUBPART_SEPARATOR);
+ ComponentConnector connector = findConnectorByPath(pathComponents[0],
+ root);
+ if (connector != null) {
+ if (pathComponents.length > 1) {
+ // We have subparts
+ if (connector.getWidget() instanceof SubPartAware) {
+ return ((SubPartAware) connector.getWidget())
+ .getSubPartElement(pathComponents[1]);
+ } else {
+ return null;
+ }
+ }
+ return connector.getWidget().getElement();
+ }
+ return null;
+ }
+
+ /**
+ * Recursively finds a connector for the element identified by the provided
+ * path by traversing the connector hierarchy starting from the
+ * {@code parent} connector.
*
* @param path
* The path identifying an element.
* @param parent
* The connector to start traversing from.
- * @return The element identified by {@code path} or null if it no such
- * element could be found.
+ * @return The connector identified by {@code path} or null if it no such
+ * connector could be found.
*/
- private Element findElementByPath(String path, ComponentConnector parent) {
+ private ComponentConnector findConnectorByPath(String path,
+ ComponentConnector parent) {
boolean findRecursively = path.startsWith("//");
// Strip away the one or two slashes from the beginning of the path
path = path.substring(findRecursively ? 2 : 1);
@@ -138,9 +171,9 @@ public class VaadinFinderLocatorStrategy implements LocatorStrategy {
extractPredicateString(fragments[0]));
if (connector != null) {
if (fragments.length > 1) {
- return findElementByPath(fragments[1], connector);
+ return findConnectorByPath(fragments[1], connector);
} else {
- return connector.getWidget().getElement();
+ return connector;
}
}
return null;
diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java
index 3733ee204a..fe2e99a28f 100644
--- a/client/src/com/vaadin/client/ui/VScrollTable.java
+++ b/client/src/com/vaadin/client/ui/VScrollTable.java
@@ -61,6 +61,8 @@ import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.regexp.shared.MatchResult;
+import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
@@ -123,7 +125,7 @@ import com.vaadin.shared.ui.table.TableConstants;
*/
public class VScrollTable extends FlowPanel implements HasWidgets,
ScrollHandler, VHasDropHandler, FocusHandler, BlurHandler, Focusable,
- ActionOwner {
+ ActionOwner, SubPartAware {
public static final String STYLENAME = "v-table";
@@ -5031,6 +5033,20 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
}
+ public int indexOf(Widget row) {
+ int relIx = -1;
+ for (int ix = 0; ix < renderedRows.size(); ix++) {
+ if (renderedRows.get(ix) == row) {
+ relIx = ix;
+ break;
+ }
+ }
+ if (relIx >= 0) {
+ return this.firstRendered + relIx;
+ }
+ return -1;
+ }
+
public class VScrollTableRow extends Panel implements ActionOwner {
private static final int TOUCHSCROLL_TIMEOUT = 100;
@@ -7728,4 +7744,94 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
return this;
}
+ private static final String SUBPART_HEADER = "header";
+ private static final String SUBPART_FOOTER = "footer";
+ private static final String SUBPART_ROW = "row";
+ private static final String SUBPART_COL = "col";
+ /** Matches header[ix] - used for extracting the index of the targeted header cell */
+ private static final RegExp SUBPART_HEADER_REGEXP = RegExp
+ .compile(SUBPART_HEADER + "\\[(\\d+)\\]");
+ /** Matches footer[ix] - used for extracting the index of the targeted footer cell */
+ private static final RegExp SUBPART_FOOTER_REGEXP = RegExp
+ .compile(SUBPART_FOOTER + "\\[(\\d+)\\]");
+ /** Matches row[ix] - used for extracting the index of the targeted row */
+ private static final RegExp SUBPART_ROW_REGEXP = RegExp.compile(SUBPART_ROW
+ + "\\[(\\d+)]");
+ /** Matches col[ix] - used for extracting the index of the targeted column */
+ private static final RegExp SUBPART_ROW_COL_REGEXP = RegExp
+ .compile(SUBPART_ROW + "\\[(\\d+)\\]/" + SUBPART_COL + "\\[(\\d+)\\]");
+
+ @Override
+ public Element getSubPartElement(String subPart) {
+ if (SUBPART_ROW_COL_REGEXP.test(subPart)) {
+ MatchResult result = SUBPART_ROW_COL_REGEXP.exec(subPart);
+ int rowIx = Integer.valueOf(result.getGroup(1));
+ int colIx = Integer.valueOf(result.getGroup(2));
+ VScrollTableRow row = scrollBody.getRowByRowIndex(rowIx);
+ if (row != null) {
+ Element rowElement = row.getElement();
+ if (colIx < rowElement.getChildCount()) {
+ return rowElement.getChild(colIx).getFirstChild().cast();
+ }
+ }
+
+ } else if (SUBPART_ROW_REGEXP.test(subPart)) {
+ MatchResult result = SUBPART_ROW_REGEXP.exec(subPart);
+ int rowIx = Integer.valueOf(result.getGroup(1));
+ VScrollTableRow row = scrollBody.getRowByRowIndex(rowIx);
+ if (row != null) {
+ return row.getElement();
+ }
+
+ } else if (SUBPART_HEADER_REGEXP.test(subPart)) {
+ MatchResult result = SUBPART_HEADER_REGEXP.exec(subPart);
+ int headerIx = Integer.valueOf(result.getGroup(1));
+ HeaderCell headerCell = tHead.getHeaderCell(headerIx);
+ if (headerCell != null) {
+ return headerCell.getElement();
+ }
+
+ } else if (SUBPART_FOOTER_REGEXP.test(subPart)) {
+ MatchResult result = SUBPART_FOOTER_REGEXP.exec(subPart);
+ int footerIx = Integer.valueOf(result.getGroup(1));
+ FooterCell footerCell = tFoot.getFooterCell(footerIx);
+ if (footerCell != null) {
+ return footerCell.getElement();
+ }
+ }
+ // Nothing found.
+ return null;
+ }
+
+ @Override
+ public String getSubPartName(Element subElement) {
+ Widget widget = Util.findWidget(subElement, null);
+ if (widget instanceof HeaderCell) {
+ return SUBPART_HEADER + "[" + tHead.visibleCells.indexOf(widget)
+ + "]";
+ } else if (widget instanceof FooterCell) {
+ return SUBPART_FOOTER + "[" + tFoot.visibleCells.indexOf(widget)
+ + "]";
+ } else if (widget instanceof VScrollTableRow) {
+ // a cell in a row
+ VScrollTableRow row = (VScrollTableRow) widget;
+ int rowIx = scrollBody.indexOf(row);
+ if (rowIx >= 0) {
+ int colIx = -1;
+ for (int ix = 0; ix < row.getElement().getChildCount(); ix++) {
+ if (row.getElement().getChild(ix).isOrHasChild(subElement)) {
+ colIx = ix;
+ break;
+ }
+ }
+ if (colIx >= 0) {
+ return SUBPART_ROW + "[" + rowIx + "]/" + SUBPART_COL + "["
+ + colIx + "]";
+ }
+ return SUBPART_ROW + "[" + rowIx + "]";
+ }
+ }
+ // Nothing found.
+ return null;
+ }
}