diff options
author | Artur Signell <artur@vaadin.com> | 2015-07-12 20:11:41 +0300 |
---|---|---|
committer | Mika Murtojarvi <mika@vaadin.com> | 2015-09-15 10:51:02 +0300 |
commit | 18cf80534a98651510f2b743d215083206aea53a (patch) | |
tree | de9332299aef1f23b447c7f96940ae5faa8d6bbb | |
parent | efdc36027dec55e8b1084c7ea94ccb843b8a7c99 (diff) | |
download | vaadin-framework-18cf80534a98651510f2b743d215083206aea53a.tar.gz vaadin-framework-18cf80534a98651510f2b743d215083206aea53a.zip |
Backport fix for #16992 to Vaadin 7.5.
Change-Id: I4899aac895f061cffffaccc5b0e33f92bada28b0
6 files changed, 277 insertions, 11 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index 5547b02895..24cfdf62b9 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -63,7 +63,6 @@ import com.google.gwt.user.client.Window.ClosingHandler; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConfiguration.ErrorMessage; -import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent; import com.vaadin.client.ResourceLoader.ResourceLoadEvent; import com.vaadin.client.ResourceLoader.ResourceLoadListener; import com.vaadin.client.communication.HasJavaScriptConnectorHelper; @@ -1693,18 +1692,20 @@ public class ApplicationConnection implements HasHandlers { updatingState = false; - if (!onlyNoLayoutUpdates) { - Profiler.enter("Layout processing"); - try { - LayoutManager layoutManager = getLayoutManager(); + Profiler.enter("Layout processing"); + try { + LayoutManager layoutManager = getLayoutManager(); + if (!onlyNoLayoutUpdates) { layoutManager.setEverythingNeedsMeasure(); + } + if (layoutManager.isLayoutNeeded()) { layoutManager.layoutNow(); - } catch (final Throwable e) { - getLogger().log(Level.SEVERE, - "Error processing layouts", e); } - Profiler.leave("Layout processing"); + } catch (final Throwable e) { + getLogger() + .log(Level.SEVERE, "Error processing layouts", e); } + Profiler.leave("Layout processing"); if (ApplicationConfiguration.isDebugMode()) { Profiler.enter("Dumping state changes to the console"); diff --git a/client/src/com/vaadin/client/LayoutManager.java b/client/src/com/vaadin/client/LayoutManager.java index 102e618f5e..2d10d0c082 100644 --- a/client/src/com/vaadin/client/LayoutManager.java +++ b/client/src/com/vaadin/client/LayoutManager.java @@ -1800,4 +1800,25 @@ public class LayoutManager { return Logger.getLogger(LayoutManager.class.getName()); } + /** + * Checks if there is something waiting for a layout to take place. + * + * @since 7.5.6 + * @return true if there are connectors waiting for measurement or layout, + * false otherwise + */ + public boolean isLayoutNeeded() { + if (!needsHorizontalLayout.isEmpty() || !needsVerticalLayout.isEmpty()) { + return true; + } + if (!needsMeasure.isEmpty()) { + return true; + } + + if (everythingNeedsMeasure) { + return true; + } + + return false; + } } diff --git a/client/src/com/vaadin/client/ui/layout/LayoutDependencyTree.java b/client/src/com/vaadin/client/ui/layout/LayoutDependencyTree.java index 07bb6688e3..a4c5668948 100644 --- a/client/src/com/vaadin/client/ui/layout/LayoutDependencyTree.java +++ b/client/src/com/vaadin/client/ui/layout/LayoutDependencyTree.java @@ -17,6 +17,7 @@ package com.vaadin.client.ui.layout; import java.util.ArrayList; import java.util.Collection; +import java.util.logging.Logger; import com.google.gwt.core.client.JsArrayString; import com.vaadin.client.ApplicationConnection; @@ -500,6 +501,12 @@ public class LayoutDependencyTree { if (connector == null) { connector = (ComponentConnector) ConnectorMap.get(connection) .getConnector(connectorId); + if (connector == null) { + getLogger().warning( + "No connector found for id " + connectorId + + " while creating LayoutDependency"); + return null; + } } dependency = new LayoutDependency(connector, direction); dependencies.put(connectorId, dependency); @@ -531,7 +538,12 @@ public class LayoutDependencyTree { public void setNeedsHorizontalLayout(String connectorId, boolean needsLayout) { LayoutDependency dependency = getDependency(connectorId, HORIZONTAL); - dependency.setNeedsLayout(needsLayout); + if (dependency != null) { + dependency.setNeedsLayout(needsLayout); + } else { + getLogger().warning( + "No dependency found in setNeedsHorizontalLayout"); + } } /** @@ -549,7 +561,13 @@ public class LayoutDependencyTree { public void setNeedsVerticalLayout(String connectorId, boolean needsLayout) { LayoutDependency dependency = getDependency(connectorId, VERTICAL); - dependency.setNeedsLayout(needsLayout); + if (dependency != null) { + dependency.setNeedsLayout(needsLayout); + } else { + getLogger() + .warning("No dependency found in setNeedsVerticalLayout"); + } + } public void markAsHorizontallyLayouted(ManagedLayout layout) { @@ -736,4 +754,9 @@ public class LayoutDependencyTree { } return dependency.scrollingBoundary; } + + private static Logger getLogger() { + return Logger.getLogger(LayoutDependencyTree.class.getName()); + } + } diff --git a/uitest/src/com/vaadin/tests/components/NoLayoutUpdateWhichNeedsLayout.java b/uitest/src/com/vaadin/tests/components/NoLayoutUpdateWhichNeedsLayout.java new file mode 100644 index 0000000000..9f63970f85 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/NoLayoutUpdateWhichNeedsLayout.java @@ -0,0 +1,117 @@ +package com.vaadin.tests.components; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import com.vaadin.annotations.Theme; +import com.vaadin.server.VaadinRequest; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.ProgressBar; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; + +@SuppressWarnings("serial") +@Theme("valo") +public class NoLayoutUpdateWhichNeedsLayout extends UI { + + private ProgressBar progressBar; + private Window w; + + @Override + protected void init(VaadinRequest request) { + final VerticalLayout layout = new VerticalLayout(); + layout.setMargin(true); + setContent(layout); + + setPollInterval(1000); + + Button button = new Button( + "1. Execute scheduled task and show progress in a window"); + button.setId("openWindow"); + button.addClickListener(new Button.ClickListener() { + + private Window w2; + + @Override + public void buttonClick(ClickEvent event) { + GridLayout glo = new GridLayout(); + progressBar = new ProgressBar(); + progressBar.setIndeterminate(false); + progressBar.setId("progress"); + glo.addComponent(progressBar); + + w2 = new Window("test"); + w2.setWidth("600px"); + w2.setHeight("200px"); + w2.setContent(glo); + w2.center(); + Button closeB = new Button( + "2. Click to close after the progress is updated"); + closeB.setId("closeWindow"); + closeB.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + w2.close(); + w2 = null; + } + }); + glo.addComponent(closeB); + addWindow(w2); + + scheduleTask(); + } + }); + + Button openWin = new Button("3. Finally, Click to open a new Window"); + openWin.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + w = new Window("test"); + w.setWidth("300px"); + w.setHeight("300px"); + w.setContent(new VerticalLayout(new Label( + "simple test label component"))); + w.center(); + getUI().addWindow(w); + } + }); + + Button stopPolling = new Button("Stop polling", new ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + setPollInterval(-1); + } + }); + layout.addComponents(button, openWin, stopPolling); + } + + protected void scheduleTask() { + Thread t = new Thread() { + + @Override + public void run() { + getUI().access(new Runnable() { + @Override + public void run() { + updateProgresBar(50); + } + }); + } + }; + ScheduledExecutorService worker = Executors + .newSingleThreadScheduledExecutor(); + worker.schedule(t, 2, TimeUnit.SECONDS); + } + + public void updateProgresBar(int pc) { + progressBar.setValue((float) (pc / 100.0)); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/NoLayoutUpdateWhichNeedsLayoutTest.java b/uitest/src/com/vaadin/tests/components/NoLayoutUpdateWhichNeedsLayoutTest.java new file mode 100644 index 0000000000..bc12919ccd --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/NoLayoutUpdateWhichNeedsLayoutTest.java @@ -0,0 +1,48 @@ +/* + * 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.tests.components; + +import org.junit.Test; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.support.ui.ExpectedCondition; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.customelements.CustomProgressBarElement; +import com.vaadin.tests.tb3.SingleBrowserTest; + +public class NoLayoutUpdateWhichNeedsLayoutTest extends SingleBrowserTest { + + @Test + public void layoutRunForNoLayoutUpdate() { + openTestURL("debug"); + ButtonElement open = $(ButtonElement.class).id("openWindow"); + open.click(); + final CustomProgressBarElement progress = $( + CustomProgressBarElement.class).first(); + waitUntil(new ExpectedCondition<Boolean>() { + @Override + public Boolean apply(WebDriver input) { + double p = progress.getValue(); + return Math.abs(p - 0.5) < 0.01; + } + }); + + ButtonElement close = $(ButtonElement.class).id("closeWindow"); + close.click(); + + assertNoErrorNotifications(); + } +} diff --git a/uitest/src/com/vaadin/tests/customelements/CustomProgressBarElement.java b/uitest/src/com/vaadin/tests/customelements/CustomProgressBarElement.java new file mode 100644 index 0000000000..663f398bba --- /dev/null +++ b/uitest/src/com/vaadin/tests/customelements/CustomProgressBarElement.java @@ -0,0 +1,56 @@ +/* + * 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.tests.customelements; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.ProgressBarElement; +import com.vaadin.testbench.elementsbase.ServerClass; + +@ServerClass("com.vaadin.ui.ProgressBar") +public class CustomProgressBarElement extends ProgressBarElement { + + public double getValue() { + WebElement indicator = findElement(By + .className("v-progressbar-indicator")); + String width = getStyleAttribute(indicator, "width"); + if (!width.endsWith("%")) { + return 0; + } + + return Double.parseDouble(width.replace("%", "")) / 100.0; + } + + /** + * @since 7.5.6 + * @param indicator + * @param string + * @return + */ + private String getStyleAttribute(WebElement element, String styleName) { + String style = element.getAttribute("style"); + String[] styles = style.split(";"); + for (String s : styles) { + if (s.startsWith(styleName + ":")) { + return s.substring(styleName.length() + 1).trim(); + } + } + + return null; + } + +}
\ No newline at end of file |