aboutsummaryrefslogtreecommitdiffstats
path: root/src/com/vaadin/terminal/gwt/client/LayoutManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/vaadin/terminal/gwt/client/LayoutManager.java')
-rw-r--r--src/com/vaadin/terminal/gwt/client/LayoutManager.java1215
1 files changed, 0 insertions, 1215 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/LayoutManager.java b/src/com/vaadin/terminal/gwt/client/LayoutManager.java
deleted file mode 100644
index 74586a6def..0000000000
--- a/src/com/vaadin/terminal/gwt/client/LayoutManager.java
+++ /dev/null
@@ -1,1215 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import com.google.gwt.core.client.Duration;
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.Style;
-import com.google.gwt.dom.client.Style.Overflow;
-import com.google.gwt.user.client.Timer;
-import com.vaadin.terminal.gwt.client.MeasuredSize.MeasureResult;
-import com.vaadin.terminal.gwt.client.ui.ManagedLayout;
-import com.vaadin.terminal.gwt.client.ui.PostLayoutListener;
-import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout;
-import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeEvent;
-import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeListener;
-import com.vaadin.terminal.gwt.client.ui.layout.LayoutDependencyTree;
-import com.vaadin.terminal.gwt.client.ui.notification.VNotification;
-
-public class LayoutManager {
- private static final String LOOP_ABORT_MESSAGE = "Aborting layout after 100 passes. This would probably be an infinite loop.";
-
- private static final boolean debugLogging = false;
-
- private ApplicationConnection connection;
- private final Set<Element> measuredNonConnectorElements = new HashSet<Element>();
- private final MeasuredSize nullSize = new MeasuredSize();
-
- private LayoutDependencyTree currentDependencyTree;
-
- private final Collection<ManagedLayout> needsHorizontalLayout = new HashSet<ManagedLayout>();
- private final Collection<ManagedLayout> needsVerticalLayout = new HashSet<ManagedLayout>();
-
- private final Collection<ComponentConnector> needsMeasure = new HashSet<ComponentConnector>();
-
- private Collection<ComponentConnector> pendingOverflowFixes = new HashSet<ComponentConnector>();
-
- private final Map<Element, Collection<ElementResizeListener>> elementResizeListeners = new HashMap<Element, Collection<ElementResizeListener>>();
- private final Set<Element> listenersToFire = new HashSet<Element>();
-
- private boolean layoutPending = false;
- private Timer layoutTimer = new Timer() {
- @Override
- public void run() {
- cancel();
- layoutNow();
- }
- };
- private boolean everythingNeedsMeasure = false;
-
- public void setConnection(ApplicationConnection connection) {
- if (this.connection != null) {
- throw new RuntimeException(
- "LayoutManager connection can never be changed");
- }
- this.connection = connection;
- }
-
- /**
- * Gets the layout manager associated with the given
- * {@link ApplicationConnection}.
- *
- * @param connection
- * the application connection to get a layout manager for
- * @return the layout manager associated with the provided application
- * connection
- */
- public static LayoutManager get(ApplicationConnection connection) {
- return connection.getLayoutManager();
- }
-
- /**
- * Registers that a ManagedLayout is depending on the size of an Element.
- * This causes this layout manager to measure the element in the beginning
- * of every layout phase and call the appropriate layout method of the
- * managed layout if the size of the element has changed.
- *
- * @param owner
- * the ManagedLayout that depends on an element
- * @param element
- * the Element that should be measured
- */
- public void registerDependency(ManagedLayout owner, Element element) {
- MeasuredSize measuredSize = ensureMeasured(element);
- setNeedsLayout(owner);
- measuredSize.addDependent(owner.getConnectorId());
- }
-
- private MeasuredSize ensureMeasured(Element element) {
- MeasuredSize measuredSize = getMeasuredSize(element, null);
- if (measuredSize == null) {
- measuredSize = new MeasuredSize();
-
- if (ConnectorMap.get(connection).getConnector(element) == null) {
- measuredNonConnectorElements.add(element);
- }
- setMeasuredSize(element, measuredSize);
- }
- return measuredSize;
- }
-
- private boolean needsMeasure(Element e) {
- if (connection.getConnectorMap().getConnectorId(e) != null) {
- return true;
- } else if (elementResizeListeners.containsKey(e)) {
- return true;
- } else if (getMeasuredSize(e, nullSize).hasDependents()) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Assigns a measured size to an element. Method defined as protected to
- * allow separate implementation for IE8.
- *
- * @param element
- * the dom element to attach the measured size to
- * @param measuredSize
- * the measured size to attach to the element. If
- * <code>null</code>, any previous measured size is removed.
- */
- protected native void setMeasuredSize(Element element,
- MeasuredSize measuredSize)
- /*-{
- if (measuredSize) {
- element.vMeasuredSize = measuredSize;
- } else {
- delete element.vMeasuredSize;
- }
- }-*/;
-
- /**
- * Gets the measured size for an element. Method defined as protected to
- * allow separate implementation for IE8.
- *
- * @param element
- * The element to get measured size for
- * @param defaultSize
- * The size to return if no measured size could be found
- * @return The measured size for the element or {@literal defaultSize}
- */
- protected native MeasuredSize getMeasuredSize(Element element,
- MeasuredSize defaultSize)
- /*-{
- return element.vMeasuredSize || defaultSize;
- }-*/;
-
- private final MeasuredSize getMeasuredSize(ComponentConnector connector) {
- Element element = connector.getWidget().getElement();
- MeasuredSize measuredSize = getMeasuredSize(element, null);
- if (measuredSize == null) {
- measuredSize = new MeasuredSize();
- setMeasuredSize(element, measuredSize);
- }
- return measuredSize;
- }
-
- /**
- * Registers that a ManagedLayout is no longer depending on the size of an
- * Element.
- *
- * @see #registerDependency(ManagedLayout, Element)
- *
- * @param owner
- * the ManagedLayout no longer depends on an element
- * @param element
- * the Element that that no longer needs to be measured
- */
- public void unregisterDependency(ManagedLayout owner, Element element) {
- MeasuredSize measuredSize = getMeasuredSize(element, null);
- if (measuredSize == null) {
- return;
- }
- measuredSize.removeDependent(owner.getConnectorId());
- stopMeasuringIfUnecessary(element);
- }
-
- public boolean isLayoutRunning() {
- return currentDependencyTree != null;
- }
-
- private void countLayout(Map<ManagedLayout, Integer> layoutCounts,
- ManagedLayout layout) {
- Integer count = layoutCounts.get(layout);
- if (count == null) {
- count = Integer.valueOf(0);
- } else {
- count = Integer.valueOf(count.intValue() + 1);
- }
- layoutCounts.put(layout, count);
- if (count.intValue() > 2) {
- VConsole.error(Util.getConnectorString(layout)
- + " has been layouted " + count.intValue() + " times");
- }
- }
-
- private void layoutLater() {
- if (!layoutPending) {
- layoutPending = true;
- layoutTimer.schedule(100);
- }
- }
-
- public void layoutNow() {
- if (isLayoutRunning()) {
- throw new IllegalStateException(
- "Can't start a new layout phase before the previous layout phase ends.");
- }
- layoutPending = false;
- try {
- currentDependencyTree = new LayoutDependencyTree();
- doLayout();
- } finally {
- currentDependencyTree = null;
- }
- }
-
- private void doLayout() {
- VConsole.log("Starting layout phase");
-
- Map<ManagedLayout, Integer> layoutCounts = new HashMap<ManagedLayout, Integer>();
-
- int passes = 0;
- Duration totalDuration = new Duration();
-
- for (ManagedLayout layout : needsHorizontalLayout) {
- currentDependencyTree.setNeedsHorizontalLayout(layout, true);
- }
- for (ManagedLayout layout : needsVerticalLayout) {
- currentDependencyTree.setNeedsVerticalLayout(layout, true);
- }
- needsHorizontalLayout.clear();
- needsVerticalLayout.clear();
-
- for (ComponentConnector connector : needsMeasure) {
- currentDependencyTree.setNeedsMeasure(connector, true);
- }
- needsMeasure.clear();
-
- measureNonConnectors();
-
- VConsole.log("Layout init in " + totalDuration.elapsedMillis() + " ms");
-
- while (true) {
- Duration passDuration = new Duration();
- passes++;
-
- int measuredConnectorCount = measureConnectors(
- currentDependencyTree, everythingNeedsMeasure);
- everythingNeedsMeasure = false;
- if (measuredConnectorCount == 0) {
- VConsole.log("No more changes in pass " + passes);
- break;
- }
-
- int measureTime = passDuration.elapsedMillis();
- VConsole.log(" Measured " + measuredConnectorCount
- + " elements in " + measureTime + " ms");
-
- if (!listenersToFire.isEmpty()) {
- for (Element element : listenersToFire) {
- Collection<ElementResizeListener> listeners = elementResizeListeners
- .get(element);
- ElementResizeListener[] array = listeners
- .toArray(new ElementResizeListener[listeners.size()]);
- ElementResizeEvent event = new ElementResizeEvent(this,
- element);
- for (ElementResizeListener listener : array) {
- try {
- listener.onElementResize(event);
- } catch (RuntimeException e) {
- VConsole.error(e);
- }
- }
- }
- int measureListenerTime = passDuration.elapsedMillis();
- VConsole.log(" Fired resize listeners for "
- + listenersToFire.size() + " elements in "
- + (measureListenerTime - measureTime) + " ms");
- measureTime = measuredConnectorCount;
- listenersToFire.clear();
- }
-
- FastStringSet updatedSet = FastStringSet.create();
-
- while (currentDependencyTree.hasHorizontalConnectorToLayout()
- || currentDependencyTree.hasVerticaConnectorToLayout()) {
- for (ManagedLayout layout : currentDependencyTree
- .getHorizontalLayoutTargets()) {
- if (layout instanceof DirectionalManagedLayout) {
- currentDependencyTree
- .markAsHorizontallyLayouted(layout);
- DirectionalManagedLayout cl = (DirectionalManagedLayout) layout;
- try {
- cl.layoutHorizontally();
- } catch (RuntimeException e) {
- VConsole.log(e);
- }
- countLayout(layoutCounts, cl);
- } else {
- currentDependencyTree
- .markAsHorizontallyLayouted(layout);
- currentDependencyTree.markAsVerticallyLayouted(layout);
- SimpleManagedLayout rr = (SimpleManagedLayout) layout;
- try {
- rr.layout();
- } catch (RuntimeException e) {
- VConsole.log(e);
- }
- countLayout(layoutCounts, rr);
- }
- if (debugLogging) {
- updatedSet.add(layout.getConnectorId());
- }
- }
-
- for (ManagedLayout layout : currentDependencyTree
- .getVerticalLayoutTargets()) {
- if (layout instanceof DirectionalManagedLayout) {
- currentDependencyTree.markAsVerticallyLayouted(layout);
- DirectionalManagedLayout cl = (DirectionalManagedLayout) layout;
- try {
- cl.layoutVertically();
- } catch (RuntimeException e) {
- VConsole.log(e);
- }
- countLayout(layoutCounts, cl);
- } else {
- currentDependencyTree
- .markAsHorizontallyLayouted(layout);
- currentDependencyTree.markAsVerticallyLayouted(layout);
- SimpleManagedLayout rr = (SimpleManagedLayout) layout;
- try {
- rr.layout();
- } catch (RuntimeException e) {
- VConsole.log(e);
- }
- countLayout(layoutCounts, rr);
- }
- if (debugLogging) {
- updatedSet.add(layout.getConnectorId());
- }
- }
- }
-
- if (debugLogging) {
- JsArrayString changedCids = updatedSet.dump();
-
- StringBuilder b = new StringBuilder(" ");
- b.append(changedCids.length());
- b.append(" requestLayout invocations in ");
- b.append(passDuration.elapsedMillis() - measureTime);
- b.append(" ms");
- if (changedCids.length() < 30) {
- for (int i = 0; i < changedCids.length(); i++) {
- if (i != 0) {
- b.append(", ");
- } else {
- b.append(": ");
- }
- String connectorString = changedCids.get(i);
- if (changedCids.length() < 10) {
- ServerConnector connector = ConnectorMap.get(
- connection).getConnector(connectorString);
- connectorString = Util
- .getConnectorString(connector);
- }
- b.append(connectorString);
- }
- }
- VConsole.log(b.toString());
- }
-
- VConsole.log("Pass " + passes + " completed in "
- + passDuration.elapsedMillis() + " ms");
-
- if (passes > 100) {
- VConsole.log(LOOP_ABORT_MESSAGE);
- VNotification.createNotification(VNotification.DELAY_FOREVER)
- .show(LOOP_ABORT_MESSAGE, VNotification.CENTERED,
- "error");
- break;
- }
- }
-
- int postLayoutStart = totalDuration.elapsedMillis();
- for (ComponentConnector connector : connection.getConnectorMap()
- .getComponentConnectors()) {
- if (connector instanceof PostLayoutListener) {
- ((PostLayoutListener) connector).postLayout();
- }
- }
- int postLayoutDone = (totalDuration.elapsedMillis() - postLayoutStart);
- VConsole.log("Invoke post layout listeners in " + postLayoutDone
- + " ms");
-
- cleanMeasuredSizes();
- int cleaningDone = (totalDuration.elapsedMillis() - postLayoutDone);
- VConsole.log("Cleaned old measured sizes in " + cleaningDone + "ms");
-
- VConsole.log("Total layout phase time: "
- + totalDuration.elapsedMillis() + "ms");
- }
-
- private void logConnectorStatus(int connectorId) {
- currentDependencyTree
- .logDependencyStatus((ComponentConnector) ConnectorMap.get(
- connection).getConnector(Integer.toString(connectorId)));
- }
-
- private int measureConnectors(LayoutDependencyTree layoutDependencyTree,
- boolean measureAll) {
- if (!pendingOverflowFixes.isEmpty()) {
- Duration duration = new Duration();
-
- HashMap<Element, String> originalOverflows = new HashMap<Element, String>();
-
- HashSet<ComponentConnector> delayedOverflowFixes = new HashSet<ComponentConnector>();
-
- // First set overflow to hidden (and save previous value so it can
- // be restored later)
- for (ComponentConnector componentConnector : pendingOverflowFixes) {
- // Delay the overflow fix if the involved connectors might still
- // change
- boolean connectorChangesExpected = !currentDependencyTree
- .noMoreChangesExpected(componentConnector);
- boolean parentChangesExcpected = componentConnector.getParent() instanceof ComponentConnector
- && !currentDependencyTree
- .noMoreChangesExpected((ComponentConnector) componentConnector
- .getParent());
- if (connectorChangesExpected || parentChangesExcpected) {
- delayedOverflowFixes.add(componentConnector);
- continue;
- }
-
- if (debugLogging) {
- VConsole.log("Doing overflow fix for "
- + Util.getConnectorString(componentConnector)
- + " in "
- + Util.getConnectorString(componentConnector
- .getParent()));
- }
-
- Element parentElement = componentConnector.getWidget()
- .getElement().getParentElement();
- Style style = parentElement.getStyle();
- String originalOverflow = style.getOverflow();
-
- if (originalOverflow != null
- && !originalOverflows.containsKey(parentElement)) {
- // Store original value for restore, but only the first time
- // the value is changed
- originalOverflows.put(parentElement, originalOverflow);
- }
-
- style.setOverflow(Overflow.HIDDEN);
- }
-
- pendingOverflowFixes.removeAll(delayedOverflowFixes);
-
- // Then ensure all scrolling elements are reflowed by measuring
- for (ComponentConnector componentConnector : pendingOverflowFixes) {
- componentConnector.getWidget().getElement().getParentElement()
- .getOffsetHeight();
- }
-
- // Finally restore old overflow value and update bookkeeping
- for (ComponentConnector componentConnector : pendingOverflowFixes) {
- Element parentElement = componentConnector.getWidget()
- .getElement().getParentElement();
- parentElement.getStyle().setProperty("overflow",
- originalOverflows.get(parentElement));
-
- layoutDependencyTree.setNeedsMeasure(componentConnector, true);
- }
- if (!pendingOverflowFixes.isEmpty()) {
- VConsole.log("Did overflow fix for "
- + pendingOverflowFixes.size() + " elements in "
- + duration.elapsedMillis() + " ms");
- }
- pendingOverflowFixes = delayedOverflowFixes;
- }
-
- int measureCount = 0;
- if (measureAll) {
- ComponentConnector[] connectors = ConnectorMap.get(connection)
- .getComponentConnectors();
- for (ComponentConnector connector : connectors) {
- measureConnector(connector);
- }
- for (ComponentConnector connector : connectors) {
- layoutDependencyTree.setNeedsMeasure(connector, false);
- }
- measureCount += connectors.length;
- }
-
- while (layoutDependencyTree.hasConnectorsToMeasure()) {
- Collection<ComponentConnector> measureTargets = layoutDependencyTree
- .getMeasureTargets();
- for (ComponentConnector connector : measureTargets) {
- measureConnector(connector);
- measureCount++;
- }
- for (ComponentConnector connector : measureTargets) {
- layoutDependencyTree.setNeedsMeasure(connector, false);
- }
- }
- return measureCount;
- }
-
- private void measureConnector(ComponentConnector connector) {
- Element element = connector.getWidget().getElement();
- MeasuredSize measuredSize = getMeasuredSize(connector);
- MeasureResult measureResult = measuredAndUpdate(element, measuredSize);
-
- if (measureResult.isChanged()) {
- onConnectorChange(connector, measureResult.isWidthChanged(),
- measureResult.isHeightChanged());
- }
- }
-
- private void onConnectorChange(ComponentConnector connector,
- boolean widthChanged, boolean heightChanged) {
- setNeedsOverflowFix(connector);
- if (heightChanged) {
- currentDependencyTree.markHeightAsChanged(connector);
- }
- if (widthChanged) {
- currentDependencyTree.markWidthAsChanged(connector);
- }
- }
-
- private void setNeedsOverflowFix(ComponentConnector connector) {
- // IE9 doesn't need the original fix, but for some reason it needs this
- if (BrowserInfo.get().requiresOverflowAutoFix()
- || BrowserInfo.get().isIE9()) {
- ComponentConnector scrollingBoundary = currentDependencyTree
- .getScrollingBoundary(connector);
- if (scrollingBoundary != null) {
- pendingOverflowFixes.add(scrollingBoundary);
- }
- }
- }
-
- private void measureNonConnectors() {
- for (Element element : measuredNonConnectorElements) {
- measuredAndUpdate(element, getMeasuredSize(element, null));
- }
- VConsole.log("Measured " + measuredNonConnectorElements.size()
- + " non connector elements");
- }
-
- private MeasureResult measuredAndUpdate(Element element,
- MeasuredSize measuredSize) {
- MeasureResult measureResult = measuredSize.measure(element);
- if (measureResult.isChanged()) {
- notifyListenersAndDepdendents(element,
- measureResult.isWidthChanged(),
- measureResult.isHeightChanged());
- }
- return measureResult;
- }
-
- private void notifyListenersAndDepdendents(Element element,
- boolean widthChanged, boolean heightChanged) {
- assert widthChanged || heightChanged;
-
- MeasuredSize measuredSize = getMeasuredSize(element, nullSize);
- JsArrayString dependents = measuredSize.getDependents();
- for (int i = 0; i < dependents.length(); i++) {
- String pid = dependents.get(i);
- ManagedLayout dependent = (ManagedLayout) connection
- .getConnectorMap().getConnector(pid);
- if (dependent != null) {
- if (heightChanged) {
- currentDependencyTree.setNeedsVerticalLayout(dependent,
- true);
- }
- if (widthChanged) {
- currentDependencyTree.setNeedsHorizontalLayout(dependent,
- true);
- }
- }
- }
- if (elementResizeListeners.containsKey(element)) {
- listenersToFire.add(element);
- }
- }
-
- private static boolean isManagedLayout(ComponentConnector connector) {
- return connector instanceof ManagedLayout;
- }
-
- public void forceLayout() {
- ConnectorMap connectorMap = connection.getConnectorMap();
- ComponentConnector[] componentConnectors = connectorMap
- .getComponentConnectors();
- for (ComponentConnector connector : componentConnectors) {
- if (connector instanceof ManagedLayout) {
- setNeedsLayout((ManagedLayout) connector);
- }
- }
- setEverythingNeedsMeasure();
- layoutNow();
- }
-
- /**
- * Marks that a ManagedLayout should be layouted in the next layout phase
- * even if none of the elements managed by the layout have been resized.
- *
- * @param layout
- * the managed layout that should be layouted
- */
- public final void setNeedsLayout(ManagedLayout layout) {
- setNeedsHorizontalLayout(layout);
- setNeedsVerticalLayout(layout);
- }
-
- /**
- * Marks that a ManagedLayout should be layouted horizontally in the next
- * layout phase even if none of the elements managed by the layout have been
- * resized horizontally.
- *
- * For SimpleManagedLayout which is always layouted in both directions, this
- * has the same effect as {@link #setNeedsLayout(ManagedLayout)}.
- *
- * @param layout
- * the managed layout that should be layouted
- */
- public final void setNeedsHorizontalLayout(ManagedLayout layout) {
- needsHorizontalLayout.add(layout);
- }
-
- /**
- * Marks that a ManagedLayout should be layouted vertically in the next
- * layout phase even if none of the elements managed by the layout have been
- * resized vertically.
- *
- * For SimpleManagedLayout which is always layouted in both directions, this
- * has the same effect as {@link #setNeedsLayout(ManagedLayout)}.
- *
- * @param layout
- * the managed layout that should be layouted
- */
- public final void setNeedsVerticalLayout(ManagedLayout layout) {
- needsVerticalLayout.add(layout);
- }
-
- /**
- * Gets the outer height (including margins, paddings and borders) of the
- * given element, provided that it has been measured. These elements are
- * guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * -1 is returned if the element has not been measured. If 0 is returned, it
- * might indicate that the element is not attached to the DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured outer height (including margins, paddings and
- * borders) of the element in pixels.
- */
- public final int getOuterHeight(Element element) {
- return getMeasuredSize(element, nullSize).getOuterHeight();
- }
-
- /**
- * Gets the outer width (including margins, paddings and borders) of the
- * given element, provided that it has been measured. These elements are
- * guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * -1 is returned if the element has not been measured. If 0 is returned, it
- * might indicate that the element is not attached to the DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured outer width (including margins, paddings and
- * borders) of the element in pixels.
- */
- public final int getOuterWidth(Element element) {
- return getMeasuredSize(element, nullSize).getOuterWidth();
- }
-
- /**
- * Gets the inner height (excluding margins, paddings and borders) of the
- * given element, provided that it has been measured. These elements are
- * guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * -1 is returned if the element has not been measured. If 0 is returned, it
- * might indicate that the element is not attached to the DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured inner height (excluding margins, paddings and
- * borders) of the element in pixels.
- */
- public final int getInnerHeight(Element element) {
- return getMeasuredSize(element, nullSize).getInnerHeight();
- }
-
- /**
- * Gets the inner width (excluding margins, paddings and borders) of the
- * given element, provided that it has been measured. These elements are
- * guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * -1 is returned if the element has not been measured. If 0 is returned, it
- * might indicate that the element is not attached to the DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured inner width (excluding margins, paddings and
- * borders) of the element in pixels.
- */
- public final int getInnerWidth(Element element) {
- return getMeasuredSize(element, nullSize).getInnerWidth();
- }
-
- /**
- * Gets the border height (top border + bottom border) of the given element,
- * provided that it has been measured. These elements are guaranteed to be
- * measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured border height (top border + bottom border) of the
- * element in pixels.
- */
- public final int getBorderHeight(Element element) {
- return getMeasuredSize(element, nullSize).getBorderHeight();
- }
-
- /**
- * Gets the padding height (top padding + bottom padding) of the given
- * element, provided that it has been measured. These elements are
- * guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured padding height (top padding + bottom padding) of the
- * element in pixels.
- */
- public int getPaddingHeight(Element element) {
- return getMeasuredSize(element, nullSize).getPaddingHeight();
- }
-
- /**
- * Gets the border width (left border + right border) of the given element,
- * provided that it has been measured. These elements are guaranteed to be
- * measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured border width (left border + right border) of the
- * element in pixels.
- */
- public int getBorderWidth(Element element) {
- return getMeasuredSize(element, nullSize).getBorderWidth();
- }
-
- /**
- * Gets the padding width (left padding + right padding) of the given
- * element, provided that it has been measured. These elements are
- * guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured padding width (left padding + right padding) of the
- * element in pixels.
- */
- public int getPaddingWidth(Element element) {
- return getMeasuredSize(element, nullSize).getPaddingWidth();
- }
-
- /**
- * Gets the top padding of the given element, provided that it has been
- * measured. These elements are guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured top padding of the element in pixels.
- */
- public int getPaddingTop(Element element) {
- return getMeasuredSize(element, nullSize).getPaddingTop();
- }
-
- /**
- * Gets the left padding of the given element, provided that it has been
- * measured. These elements are guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured left padding of the element in pixels.
- */
- public int getPaddingLeft(Element element) {
- return getMeasuredSize(element, nullSize).getPaddingLeft();
- }
-
- /**
- * Gets the bottom padding of the given element, provided that it has been
- * measured. These elements are guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured bottom padding of the element in pixels.
- */
- public int getPaddingBottom(Element element) {
- return getMeasuredSize(element, nullSize).getPaddingBottom();
- }
-
- /**
- * Gets the right padding of the given element, provided that it has been
- * measured. These elements are guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured right padding of the element in pixels.
- */
- public int getPaddingRight(Element element) {
- return getMeasuredSize(element, nullSize).getPaddingRight();
- }
-
- /**
- * Gets the top margin of the given element, provided that it has been
- * measured. These elements are guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured top margin of the element in pixels.
- */
- public int getMarginTop(Element element) {
- return getMeasuredSize(element, nullSize).getMarginTop();
- }
-
- /**
- * Gets the right margin of the given element, provided that it has been
- * measured. These elements are guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured right margin of the element in pixels.
- */
- public int getMarginRight(Element element) {
- return getMeasuredSize(element, nullSize).getMarginRight();
- }
-
- /**
- * Gets the bottom margin of the given element, provided that it has been
- * measured. These elements are guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured bottom margin of the element in pixels.
- */
- public int getMarginBottom(Element element) {
- return getMeasuredSize(element, nullSize).getMarginBottom();
- }
-
- /**
- * Gets the left margin of the given element, provided that it has been
- * measured. These elements are guaranteed to be measured:
- * <ul>
- * <li>ManagedLayotus and their child Connectors
- * <li>Elements for which there is at least one ElementResizeListener
- * <li>Elements for which at least one ManagedLayout has registered a
- * dependency
- * </ul>
- *
- * A negative number is returned if the element has not been measured. If 0
- * is returned, it might indicate that the element is not attached to the
- * DOM.
- *
- * @param element
- * the element to get the measured size for
- * @return the measured left margin of the element in pixels.
- */
- public int getMarginLeft(Element element) {
- return getMeasuredSize(element, nullSize).getMarginLeft();
- }
-
- /**
- * Registers the outer height (including margins, borders and paddings) of a
- * component. This can be used as an optimization by ManagedLayouts; by
- * informing the LayoutManager about what size a component will have, the
- * layout propagation can continue directly without first measuring the
- * potentially resized elements.
- *
- * @param component
- * the component for which the size is reported
- * @param outerHeight
- * the new outer height (including margins, borders and paddings)
- * of the component in pixels
- */
- public void reportOuterHeight(ComponentConnector component, int outerHeight) {
- MeasuredSize measuredSize = getMeasuredSize(component);
- if (isLayoutRunning()) {
- boolean heightChanged = measuredSize.setOuterHeight(outerHeight);
-
- if (heightChanged) {
- onConnectorChange(component, false, true);
- notifyListenersAndDepdendents(component.getWidget()
- .getElement(), false, true);
- }
- currentDependencyTree.setNeedsVerticalMeasure(component, false);
- } else if (measuredSize.getOuterHeight() != outerHeight) {
- setNeedsMeasure(component);
- }
- }
-
- /**
- * Registers the height reserved for a relatively sized component. This can
- * be used as an optimization by ManagedLayouts; by informing the
- * LayoutManager about what size a component will have, the layout
- * propagation can continue directly without first measuring the potentially
- * resized elements.
- *
- * @param component
- * the relatively sized component for which the size is reported
- * @param assignedHeight
- * the inner height of the relatively sized component's parent
- * element in pixels
- */
- public void reportHeightAssignedToRelative(ComponentConnector component,
- int assignedHeight) {
- assert component.isRelativeHeight();
-
- float percentSize = parsePercent(component.getState().getHeight());
- int effectiveHeight = Math.round(assignedHeight * (percentSize / 100));
-
- reportOuterHeight(component, effectiveHeight);
- }
-
- /**
- * Registers the width reserved for a relatively sized component. This can
- * be used as an optimization by ManagedLayouts; by informing the
- * LayoutManager about what size a component will have, the layout
- * propagation can continue directly without first measuring the potentially
- * resized elements.
- *
- * @param component
- * the relatively sized component for which the size is reported
- * @param assignedWidth
- * the inner width of the relatively sized component's parent
- * element in pixels
- */
- public void reportWidthAssignedToRelative(ComponentConnector component,
- int assignedWidth) {
- assert component.isRelativeWidth();
-
- float percentSize = parsePercent(component.getState().getWidth());
- int effectiveWidth = Math.round(assignedWidth * (percentSize / 100));
-
- reportOuterWidth(component, effectiveWidth);
- }
-
- private static float parsePercent(String size) {
- return Float.parseFloat(size.substring(0, size.length() - 1));
- }
-
- /**
- * Registers the outer width (including margins, borders and paddings) of a
- * component. This can be used as an optimization by ManagedLayouts; by
- * informing the LayoutManager about what size a component will have, the
- * layout propagation can continue directly without first measuring the
- * potentially resized elements.
- *
- * @param component
- * the component for which the size is reported
- * @param outerWidth
- * the new outer width (including margins, borders and paddings)
- * of the component in pixels
- */
- public void reportOuterWidth(ComponentConnector component, int outerWidth) {
- MeasuredSize measuredSize = getMeasuredSize(component);
- if (isLayoutRunning()) {
- boolean widthChanged = measuredSize.setOuterWidth(outerWidth);
-
- if (widthChanged) {
- onConnectorChange(component, true, false);
- notifyListenersAndDepdendents(component.getWidget()
- .getElement(), true, false);
- }
- currentDependencyTree.setNeedsHorizontalMeasure(component, false);
- } else if (measuredSize.getOuterWidth() != outerWidth) {
- setNeedsMeasure(component);
- }
- }
-
- /**
- * Adds a listener that will be notified whenever the size of a specific
- * element changes. Adding a listener to an element also ensures that all
- * sizes for that element will be available starting from the next layout
- * phase.
- *
- * @param element
- * the element that should be checked for size changes
- * @param listener
- * an ElementResizeListener that will be informed whenever the
- * size of the target element has changed
- */
- public void addElementResizeListener(Element element,
- ElementResizeListener listener) {
- Collection<ElementResizeListener> listeners = elementResizeListeners
- .get(element);
- if (listeners == null) {
- listeners = new HashSet<ElementResizeListener>();
- elementResizeListeners.put(element, listeners);
- ensureMeasured(element);
- }
- listeners.add(listener);
- }
-
- /**
- * Removes an element resize listener from the provided element. This might
- * cause this LayoutManager to stop tracking the size of the element if no
- * other sources are interested in the size.
- *
- * @param element
- * the element to which the element resize listener was
- * previously added
- * @param listener
- * the ElementResizeListener that should no longer get informed
- * about size changes to the target element.
- */
- public void removeElementResizeListener(Element element,
- ElementResizeListener listener) {
- Collection<ElementResizeListener> listeners = elementResizeListeners
- .get(element);
- if (listeners != null) {
- listeners.remove(listener);
- if (listeners.isEmpty()) {
- elementResizeListeners.remove(element);
- stopMeasuringIfUnecessary(element);
- }
- }
- }
-
- private void stopMeasuringIfUnecessary(Element element) {
- if (!needsMeasure(element)) {
- measuredNonConnectorElements.remove(element);
- setMeasuredSize(element, null);
- }
- }
-
- /**
- * Informs this LayoutManager that the size of a component might have
- * changed. If there is no upcoming layout phase, a new layout phase is
- * scheduled. This method should be used whenever a size might have changed
- * from outside of Vaadin's normal update phase, e.g. when an icon has been
- * loaded or when the user resizes some part of the UI using the mouse.
- *
- * @param component
- * the component whose size might have changed.
- */
- public void setNeedsMeasure(ComponentConnector component) {
- if (isLayoutRunning()) {
- currentDependencyTree.setNeedsMeasure(component, true);
- } else {
- needsMeasure.add(component);
- layoutLater();
- }
- }
-
- public void setEverythingNeedsMeasure() {
- everythingNeedsMeasure = true;
- }
-
- /**
- * Clean measured sizes which are no longer needed. Only for IE8.
- */
- protected void cleanMeasuredSizes() {
- }
-
-}