summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/ApplicationConfiguration.java6
-rw-r--r--client/src/com/vaadin/client/ApplicationConnection.java55
-rw-r--r--client/src/com/vaadin/client/ConnectorMap.java3
-rw-r--r--client/src/com/vaadin/client/FastStringMap.java2
-rw-r--r--client/src/com/vaadin/client/JsArrayObject.java2
-rw-r--r--client/src/com/vaadin/client/VCaption.java24
-rw-r--r--client/src/com/vaadin/client/VTooltip.java2
-rw-r--r--client/src/com/vaadin/client/metadata/AsyncBundleLoader.java4
-rw-r--r--client/src/com/vaadin/client/metadata/TypeDataStore.java19
-rw-r--r--client/src/com/vaadin/client/ui/AbstractComponentConnector.java93
-rw-r--r--client/src/com/vaadin/client/ui/AbstractConnector.java4
-rw-r--r--client/src/com/vaadin/client/ui/VAbsoluteLayout.java11
-rw-r--r--client/src/com/vaadin/client/ui/VCssLayout.java4
-rw-r--r--client/src/com/vaadin/client/ui/VScrollTable.java508
-rw-r--r--client/src/com/vaadin/client/ui/VTextField.java15
-rw-r--r--client/src/com/vaadin/client/ui/VTreeTable.java38
-rw-r--r--client/src/com/vaadin/client/ui/VUI.java3
-rw-r--r--client/src/com/vaadin/client/ui/label/LabelConnector.java6
-rw-r--r--client/src/com/vaadin/client/ui/link/LinkConnector.java6
-rw-r--r--client/src/com/vaadin/client/ui/table/TableConnector.java1
-rw-r--r--client/src/com/vaadin/client/ui/tabsheet/TabsheetBaseConnector.java8
-rw-r--r--client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java6
-rw-r--r--client/src/com/vaadin/client/ui/ui/UIConnector.java19
23 files changed, 710 insertions, 129 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConfiguration.java b/client/src/com/vaadin/client/ApplicationConfiguration.java
index 5c3ec36d78..9ba660626e 100644
--- a/client/src/com/vaadin/client/ApplicationConfiguration.java
+++ b/client/src/com/vaadin/client/ApplicationConfiguration.java
@@ -381,11 +381,14 @@ public class ApplicationConfiguration implements EntryPoint {
@Override
public void execute() {
+ Profiler.enter("ApplicationConfiguration.startApplication");
ApplicationConfiguration appConf = getConfigFromDOM(applicationId);
ApplicationConnection a = GWT
.create(ApplicationConnection.class);
a.init(widgetSet, appConf);
runningApplications.add(a);
+ Profiler.leave("ApplicationConfiguration.startApplication");
+
a.start();
}
});
@@ -532,6 +535,8 @@ public class ApplicationConfiguration implements EntryPoint {
@Override
public void onModuleLoad() {
+ Profiler.reset();
+ Profiler.enter("ApplicationConfiguration.onModuleLoad");
BrowserInfo browserInfo = BrowserInfo.get();
@@ -567,6 +572,7 @@ public class ApplicationConfiguration implements EntryPoint {
VConsole.getImplementation().error(e);
}
});
+ Profiler.leave("ApplicationConfiguration.onModuleLoad");
if (SuperDevMode.enableBasedOnParameter()) {
// Do not start any application as super dev mode will refresh the
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java
index 44c7397655..de034a65a6 100644
--- a/client/src/com/vaadin/client/ApplicationConnection.java
+++ b/client/src/com/vaadin/client/ApplicationConnection.java
@@ -1311,8 +1311,6 @@ public class ApplicationConnection {
return;
}
- Profiler.reset();
-
VConsole.log("Handling message from server");
eventBus.fireEvent(new ResponseHandlingStartedEvent(this));
@@ -1397,15 +1395,12 @@ public class ApplicationConnection {
Profiler.leave("Handling locales");
Profiler.enter("Handling meta information");
- boolean repaintAll = false;
ValueMap meta = null;
if (json.containsKey("meta")) {
VConsole.log(" * Handling meta information");
meta = json.getValueMap("meta");
if (meta.containsKey("repaintAll")) {
- repaintAll = true;
- uIConnector.getWidget().clear();
- getConnectorMap().clear();
+ prepareRepaintAll();
if (meta.containsKey("invalidLayouts")) {
validatingLayouts = true;
}
@@ -1528,10 +1523,46 @@ public class ApplicationConnection {
endRequest();
if (Profiler.isEnabled()) {
- Profiler.logTimings();
- Profiler.reset();
+ Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+ @Override
+ public void execute() {
+ Profiler.logTimings();
+ Profiler.reset();
+ }
+ });
+ }
+
+ }
+
+ /**
+ * Properly clean up any old stuff to ensure everything is properly
+ * reinitialized.
+ */
+ private void prepareRepaintAll() {
+ String uiConnectorId = uIConnector.getConnectorId();
+ if (uiConnectorId == null) {
+ // Nothing to clear yet
+ return;
}
+ // Create fake server response that says that the uiConnector
+ // has no children
+ JSONObject fakeHierarchy = new JSONObject();
+ fakeHierarchy.put(uiConnectorId, new JSONArray());
+ JSONObject fakeJson = new JSONObject();
+ fakeJson.put("hierarchy", fakeHierarchy);
+ ValueMap fakeValueMap = fakeJson.getJavaScriptObject().cast();
+
+ // Update hierarchy based on the fake response
+ ConnectorHierarchyUpdateResult connectorHierarchyUpdateResult = updateConnectorHierarchy(fakeValueMap);
+
+ // Send hierarchy events based on the fake update
+ sendHierarchyChangeEvents(connectorHierarchyUpdateResult.events);
+
+ // Unregister all the old connectors that have now been removed
+ unregisterRemovedConnectors();
+
+ getLayoutManager().cleanMeasuredSizes();
}
private void updateCaptions(
@@ -1548,8 +1579,10 @@ public class ApplicationConnection {
// Find components with potentially changed caption state
for (StateChangeEvent event : pendingStateChangeEvents) {
- ServerConnector connector = event.getConnector();
- needsCaptionUpdate.add(connector);
+ if (VCaption.mightChange(event)) {
+ ServerConnector connector = event.getConnector();
+ needsCaptionUpdate.add(connector);
+ }
}
// Update captions for all suitable candidates
@@ -1916,6 +1949,7 @@ public class ApplicationConnection {
}
}
+ Profiler.enter("updateConnectorState newWithoutState");
// Fire events for properties using the default value for newly
// created connectors even if there were no state changes
for (ServerConnector connector : remainingNewConnectors) {
@@ -1928,6 +1962,7 @@ public class ApplicationConnection {
events.add(event);
}
+ Profiler.leave("updateConnectorState newWithoutState");
Profiler.leave("updateConnectorState");
diff --git a/client/src/com/vaadin/client/ConnectorMap.java b/client/src/com/vaadin/client/ConnectorMap.java
index 5f6053dd32..810f12824a 100644
--- a/client/src/com/vaadin/client/ConnectorMap.java
+++ b/client/src/com/vaadin/client/ConnectorMap.java
@@ -126,8 +126,9 @@ public class ConnectorMap {
componentDetail.setConnector(connector);
if (connector instanceof ComponentConnector) {
ComponentConnector pw = (ComponentConnector) connector;
+ Widget widget = pw.getWidget();
Profiler.enter("ConnectorMap.setConnectorId");
- setConnectorId(pw.getWidget().getElement(), id);
+ setConnectorId(widget.getElement(), id);
Profiler.leave("ConnectorMap.setConnectorId");
}
Profiler.leave("ConnectorMap.registerConnector");
diff --git a/client/src/com/vaadin/client/FastStringMap.java b/client/src/com/vaadin/client/FastStringMap.java
index cbb61427d2..5b15b1263a 100644
--- a/client/src/com/vaadin/client/FastStringMap.java
+++ b/client/src/com/vaadin/client/FastStringMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Vaadin Ltd.
+ * Copyright 2000-2013 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
diff --git a/client/src/com/vaadin/client/JsArrayObject.java b/client/src/com/vaadin/client/JsArrayObject.java
index 182b68ac3f..5b45650684 100644
--- a/client/src/com/vaadin/client/JsArrayObject.java
+++ b/client/src/com/vaadin/client/JsArrayObject.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Vaadin Ltd.
+ * Copyright 2000-2013 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
diff --git a/client/src/com/vaadin/client/VCaption.java b/client/src/com/vaadin/client/VCaption.java
index efa9be1850..47287636c4 100644
--- a/client/src/com/vaadin/client/VCaption.java
+++ b/client/src/com/vaadin/client/VCaption.java
@@ -20,6 +20,7 @@ import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.HTML;
+import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractFieldConnector;
import com.vaadin.client.ui.Icon;
import com.vaadin.shared.AbstractComponentState;
@@ -408,6 +409,29 @@ public class VCaption extends HTML {
}
/**
+ * Checks whether anything in a given state change might cause the caption
+ * to change.
+ *
+ * @param event
+ * the state change event to check
+ * @return <code>true</code> if the caption might have changed; otherwise
+ * <code>false</code>
+ */
+ public static boolean mightChange(StateChangeEvent event) {
+ if (event.hasPropertyChanged("caption")) {
+ return true;
+ }
+ if (event.hasPropertyChanged("resources")) {
+ return true;
+ }
+ if (event.hasPropertyChanged("errorMessage")) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
* Returns Paintable for which this Caption belongs to.
*
* @return owner Widget
diff --git a/client/src/com/vaadin/client/VTooltip.java b/client/src/com/vaadin/client/VTooltip.java
index 6e365b4017..759b90a8cd 100644
--- a/client/src/com/vaadin/client/VTooltip.java
+++ b/client/src/com/vaadin/client/VTooltip.java
@@ -366,8 +366,10 @@ public class VTooltip extends VOverlay {
* Widget which DOM handlers are connected
*/
public void connectHandlersToWidget(Widget widget) {
+ Profiler.enter("VTooltip.connectHandlersToWidget");
widget.addDomHandler(tooltipEventHandler, MouseMoveEvent.getType());
widget.addDomHandler(tooltipEventHandler, ClickEvent.getType());
widget.addDomHandler(tooltipEventHandler, KeyDownEvent.getType());
+ Profiler.leave("VTooltip.connectHandlersToWidget");
}
}
diff --git a/client/src/com/vaadin/client/metadata/AsyncBundleLoader.java b/client/src/com/vaadin/client/metadata/AsyncBundleLoader.java
index e0ebb5e047..6be89c9cc9 100644
--- a/client/src/com/vaadin/client/metadata/AsyncBundleLoader.java
+++ b/client/src/com/vaadin/client/metadata/AsyncBundleLoader.java
@@ -19,6 +19,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import com.vaadin.client.Profiler;
+
public abstract class AsyncBundleLoader {
public enum State {
NOT_STARTED, LOADING, LOADED, ERROR;
@@ -63,9 +65,11 @@ public abstract class AsyncBundleLoader {
public void load(BundleLoadCallback callback, TypeDataStore store) {
assert state == State.NOT_STARTED;
+ Profiler.enter("AsyncBundleLoader.load");
state = State.LOADING;
addCallback(callback);
load(store);
+ Profiler.leave("AsyncBundleLoader.load");
}
public void addCallback(BundleLoadCallback callback) {
diff --git a/client/src/com/vaadin/client/metadata/TypeDataStore.java b/client/src/com/vaadin/client/metadata/TypeDataStore.java
index 5b466146a3..c1eca0a168 100644
--- a/client/src/com/vaadin/client/metadata/TypeDataStore.java
+++ b/client/src/com/vaadin/client/metadata/TypeDataStore.java
@@ -38,6 +38,7 @@ public class TypeDataStore {
private final FastStringSet delayedMethods = FastStringSet.create();
private final FastStringSet lastOnlyMethods = FastStringSet.create();
+ private final FastStringSet hasGetTooltipInfo = FastStringSet.create();
private final FastStringMap<Type> returnTypes = FastStringMap.create();
private final FastStringMap<Invoker> invokers = FastStringMap.create();
@@ -276,4 +277,22 @@ public class TypeDataStore {
public static boolean hasProperties(Type type) {
return get().properties.containsKey(type.getSignature());
}
+
+ /**
+ * @deprecated As of 7.0.1. This is just a hack to avoid breaking backwards
+ * compatibility and will be removed in Vaadin 7.1
+ */
+ @Deprecated
+ public void setHasGetTooltipInfo(Class<?> clazz) {
+ hasGetTooltipInfo.add(getType(clazz).getSignature());
+ }
+
+ /**
+ * @deprecated As of 7.0.1. This is just a hack to avoid breaking backwards
+ * compatibility and will be removed in Vaadin 7.1
+ */
+ @Deprecated
+ public static boolean getHasGetTooltipInfo(Class clazz) {
+ return get().hasGetTooltipInfo.contains(getType(clazz).getSignature());
+ }
}
diff --git a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java
index e35e3eafcf..694db6f02c 100644
--- a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java
+++ b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java
@@ -15,9 +15,6 @@
*/
package com.vaadin.client.ui;
-import java.util.ArrayList;
-import java.util.List;
-
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.Focusable;
@@ -27,6 +24,7 @@ import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.HasComponentsConnector;
import com.vaadin.client.LayoutManager;
+import com.vaadin.client.Profiler;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.StyleConstants;
import com.vaadin.client.TooltipInfo;
@@ -37,6 +35,7 @@ import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.metadata.NoDataException;
import com.vaadin.client.metadata.Type;
import com.vaadin.client.metadata.TypeData;
+import com.vaadin.client.metadata.TypeDataStore;
import com.vaadin.client.ui.datefield.PopupDateFieldConnector;
import com.vaadin.client.ui.ui.UIConnector;
import com.vaadin.shared.AbstractComponentState;
@@ -55,6 +54,8 @@ public abstract class AbstractComponentConnector extends AbstractConnector
private boolean initialStateEvent = true;
+ private boolean tooltipListenersAttached = false;
+
/**
* The style names from getState().getStyles() which are currently applied
* to the widget.
@@ -67,14 +68,6 @@ public abstract class AbstractComponentConnector extends AbstractConnector
public AbstractComponentConnector() {
}
- @Override
- protected void init() {
- super.init();
-
- getConnection().getVTooltip().connectHandlersToWidget(getWidget());
-
- }
-
/**
* Creates and returns the widget for this VPaintableWidget. This method
* should only be called once when initializing the paintable.
@@ -105,7 +98,11 @@ public abstract class AbstractComponentConnector extends AbstractConnector
@Override
public Widget getWidget() {
if (widget == null) {
+ Profiler.enter("AbstractComponentConnector.createWidget for "
+ + Util.getSimpleName(this));
widget = createWidget();
+ Profiler.leave("AbstractComponentConnector.createWidget for "
+ + Util.getSimpleName(this));
}
return widget;
@@ -123,6 +120,8 @@ public abstract class AbstractComponentConnector extends AbstractConnector
@Override
public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ Profiler.enter("AbstractComponentConnector.onStateChanged");
+ Profiler.enter("AbstractComponentConnector.onStateChanged update id");
if (stateChangeEvent.hasPropertyChanged("id")) {
if (getState().id != null) {
getWidget().getElement().setId(getState().id);
@@ -130,17 +129,20 @@ public abstract class AbstractComponentConnector extends AbstractConnector
getWidget().getElement().removeAttribute("id");
}
}
+ Profiler.leave("AbstractComponentConnector.onStateChanged update id");
/*
* Disabled state may affect (override) tabindex so the order must be
* first setting tabindex, then enabled state (through super
* implementation).
*/
+ Profiler.enter("AbstractComponentConnector.onStateChanged update tab index");
if (getState() instanceof TabIndexState
&& getWidget() instanceof Focusable) {
((Focusable) getWidget())
.setTabIndex(((TabIndexState) getState()).tabIndex);
}
+ Profiler.leave("AbstractComponentConnector.onStateChanged update tab index");
super.onStateChanged(stateChangeEvent);
@@ -154,7 +156,20 @@ public abstract class AbstractComponentConnector extends AbstractConnector
updateComponentSize();
+ Profiler.enter("AbstractComponentContainer.onStateChanged check tooltip");
+ if (!tooltipListenersAttached && hasTooltip()) {
+ /*
+ * Add event handlers for tooltips if they are needed but have not
+ * yet been added.
+ */
+ tooltipListenersAttached = true;
+ getConnection().getVTooltip().connectHandlersToWidget(getWidget());
+ }
+ Profiler.leave("AbstractComponentContainer.onStateChanged check tooltip");
+
initialStateEvent = false;
+
+ Profiler.leave("AbstractComponentConnector.onStateChanged");
}
@Override
@@ -182,6 +197,8 @@ public abstract class AbstractComponentConnector extends AbstractConnector
}
private void updateComponentSize() {
+ Profiler.enter("AbstractComponentConnector.updateComponentSize");
+
String newWidth = getState().width == null ? "" : getState().width;
String newHeight = getState().height == null ? "" : getState().height;
@@ -209,11 +226,17 @@ public abstract class AbstractComponentConnector extends AbstractConnector
// Set defined sizes
Widget widget = getWidget();
+ Profiler.enter("AbstractComponentConnector.updateComponentSize update styleNames");
widget.setStyleName("v-has-width", !isUndefinedWidth());
widget.setStyleName("v-has-height", !isUndefinedHeight());
+ Profiler.leave("AbstractComponentConnector.updateComponentSize update styleNames");
+ Profiler.enter("AbstractComponentConnector.updateComponentSize update DOM");
widget.setHeight(newHeight);
widget.setWidth(newWidth);
+ Profiler.leave("AbstractComponentConnector.updateComponentSize update DOM");
+
+ Profiler.leave("AbstractComponentConnector.updateComponentSize");
}
@Override
@@ -257,10 +280,12 @@ public abstract class AbstractComponentConnector extends AbstractConnector
* </p>
*/
protected void updateWidgetStyleNames() {
+ Profiler.enter("AbstractComponentConnector.updateWidgetStyleNames");
AbstractComponentState state = getState();
String primaryStyleName = getWidget().getStylePrimaryName();
- if (state.primaryStyleName != null) {
+ if (state.primaryStyleName != null
+ && !state.primaryStyleName.equals(primaryStyleName)) {
/*
* We overwrite the widgets primary stylename if state defines a
* primary stylename.
@@ -302,7 +327,7 @@ public abstract class AbstractComponentConnector extends AbstractConnector
}
}
-
+ Profiler.leave("AbstractComponentConnector.updateWidgetStyleNames");
}
/**
@@ -394,11 +419,16 @@ public abstract class AbstractComponentConnector extends AbstractConnector
}
}
- /*
- * (non-Javadoc)
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * When overriding this method, {@link #hasTooltip()} should also be
+ * overridden to return true in all situations where this method might
+ * return a non-empty result.
+ * </p>
*
- * @see com.vaadin.client.ComponentConnector#getTooltipInfo(com.
- * google.gwt.dom.client.Element)
+ * @see ComponentConnector#getTooltipInfo(Element)
*/
@Override
public TooltipInfo getTooltipInfo(Element element) {
@@ -406,6 +436,35 @@ public abstract class AbstractComponentConnector extends AbstractConnector
}
/**
+ * Check whether there might be a tooltip for this component. The framework
+ * will only add event listeners for automatically handling tooltips (using
+ * {@link #getTooltipInfo(Element)}) if this method returns true.
+ *
+ * @return <code>true</code> if some part of the component might have a
+ * tooltip, otherwise <code>false</code>
+ */
+ private boolean hasTooltip() {
+ /*
+ * Hack to avoid breaking backwards compatibility - use a generator to
+ * know whether there's a custom implementation of getTooltipInfo, and
+ * in that case always assume that there might be tooltip.
+ */
+ if (TypeDataStore.getHasGetTooltipInfo(getClass())) {
+ return true;
+ }
+
+ // Normally, there is a tooltip if description or errorMessage is set
+ AbstractComponentState state = getState();
+ if (state.description != null && !state.description.equals("")) {
+ return true;
+ } else if (state.errorMessage != null && !state.errorMessage.equals("")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
* Gets the icon set for this component.
*
* @return the URL of the icon, or <code>null</code> if no icon has been
diff --git a/client/src/com/vaadin/client/ui/AbstractConnector.java b/client/src/com/vaadin/client/ui/AbstractConnector.java
index 32f5370dc3..2c76aa93fe 100644
--- a/client/src/com/vaadin/client/ui/AbstractConnector.java
+++ b/client/src/com/vaadin/client/ui/AbstractConnector.java
@@ -218,6 +218,7 @@ public abstract class AbstractConnector implements ServerConnector,
}
if (statePropertyHandlerManagers != null
&& event instanceof StateChangeEvent) {
+ Profiler.enter("AbstractConnector.fireEvent statePropertyHandlerManagers");
StateChangeEvent stateChangeEvent = (StateChangeEvent) event;
JsArrayString keys = statePropertyHandlerManagers.getKeys();
for (int i = 0; i < keys.length(); i++) {
@@ -226,6 +227,7 @@ public abstract class AbstractConnector implements ServerConnector,
statePropertyHandlerManagers.get(property).fireEvent(event);
}
}
+ Profiler.leave("AbstractConnector.fireEvent statePropertyHandlerManagers");
}
if (Profiler.isEnabled()) {
Profiler.leave(profilerKey);
@@ -400,6 +402,7 @@ public abstract class AbstractConnector implements ServerConnector,
if (lastEnabledState == enabledState) {
return;
}
+ Profiler.enter("AbstractConnector.updateEnabledState");
lastEnabledState = enabledState;
for (ServerConnector c : getChildren()) {
@@ -407,6 +410,7 @@ public abstract class AbstractConnector implements ServerConnector,
// their parent
c.updateEnabledState(c.isEnabled());
}
+ Profiler.leave("AbstractConnector.updateEnabledState");
}
/**
diff --git a/client/src/com/vaadin/client/ui/VAbsoluteLayout.java b/client/src/com/vaadin/client/ui/VAbsoluteLayout.java
index 92a51f209d..88fbae6e88 100644
--- a/client/src/com/vaadin/client/ui/VAbsoluteLayout.java
+++ b/client/src/com/vaadin/client/ui/VAbsoluteLayout.java
@@ -326,6 +326,10 @@ public class VAbsoluteLayout extends ComplexPanel {
Style wrapperStyle = wrapper.getElement().getStyle();
Style widgetStyle = wrapper.getWidget().getElement().getStyle();
+
+ // Ensure previous heights do not affect the measures
+ wrapperStyle.clearHeight();
+
if (widgetStyle.getHeight() != null
&& widgetStyle.getHeight().endsWith("%")) {
int h;
@@ -343,8 +347,6 @@ public class VAbsoluteLayout extends ComplexPanel {
- wrapper.getElement().getOffsetTop();
}
wrapperStyle.setHeight(h, Unit.PX);
- } else {
- wrapperStyle.clearHeight();
}
wrapper.updateCaptionPosition();
@@ -380,6 +382,9 @@ public class VAbsoluteLayout extends ComplexPanel {
Style wrapperStyle = wrapper.getElement().getStyle();
Style widgetStyle = wrapper.getWidget().getElement().getStyle();
+ // Ensure previous heights do not affect the measures
+ wrapperStyle.clearWidth();
+
if (widgetStyle.getWidth() != null
&& widgetStyle.getWidth().endsWith("%")) {
int w;
@@ -398,8 +403,6 @@ public class VAbsoluteLayout extends ComplexPanel {
- wrapper.getElement().getOffsetLeft();
}
wrapperStyle.setWidth(w, Unit.PX);
- } else {
- wrapperStyle.clearWidth();
}
wrapper.updateCaptionPosition();
diff --git a/client/src/com/vaadin/client/ui/VCssLayout.java b/client/src/com/vaadin/client/ui/VCssLayout.java
index 0936859ace..4357116707 100644
--- a/client/src/com/vaadin/client/ui/VCssLayout.java
+++ b/client/src/com/vaadin/client/ui/VCssLayout.java
@@ -18,6 +18,7 @@ package com.vaadin.client.ui;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.Profiler;
import com.vaadin.client.StyleConstants;
/**
@@ -41,12 +42,15 @@ public class VCssLayout extends FlowPanel {
* For internal use only. May be removed or replaced in the future.
*/
public void addOrMove(Widget child, int index) {
+ Profiler.enter("VCssLayout.addOrMove");
if (child.getParent() == this) {
int currentIndex = getWidgetIndex(child);
if (index == currentIndex) {
+ Profiler.leave("VCssLayout.addOrMove");
return;
}
}
insert(child, index);
+ Profiler.leave("VCssLayout.addOrMove");
}
}
diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java
index 75d67b82d6..c76dd38d8f 100644
--- a/client/src/com/vaadin/client/ui/VScrollTable.java
+++ b/client/src/com/vaadin/client/ui/VScrollTable.java
@@ -1191,6 +1191,39 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
return totalRows;
}
+ /**
+ * Returns the extra space that is given to the header column when column
+ * width is determined by header text.
+ *
+ * @return extra space in pixels
+ */
+ private int getHeaderPadding() {
+ return scrollBody.getCellExtraWidth();
+ }
+
+ /**
+ * This method exists for the needs of {@link VTreeTable} only. Not part of
+ * the official API, <b>extend at your own risk</b>. May be removed or
+ * replaced in the future.
+ *
+ * @return index of TreeTable's hierarchy column, or -1 if not applicable
+ */
+ protected int getHierarchyColumnIndex() {
+ return -1;
+ }
+
+ /**
+ * For internal use only. May be removed or replaced in the future.
+ */
+ public void updateMaxIndent() {
+ int oldIndent = scrollBody.getMaxIndent();
+ scrollBody.calculateMaxIndent();
+ if (oldIndent != scrollBody.getMaxIndent()) {
+ // indent updated, headers might need adjusting
+ triggerLazyColumnAdjustment(true);
+ }
+ }
+
/** For internal use only. May be removed or replaced in the future. */
public void focusRowFromBody() {
if (selectedRowKeys.size() == 1) {
@@ -1382,6 +1415,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* amount of rows in data set
*/
public void updateBody(UIDL uidl, int firstRow, int reqRows) {
+ int oldIndent = scrollBody.getMaxIndent();
if (uidl == null || reqRows < 1) {
// container is empty, remove possibly existing rows
if (firstRow <= 0) {
@@ -1399,6 +1433,11 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
scrollBody.renderRows(uidl, firstRow, reqRows);
discardRowsOutsideCacheWindow();
+ scrollBody.calculateMaxIndent();
+ if (oldIndent != scrollBody.getMaxIndent()) {
+ // indent updated, headers might need adjusting
+ headerChangedDuringUpdate = true;
+ }
}
/** For internal use only. May be removed or replaced in the future. */
@@ -1591,31 +1630,55 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
return tHead.getHeaderCell(index).getColKey();
}
- private void setColWidth(int colIndex, int w, boolean isDefinedWidth) {
+ /**
+ * Note: not part of the official API, extend at your own risk. May be
+ * removed or replaced in the future.
+ *
+ * Sets the indicated column's width for headers and scrollBody alike.
+ *
+ * @param colIndex
+ * index of the modified column
+ * @param w
+ * new width (may be subject to modifications if doesn't meet
+ * minimum requirements)
+ * @param isDefinedWidth
+ * disables expand ratio if set true
+ */
+ protected void setColWidth(int colIndex, int w, boolean isDefinedWidth) {
final HeaderCell hcell = tHead.getHeaderCell(colIndex);
// Make sure that the column grows to accommodate the sort indicator if
// necessary.
- if (w < hcell.getMinWidth()) {
- w = hcell.getMinWidth();
+ // get min width with no indent or padding
+ int minWidth = hcell.getMinWidth(false, false);
+ if (w < minWidth) {
+ w = minWidth;
}
- // Set header column width
+ // Set header column width WITHOUT INDENT
hcell.setWidth(w, isDefinedWidth);
+ // Set footer column width likewise
+ FooterCell fcell = tFoot.getFooterCell(colIndex);
+ fcell.setWidth(w, isDefinedWidth);
+
// Ensure indicators have been taken into account
tHead.resizeCaptionContainer(hcell);
+ // Make sure that the body column grows to accommodate the indent if
+ // necessary.
+ // get min width with indent, no padding
+ minWidth = hcell.getMinWidth(true, false);
+ if (w < minWidth) {
+ w = minWidth;
+ }
+
// Set body column width
scrollBody.setColWidth(colIndex, w);
-
- // Set footer column width
- FooterCell fcell = tFoot.getFooterCell(colIndex);
- fcell.setWidth(w, isDefinedWidth);
}
private int getColWidth(String colKey) {
- return tHead.getHeaderCell(colKey).getWidth();
+ return tHead.getHeaderCell(colKey).getWidthWithIndent();
}
/**
@@ -1813,22 +1876,37 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
tHead.enableBrowserIntelligence();
tFoot.enableBrowserIntelligence();
+ int hierarchyColumnIndent = scrollBody != null ? scrollBody
+ .getMaxIndent() : 0;
+ HeaderCell hierarchyHeaderWithExpandRatio = null;
+
// first loop: collect natural widths
while (headCells.hasNext()) {
final HeaderCell hCell = (HeaderCell) headCells.next();
final FooterCell fCell = (FooterCell) footCells.next();
+ boolean needsIndent = hierarchyColumnIndent > 0
+ && hCell.isHierarchyColumn();
int w = hCell.getWidth();
if (hCell.isDefinedWidth()) {
// server has defined column width explicitly
+ if (needsIndent && w < hierarchyColumnIndent) {
+ // hierarchy indent overrides explicitly set width
+ w = hierarchyColumnIndent;
+ }
totalExplicitColumnsWidths += w;
} else {
if (hCell.getExpandRatio() > 0) {
expandRatioDivider += hCell.getExpandRatio();
w = 0;
+ if (needsIndent && w < hierarchyColumnIndent) {
+ hierarchyHeaderWithExpandRatio = hCell;
+ // don't add to widths here, because will be included in
+ // the expand ratio space if there's enough of it
+ }
} else {
// get and store greater of header width and column width,
- // and
- // store it as a minimumn natural col width
+ // and store it as a minimum natural column width (these
+ // already contain the indent if any)
int headerWidth = hCell.getNaturalColumnWidth(i);
int footerWidth = fCell.getNaturalColumnWidth(i);
w = headerWidth > footerWidth ? headerWidth : footerWidth;
@@ -1840,6 +1918,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
total += w;
i++;
}
+ if (hierarchyHeaderWithExpandRatio != null) {
+ total += hierarchyColumnIndent;
+ }
tHead.disableBrowserIntelligence();
tFoot.disableBrowserIntelligence();
@@ -1871,13 +1952,24 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (availW > total) {
// natural size is smaller than available space
- final int extraSpace = availW - total;
+ int extraSpace = availW - total;
+ if (hierarchyHeaderWithExpandRatio != null) {
+ /*
+ * add the indent's space back to ensure each column gets an
+ * even share according to the expand ratios (note: if the
+ * allocated space isn't enough for the hierarchy column it
+ * shall be treated like a defined width column and the indent
+ * space gets removed from the extra space again)
+ */
+ extraSpace += hierarchyColumnIndent;
+ }
final int totalWidthR = total - totalExplicitColumnsWidths;
int checksum = 0;
if (extraSpace == 1) {
// We cannot divide one single pixel so we give it the first
// undefined column
+ // no need to worry about indent here
headCells = tHead.iterator();
i = 0;
checksum = availW;
@@ -1891,6 +1983,22 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
} else if (expandRatioDivider > 0) {
+ boolean setIndentToHierarchyHeader = false;
+ if (hierarchyHeaderWithExpandRatio != null) {
+ // ensure first that the hierarchyColumn gets at least the
+ // space allocated for indent
+ final int newSpace = Math
+ .round((extraSpace * (hierarchyHeaderWithExpandRatio
+ .getExpandRatio() / expandRatioDivider)));
+ if (newSpace < hierarchyColumnIndent) {
+ // not enough space for indent, remove indent from the
+ // extraSpace again and handle hierarchy column's header
+ // separately
+ setIndentToHierarchyHeader = true;
+ extraSpace -= hierarchyColumnIndent;
+ }
+ }
+
// visible columns have some active expand ratios, excess
// space is divided according to them
headCells = tHead.iterator();
@@ -1899,9 +2007,17 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
HeaderCell hCell = (HeaderCell) headCells.next();
if (hCell.getExpandRatio() > 0) {
int w = widths[i];
- final int newSpace = Math.round((extraSpace * (hCell
- .getExpandRatio() / expandRatioDivider)));
- w += newSpace;
+ if (setIndentToHierarchyHeader
+ && hierarchyHeaderWithExpandRatio.equals(hCell)) {
+ // hierarchy column's header is no longer part of
+ // the expansion divide and only gets indent
+ w += hierarchyColumnIndent;
+ } else {
+ final int newSpace = Math
+ .round((extraSpace * (hCell
+ .getExpandRatio() / expandRatioDivider)));
+ w += newSpace;
+ }
widths[i] = w;
}
checksum += widths[i];
@@ -1911,6 +2027,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
// no expand ratios defined, we will share extra space
// relatively to "natural widths" among those without
// explicit width
+ // no need to worry about indent here, it's already included
headCells = tHead.iterator();
i = 0;
while (headCells.hasNext()) {
@@ -1946,7 +2063,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
} else {
- // bodys size will be more than available and scrollbar will appear
+ // body's size will be more than available and scrollbar will appear
}
// last loop: set possibly modified values or reset if new tBody
@@ -2046,8 +2163,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
/**
- * Note, this method is not official api although declared as protected.
- * Extend at you own risk.
+ * Note: this method is not part of official API although declared as
+ * protected. Extend at your own risk.
*
* @return true if content area will have scrollbars visible.
*/
@@ -2430,6 +2547,16 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
expandRatio = 0;
}
+ /**
+ * Sets width to the header cell. This width should not include any
+ * possible indent modifications that are present in
+ * {@link VScrollTableBody#getMaxIndent()}.
+ *
+ * @param w
+ * required width of the cell sans indentations
+ * @param ensureDefinedWidth
+ * disables expand ratio if required
+ */
public void setWidth(int w, boolean ensureDefinedWidth) {
if (ensureDefinedWidth) {
definedWidth = true;
@@ -2453,15 +2580,23 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* unless TD width is not explicitly set.
*/
if (scrollBody != null) {
- int tdWidth = width + scrollBody.getCellExtraWidth();
+ int maxIndent = scrollBody.getMaxIndent();
+ if (w < maxIndent && isHierarchyColumn()) {
+ w = maxIndent;
+ }
+ int tdWidth = w + scrollBody.getCellExtraWidth();
setWidth(tdWidth + "px");
} else {
Scheduler.get().scheduleDeferred(new Command() {
@Override
public void execute() {
- int tdWidth = width
- + scrollBody.getCellExtraWidth();
+ int maxIndent = scrollBody.getMaxIndent();
+ int tdWidth = width;
+ if (tdWidth < maxIndent && isHierarchyColumn()) {
+ tdWidth = maxIndent;
+ }
+ tdWidth += scrollBody.getCellExtraWidth();
setWidth(tdWidth + "px");
}
});
@@ -2484,10 +2619,45 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
return definedWidth && width >= 0;
}
+ /**
+ * This method exists for the needs of {@link VTreeTable} only.
+ *
+ * Returns the pixels width of the header cell. This includes the
+ * indent, if applicable.
+ *
+ * @return The width in pixels
+ */
+ protected int getWidthWithIndent() {
+ if (scrollBody != null && isHierarchyColumn()) {
+ int maxIndent = scrollBody.getMaxIndent();
+ if (maxIndent > width) {
+ return maxIndent;
+ }
+ }
+ return width;
+ }
+
+ /**
+ * Returns the pixels width of the header cell.
+ *
+ * @return The width in pixels
+ */
public int getWidth() {
return width;
}
+ /**
+ * This method exists for the needs of {@link VTreeTable} only.
+ *
+ * @return <code>true</code> if this is hierarcyColumn's header cell,
+ * <code>false</code> otherwise
+ */
+ private boolean isHierarchyColumn() {
+ int hierarchyColumnIndex = getHierarchyColumnIndex();
+ return hierarchyColumnIndex >= 0
+ && tHead.visibleCells.indexOf(this) == hierarchyColumnIndex;
+ }
+
public void setText(String headerText) {
DOM.setInnerHTML(captionContainer, headerText);
}
@@ -2742,7 +2912,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
DOM.setCapture(getElement());
dragStartX = DOM.eventGetClientX(event);
colIndex = getColIndexByKey(cid);
- originalWidth = getWidth();
+ originalWidth = getWidthWithIndent();
DOM.eventPreventDefault(event);
break;
case Event.ONMOUSEUP:
@@ -2774,8 +2944,11 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
tHead.disableAutoColumnWidthCalculation(this);
int newWidth = originalWidth + deltaX;
- if (newWidth < getMinWidth()) {
- newWidth = getMinWidth();
+ // get min width with indent, no padding
+ int minWidth = getMinWidth(true, false);
+ if (newWidth < minWidth) {
+ // already includes indent if any
+ newWidth = minWidth;
}
setColWidth(colIndex, newWidth, true);
triggerLazyColumnAdjustment(false);
@@ -2787,12 +2960,37 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
}
- public int getMinWidth() {
- int cellExtraWidth = 0;
+ /**
+ * Returns the smallest possible cell width in pixels.
+ *
+ * @param includeIndent
+ * - width should include hierarchy column indent if
+ * applicable (VTreeTable only)
+ * @param includeCellExtraWidth
+ * - width should include paddings etc.
+ * @return
+ */
+ private int getMinWidth(boolean includeIndent,
+ boolean includeCellExtraWidth) {
+ int minWidth = sortIndicator.getOffsetWidth();
if (scrollBody != null) {
- cellExtraWidth += scrollBody.getCellExtraWidth();
+ // check the need for indent before adding paddings etc.
+ if (includeIndent && isHierarchyColumn()) {
+ int maxIndent = scrollBody.getMaxIndent();
+ if (minWidth < maxIndent) {
+ minWidth = maxIndent;
+ }
+ }
+ if (includeCellExtraWidth) {
+ minWidth += scrollBody.getCellExtraWidth();
+ }
}
- return cellExtraWidth + sortIndicator.getOffsetWidth();
+ return minWidth;
+ }
+
+ public int getMinWidth() {
+ // get min width with padding, no indent
+ return getMinWidth(false, true);
}
public String getCaption() {
@@ -2823,16 +3021,20 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* @return
*/
public int getNaturalColumnWidth(int columnIndex) {
+ final int iw = columnIndex == getHierarchyColumnIndex() ? scrollBody
+ .getMaxIndent() : 0;
if (isDefinedWidth()) {
+ if (iw > width) {
+ return iw;
+ }
return width;
} else {
if (naturalWidth < 0) {
// This is recently revealed column. Try to detect a proper
- // value (greater of header and data
- // cols)
+ // value (greater of header and data columns)
int hw = captionContainer.getOffsetWidth()
- + scrollBody.getCellExtraWidth();
+ + getHeaderPadding();
if (BrowserInfo.get().isGecko()) {
hw += sortIndicator.getOffsetWidth();
}
@@ -2848,7 +3050,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
final int cw = scrollBody.getColWidth(columnIndex);
naturalWidth = (hw > cw ? hw : cw);
}
- return naturalWidth;
+ if (iw > naturalWidth) {
+ // indent is temporary value, naturalWidth shouldn't be
+ // updated
+ return iw;
+ } else {
+ return naturalWidth;
+ }
}
}
@@ -2945,32 +3153,49 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
public void resizeCaptionContainer(HeaderCell cell) {
HeaderCell lastcell = getHeaderCell(visibleCells.size() - 1);
+ int columnSelectorOffset = columnSelector.getOffsetWidth();
- // Measure column widths
- int columnTotalWidth = 0;
- for (Widget w : visibleCells) {
- columnTotalWidth += w.getOffsetWidth();
- }
-
- if (cell == lastcell
- && columnSelector.getOffsetWidth() > 0
- && columnTotalWidth >= div.getOffsetWidth()
- - columnSelector.getOffsetWidth()
+ if (cell == lastcell && columnSelectorOffset > 0
&& !hasVerticalScrollbar()) {
- // Ensure column caption is visible when placed under the column
- // selector widget by shifting and resizing the caption.
- int offset = 0;
- int diff = div.getOffsetWidth() - columnTotalWidth;
- if (diff < columnSelector.getOffsetWidth() && diff > 0) {
- // If the difference is less than the column selectors width
- // then just offset by the
- // difference
- offset = columnSelector.getOffsetWidth() - diff;
+
+ // Measure column widths
+ int columnTotalWidth = 0;
+ for (Widget w : visibleCells) {
+ int cellExtraWidth = w.getOffsetWidth();
+ if (scrollBody != null
+ && visibleCells.indexOf(w) == getHierarchyColumnIndex()
+ && cellExtraWidth < scrollBody.getMaxIndent()) {
+ // indent must be taken into consideration even if it
+ // hasn't been applied yet
+ columnTotalWidth += scrollBody.getMaxIndent();
+ } else {
+ columnTotalWidth += cellExtraWidth;
+ }
+ }
+
+ int divOffset = div.getOffsetWidth();
+ if (columnTotalWidth >= divOffset - columnSelectorOffset) {
+ /*
+ * Ensure column caption is visible when placed under the
+ * column selector widget by shifting and resizing the
+ * caption.
+ */
+ int offset = 0;
+ int diff = divOffset - columnTotalWidth;
+ if (diff < columnSelectorOffset && diff > 0) {
+ /*
+ * If the difference is less than the column selectors
+ * width then just offset by the difference
+ */
+ offset = columnSelectorOffset - diff;
+ } else {
+ // Else offset by the whole column selector
+ offset = columnSelectorOffset;
+ }
+ lastcell.resizeCaptionContainer(offset);
} else {
- // Else offset by the whole column selector
- offset = columnSelector.getOffsetWidth();
+ cell.resizeCaptionContainer(0);
}
- lastcell.resizeCaptionContainer(offset);
} else {
cell.resizeCaptionContainer(0);
}
@@ -3033,10 +3258,14 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
// Make sure to accomodate for the sort indicator if
// necessary.
int width = Integer.parseInt(widthStr);
- if (width < c.getMinWidth()) {
- width = c.getMinWidth();
+ int widthWithoutAddedIndent = width;
+
+ // get min width with indent, no padding
+ int minWidth = c.getMinWidth(true, false);
+ if (width < minWidth) {
+ width = minWidth;
}
- if (width != c.getWidth() && scrollBody != null) {
+ if (scrollBody != null && width != c.getWidthWithIndent()) {
// Do a more thorough update if a column is resized from
// the server *after* the header has been properly
// initialized
@@ -3052,7 +3281,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
});
refreshContentWidths = true;
} else {
- c.setWidth(width, true);
+ // get min width with no indent or padding
+ minWidth = c.getMinWidth(false, false);
+ if (widthWithoutAddedIndent < minWidth) {
+ widthWithoutAddedIndent = minWidth;
+ }
+ // save min width without indent
+ c.setWidth(widthWithoutAddedIndent, true);
}
} else if (recalcWidths) {
c.setUndefinedWidth();
@@ -3507,12 +3742,14 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
/**
- * Sets the width of the cell
+ * Sets the width of the cell. This width should not include any
+ * possible indent modifications that are present in
+ * {@link VScrollTableBody#getMaxIndent()}.
*
* @param w
* The width of the cell
* @param ensureDefinedWidth
- * Ensures the the given width is not recalculated
+ * Ensures that the given width is not recalculated
*/
public void setWidth(int w, boolean ensureDefinedWidth) {
@@ -3549,7 +3786,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* unless TD width is not explicitly set.
*/
if (scrollBody != null) {
- int tdWidth = width + scrollBody.getCellExtraWidth()
+ int maxIndent = scrollBody.getMaxIndent();
+ if (w < maxIndent
+ && tFoot.visibleCells.indexOf(this) == getHierarchyColumnIndex()) {
+ // ensure there's room for the indent
+ w = maxIndent;
+ }
+ int tdWidth = w + scrollBody.getCellExtraWidth()
- borderWidths;
setWidth(Math.max(tdWidth, 0) + "px");
} else {
@@ -3557,8 +3800,14 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
@Override
public void execute() {
- int tdWidth = width
- + scrollBody.getCellExtraWidth()
+ int tdWidth = width;
+ int maxIndent = scrollBody.getMaxIndent();
+ if (tdWidth < maxIndent
+ && tFoot.visibleCells.indexOf(this) == getHierarchyColumnIndex()) {
+ // ensure there's room for the indent
+ tdWidth = maxIndent;
+ }
+ tdWidth += scrollBody.getCellExtraWidth()
- borderWidths;
setWidth(Math.max(tdWidth, 0) + "px");
}
@@ -3571,6 +3820,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* Sets the width to undefined
*/
public void setUndefinedWidth() {
+ definedWidth = false;
setWidth(-1, false);
}
@@ -3585,7 +3835,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
/**
- * Returns the pixels width of the footer cell
+ * Returns the pixels width of the footer cell.
*
* @return The width in pixels
*/
@@ -3699,7 +3949,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* @return
*/
public int getNaturalColumnWidth(int columnIndex) {
+ final int iw = columnIndex == getHierarchyColumnIndex() ? scrollBody
+ .getMaxIndent() : 0;
if (isDefinedWidth()) {
+ if (iw > width) {
+ return iw;
+ }
return width;
} else {
if (naturalWidth < 0) {
@@ -3708,7 +3963,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
// cols)
final int hw = ((Element) getElement().getLastChild())
- .getOffsetWidth() + scrollBody.getCellExtraWidth();
+ .getOffsetWidth() + getHeaderPadding();
if (columnIndex < 0) {
columnIndex = 0;
for (Iterator<Widget> it = tHead.iterator(); it
@@ -3721,7 +3976,11 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
final int cw = scrollBody.getColWidth(columnIndex);
naturalWidth = (hw > cw ? hw : cw);
}
- return naturalWidth;
+ if (iw > naturalWidth) {
+ return iw;
+ } else {
+ return naturalWidth;
+ }
}
}
@@ -4627,6 +4886,28 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
return cellExtraWidth;
}
+ /**
+ * This method exists for the needs of {@link VTreeTable} only. May be
+ * removed or replaced in the future.</br> </br> Returns the maximum
+ * indent of the hierarcyColumn, if applicable.
+ *
+ * @see {@link VScrollTable#getHierarchyColumnIndex()}
+ *
+ * @return maximum indent in pixels
+ */
+ protected int getMaxIndent() {
+ return 0;
+ }
+
+ /**
+ * This method exists for the needs of {@link VTreeTable} only. May be
+ * removed or replaced in the future.</br> </br> Calculates the maximum
+ * indent of the hierarcyColumn, if applicable.
+ */
+ protected void calculateMaxIndent() {
+ // NOP
+ }
+
private void detectExtrawidth() {
NodeList<TableRowElement> rows = tBodyElement.getRows();
if (rows.getLength() == 0) {
@@ -4806,8 +5087,23 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
protected void setCellWidth(int cellIx, int width) {
final Element cell = DOM.getChild(getElement(), cellIx);
- cell.getFirstChildElement().getStyle()
- .setPropertyPx("width", width);
+ Style wrapperStyle = cell.getFirstChildElement().getStyle();
+ int wrapperWidth = width;
+ if (BrowserInfo.get().isWebkit()
+ || BrowserInfo.get().isOpera10()) {
+ /*
+ * Some versions of Webkit and Opera ignore the width
+ * definition of zero width table cells. Instead, use 1px
+ * and compensate with a negative margin.
+ */
+ if (width == 0) {
+ wrapperWidth = 1;
+ wrapperStyle.setMarginRight(-1, Unit.PX);
+ } else {
+ wrapperStyle.clearMarginRight();
+ }
+ }
+ wrapperStyle.setPropertyPx("width", wrapperWidth);
cell.getStyle().setPropertyPx("width", width);
}
@@ -5866,7 +6162,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
@Override
public void execute() {
if (showRowHeaders) {
- setCellWidth(0, tHead.getHeaderCell(0).getWidth());
+ setCellWidth(0, tHead.getHeaderCell(0)
+ .getWidthWithIndent());
calcAndSetSpanWidthOnCell(1);
} else {
calcAndSetSpanWidthOnCell(0);
@@ -6100,14 +6397,35 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
int totalExplicitColumnsWidths = 0;
float expandRatioDivider = 0;
int colIndex = 0;
+
+ int hierarchyColumnIndent = scrollBody.getMaxIndent();
+ int hierarchyColumnIndex = getHierarchyColumnIndex();
+ HeaderCell hierarchyHeaderInNeedOfFurtherHandling = null;
+
while (headCells.hasNext()) {
final HeaderCell hCell = (HeaderCell) headCells.next();
+ boolean hasIndent = hierarchyColumnIndent > 0
+ && hCell.isHierarchyColumn();
if (hCell.isDefinedWidth()) {
- totalExplicitColumnsWidths += hCell.getWidth();
- usedMinimumWidth += hCell.getWidth();
+ // get width without indent to find out whether adjustments
+ // are needed (requires special handling further ahead)
+ int w = hCell.getWidth();
+ if (hasIndent && w < hierarchyColumnIndent) {
+ // enforce indent if necessary
+ w = hierarchyColumnIndent;
+ hierarchyHeaderInNeedOfFurtherHandling = hCell;
+ }
+ totalExplicitColumnsWidths += w;
+ usedMinimumWidth += w;
} else {
- usedMinimumWidth += hCell.getNaturalColumnWidth(colIndex);
+ // natural width already includes indent if any
+ int naturalColumnWidth = hCell
+ .getNaturalColumnWidth(colIndex);
+ usedMinimumWidth += naturalColumnWidth;
expandRatioDivider += hCell.getExpandRatio();
+ if (hasIndent) {
+ hierarchyHeaderInNeedOfFurtherHandling = hCell;
+ }
}
colIndex++;
}
@@ -6152,6 +6470,28 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
int totalUndefinedNaturalWidths = usedMinimumWidth
- totalExplicitColumnsWidths;
+ if (hierarchyHeaderInNeedOfFurtherHandling != null
+ && !hierarchyHeaderInNeedOfFurtherHandling.isDefinedWidth()) {
+ // ensure the cell gets enough space for the indent
+ int w = hierarchyHeaderInNeedOfFurtherHandling
+ .getNaturalColumnWidth(hierarchyColumnIndex);
+ int newSpace = Math.round(w + (float) extraSpace * (float) w
+ / totalUndefinedNaturalWidths);
+ if (newSpace >= hierarchyColumnIndent) {
+ // no special handling required
+ hierarchyHeaderInNeedOfFurtherHandling = null;
+ } else {
+ // treat as a defined width column of indent's width
+ totalExplicitColumnsWidths += hierarchyColumnIndent;
+ usedMinimumWidth -= w - hierarchyColumnIndent;
+ totalUndefinedNaturalWidths = usedMinimumWidth
+ - totalExplicitColumnsWidths;
+ expandRatioDivider += hierarchyHeaderInNeedOfFurtherHandling
+ .getExpandRatio();
+ extraSpace = Math.max(availW - usedMinimumWidth, 0);
+ }
+ }
+
// we have some space that can be divided optimally
HeaderCell hCell;
colIndex = 0;
@@ -6167,7 +6507,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
newSpace = Math.round((w + extraSpace
* hCell.getExpandRatio() / expandRatioDivider));
} else {
- if (totalUndefinedNaturalWidths != 0) {
+ if (hierarchyHeaderInNeedOfFurtherHandling == hCell) {
+ // still exists, so needs exactly the indent's width
+ newSpace = hierarchyColumnIndent;
+ } else if (totalUndefinedNaturalWidths != 0) {
// divide relatively to natural column widths
newSpace = Math.round(w + (float) extraSpace
* (float) w / totalUndefinedNaturalWidths);
@@ -6177,8 +6520,21 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
checksum += newSpace;
setColWidth(colIndex, newSpace, false);
+
} else {
- checksum += hCell.getWidth();
+ if (hierarchyHeaderInNeedOfFurtherHandling == hCell) {
+ // defined with enforced into indent width
+ checksum += hierarchyColumnIndent;
+ setColWidth(colIndex, hierarchyColumnIndent, false);
+ } else {
+ int cellWidth = hCell.getWidthWithIndent();
+ checksum += cellWidth;
+ if (hCell.isHierarchyColumn()) {
+ // update in case the indent has changed
+ // (not detectable earlier)
+ setColWidth(colIndex, cellWidth, true);
+ }
+ }
}
colIndex++;
}
@@ -6194,8 +6550,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
while (headCells.hasNext()) {
HeaderCell hc = (HeaderCell) headCells.next();
if (!hc.isDefinedWidth()) {
- setColWidth(colIndex,
- hc.getWidth() + availW - checksum, false);
+ setColWidth(colIndex, hc.getWidthWithIndent() + availW
+ - checksum, false);
break;
}
colIndex++;
diff --git a/client/src/com/vaadin/client/ui/VTextField.java b/client/src/com/vaadin/client/ui/VTextField.java
index 1229eda093..0fbed0dd90 100644
--- a/client/src/com/vaadin/client/ui/VTextField.java
+++ b/client/src/com/vaadin/client/ui/VTextField.java
@@ -272,19 +272,16 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler,
/** For internal use only. May be removed or replaced in the future. */
public void setMaxLength(int newMaxLength) {
- if (newMaxLength >= 0 && newMaxLength != maxLength) {
- maxLength = newMaxLength;
- updateMaxLength(maxLength);
- } else if (maxLength != -1) {
- maxLength = -1;
- updateMaxLength(maxLength);
+ if (newMaxLength == maxLength) {
+ return;
}
-
+ maxLength = newMaxLength;
+ updateMaxLength(maxLength);
}
/**
- * This method is reponsible for updating the DOM or otherwise ensuring that
- * the given max length is enforced. Called when the max length for the
+ * This method is responsible for updating the DOM or otherwise ensuring
+ * that the given max length is enforced. Called when the max length for the
* field has changed.
*
* @param maxLength
diff --git a/client/src/com/vaadin/client/ui/VTreeTable.java b/client/src/com/vaadin/client/ui/VTreeTable.java
index f65198865c..097b9c7ab2 100644
--- a/client/src/com/vaadin/client/ui/VTreeTable.java
+++ b/client/src/com/vaadin/client/ui/VTreeTable.java
@@ -122,8 +122,14 @@ public class VTreeTable extends VScrollTable {
}
}
+ @Override
+ protected int getHierarchyColumnIndex() {
+ return colIndexOfHierarchy + (showRowHeaders ? 1 : 0);
+ }
+
public class VTreeTableScrollBody extends VScrollTable.VScrollTableBody {
private int indentWidth = -1;
+ private int maxIndent = 0;
VTreeTableScrollBody() {
super();
@@ -232,6 +238,11 @@ public class VTreeTable extends VScrollTable {
treeSpacer.getParentElement().getStyle()
.setPaddingLeft(getIndent(), Unit.PX);
treeSpacer.getStyle().setWidth(getIndent(), Unit.PX);
+ int colWidth = getColWidth(getHierarchyColumnIndex());
+ if (colWidth > 0 && getIndent() > colWidth) {
+ VTreeTable.this.setColWidth(getHierarchyColumnIndex(),
+ getIndent(), false);
+ }
}
}
@@ -277,16 +288,12 @@ public class VTreeTable extends VScrollTable {
// hierarchy column
int indent = getIndent();
if (indent != -1) {
- width = Math.max(width - getIndent(), 0);
+ width = Math.max(width - indent, 0);
}
}
super.setCellWidth(cellIx, width);
}
- private int getHierarchyColumnIndex() {
- return colIndexOfHierarchy + (showRowHeaders ? 1 : 0);
- }
-
private int getIndent() {
return (depth + 1) * getIndentWidth();
}
@@ -323,7 +330,8 @@ public class VTreeTable extends VScrollTable {
@Override
public void execute() {
if (showRowHeaders) {
- setCellWidth(0, tHead.getHeaderCell(0).getWidth());
+ setCellWidth(0, tHead.getHeaderCell(0)
+ .getWidthWithIndent());
calcAndSetSpanWidthOnCell(1);
} else {
calcAndSetSpanWidthOnCell(0);
@@ -421,6 +429,22 @@ public class VTreeTable extends VScrollTable {
return indentWidth;
}
+ @Override
+ protected int getMaxIndent() {
+ return maxIndent;
+ }
+
+ @Override
+ protected void calculateMaxIndent() {
+ int maxIndent = 0;
+ Iterator<Widget> iterator = iterator();
+ while (iterator.hasNext()) {
+ VTreeTableRow next = (VTreeTableRow) iterator.next();
+ maxIndent = Math.max(maxIndent, next.getIndent());
+ }
+ this.maxIndent = maxIndent;
+ }
+
private void detectIndent(VTreeTableRow vTreeTableRow) {
indentWidth = vTreeTableRow.treeSpacer.getOffsetWidth();
if (indentWidth == 0) {
@@ -432,6 +456,7 @@ public class VTreeTable extends VScrollTable {
VTreeTableRow next = (VTreeTableRow) iterator.next();
next.setIndent();
}
+ calculateMaxIndent();
}
protected void unlinkRowsAnimatedAndUpdateCacheWhenFinished(
@@ -471,6 +496,7 @@ public class VTreeTable extends VScrollTable {
RowExpandAnimation anim = new RowExpandAnimation(insertedRows);
anim.run(150);
}
+ scrollBody.calculateMaxIndent();
return insertedRows;
}
diff --git a/client/src/com/vaadin/client/ui/VUI.java b/client/src/com/vaadin/client/ui/VUI.java
index 6e6bcaf587..b627d4a2a9 100644
--- a/client/src/com/vaadin/client/ui/VUI.java
+++ b/client/src/com/vaadin/client/ui/VUI.java
@@ -41,6 +41,7 @@ import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorMap;
import com.vaadin.client.Focusable;
import com.vaadin.client.LayoutManager;
+import com.vaadin.client.Profiler;
import com.vaadin.client.VConsole;
import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
import com.vaadin.client.ui.TouchScrollDelegate.TouchScrollHandler;
@@ -395,11 +396,13 @@ public class VUI extends SimplePanel implements ResizeHandler,
* For internal use only. May be removed or replaced in the future.
*/
public void sendClientResized() {
+ Profiler.enter("VUI.sendClientResized");
Element parentElement = getElement().getParentElement();
int viewHeight = parentElement.getClientHeight();
int viewWidth = parentElement.getClientWidth();
ResizeEvent.fire(this, viewWidth, viewHeight);
+ Profiler.leave("VUI.sendClientResized");
}
public native static void goTo(String url)
diff --git a/client/src/com/vaadin/client/ui/label/LabelConnector.java b/client/src/com/vaadin/client/ui/label/LabelConnector.java
index 896c9d8573..9639987e8d 100644
--- a/client/src/com/vaadin/client/ui/label/LabelConnector.java
+++ b/client/src/com/vaadin/client/ui/label/LabelConnector.java
@@ -17,6 +17,7 @@ package com.vaadin.client.ui.label;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.PreElement;
+import com.vaadin.client.Profiler;
import com.vaadin.client.Util;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractComponentConnector;
@@ -44,6 +45,7 @@ public class LabelConnector extends AbstractComponentConnector {
public void onStateChanged(StateChangeEvent stateChangeEvent) {
super.onStateChanged(stateChangeEvent);
boolean sinkOnloads = false;
+ Profiler.enter("LabelConnector.onStateChanged update content");
switch (getState().contentMode) {
case PREFORMATTED:
PreElement preElement = Document.get().createPreElement();
@@ -69,8 +71,12 @@ public class LabelConnector extends AbstractComponentConnector {
break;
}
+ Profiler.leave("LabelConnector.onStateChanged update content");
+
if (sinkOnloads) {
+ Profiler.enter("LabelConnector.onStateChanged sinkOnloads");
Util.sinkOnloadForImages(getWidget().getElement());
+ Profiler.leave("LabelConnector.onStateChanged sinkOnloads");
}
}
diff --git a/client/src/com/vaadin/client/ui/link/LinkConnector.java b/client/src/com/vaadin/client/ui/link/LinkConnector.java
index 807a9bcc64..228897278e 100644
--- a/client/src/com/vaadin/client/ui/link/LinkConnector.java
+++ b/client/src/com/vaadin/client/ui/link/LinkConnector.java
@@ -42,7 +42,11 @@ public class LinkConnector extends AbstractComponentConnector implements
@Override
public void onStateChanged(StateChangeEvent stateChangeEvent) {
getWidget().src = getResourceUrl(LinkConstants.HREF_RESOURCE);
- getWidget().anchor.setAttribute("href", getWidget().src);
+ if (getWidget().src == null) {
+ getWidget().anchor.removeAttribute("href");
+ } else {
+ getWidget().anchor.setAttribute("href", getWidget().src);
+ }
}
});
}
diff --git a/client/src/com/vaadin/client/ui/table/TableConnector.java b/client/src/com/vaadin/client/ui/table/TableConnector.java
index c967642059..fc31cdf8ea 100644
--- a/client/src/com/vaadin/client/ui/table/TableConnector.java
+++ b/client/src/com/vaadin/client/ui/table/TableConnector.java
@@ -176,6 +176,7 @@ public class TableConnector extends AbstractHasComponentsConnector implements
// amount of rows)
getWidget().scrollBody.setLastRendered(getWidget().scrollBody
.getLastRendered());
+ getWidget().updateMaxIndent();
} else {
getWidget().postponeSanityCheckForLastRendered = false;
UIDL rowData = uidl.getChildByTagName("rows");
diff --git a/client/src/com/vaadin/client/ui/tabsheet/TabsheetBaseConnector.java b/client/src/com/vaadin/client/ui/tabsheet/TabsheetBaseConnector.java
index 9944ec5308..283bc1b63b 100644
--- a/client/src/com/vaadin/client/ui/tabsheet/TabsheetBaseConnector.java
+++ b/client/src/com/vaadin/client/ui/tabsheet/TabsheetBaseConnector.java
@@ -89,6 +89,14 @@ public abstract class TabsheetBaseConnector extends
}
}
+ // Detach any old tab widget, should be max 1
+ for (Iterator<Widget> iterator = oldWidgets.iterator(); iterator
+ .hasNext();) {
+ Widget oldWidget = iterator.next();
+ if (oldWidget.isAttached()) {
+ oldWidget.removeFromParent();
+ }
+ }
}
@Override
diff --git a/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java b/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java
index 922e8d4a32..e2ede121b6 100644
--- a/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java
+++ b/client/src/com/vaadin/client/ui/textfield/TextFieldConnector.java
@@ -77,8 +77,10 @@ public class TextFieldConnector extends AbstractFieldConnector implements
}
getWidget().setColumns(getState().columns);
- final String text = getState().text;
-
+ String text = getState().text;
+ if (text == null) {
+ text = "";
+ }
/*
* We skip the text content update if field has been repainted, but text
* has not been changed. Additional sanity check verifies there is no
diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java
index 85e75b943e..0fb7439587 100644
--- a/client/src/com/vaadin/client/ui/ui/UIConnector.java
+++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java
@@ -20,6 +20,7 @@ import java.util.Iterator;
import java.util.List;
import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Position;
@@ -43,6 +44,7 @@ import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.ConnectorMap;
import com.vaadin.client.Focusable;
import com.vaadin.client.Paintable;
+import com.vaadin.client.TooltipInfo;
import com.vaadin.client.UIDL;
import com.vaadin.client.VConsole;
import com.vaadin.client.communication.StateChangeEvent;
@@ -312,7 +314,12 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
if (firstPaint) {
// Queue the initial window size to be sent with the following
// request.
- getWidget().sendClientResized();
+ Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+ @Override
+ public void execute() {
+ getWidget().sendClientResized();
+ }
+ });
}
getWidget().rendering = false;
}
@@ -467,6 +474,16 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
}
}
+ @Override
+ public TooltipInfo getTooltipInfo(com.google.gwt.dom.client.Element element) {
+ /*
+ * Override method to make AbstractComponentConnector.hasTooltip()
+ * return true so there's a top level handler that takes care of hiding
+ * tooltips whenever the mouse is moved somewhere else.
+ */
+ return super.getTooltipInfo(element);
+ }
+
/**
* Tries to scroll the viewport so that the given connector is in view.
*