summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2013-08-30 13:43:34 +0300
committerLeif Åstrand <leif@vaadin.com>2013-08-30 13:43:34 +0300
commitbe3953c0686a4bd59fe9df2c401d882104a7afac (patch)
treedcefc03352e742a41d3551d781651bfbe19875d6 /client
parentd827a1760da477575294f0105933e868c1bf3ad3 (diff)
parentad669c39c603650cc8193eef83fe1b6a39be0e45 (diff)
downloadvaadin-framework-be3953c0686a4bd59fe9df2c401d882104a7afac.tar.gz
vaadin-framework-be3953c0686a4bd59fe9df2c401d882104a7afac.zip
Merge changes from origin/7.1
4f3e81a Use <code> instead of {@code} for sample containing { and } (#12311) c7a48ae Delay sending DateField popup value to server until popup is closed #6252 dc491a4 Reset waitingForFilteringResponse flag to false inside onBlur (#12325) 4fb775a Fixed a typo in FieldGroup.isModified() JavaDoc. (#12172) aa47197 Add a chapter on installing IvyDE (for #12359) eaec281 GWT requires max 1.6 compiler compliance level currently - #12345 f72be69 Terminate JVM if server.close() has no effect (#12363) 36413cb Make sure that no fileIds are replayed to the client (#12330) 7182665 Fix scrollbar for Window under WebKit browsers (#11994) 61dbe9c Search only remaining message for delimiter (#12404) b5a212a Report min and max times from Profiler (#12409) 7220ca8 Fixed DragAndDropWrapper using wrong drop target in IE8 #12406 c87772b Escape markup in CustomLayout's JavaDoc (#12410) f5b67af Optimize ComputedStyle.getIntProperty() (#12411) 0473036 Add more detailed profiling for some client side hotspots (#12418) 7dfe5ae Fixed test broken by fixes to drag&drop #12406 234ed1c Fixed test broken by PopupDateField communication change #6252 c7a8c3f Fixed failing TabKeyboardNavigation test #12433 fac9ff6 Optimize resetting of state when detaching components (#10899, #11284) af995de Optimize large Vertical/HorizontalLayout client side (#12420, #10899) 39fd5fc Fix bug for spacing on first widget (#12420) bd4442b Fixed broken test due to changes in drop position by #12406 b83240f Optimize CssLayout hierarchy update (#11284) a52b286 Added controlDirective to ifContentStatement. Fixes ticket #12105. 8ce45c7 Disable slow sanity check when not in debug mode (#12463) 232eb42 Enable use of profiler without debug window (#12465) 6dc46c5 Use the add() path of CssLayout only when appending to the end (#11284) bea7fa3 Only consider caption tooltips for own slots (#12469) dce63d1 Allow creating session for Portlet UI init request (#12473) ad669c3 Adds junit to the ide configuration for the theme-compiler module. Change-Id: Icd734d6849cc4f4014e1268f4fabe1ed92f72e38
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/ApplicationConnection.java81
-rw-r--r--client/src/com/vaadin/client/ComputedStyle.java42
-rw-r--r--client/src/com/vaadin/client/LayoutManager.java14
-rw-r--r--client/src/com/vaadin/client/Profiler.java22
-rw-r--r--client/src/com/vaadin/client/debug/internal/ProfilerSection.java56
-rw-r--r--client/src/com/vaadin/client/ui/AbstractComponentConnector.java6
-rw-r--r--client/src/com/vaadin/client/ui/VCssLayout.java12
-rw-r--r--client/src/com/vaadin/client/ui/VFilterSelect.java1
-rw-r--r--client/src/com/vaadin/client/ui/VPopupCalendar.java3
-rw-r--r--client/src/com/vaadin/client/ui/VWindow.java31
-rw-r--r--client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java7
-rw-r--r--client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java32
-rw-r--r--client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java4
-rw-r--r--client/src/com/vaadin/client/ui/layout/LayoutDependencyTree.java15
-rw-r--r--client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java19
-rw-r--r--client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java57
-rw-r--r--client/src/com/vaadin/client/ui/panel/PanelConnector.java10
17 files changed, 353 insertions, 59 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java
index 0b64f56c3e..0d9c859ee8 100644
--- a/client/src/com/vaadin/client/ApplicationConnection.java
+++ b/client/src/com/vaadin/client/ApplicationConnection.java
@@ -1686,8 +1686,15 @@ public class ApplicationConnection {
for (int i = 0; i < size; i++) {
ServerConnector c = currentConnectors.get(i);
if (c.getParent() != null) {
- if (!c.getParent().getChildren().contains(c)) {
- VConsole.error("ERROR: Connector is connected to a parent but the parent does not contain the connector");
+ // only do this check if debug mode is active
+ if (ApplicationConfiguration.isDebugMode()) {
+ Profiler.enter("unregisterRemovedConnectors check parent - this is only performed in debug mode");
+ // this is slow for large layouts, 25-30% of total
+ // time for some operations even on modern browsers
+ if (!c.getParent().getChildren().contains(c)) {
+ VConsole.error("ERROR: Connector is connected to a parent but the parent does not contain the connector");
+ }
+ Profiler.leave("unregisterRemovedConnectors check parent - this is only performed in debug mode");
}
} else if (c == getUIConnector()) {
// UIConnector for this connection, leave as-is
@@ -1701,7 +1708,9 @@ public class ApplicationConnection {
// hierarchy, unregister it and any possible
// children. The UIConnector should never be
// unregistered even though it has no parent.
+ Profiler.enter("unregisterRemovedConnectors unregisterConnector");
connectorMap.unregisterConnector(c);
+ Profiler.leave("unregisterRemovedConnectors unregisterConnector");
unregistered++;
}
@@ -1984,6 +1993,8 @@ public class ApplicationConnection {
JsArrayString hierarchyKeys = hierarchies.getKeyArray();
for (int i = 0; i < hierarchyKeys.length(); i++) {
try {
+ Profiler.enter("updateConnectorHierarchy hierarchy entry");
+
String connectorId = hierarchyKeys.get(i);
ServerConnector parentConnector = connectorMap
.getConnector(connectorId);
@@ -1991,6 +2002,8 @@ public class ApplicationConnection {
.getJSStringArray(connectorId);
int childConnectorSize = childConnectorIds.length();
+ Profiler.enter("updateConnectorHierarchy find new connectors");
+
List<ServerConnector> newChildren = new ArrayList<ServerConnector>();
List<ComponentConnector> newComponents = new ArrayList<ComponentConnector>();
for (int connectorIndex = 0; connectorIndex < childConnectorSize; connectorIndex++) {
@@ -2029,6 +2042,8 @@ public class ApplicationConnection {
}
}
+ Profiler.leave("updateConnectorHierarchy find new connectors");
+
// TODO This check should be done on the server side in
// the future so the hierarchy update is only sent when
// something actually has changed
@@ -2041,6 +2056,8 @@ public class ApplicationConnection {
continue;
}
+ Profiler.enter("updateConnectorHierarchy handle HasComponentsConnector");
+
if (parentConnector instanceof HasComponentsConnector) {
HasComponentsConnector ccc = (HasComponentsConnector) parentConnector;
List<ComponentConnector> oldComponents = ccc
@@ -2062,7 +2079,13 @@ public class ApplicationConnection {
+ " has component children even though it isn't a HasComponentsConnector");
}
+ Profiler.leave("updateConnectorHierarchy handle HasComponentsConnector");
+
+ Profiler.enter("updateConnectorHierarchy setChildren");
parentConnector.setChildren(newChildren);
+ Profiler.leave("updateConnectorHierarchy setChildren");
+
+ Profiler.enter("updateConnectorHierarchy find removed children");
/*
* Find children removed from this parent and mark for
@@ -2084,11 +2107,17 @@ public class ApplicationConnection {
maybeDetached.add(oldChild.getConnectorId());
}
}
+
+ Profiler.leave("updateConnectorHierarchy find removed children");
} catch (final Throwable e) {
VConsole.error(e);
+ } finally {
+ Profiler.leave("updateConnectorHierarchy hierarchy entry");
}
}
+ Profiler.enter("updateConnectorHierarchy detach removed connectors");
+
/*
* Connector is in maybeDetached at this point if it has been
* removed from its parent but not added to any other parent
@@ -2100,6 +2129,8 @@ public class ApplicationConnection {
recursivelyDetach(removed, result.events);
}
+ Profiler.leave("updateConnectorHierarchy detach removed connectors");
+
Profiler.leave("updateConnectorHierarchy");
return result;
@@ -2116,27 +2147,44 @@ public class ApplicationConnection {
* is the closest we can get without data from the server.
* #10151
*/
+ Profiler.enter("ApplicationConnection recursivelyDetach reset state");
try {
+ Profiler.enter("ApplicationConnection recursivelyDetach reset state - getStateType");
Type stateType = AbstractConnector.getStateType(connector);
+ Profiler.leave("ApplicationConnection recursivelyDetach reset state - getStateType");
// Empty state instance to get default property values from
+ Profiler.enter("ApplicationConnection recursivelyDetach reset state - createInstance");
Object defaultState = stateType.createInstance();
+ Profiler.leave("ApplicationConnection recursivelyDetach reset state - createInstance");
- SharedState state = connector.getState();
-
- JsArrayObject<Property> properties = stateType
- .getPropertiesAsArray();
- int size = properties.size();
- for (int i = 0; i < size; i++) {
- Property property = properties.get(i);
- property.setValue(state,
- property.getValue(defaultState));
+ if (connector instanceof AbstractConnector) {
+ // optimization as the loop setting properties is very
+ // slow, especially on IE8
+ replaceState((AbstractConnector) connector,
+ defaultState);
+ } else {
+ SharedState state = connector.getState();
+
+ Profiler.enter("ApplicationConnection recursivelyDetach reset state - properties");
+ JsArrayObject<Property> properties = stateType
+ .getPropertiesAsArray();
+ int size = properties.size();
+ for (int i = 0; i < size; i++) {
+ Property property = properties.get(i);
+ property.setValue(state,
+ property.getValue(defaultState));
+ }
+ Profiler.leave("ApplicationConnection recursivelyDetach reset state - properties");
}
} catch (NoDataException e) {
throw new RuntimeException("Can't reset state for "
+ Util.getConnectorString(connector), e);
+ } finally {
+ Profiler.leave("ApplicationConnection recursivelyDetach reset state");
}
+ Profiler.enter("ApplicationConnection recursivelyDetach perform detach");
/*
* Recursively detach children to make sure they get
* setParent(null) and hierarchy change events as needed.
@@ -2153,18 +2201,22 @@ public class ApplicationConnection {
}
recursivelyDetach(child, events);
}
+ Profiler.leave("ApplicationConnection recursivelyDetach perform detach");
/*
* Clear child list and parent
*/
+ Profiler.enter("ApplicationConnection recursivelyDetach clear children and parent");
connector
.setChildren(Collections.<ServerConnector> emptyList());
connector.setParent(null);
+ Profiler.leave("ApplicationConnection recursivelyDetach clear children and parent");
/*
* Create an artificial hierarchy event for containers to give
* it a chance to clean up after its children if it has any
*/
+ Profiler.enter("ApplicationConnection recursivelyDetach create hierarchy event");
if (connector instanceof HasComponentsConnector) {
HasComponentsConnector ccc = (HasComponentsConnector) connector;
List<ComponentConnector> oldChildren = ccc
@@ -2185,8 +2237,15 @@ public class ApplicationConnection {
events.add(event);
}
}
+ Profiler.leave("ApplicationConnection recursivelyDetach create hierarchy event");
}
+ private native void replaceState(AbstractConnector connector,
+ Object defaultState)
+ /*-{
+ connector.@com.vaadin.client.ui.AbstractConnector::state = defaultState;
+ }-*/;
+
private void handleRpcInvocations(ValueMap json) {
if (json.containsKey("rpc")) {
Profiler.enter("handleRpcInvocations");
diff --git a/client/src/com/vaadin/client/ComputedStyle.java b/client/src/com/vaadin/client/ComputedStyle.java
index 499d9cd2d6..db8ed037bf 100644
--- a/client/src/com/vaadin/client/ComputedStyle.java
+++ b/client/src/com/vaadin/client/ComputedStyle.java
@@ -130,11 +130,11 @@ public class ComputedStyle {
}-*/;
public final int getIntProperty(String name) {
- Integer parsed = parseInt(getProperty(name));
- if (parsed != null) {
- return parsed.intValue();
- }
- return 0;
+ Profiler.enter("ComputedStyle.getIntProperty");
+ String value = getProperty(name);
+ int result = parseIntNative(value);
+ Profiler.leave("ComputedStyle.getIntProperty");
+ return result;
}
/**
@@ -177,14 +177,20 @@ public class ComputedStyle {
}
/**
- * Takes a String value e.g. "12px" and parses that to int 12.
+ * Takes a String value e.g. "12px" and parses that to Integer 12.
*
* @param String
* a value starting with a number
- * @return int the value from the string before any non-numeric characters.
- * If the value cannot be parsed to a number, returns
+ * @return Integer the value from the string before any non-numeric
+ * characters. If the value cannot be parsed to a number, returns
* <code>null</code>.
+ *
+ * @deprecated Since 7.1.4, the method {@link #parseIntNative(String)} is
+ * used internally and this method does not belong in the public
+ * API of {@link ComputedStyle}. {@link #parseInt(String)} might
+ * be removed or moved to a utility class in future versions.
*/
+ @Deprecated
public static native Integer parseInt(final String value)
/*-{
var number = parseInt(value, 10);
@@ -195,4 +201,24 @@ public class ComputedStyle {
return @java.lang.Integer::valueOf(I)(number);
}-*/;
+ /**
+ * Takes a String value e.g. "12px" and parses that to int 12.
+ *
+ * <p>
+ * This method returns 0 for <code>NaN</code>.
+ *
+ * @param String
+ * a value starting with a number
+ * @return int the value from the string before any non-numeric characters.
+ * If the value cannot be parsed to a number, returns 0.
+ */
+ private static native int parseIntNative(final String value)
+ /*-{
+ var number = parseInt(value, 10);
+ if (isNaN(number))
+ return 0;
+ else
+ return number;
+ }-*/;
+
}
diff --git a/client/src/com/vaadin/client/LayoutManager.java b/client/src/com/vaadin/client/LayoutManager.java
index 1f9884de67..5d27527793 100644
--- a/client/src/com/vaadin/client/LayoutManager.java
+++ b/client/src/com/vaadin/client/LayoutManager.java
@@ -322,17 +322,22 @@ public class LayoutManager {
Collection<ElementResizeListener> listeners = elementResizeListeners
.get(element);
if (listeners != null) {
+ Profiler.enter("Layout fire resize events - listeners not null");
+ Profiler.enter("ElementResizeListener.onElementResize copy list");
ElementResizeListener[] array = listeners
.toArray(new ElementResizeListener[listeners
.size()]);
+ Profiler.leave("ElementResizeListener.onElementResize copy list");
ElementResizeEvent event = new ElementResizeEvent(this,
element);
for (ElementResizeListener listener : array) {
try {
String key = null;
if (Profiler.isEnabled()) {
- key = "ElementReizeListener.onElementReize for "
+ Profiler.enter("ElementResizeListener.onElementResize construct profiler key");
+ key = "ElementResizeListener.onElementResize for "
+ Util.getSimpleName(listener);
+ Profiler.leave("ElementResizeListener.onElementResize construct profiler key");
Profiler.enter(key);
}
@@ -344,6 +349,7 @@ public class LayoutManager {
VConsole.error(e);
}
}
+ Profiler.leave("Layout fire resize events - listeners not null");
}
}
listenersToFire.clear();
@@ -716,13 +722,19 @@ public class LayoutManager {
private void onConnectorChange(ComponentConnector connector,
boolean widthChanged, boolean heightChanged) {
Profiler.enter("LayoutManager.onConnectorChange");
+ Profiler.enter("LayoutManager.onConnectorChange setNeedsOverflowFix");
setNeedsOverflowFix(connector);
+ Profiler.leave("LayoutManager.onConnectorChange setNeedsOverflowFix");
+ Profiler.enter("LayoutManager.onConnectorChange heightChanged");
if (heightChanged) {
currentDependencyTree.markHeightAsChanged(connector);
}
+ Profiler.leave("LayoutManager.onConnectorChange heightChanged");
+ Profiler.enter("LayoutManager.onConnectorChange widthChanged");
if (widthChanged) {
currentDependencyTree.markWidthAsChanged(connector);
}
+ Profiler.leave("LayoutManager.onConnectorChange widthChanged");
Profiler.leave("LayoutManager.onConnectorChange");
}
diff --git a/client/src/com/vaadin/client/Profiler.java b/client/src/com/vaadin/client/Profiler.java
index caa512b34e..083f2559b1 100644
--- a/client/src/com/vaadin/client/Profiler.java
+++ b/client/src/com/vaadin/client/Profiler.java
@@ -224,7 +224,7 @@ public class Profiler {
&& eventName.equals(stack.get(stack.size() - 2).getName())
&& !isBeginEvent) {
// back out of sub event
- stackTop.addTime(gwtStatsEvent.getMillis());
+ stackTop.leave(gwtStatsEvent.getMillis());
stack.removeLast();
stackTop = stack.getLast();
@@ -240,7 +240,7 @@ public class Profiler {
return;
}
Node previousStackTop = stack.removeLast();
- previousStackTop.addTime(gwtStatsEvent.getMillis());
+ previousStackTop.leave(gwtStatsEvent.getMillis());
} else {
if (!inEvent) {
stackTop = stackTop.enterChild(eventName,
@@ -273,7 +273,9 @@ public class Profiler {
}
});
- getConsumer().addProfilerData(stack.getFirst(), totalList);
+ if (getConsumer() != null) {
+ getConsumer().addProfilerData(stack.getFirst(), totalList);
+ }
}
/**
@@ -325,7 +327,9 @@ public class Profiler {
return;
}
- getConsumer().addBootstrapData(timings);
+ if (getConsumer() != null) {
+ getConsumer().addBootstrapData(timings);
+ }
}
}
@@ -386,11 +390,11 @@ public class Profiler {
* <b>Warning!</b> This is internal API and should not be used by
* applications or add-ons.
*
- * @since 7.1
+ * @since 7.1.4
* @param profilerResultConsumer
* the consumer that gets profiler data
*/
- public static void setProfilerResultConsuer(
+ public static void setProfilerResultConsumer(
ProfilerResultConsumer profilerResultConsumer) {
if (consumer != null) {
throw new IllegalStateException("The consumer has already been set");
@@ -399,11 +403,7 @@ public class Profiler {
}
private static ProfilerResultConsumer getConsumer() {
- if (consumer == null) {
- throw new IllegalStateException("No consumer has been registered");
- } else {
- return consumer;
- }
+ return consumer;
}
private static Logger getLogger() {
diff --git a/client/src/com/vaadin/client/debug/internal/ProfilerSection.java b/client/src/com/vaadin/client/debug/internal/ProfilerSection.java
index aa40e8ff17..4a2a3a1c38 100644
--- a/client/src/com/vaadin/client/debug/internal/ProfilerSection.java
+++ b/client/src/com/vaadin/client/debug/internal/ProfilerSection.java
@@ -71,6 +71,9 @@ public class ProfilerSection implements Section {
private final LinkedHashMap<String, Node> children = new LinkedHashMap<String, Node>();
private double time = 0;
private int count = 0;
+ private double enterTime = 0;
+ private double minTime = 1000000000;
+ private double maxTime = 0;
/**
* Create a new node with the given name.
@@ -96,17 +99,17 @@ public class ProfilerSection implements Section {
*
* @param name
* the name of the child
- * @param time
+ * @param timestamp
* the timestamp for when the node is entered
* @return the child node object
*/
- public Node enterChild(String name, double time) {
+ public Node enterChild(String name, double timestamp) {
Node child = children.get(name);
if (child == null) {
child = new Node(name);
children.put(name, child);
}
- child.time -= time;
+ child.enterTime = timestamp;
child.count++;
return child;
}
@@ -122,6 +125,26 @@ public class ProfilerSection implements Section {
}
/**
+ * Gets the minimum time spent for one invocation of this node,
+ * including time spent in sub nodes
+ *
+ * @return the time spent for the fastest invocation, in milliseconds
+ */
+ public double getMinTimeSpent() {
+ return minTime;
+ }
+
+ /**
+ * Gets the maximum time spent for one invocation of this node,
+ * including time spent in sub nodes
+ *
+ * @return the time spent for the slowest invocation, in milliseconds
+ */
+ public double getMaxTimeSpent() {
+ return maxTime;
+ }
+
+ /**
* Gets the number of times this node has been entered
*
* @return the number of times the node has been entered
@@ -180,7 +203,11 @@ public class ProfilerSection implements Section {
+ getCount()
+ " times ("
+ roundToSignificantFigures(getTimeSpent() / getCount())
- + " ms per time).";
+ + " ms per time, min "
+ + roundToSignificantFigures(getMinTimeSpent())
+ + " ms, max "
+ + roundToSignificantFigures(getMaxTimeSpent())
+ + " ms).";
}
if (!children.isEmpty()) {
double ownTime = getOwnTime();
@@ -221,6 +248,10 @@ public class ProfilerSection implements Section {
totalNode.time += getOwnTime();
totalNode.count += getCount();
+ totalNode.minTime = Math.min(totalNode.minTime,
+ getMinTimeSpent());
+ totalNode.maxTime = Math.max(totalNode.maxTime,
+ getMaxTimeSpent());
}
for (Node node : children.values()) {
node.sumUpTotals(totals);
@@ -228,11 +259,18 @@ public class ProfilerSection implements Section {
}
/**
- * @since
- * @param time
+ * @param timestamp
*/
- public void addTime(double time) {
- this.time += time;
+ public void leave(double timestamp) {
+ double elapsed = (timestamp - enterTime);
+ time += elapsed;
+ enterTime = 0;
+ if (elapsed < minTime) {
+ minTime = elapsed;
+ }
+ if (elapsed > maxTime) {
+ maxTime = elapsed;
+ }
}
}
@@ -245,7 +283,7 @@ public class ProfilerSection implements Section {
private final FlowPanel content = new FlowPanel();
public ProfilerSection() {
- Profiler.setProfilerResultConsuer(new ProfilerResultConsumer() {
+ Profiler.setProfilerResultConsumer(new ProfilerResultConsumer() {
@Override
public void addProfilerData(Node rootNode, List<Node> totals) {
double totalTime = 0;
diff --git a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java
index d384549ee3..6f98e29d03 100644
--- a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java
+++ b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java
@@ -150,17 +150,23 @@ public abstract class AbstractComponentConnector extends AbstractConnector
}
Profiler.leave("AbstractComponentConnector.onStateChanged update tab index");
+ Profiler.enter("AbstractComponentConnector.onStateChanged AbstractConnector.onStateChanged()");
super.onStateChanged(stateChangeEvent);
+ Profiler.leave("AbstractComponentConnector.onStateChanged AbstractConnector.onStateChanged()");
// Style names
+ Profiler.enter("AbstractComponentConnector.onStateChanged updateWidgetStyleNames");
updateWidgetStyleNames();
+ Profiler.leave("AbstractComponentConnector.onStateChanged updateWidgetStyleNames");
/*
* updateComponentSize need to be after caption update so caption can be
* taken into account
*/
+ Profiler.enter("AbstractComponentConnector.onStateChanged updateComponentSize");
updateComponentSize();
+ Profiler.leave("AbstractComponentConnector.onStateChanged updateComponentSize");
Profiler.enter("AbstractComponentContainer.onStateChanged check tooltip");
if (!tooltipListenersAttached && hasTooltip()) {
diff --git a/client/src/com/vaadin/client/ui/VCssLayout.java b/client/src/com/vaadin/client/ui/VCssLayout.java
index 4357116707..e4fac6acb3 100644
--- a/client/src/com/vaadin/client/ui/VCssLayout.java
+++ b/client/src/com/vaadin/client/ui/VCssLayout.java
@@ -44,13 +44,25 @@ public class VCssLayout extends FlowPanel {
public void addOrMove(Widget child, int index) {
Profiler.enter("VCssLayout.addOrMove");
if (child.getParent() == this) {
+ Profiler.enter("VCssLayout.addOrMove getWidgetIndex");
int currentIndex = getWidgetIndex(child);
+ Profiler.leave("VCssLayout.addOrMove getWidgetIndex");
if (index == currentIndex) {
Profiler.leave("VCssLayout.addOrMove");
return;
}
+ } else if (index == getWidgetCount()) {
+ // optimized path for appending components - faster especially for
+ // initial rendering
+ Profiler.enter("VCssLayout.addOrMove add");
+ add(child);
+ Profiler.leave("VCssLayout.addOrMove add");
+ Profiler.leave("VCssLayout.addOrMove");
+ return;
}
+ Profiler.enter("VCssLayout.addOrMove insert");
insert(child, index);
+ Profiler.leave("VCssLayout.addOrMove insert");
Profiler.leave("VCssLayout.addOrMove");
}
}
diff --git a/client/src/com/vaadin/client/ui/VFilterSelect.java b/client/src/com/vaadin/client/ui/VFilterSelect.java
index a5c1e566ca..7aac581008 100644
--- a/client/src/com/vaadin/client/ui/VFilterSelect.java
+++ b/client/src/com/vaadin/client/ui/VFilterSelect.java
@@ -1803,6 +1803,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
|| suggestionPopup.isJustClosed()) {
// typing so fast the popup was never opened, or it's just
// closed
+ waitingForFilteringResponse = false;
suggestionPopup.menu.doSelectedItemAction();
}
if (selectedOptionKey == null) {
diff --git a/client/src/com/vaadin/client/ui/VPopupCalendar.java b/client/src/com/vaadin/client/ui/VPopupCalendar.java
index e431da127d..57a0222118 100644
--- a/client/src/com/vaadin/client/ui/VPopupCalendar.java
+++ b/client/src/com/vaadin/client/ui/VPopupCalendar.java
@@ -217,9 +217,6 @@ public class VPopupCalendar extends VTextualDate implements Field,
}
}
}
- if (isImmediate()) {
- getClient().sendPendingVariableChanges();
- }
}
}
diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java
index fd28e4137e..18df2222a4 100644
--- a/client/src/com/vaadin/client/ui/VWindow.java
+++ b/client/src/com/vaadin/client/ui/VWindow.java
@@ -536,6 +536,37 @@ public class VWindow extends VWindowOverlay implements
if (!visibilityChangesDisabled) {
super.setVisible(visible);
}
+
+ if (visible && BrowserInfo.get().isWebkit()) {
+
+ /*
+ * Shake up the DOM a bit to make the window shed unnecessary
+ * scrollbars and resize correctly afterwards. This resulting code
+ * took over a week to summon forth, and involved some pretty hairy
+ * black magic. Don't touch it unless you know what you're doing!
+ * Fixes ticket #11994
+ */
+ Scheduler.get().scheduleFinally(new ScheduledCommand() {
+ @Override
+ public void execute() {
+ final com.google.gwt.dom.client.Element scrollable = contents
+ .getFirstChildElement();
+ final String oldWidth = scrollable.getStyle().getWidth();
+ final String oldHeight = scrollable.getStyle().getHeight();
+
+ scrollable.getStyle().setWidth(110, Unit.PCT);
+ scrollable.getOffsetWidth();
+ scrollable.getStyle().setProperty("width", oldWidth);
+
+ scrollable.getStyle().setHeight(110, Unit.PCT);
+ scrollable.getOffsetHeight();
+ scrollable.getStyle().setProperty("height", oldHeight);
+
+ updateContentsSize();
+ positionOrSizeUpdated();
+ }
+ });
+ }
}
/** For internal use only. May be removed or replaced in the future. */
diff --git a/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java b/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java
index 4c8d1a3ecc..45e52c890e 100644
--- a/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java
+++ b/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java
@@ -22,6 +22,7 @@ import com.vaadin.client.BrowserInfo;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.FastStringMap;
+import com.vaadin.client.Profiler;
import com.vaadin.client.Util;
import com.vaadin.client.VCaption;
import com.vaadin.client.communication.StateChangeEvent;
@@ -120,6 +121,8 @@ public class CssLayoutConnector extends AbstractLayoutConnector {
*/
@Override
public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
+ Profiler.enter("CssLayoutConnector.onConnectorHierarchyChange");
+ Profiler.enter("CssLayoutConnector.onConnectorHierarchyChange add children");
int index = 0;
for (ComponentConnector child : getChildComponents()) {
VCaption childCaption = childIdToCaption
@@ -129,8 +132,10 @@ public class CssLayoutConnector extends AbstractLayoutConnector {
}
getWidget().addOrMove(child.getWidget(), index++);
}
+ Profiler.leave("CssLayoutConnector.onConnectorHierarchyChange add children");
// Detach old child widgets and possibly their caption
+ Profiler.enter("CssLayoutConnector.onConnectorHierarchyChange remove old children");
for (ComponentConnector child : event.getOldChildren()) {
if (child.getParent() == this) {
// Skip current children
@@ -143,6 +148,8 @@ public class CssLayoutConnector extends AbstractLayoutConnector {
getWidget().remove(vCaption);
}
}
+ Profiler.leave("CssLayoutConnector.onConnectorHierarchyChange remove old children");
+ Profiler.leave("CssLayoutConnector.onConnectorHierarchyChange");
}
/**
diff --git a/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java b/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java
index 7257af4a08..627478ebe5 100644
--- a/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java
+++ b/client/src/com/vaadin/client/ui/datefield/PopupDateFieldConnector.java
@@ -18,6 +18,9 @@ package com.vaadin.client.ui.datefield;
import java.util.Date;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.user.client.ui.PopupPanel;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.DateTimeService;
import com.vaadin.client.UIDL;
@@ -36,6 +39,35 @@ public class PopupDateFieldConnector extends TextualDateConnector {
/*
* (non-Javadoc)
*
+ * @see com.vaadin.client.ui.AbstractConnector#init()
+ */
+ @Override
+ protected void init() {
+ getWidget().popup.addCloseHandler(new CloseHandler<PopupPanel>() {
+
+ @Override
+ public void onClose(CloseEvent<PopupPanel> event) {
+ /*
+ * FIXME This is a hack so we do not have to rewrite half of the
+ * datefield so values are not sent while selecting a date
+ * (#6252).
+ *
+ * The datefield will now only set the date UIDL variables while
+ * the user is selecting year/month/date/time and not send them
+ * directly. Only when the user closes the popup (by clicking on
+ * a day/enter/clicking outside of popup) then the new value is
+ * communicated to the server.
+ */
+ if (getWidget().isImmediate()) {
+ getConnection().sendPendingVariableChanges();
+ }
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
* @see com.vaadin.client.ui.VTextualDate#updateFromUIDL(com.vaadin
* .client.UIDL, com.vaadin.client.ApplicationConnection)
*/
diff --git a/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java b/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java
index dd838fdeff..b4cf008a38 100644
--- a/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java
+++ b/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java
@@ -93,9 +93,7 @@ public class VDragAndDropManager {
targetElement = targetNode.getParentElement();
}
- if (Util.isTouchEvent(nativeEvent)
- || (dragElement != null && dragElement
- .isOrHasChild(targetElement))) {
+ if (Util.isTouchEvent(nativeEvent) || dragElement != null) {
// to detect the "real" target, hide dragelement temporary and
// use elementFromPoint
String display = dragElement.getStyle().getDisplay();
diff --git a/client/src/com/vaadin/client/ui/layout/LayoutDependencyTree.java b/client/src/com/vaadin/client/ui/layout/LayoutDependencyTree.java
index 2ce45623d0..e148742b0b 100644
--- a/client/src/com/vaadin/client/ui/layout/LayoutDependencyTree.java
+++ b/client/src/com/vaadin/client/ui/layout/LayoutDependencyTree.java
@@ -26,6 +26,7 @@ import com.vaadin.client.FastStringMap;
import com.vaadin.client.FastStringSet;
import com.vaadin.client.HasComponentsConnector;
import com.vaadin.client.JsArrayObject;
+import com.vaadin.client.Profiler;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.Util;
import com.vaadin.client.VConsole;
@@ -267,6 +268,7 @@ public class LayoutDependencyTree {
}
public void markSizeAsChanged() {
+ Profiler.enter("LayoutDependency.markSizeAsChanged phase 1");
// When the size has changed, all that use that size should be
// layouted
JsArrayString needsSizeForLayout = getNeedsSizeForLayout();
@@ -276,14 +278,20 @@ public class LayoutDependencyTree {
LayoutDependency layoutDependency = getDependency(connectorId,
direction);
if (layoutDependency.connector instanceof ManagedLayout) {
+ Profiler.enter("LayoutDependency.markSizeAsChanged setNeedsLayout");
layoutDependency.setNeedsLayout(true);
+ Profiler.leave("LayoutDependency.markSizeAsChanged setNeedsLayout");
} else {
+ Profiler.enter("LayoutDependency.markSizeAsChanged propagatePostLayoutMeasure");
// Should simulate setNeedsLayout(true) + markAsLayouted ->
// propagate needs measure
layoutDependency.propagatePostLayoutMeasure();
+ Profiler.leave("LayoutDependency.markSizeAsChanged propagatePostLayoutMeasure");
}
}
+ Profiler.leave("LayoutDependency.markSizeAsChanged phase 1");
+ Profiler.enter("LayoutDependency.markSizeAsChanged scrollbars");
// Should also go through the hierarchy to discover appeared or
// disappeared scrollbars
ComponentConnector scrollingBoundary = getScrollingBoundary(connector);
@@ -291,6 +299,7 @@ public class LayoutDependencyTree {
getDependency(scrollingBoundary.getConnectorId(),
getOppositeDirection()).setNeedsMeasure(true);
}
+ Profiler.leave("LayoutDependency.markSizeAsChanged scrollbars");
}
@@ -332,22 +341,28 @@ public class LayoutDependencyTree {
}
private void propagatePostLayoutMeasure() {
+ Profiler.enter("LayoutDependency.propagatePostLayoutMeasure getResizedByLayout");
JsArrayString resizedByLayout = getResizedByLayout();
+ Profiler.leave("LayoutDependency.propagatePostLayoutMeasure getResizedByLayout");
int length = resizedByLayout.length();
for (int i = 0; i < length; i++) {
+ Profiler.enter("LayoutDependency.propagatePostLayoutMeasure setNeedsMeasure");
String resizedId = resizedByLayout.get(i);
LayoutDependency layoutDependency = getDependency(resizedId,
direction);
layoutDependency.setNeedsMeasure(true);
+ Profiler.leave("LayoutDependency.propagatePostLayoutMeasure setNeedsMeasure");
}
// Special case for e.g. wrapping texts
+ Profiler.enter("LayoutDependency.propagatePostLayoutMeasure horizontal case");
if (direction == HORIZONTAL && !connector.isUndefinedWidth()
&& connector.isUndefinedHeight()) {
LayoutDependency dependency = getDependency(
connector.getConnectorId(), VERTICAL);
dependency.setNeedsMeasure(true);
}
+ Profiler.leave("LayoutDependency.propagatePostLayoutMeasure horizontal case");
}
@Override
diff --git a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
index cea993310f..e0dc0d51df 100644
--- a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
+++ b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
@@ -294,7 +294,11 @@ public abstract class AbstractOrderedLayoutConnector extends
int currentIndex = 0;
VAbstractOrderedLayout layout = getWidget();
- layout.setSpacing(getState().spacing);
+ // remove spacing as it is exists as separate elements that cannot be
+ // removed easily after reordering the contents
+ Profiler.enter("AOLC.onConnectorHierarchyChange addOrMoveSlot temporarily remove spacing");
+ layout.setSpacing(false);
+ Profiler.leave("AOLC.onConnectorHierarchyChange addOrMoveSlot temporarily remove spacing");
for (ComponentConnector child : getChildComponents()) {
Profiler.enter("AOLC.onConnectorHierarchyChange add children");
@@ -305,12 +309,20 @@ public abstract class AbstractOrderedLayoutConnector extends
Profiler.leave("AOLC.onConnectorHierarchyChange add state change handler");
}
Profiler.enter("AOLC.onConnectorHierarchyChange addOrMoveSlot");
- layout.addOrMoveSlot(slot, currentIndex++);
+ layout.addOrMoveSlot(slot, currentIndex++, false);
Profiler.leave("AOLC.onConnectorHierarchyChange addOrMoveSlot");
Profiler.leave("AOLC.onConnectorHierarchyChange add children");
}
+ // re-add spacing for the elements that should have it
+ Profiler.enter("AOLC.onConnectorHierarchyChange addOrMoveSlot setSpacing");
+ // spacings were removed above
+ if (getState().spacing) {
+ layout.setSpacing(true);
+ }
+ Profiler.leave("AOLC.onConnectorHierarchyChange addOrMoveSlot setSpacing");
+
for (ComponentConnector child : previousChildren) {
Profiler.enter("AOLC.onConnectorHierarchyChange remove children");
if (child.getParent() != this) {
@@ -325,7 +337,7 @@ public abstract class AbstractOrderedLayoutConnector extends
child.removeStateChangeHandler(childStateChangeHandler);
layout.removeWidget(child.getWidget());
}
- Profiler.leave("AOL.onConnectorHierarchyChange remove children");
+ Profiler.leave("AOLC.onConnectorHierarchyChange remove children");
}
Profiler.leave("AOLC.onConnectorHierarchyChange");
@@ -363,6 +375,7 @@ public abstract class AbstractOrderedLayoutConnector extends
Slot slot = Util.findWidget(
(com.google.gwt.user.client.Element) element, Slot.class);
if (slot != null && slot.getCaptionElement() != null
+ && slot.getParent() == getWidget()
&& slot.getCaptionElement().isOrHasChild(element)) {
ComponentConnector connector = Util.findConnectorFor(slot
.getWidget());
diff --git a/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java b/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java
index b5a6262693..54c9eb6c68 100644
--- a/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java
+++ b/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java
@@ -31,6 +31,7 @@ import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.BrowserInfo;
import com.vaadin.client.LayoutManager;
+import com.vaadin.client.Profiler;
import com.vaadin.client.Util;
import com.vaadin.shared.ui.MarginInfo;
@@ -63,6 +64,23 @@ public class VAbstractOrderedLayout extends FlowPanel {
}
/**
+ * See the method {@link #addOrMoveSlot(Slot, int, boolean)}.
+ *
+ * <p>
+ * This method always adjusts spacings for the whole layout.
+ *
+ * @param slot
+ * The slot to move or add
+ * @param index
+ * The index where the slot should be placed.
+ * @deprecated since 7.1.4, use {@link #addOrMoveSlot(Slot, int, boolean)}
+ */
+ @Deprecated
+ public void addOrMoveSlot(Slot slot, int index) {
+ addOrMoveSlot(slot, index, true);
+ }
+
+ /**
* Add or move a slot to another index.
* <p>
* For internal use only. May be removed or replaced in the future.
@@ -83,27 +101,42 @@ public class VAbstractOrderedLayout extends FlowPanel {
* </pre>
*
* When using this method never account for spacings.
+ * <p>
+ * The caller should remove all spacings before calling this method and
+ * re-add them (if necessary) after this method. This can be done before and
+ * after all slots have been added/moved.
* </p>
*
+ * @since 7.1.4
+ *
* @param slot
* The slot to move or add
* @param index
* The index where the slot should be placed.
+ * @param adjustSpacing
+ * true to recalculate spacings for the whole layout after the
+ * operation
*/
- public void addOrMoveSlot(Slot slot, int index) {
+ public void addOrMoveSlot(Slot slot, int index, boolean adjustSpacing) {
+ Profiler.enter("VAOL.onConnectorHierarchyChange addOrMoveSlot find index");
if (slot.getParent() == this) {
int currentIndex = getWidgetIndex(slot);
if (index == currentIndex) {
+ Profiler.leave("VAOL.onConnectorHierarchyChange addOrMoveSlot find index");
return;
}
}
+ Profiler.leave("VAOL.onConnectorHierarchyChange addOrMoveSlot find index");
+ Profiler.enter("VAOL.onConnectorHierarchyChange addOrMoveSlot insert");
insert(slot, index);
+ Profiler.leave("VAOL.onConnectorHierarchyChange addOrMoveSlot insert");
- /*
- * We need to confirm spacings are correctly applied after each insert.
- */
- setSpacing(spacing);
+ if (adjustSpacing) {
+ Profiler.enter("VAOL.onConnectorHierarchyChange addOrMoveSlot setSpacing");
+ setSpacing(spacing);
+ Profiler.leave("VAOL.onConnectorHierarchyChange addOrMoveSlot setSpacing");
+ }
}
/**
@@ -329,14 +362,18 @@ public class VAbstractOrderedLayout extends FlowPanel {
* True if spacing should be used, false if not
*/
public void setSpacing(boolean spacing) {
+ Profiler.enter("VAOL.onConnectorHierarchyChange setSpacing");
this.spacing = spacing;
+ // first widget does not have spacing on
+ // optimization to avoid looking up widget indices on every iteration
+ Widget firstSlot = null;
+ if (getWidgetCount() > 0) {
+ firstSlot = getWidget(0);
+ }
for (Slot slot : widgetToSlot.values()) {
- if (getWidgetIndex(slot) > 0) {
- slot.setSpacing(spacing);
- } else {
- slot.setSpacing(false);
- }
+ slot.setSpacing(spacing && firstSlot != slot);
}
+ Profiler.leave("VAOL.onConnectorHierarchyChange setSpacing");
}
/**
diff --git a/client/src/com/vaadin/client/ui/panel/PanelConnector.java b/client/src/com/vaadin/client/ui/panel/PanelConnector.java
index fe211901c9..4011f86c76 100644
--- a/client/src/com/vaadin/client/ui/panel/PanelConnector.java
+++ b/client/src/com/vaadin/client/ui/panel/PanelConnector.java
@@ -23,6 +23,7 @@ import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.LayoutManager;
import com.vaadin.client.Paintable;
+import com.vaadin.client.Profiler;
import com.vaadin.client.UIDL;
import com.vaadin.client.ui.AbstractSingleComponentContainerConnector;
import com.vaadin.client.ui.ClickEventHandler;
@@ -194,22 +195,31 @@ public class PanelConnector extends AbstractSingleComponentContainerConnector
VPanel panel = getWidget();
LayoutManager layoutManager = getLayoutManager();
+ Profiler.enter("PanelConnector.layout getHeights");
int top = layoutManager.getOuterHeight(panel.captionNode);
int bottom = layoutManager.getInnerHeight(panel.bottomDecoration);
+ Profiler.leave("PanelConnector.layout getHeights");
+ Profiler.enter("PanelConnector.layout modify style");
Style style = panel.getElement().getStyle();
panel.captionNode.getParentElement().getStyle()
.setMarginTop(-top, Unit.PX);
panel.bottomDecoration.getStyle().setMarginBottom(-bottom, Unit.PX);
style.setPaddingTop(top, Unit.PX);
style.setPaddingBottom(bottom, Unit.PX);
+ Profiler.leave("PanelConnector.layout modify style");
// Update scroll positions
+ Profiler.enter("PanelConnector.layout update scroll positions");
panel.contentNode.setScrollTop(panel.scrollTop);
panel.contentNode.setScrollLeft(panel.scrollLeft);
+ Profiler.leave("PanelConnector.layout update scroll positions");
+
// Read actual value back to ensure update logic is correct
+ Profiler.enter("PanelConnector.layout read scroll positions");
panel.scrollTop = panel.contentNode.getScrollTop();
panel.scrollLeft = panel.contentNode.getScrollLeft();
+ Profiler.leave("PanelConnector.layout read scroll positions");
}
@Override