summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorHenrik Paul <henrik@vaadin.com>2015-02-12 15:04:31 +0200
committerHenrik Paul <henrik@vaadin.com>2015-02-16 12:21:10 +0200
commitc72967ba77c2bc0fcc56df499f5a75f6c7ca2c07 (patch)
tree3673d2ff8a082ed8b982676c73b57e5e2cb48a46 /client
parent556c1aa06c547933bc36f347693c4b5b85bac149 (diff)
downloadvaadin-framework-c72967ba77c2bc0fcc56df499f5a75f6c7ca2c07.tar.gz
vaadin-framework-c72967ba77c2bc0fcc56df499f5a75f6c7ca2c07.zip
Adds SpacerUpdater support for Escalator (#16644)
Change-Id: I9d73a3fc36e94e36c35859a4ae456002c75df2f5
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/widget/escalator/EscalatorUpdater.java2
-rw-r--r--client/src/com/vaadin/client/widget/escalator/Row.java1
-rw-r--r--client/src/com/vaadin/client/widget/escalator/RowContainer.java27
-rw-r--r--client/src/com/vaadin/client/widget/escalator/Spacer.java41
-rw-r--r--client/src/com/vaadin/client/widget/escalator/SpacerUpdater.java62
-rw-r--r--client/src/com/vaadin/client/widgets/Escalator.java190
6 files changed, 233 insertions, 90 deletions
diff --git a/client/src/com/vaadin/client/widget/escalator/EscalatorUpdater.java b/client/src/com/vaadin/client/widget/escalator/EscalatorUpdater.java
index 6109c5e51d..54507a7650 100644
--- a/client/src/com/vaadin/client/widget/escalator/EscalatorUpdater.java
+++ b/client/src/com/vaadin/client/widget/escalator/EscalatorUpdater.java
@@ -16,8 +16,6 @@
package com.vaadin.client.widget.escalator;
-import com.vaadin.client.widgets.Escalator;
-
/**
* An interface that allows client code to define how a certain row in Escalator
* will be displayed. The contents of an escalator's header, body and footer are
diff --git a/client/src/com/vaadin/client/widget/escalator/Row.java b/client/src/com/vaadin/client/widget/escalator/Row.java
index bcb3e163e4..fa89853120 100644
--- a/client/src/com/vaadin/client/widget/escalator/Row.java
+++ b/client/src/com/vaadin/client/widget/escalator/Row.java
@@ -17,7 +17,6 @@
package com.vaadin.client.widget.escalator;
import com.google.gwt.dom.client.TableRowElement;
-import com.vaadin.client.widgets.Escalator;
/**
* A representation of a row in an {@link Escalator}.
diff --git a/client/src/com/vaadin/client/widget/escalator/RowContainer.java b/client/src/com/vaadin/client/widget/escalator/RowContainer.java
index 5cc58cb47e..ea56c25062 100644
--- a/client/src/com/vaadin/client/widget/escalator/RowContainer.java
+++ b/client/src/com/vaadin/client/widget/escalator/RowContainer.java
@@ -44,6 +44,7 @@ public interface RowContainer {
* @see com.vaadin.client.widgets.Escalator#getBody()
*/
public interface BodyRowContainer extends RowContainer {
+
/**
* Marks a spacer and its height.
* <p>
@@ -61,6 +62,32 @@ public interface RowContainer {
*/
void setSpacer(int rowIndex, double height)
throws IllegalArgumentException;
+
+ /**
+ * Sets a new spacer updater.
+ * <p>
+ * Spacers that are currently visible will be updated, i.e.
+ * {@link SpacerUpdater#destroy(Spacer) destroyed} with the previous
+ * one, and {@link SpacerUpdater#init(Spacer) initialized} with the new
+ * one.
+ *
+ * @param spacerUpdater
+ * the new spacer updater
+ * @throws IllegalArgumentException
+ * if {@code spacerUpdater} is {@code null}
+ */
+ void setSpacerUpdater(SpacerUpdater spacerUpdater)
+ throws IllegalArgumentException;
+
+ /**
+ * Gets the spacer updater currently in use.
+ * <p>
+ * {@link SpacerUpdater#NULL} is the default.
+ *
+ * @return the spacer updater currently in use. Never <code>null</code>
+ */
+ SpacerUpdater getSpacerUpdater();
+
}
/**
diff --git a/client/src/com/vaadin/client/widget/escalator/Spacer.java b/client/src/com/vaadin/client/widget/escalator/Spacer.java
new file mode 100644
index 0000000000..0b0a2b257f
--- /dev/null
+++ b/client/src/com/vaadin/client/widget/escalator/Spacer.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.widget.escalator;
+
+import com.google.gwt.dom.client.Element;
+
+/**
+ * A representation of a spacer element in a {@link SpacerContainer}.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface Spacer {
+
+ /**
+ * Gets the root element for the spacer content.
+ *
+ * @return the root element for the spacer content
+ */
+ Element getElement();
+
+ /**
+ * Gets the row index.
+ *
+ * @return the row index.
+ */
+ int getRow();
+}
diff --git a/client/src/com/vaadin/client/widget/escalator/SpacerUpdater.java b/client/src/com/vaadin/client/widget/escalator/SpacerUpdater.java
new file mode 100644
index 0000000000..18f53db507
--- /dev/null
+++ b/client/src/com/vaadin/client/widget/escalator/SpacerUpdater.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.widget.escalator;
+
+/**
+ * An interface that handles the display of content for spacers.
+ * <p>
+ * The updater is responsible for making sure all elements are properly
+ * constructed and cleaned up.
+ *
+ * @since
+ * @author Vaadin Ltd
+ * @see Spacer
+ * @see SpacerContainer
+ */
+public interface SpacerUpdater {
+
+ /** A spacer updater that does nothing. */
+ public static final SpacerUpdater NULL = new SpacerUpdater() {
+ @Override
+ public void init(Spacer spacer) {
+ // NOOP
+ }
+
+ @Override
+ public void destroy(Spacer spacer) {
+ // NOOP
+ }
+ };
+
+ /**
+ * Called whenever a spacer should be initialized with content.
+ *
+ * @param spacer
+ * the spacer reference that should be initialized
+ */
+ void init(Spacer spacer);
+
+ /**
+ * Called whenever a spacer should be cleaned.
+ * <p>
+ * The structure to clean up is the same that has been constructed by
+ * {@link #init(Spacer)}.
+ *
+ * @param spacer
+ * the spacer reference that should be destroyed
+ */
+ void destroy(Spacer spacer);
+}
diff --git a/client/src/com/vaadin/client/widgets/Escalator.java b/client/src/com/vaadin/client/widgets/Escalator.java
index 2536356c94..6c6998277f 100644
--- a/client/src/com/vaadin/client/widgets/Escalator.java
+++ b/client/src/com/vaadin/client/widgets/Escalator.java
@@ -74,6 +74,8 @@ import com.vaadin.client.widget.escalator.RowVisibilityChangeHandler;
import com.vaadin.client.widget.escalator.ScrollbarBundle;
import com.vaadin.client.widget.escalator.ScrollbarBundle.HorizontalScrollbarBundle;
import com.vaadin.client.widget.escalator.ScrollbarBundle.VerticalScrollbarBundle;
+import com.vaadin.client.widget.escalator.Spacer;
+import com.vaadin.client.widget.escalator.SpacerUpdater;
import com.vaadin.client.widget.grid.events.ScrollEvent;
import com.vaadin.client.widget.grid.events.ScrollHandler;
import com.vaadin.client.widgets.Escalator.JsniUtil.TouchHandlerBundle;
@@ -3636,6 +3638,17 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
throws IllegalArgumentException {
spacerContainer.setSpacer(rowIndex, height);
}
+
+ @Override
+ public void setSpacerUpdater(SpacerUpdater spacerUpdater)
+ throws IllegalArgumentException {
+ spacerContainer.setSpacerUpdater(spacerUpdater);
+ }
+
+ @Override
+ public SpacerUpdater getSpacerUpdater() {
+ return spacerContainer.getSpacerUpdater();
+ }
}
private class ColumnConfigurationImpl implements ColumnConfiguration {
@@ -4116,41 +4129,21 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
/** This is used mainly for testing purposes */
private static final String SPACER_LOGICAL_ROW_PROPERTY = "vLogicalRow";
- /*
- * TODO [[optimize]] maybe convert the usage of this class to flyweight
- * or object pooling pattern?
- */
- private final class Spacer {
+ private final class SpacerImpl implements Spacer {
private TableCellElement spacerElement;
private TableRowElement root;
+ private final int rowIndex;
- public TableRowElement getRootElement() {
- return root;
- }
-
- public void setPosition(double x, double y) {
- positions.set(root, x, y);
- }
-
- /**
- * Creates a new element structure for the spacer.
- * <p>
- * {@link #createDomStructure()} and
- * {@link #setRootElement(Element)} can collectively only be called
- * once, otherwise an {@link AssertionError} will be raised (if
- * asserts are enabled).
- */
- public void createDomStructure(double height) {
- assert root == null || root.getParentElement() == null : "this spacer was already attached";
+ public SpacerImpl(int rowIndex, double height) {
+ this.rowIndex = rowIndex;
+ // Build DOM structure
root = TableRowElement.as(DOM.createTR());
spacerElement = TableCellElement.as(DOM.createTD());
root.appendChild(spacerElement);
- spacerElement.setInnerText("IAMA SPACER, AMA");
- initElements(height);
- }
+ root.setPropertyInt(SPACER_LOGICAL_ROW_PROPERTY, rowIndex);
- private void initElements(double height) {
+ // Configure DOM structure
setHeight(height);
root.getStyle().setWidth(100, Unit.PCT);
@@ -4161,15 +4154,12 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
setStylePrimaryName(getStylePrimaryName());
}
- public void setRootElement(TableRowElement tr) {
- assert root == null || root.getParentElement() == null : "this spacer was already attached";
-
- assert tr != null : "tr may not be null";
- root = tr;
+ public TableRowElement getRootElement() {
+ return root;
+ }
- assert tr.getChildCount() == 1 : "tr must have exactly one child";
- spacerElement = tr.getCells().getItem(0);
- assert spacerElement != null : "spacer element somehow was null";
+ public void setPosition(double x, double y) {
+ positions.set(root, x, y);
}
public void setStylePrimaryName(String style) {
@@ -4182,10 +4172,20 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
"spacer's height changed, but pushing rows out of "
+ "the way not implemented yet");
}
+
+ @Override
+ public Element getElement() {
+ return spacerElement;
+ }
+
+ @Override
+ public int getRow() {
+ return rowIndex;
+ }
}
- private final TreeMap<Integer, Double> rowIndexToHeight = new TreeMap<Integer, Double>();
- private final TreeMap<Integer, TableRowElement> rowIndexToSpacerElement = new TreeMap<Integer, TableRowElement>();
+ private final TreeMap<Integer, SpacerImpl> rowIndexToSpacer = new TreeMap<Integer, SpacerImpl>();
+ private SpacerUpdater spacerUpdater = SpacerUpdater.NULL;
public void setSpacer(int rowIndex, double height)
throws IllegalArgumentException {
@@ -4196,65 +4196,42 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
}
if (height >= 0) {
- insertOrUpdateSpacer(rowIndex, height);
+ if (!spacerExists(rowIndex)) {
+ insertNewSpacer(rowIndex, height);
+ } else {
+ updateExistingSpacer(rowIndex, height);
+ }
} else if (spacerExists(rowIndex)) {
removeSpacer(rowIndex);
}
}
- @SuppressWarnings("boxing")
- private void insertOrUpdateSpacer(int rowIndex, double height) {
- if (!spacerExists(rowIndex)) {
- insertSpacer(rowIndex, height);
- } else {
- updateSpacer(rowIndex, height);
- }
- rowIndexToHeight.put(rowIndex, height);
- }
-
private boolean spacerExists(int rowIndex) {
- Integer rowIndexObj = Integer.valueOf(rowIndex);
- boolean spacerExists = rowIndexToHeight.containsKey(rowIndexObj);
- assert spacerExists == rowIndexToSpacerElement
- .containsKey(rowIndexObj) : "Inconsistent bookkeeping detected.";
- return spacerExists;
+ return rowIndexToSpacer.containsKey(Integer.valueOf(rowIndex));
}
@SuppressWarnings("boxing")
- private void insertSpacer(int rowIndex, double height) {
- Spacer spacer = createSpacer(height);
- spacer.getRootElement().setPropertyInt(SPACER_LOGICAL_ROW_PROPERTY,
- rowIndex);
- TableRowElement spacerRoot = spacer.getRootElement();
- rowIndexToSpacerElement.put(rowIndex, spacerRoot);
+ private void insertNewSpacer(int rowIndex, double height) {
+
+ SpacerImpl spacer = new SpacerImpl(rowIndex, height);
+
+ rowIndexToSpacer.put(rowIndex, spacer);
spacer.setPosition(0, getSpacerTop(rowIndex));
+
+ TableRowElement spacerRoot = spacer.getRootElement();
spacerRoot.getStyle().setWidth(
columnConfiguration.calculateRowWidth(), Unit.PX);
body.getElement().appendChild(spacerRoot);
+
+ initSpacerContent(spacer);
}
- private void updateSpacer(int rowIndex, double newHeight) {
+ private void updateExistingSpacer(int rowIndex, double newHeight) {
getSpacer(rowIndex).setHeight(newHeight);
}
- @SuppressWarnings("boxing")
- private Spacer getSpacer(int rowIndex) {
- Spacer spacer = new Spacer();
- spacer.setRootElement(rowIndexToSpacerElement.get(rowIndex));
- return spacer;
- }
-
- private Spacer createSpacer(double height) {
- /*
- * Optimally, this would be a factory method in SpacerImpl, but
- * since it's not a static class, we can't do that directly. We
- * could make it static, and pass in references, but that probably
- * will become hairy pretty quickly.
- */
-
- Spacer spacer = new Spacer();
- spacer.createDomStructure(height);
- return spacer;
+ private SpacerImpl getSpacer(int rowIndex) {
+ return rowIndexToSpacer.get(Integer.valueOf(rowIndex));
}
private double getSpacerTop(int rowIndex) {
@@ -4282,32 +4259,71 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
@SuppressWarnings("boxing")
private void removeSpacer(int rowIndex) {
- Spacer spacer = getSpacer(rowIndex);
+ SpacerImpl spacer = getSpacer(rowIndex);
// fix DOM
+ destroySpacerContent(spacer);
spacer.setHeight(0); // resets row offsets
spacer.getRootElement().removeFromParent();
// fix bookkeeping
- rowIndexToHeight.remove(rowIndex);
- rowIndexToSpacerElement.remove(rowIndex);
+ rowIndexToSpacer.remove(rowIndex);
}
public void setStylePrimaryName(String style) {
- for (TableRowElement spacerRoot : rowIndexToSpacerElement.values()) {
- Spacer spacer = new Spacer();
- spacer.setRootElement(spacerRoot);
+ for (SpacerImpl spacer : rowIndexToSpacer.values()) {
spacer.setStylePrimaryName(style);
}
}
+
+ public void setSpacerUpdater(SpacerUpdater spacerUpdater)
+ throws IllegalArgumentException {
+ if (spacerUpdater == null) {
+ throw new IllegalArgumentException(
+ "spacer updater cannot be null");
+ }
+
+ destroySpacerContent(rowIndexToSpacer.values());
+ this.spacerUpdater = spacerUpdater;
+ initSpacerContent(rowIndexToSpacer.values());
+ }
+
+ public SpacerUpdater getSpacerUpdater() {
+ return spacerUpdater;
+ }
+
+ private void destroySpacerContent(Iterable<SpacerImpl> spacers) {
+ for (SpacerImpl spacer : spacers) {
+ destroySpacerContent(spacer);
+ }
+ }
+
+ private void destroySpacerContent(SpacerImpl spacer) {
+ assert getElement().isOrHasChild(spacer.getRootElement()) : "Spacer's root element somehow got detached from Escalator before detaching";
+ assert getElement().isOrHasChild(spacer.getElement()) : "Spacer element somehow got detached from Escalator before detaching";
+ spacerUpdater.destroy(spacer);
+ assert getElement().isOrHasChild(spacer.getRootElement()) : "Spacer's root element somehow got detached from Escalator before detaching";
+ assert getElement().isOrHasChild(spacer.getElement()) : "Spacer element somehow got detached from Escalator before detaching";
+ }
+
+ private void initSpacerContent(Iterable<SpacerImpl> spacers) {
+ for (SpacerImpl spacer : spacers) {
+ initSpacerContent(spacer);
+ }
+ }
+
+ private void initSpacerContent(SpacerImpl spacer) {
+ assert getElement().isOrHasChild(spacer.getRootElement()) : "Spacer's root element somehow got detached from Escalator before attaching";
+ assert getElement().isOrHasChild(spacer.getElement()) : "Spacer element somehow got detached from Escalator before attaching";
+ spacerUpdater.init(spacer);
+ 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";
+ }
}
private class ElementPositionBookkeeper {
/**
* A map containing cached values of an element's current top position.
- * <p>
- * Don't use this field directly, because it will not take proper care
- * of all the bookkeeping required.
*/
private final Map<Element, Double> elementTopPositionMap = new HashMap<Element, Double>();