Change-Id: Id48ccb3c400a78cddb8bb5c7bbcf2d65174e59d0tags/7.1.0.beta1
@@ -35,6 +35,9 @@ | |||
</target> | |||
<target name="javadoc" depends="copy-jars"> | |||
<!-- Ensure filtered webcontent files are available --> | |||
<antcall target="common.filter.webcontent" /> | |||
<!-- Unpack all source files to javadoc.temp.dir--> | |||
<antcontrib:foreach list="${modules.to.publish.to.maven}" target="unzip.to.javadoctemp" param="module" /> | |||
@@ -76,6 +79,9 @@ | |||
</target> | |||
<target name="zip" depends="copy-jars, javadoc"> | |||
<!-- Ensure filtered webcontent files are available --> | |||
<antcall target="common.filter.webcontent" /> | |||
<zip destfile="${zip.file}"> | |||
<fileset dir="${temp.dir}"> | |||
<!-- Avoid conflicts with servlet and portlet API. They are provided by the container --> |
@@ -1,16 +0,0 @@ | |||
#!/usr/bin/python | |||
import sys,string | |||
filename = sys.argv[1] | |||
fin = open(filename, "r") | |||
lines = fin.readlines() | |||
fin.close() | |||
for line in lines: | |||
fields = string.split(line, "\t") | |||
if fields[0] != "id": | |||
ticketid = "<a href=\"http://dev.vaadin.com/ticket/%s\">#%s</a>" % (fields[0],fields[0]) | |||
print " <li>%s: %s</li>" % (ticketid, fields[1]) |
@@ -36,6 +36,13 @@ | |||
</antcall> | |||
</target> | |||
<target name="fetch-release-notes-tickets"> | |||
<antcall target="common.exec-buildhelper"> | |||
<param name="main.class" value="com.vaadin.buildhelpers.FetchReleaseNotesTickets" /> | |||
<param name="output" value="${output}" /> | |||
</antcall> | |||
</target> | |||
<target name="tests" depends="checkstyle"> | |||
<!--<antcall target="common.tests.run" />--> | |||
<echo>WHAT? No JUnit tests for ${module.name}!</echo> |
@@ -27,6 +27,8 @@ | |||
<artifact type="pom" ext="pom" /> | |||
</publications> | |||
<dependencies /> | |||
<dependencies> | |||
<dependency org="commons-io" name="commons-io" rev="1.4" /> | |||
</dependencies> | |||
</ivy-module> |
@@ -0,0 +1,46 @@ | |||
package com.vaadin.buildhelpers; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.net.URL; | |||
import java.net.URLConnection; | |||
import java.util.List; | |||
import org.apache.commons.io.IOUtils; | |||
public class FetchReleaseNotesTickets { | |||
private static final String queryURL = "http://dev.vaadin.com/query?status=closed&milestone=Vaadin+@version@&resolution=fixed&format=tab&order=id"; | |||
private static final String ticketTemplate = " <li><a href=\"http://dev.vaadin.com/ticket/@ticket@\">#@ticket@</a>: @description@</li>"; | |||
public static void main(String[] args) throws IOException { | |||
String version = System.getProperty("vaadin.version"); | |||
if (version == null || version.equals("")) { | |||
usage(); | |||
} | |||
URL url = new URL(queryURL.replace("@version@", version)); | |||
URLConnection connection = url.openConnection(); | |||
InputStream urlStream = connection.getInputStream(); | |||
@SuppressWarnings("unchecked") | |||
List<String> tickets = IOUtils.readLines(urlStream); | |||
for (String ticket : tickets) { | |||
String[] fields = ticket.split("\t"); | |||
if ("id".equals(fields[0])) { | |||
// This is the header | |||
continue; | |||
} | |||
System.out.println(ticketTemplate.replace("@ticket@", fields[0]) | |||
.replace("@description@", fields[1])); | |||
} | |||
urlStream.close(); | |||
} | |||
private static void usage() { | |||
System.err.println("Usage: " | |||
+ FetchReleaseNotesTickets.class.getSimpleName() | |||
+ " -Dvaadin.version=<version>"); | |||
System.exit(1); | |||
} | |||
} |
@@ -98,6 +98,9 @@ | |||
</target> | |||
<target name="client-compiled-cache.jar" depends="default-widgetset-cache"> | |||
<!-- Ensure filtered webcontent files are available --> | |||
<antcall target="common.filter.webcontent" /> | |||
<jar file="${compiled-cache.jar}" compress="true"> | |||
<fileset dir="${gwtar.dir}"> | |||
<include name="**/*.gwtar" /> |
@@ -334,6 +334,22 @@ public class ConnectorBundleLoaderFactory extends Generator { | |||
writeGetters(logger, w, bundle); | |||
writeSerializers(logger, w, bundle); | |||
writeDelegateToWidget(logger, w, bundle); | |||
writeHasGetTooltip(logger, w, bundle); | |||
} | |||
/** | |||
* @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 | |||
private void writeHasGetTooltip(TreeLogger logger, SplittingSourceWriter w, | |||
ConnectorBundle bundle) { | |||
Set<JClassType> types = bundle.getHasGetTooltip(); | |||
for (JClassType type : types) { | |||
w.println("store.setHasGetTooltipInfo(%s);", | |||
getClassLiteralString(type)); | |||
w.splitIfNeeded(); | |||
} | |||
} | |||
private void writeDelegateToWidget(TreeLogger logger, |
@@ -63,6 +63,7 @@ public class ConnectorBundle { | |||
private final Set<JClassType> needsGwtConstructor = new HashSet<JClassType>(); | |||
private final Set<JClassType> visitedTypes = new HashSet<JClassType>(); | |||
private final Set<JClassType> needsProxySupport = new HashSet<JClassType>(); | |||
private final Set<JClassType> hasGetTooltip = new HashSet<JClassType>(); | |||
private final Map<JClassType, Set<String>> identifiers = new HashMap<JClassType, Set<String>>(); | |||
private final Map<JClassType, Set<JMethod>> needsReturnType = new HashMap<JClassType, Set<JMethod>>(); | |||
@@ -618,4 +619,38 @@ public class ConnectorBundle { | |||
public Set<Property> getNeedsDelegateToWidget() { | |||
return Collections.unmodifiableSet(needsDelegateToWidget); | |||
} | |||
/** | |||
* @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 Set<JClassType> getHasGetTooltip() { | |||
return Collections.unmodifiableSet(hasGetTooltip); | |||
} | |||
/** | |||
* @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 setHasGetTooltip(JClassType type) { | |||
if (!isHasGetTooltip(type)) { | |||
hasGetTooltip.add(type); | |||
} | |||
} | |||
/** | |||
* @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 | |||
private boolean isHasGetTooltip(JClassType type) { | |||
if (hasGetTooltip.contains(type)) { | |||
return true; | |||
} else { | |||
return previousBundle != null | |||
&& previousBundle.isHasGetTooltip(type); | |||
} | |||
} | |||
} |
@@ -47,6 +47,25 @@ public class WidgetInitVisitor extends TypeVisitor { | |||
bundle.setNeedsReturnType(type, getWidget); | |||
} | |||
// Hack to detect when getTooltipInfo has a custom implementation | |||
// #11051 | |||
JClassType getTooltipParamType = type.getOracle().findType( | |||
"com.google.gwt.dom.client.Element"); | |||
JMethod getTooltipInfoMethod = findInheritedMethod(type, | |||
"getTooltipInfo", getTooltipParamType); | |||
if (getTooltipInfoMethod == null) { | |||
logger.log(Type.ERROR, "Could not find getTooltipInfo in " | |||
+ type.getQualifiedSourceName()); | |||
throw new UnableToCompleteException(); | |||
} | |||
JClassType enclosingType = getTooltipInfoMethod.getEnclosingType(); | |||
if (!enclosingType.getQualifiedSourceName().equals( | |||
AbstractComponentConnector.class.getCanonicalName())) { | |||
logger.log(Type.WARN, type.getQualifiedSourceName() | |||
+ " has overridden getTooltipInfo"); | |||
bundle.setHasGetTooltip(type); | |||
} | |||
// Check state properties for @DelegateToWidget | |||
JMethod getState = findInheritedMethod(type, "getState"); | |||
JClassType stateType = getState.getReturnType().isClass(); |
@@ -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 |
@@ -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"); | |||
@@ -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"); |
@@ -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 |
@@ -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 |
@@ -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; | |||
@@ -407,6 +408,29 @@ public class VCaption extends HTML { | |||
return false; | |||
} | |||
/** | |||
* 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. | |||
* |
@@ -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"); | |||
} | |||
} |
@@ -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) { |
@@ -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()); | |||
} | |||
} |
@@ -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,17 +419,51 @@ 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) { | |||
return new TooltipInfo(getState().description, getState().errorMessage); | |||
} | |||
/** | |||
* 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. | |||
* |
@@ -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"); | |||
} | |||
/** |
@@ -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(); |
@@ -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"); | |||
} | |||
} |
@@ -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++; |
@@ -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 |
@@ -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; | |||
} | |||
@@ -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) |
@@ -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"); | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
}); | |||
} |
@@ -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"); |
@@ -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 |
@@ -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 |
@@ -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. | |||
* |
@@ -27,9 +27,12 @@ | |||
<union id="empty.reference" /> | |||
<property name="filtered.webcontent.dir" location="${vaadin.basedir}/result/filteredWebContent" /> | |||
<property name="release-notes-tickets-file" location="${vaadin.basedir}/result/release-notes-tickets.html" /> | |||
<target name="filter.webcontent" unless="webcontent.filtered"> | |||
<target name="filter.webcontent" unless="webcontent.filtered" depends="fetch-release-notes-tickets"> | |||
<property name="webcontent.filtered" value="true" /> | |||
<!-- Running without build.release-notes will cause an error, which is ignored --> | |||
<loadfile property="release-notes-tickets" srcFile="${release-notes-tickets-file}" failonerror="false" /> | |||
<delete dir="${filtered.webcontent.dir}" /> | |||
<copy todir="${filtered.webcontent.dir}"> | |||
@@ -57,11 +60,21 @@ | |||
<replacetokens begintoken="@" endtoken="@"> | |||
<token key="builddate" value="${build.date}" /> | |||
</replacetokens> | |||
<replacetokens begintoken="@" endtoken="@"> | |||
<token key="release-notes-tickets" value="${release-notes-tickets}" /> | |||
</replacetokens> | |||
</filterchain> | |||
</copy> | |||
</target> | |||
<target name="fetch-release-notes-tickets" unless="built.release-notes" if="build.release-notes"> | |||
<mkdir dir="${vaadin.basedir}/result"/> | |||
<subant buildpath="${vaadin.basedir}/buildhelpers" target="fetch-release-notes-tickets" antfile="build.xml" inheritall="true"> | |||
<property name="output" location="${release-notes-tickets-file}" /> | |||
</subant> | |||
<property name="built.release-notes" value="1" /> | |||
</target> | |||
<fileset dir="${filtered.webcontent.dir}" id="common.files.for.all.jars"> | |||
<patternset> | |||
<include name="release-notes.html" /> | |||
@@ -110,7 +123,7 @@ | |||
</target> | |||
<target name="sources.jar" depends="compile"> | |||
<target name="sources.jar" depends="compile, filter.webcontent"> | |||
<fail unless="result.dir" message="No result.dir parameter given" /> | |||
<fail unless="module.name" message="No module.name parameter given" /> | |||
<fail unless="src" message="No src directory parameter given" /> | |||
@@ -132,7 +145,7 @@ | |||
</target> | |||
<target name="javadoc.jar" depends="dependencies"> | |||
<target name="javadoc.jar" depends="dependencies, filter.webcontent"> | |||
<fail unless="result.dir" message="No result.dir parameter given" /> | |||
<fail unless="module.name" message="No module.name parameter given" /> | |||
<property name="src" location="{$result.dir}/../src" /> | |||
@@ -157,7 +170,7 @@ | |||
</target> | |||
<target name="jar" depends="compile, pom.xml"> | |||
<target name="jar" depends="compile, pom.xml, filter.webcontent"> | |||
<fail unless="result.dir" message="No result.dir parameter given" /> | |||
<fail unless="module.name" message="No module.name parameter given" /> | |||
@@ -261,6 +274,16 @@ | |||
</javac> | |||
</target> | |||
<target name="exec-buildhelper" depends="compile"> | |||
<fail unless="main.class" message="No main class given in 'main.class'" /> | |||
<fail unless="output" message="No output file given in 'output'" /> | |||
<java classname="${main.class}" output="${output}" failonerror="true" fork="yes"> | |||
<classpath refid="vaadin.buildhelpers.classpath" /> | |||
<classpath refid="classpath.compile.dependencies" /> | |||
<jvmarg value="-Dvaadin.version=${vaadin.version}" /> | |||
</java> | |||
</target> | |||
<target name="directories"> | |||
<property name="result.dir" location="result" /> | |||
<property name="src" location="${result.dir}/../src" /> | |||
@@ -321,7 +344,7 @@ | |||
</copy> | |||
</target> | |||
<target name="dependencies" description="Resolves dependencies needed by this module" depends="filter.webcontent"> | |||
<target name="dependencies" description="Resolves dependencies needed by this module"> | |||
<property name='conf' value="build, build-provided" /> | |||
<ivy:resolve resolveid="common" conf="${conf}" /> | |||
<ivy:cachepath pathid="classpath.compile.dependencies" conf="${conf}" /> |
@@ -110,6 +110,13 @@ public class CheckBox extends AbstractField<Boolean> { | |||
return (CheckBoxState) super.getState(); | |||
} | |||
/* | |||
* Overridden to keep the shared state in sync with the AbstractField | |||
* internal value. Should be removed once AbstractField is refactored to use | |||
* shared state. | |||
* | |||
* See tickets #10921 and #11064. | |||
*/ | |||
@Override | |||
protected void setInternalValue(Boolean newValue) { | |||
super.setInternalValue(newValue); |
@@ -157,4 +157,19 @@ public class ProgressIndicator extends AbstractField<Float> implements | |||
return getState().pollingInterval; | |||
} | |||
/* | |||
* Overridden to keep the shared state in sync with the AbstractField | |||
* internal value. Should be removed once AbstractField is refactored to use | |||
* shared state. | |||
* | |||
* See tickets #10921 and #11064. | |||
*/ | |||
@Override | |||
protected void setInternalValue(Float newValue) { | |||
super.setInternalValue(newValue); | |||
if (newValue == null) { | |||
newValue = 0.0f; | |||
} | |||
getState().state = newValue; | |||
} | |||
} |
@@ -263,6 +263,22 @@ public class Slider extends AbstractField<Double> { | |||
getState().value = newFieldValue; | |||
} | |||
/* | |||
* Overridden to keep the shared state in sync with the AbstractField | |||
* internal value. Should be removed once AbstractField is refactored to use | |||
* shared state. | |||
* | |||
* See tickets #10921 and #11064. | |||
*/ | |||
@Override | |||
protected void setInternalValue(Double newValue) { | |||
super.setInternalValue(newValue); | |||
if (newValue == null) { | |||
newValue = 0.0; | |||
} | |||
getState().value = newValue; | |||
} | |||
/** | |||
* Thrown when the value of the slider is about to be set to a value that is | |||
* outside the valid range of the slider. |
@@ -414,6 +414,9 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, | |||
final Object id = itemIdMapper.get(keys[i]); | |||
if (id != null && isExpanded(id)) { | |||
expanded.remove(id); | |||
if (expandedItemId == id) { | |||
expandedItemId = null; | |||
} | |||
fireCollapseEvent(id); | |||
} | |||
} | |||
@@ -841,6 +844,10 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, | |||
super.setContainerDataSource(new ContainerHierarchicalWrapper( | |||
newDataSource)); | |||
} | |||
// Ensure previous expanded items are cleaned up if they don't exist in | |||
// the new container | |||
cleanupExpandedItems(); | |||
} | |||
/* Expand event and listener */ | |||
@@ -1670,4 +1677,24 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, | |||
return itemDescriptionGenerator; | |||
} | |||
@Override | |||
public void containerItemSetChange( | |||
com.vaadin.data.Container.ItemSetChangeEvent event) { | |||
// Ensure removed items are cleaned up from expanded list | |||
cleanupExpandedItems(); | |||
super.containerItemSetChange(event); | |||
} | |||
private void cleanupExpandedItems() { | |||
for (Object expandedItemId : expanded) { | |||
if (getItem(expandedItemId) == null) { | |||
expanded.remove(expandedItemId); | |||
if (this.expandedItemId == expandedItemId) { | |||
this.expandedItemId = null; | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1,5 +1,8 @@ | |||
package com.vaadin.tests.server.component.tree; | |||
import java.lang.reflect.Field; | |||
import java.util.HashSet; | |||
import junit.framework.TestCase; | |||
import com.vaadin.data.Container; | |||
@@ -71,4 +74,63 @@ public class TreeTest extends TestCase { | |||
assertTrue(Container.Hierarchical.class.isAssignableFrom(tree4 | |||
.getContainerDataSource().getClass())); | |||
} | |||
public void testRemoveExpandedItems() throws Exception { | |||
tree.expandItem("parent"); | |||
tree.expandItem("child"); | |||
Field expandedField = tree.getClass() | |||
.getDeclaredField("expanded"); | |||
Field expandedItemIdField = tree.getClass().getDeclaredField( | |||
"expandedItemId"); | |||
expandedField.setAccessible(true); | |||
expandedItemIdField.setAccessible(true); | |||
HashSet<Object> expanded = (HashSet<Object>) expandedField.get(tree); | |||
Object expandedItemId = expandedItemIdField.get(tree); | |||
assertEquals(2, expanded.size()); | |||
assertTrue("Contains parent", expanded.contains("parent")); | |||
assertTrue("Contains child", expanded.contains("child")); | |||
assertEquals("child", expandedItemId); | |||
tree.removeItem("parent"); | |||
expanded = (HashSet<Object>) expandedField.get(tree); | |||
expandedItemId = expandedItemIdField.get(tree); | |||
assertEquals(1, expanded.size()); | |||
assertTrue("Contains child", expanded.contains("child")); | |||
assertEquals("child", expandedItemId); | |||
tree.removeItem("child"); | |||
expanded = (HashSet<Object>) expandedField.get(tree); | |||
expandedItemId = expandedItemIdField.get(tree); | |||
assertEquals(0, expanded.size()); | |||
assertNull(expandedItemId); | |||
} | |||
public void testRemoveExpandedItemsOnContainerChange() throws Exception { | |||
tree.expandItem("parent"); | |||
tree.expandItem("child"); | |||
tree.setContainerDataSource(new HierarchicalContainer()); | |||
Field expandedField = tree.getClass().getDeclaredField("expanded"); | |||
Field expandedItemIdField = tree.getClass().getDeclaredField( | |||
"expandedItemId"); | |||
expandedField.setAccessible(true); | |||
expandedItemIdField.setAccessible(true); | |||
HashSet<Object> expanded = (HashSet<Object>) expandedField.get(tree); | |||
assertEquals(0, expanded.size()); | |||
Object expandedItemId = expandedItemIdField.get(tree); | |||
assertNull(expandedItemId); | |||
} | |||
} |
@@ -319,10 +319,12 @@ public class Parser implements org.w3c.css.sac.Parser { | |||
String encoding = source.getEncoding(); | |||
InputStream input = source.getByteStream(); | |||
if (!input.markSupported()) { | |||
// If mark is not supported, wrap it in a stream which supports mark | |||
input = new BufferedInputStream(input); | |||
source.setByteStream(input); | |||
input.mark(100); | |||
} | |||
// Mark either the original stream or the wrapped stream | |||
input.mark(100); | |||
if(encoding == null){ | |||
encoding = "ASCII"; | |||
@@ -1056,9 +1058,6 @@ void skipUnknownRule() : | |||
| n=<UNICODERANGE> | |||
| n=<URL> | |||
| n=";" | |||
| n="+" | |||
| n=">" | |||
| n="~" | |||
| n="-" | |||
| n=<UNKNOWN> | |||
) { | |||
@@ -1081,13 +1080,18 @@ char combinator() : | |||
char connector = ' '; | |||
} | |||
{ | |||
"+" ( <S> )* { return '+'; } | |||
| ">" ( <S> )* { return '>'; } | |||
| "~" ( <S> )* { return '~'; } | |||
| <S> ( ( "+" { connector = '+'; } | |||
| ">" { connector = '>'; } | |||
| "~" { connector = '~'; } ) | |||
( <S> )* )? { return connector; } | |||
(connector = combinatorChar() | |||
| <S> (connector = combinatorChar())?) { return connector; } | |||
} | |||
/**to refactor combinator and reuse in selector().*/ | |||
char combinatorChar() : | |||
{Token t;} | |||
{ | |||
(t = <PLUS> | t = <PRECEDES> | t = <SIBLING>) (<S>)* | |||
{ | |||
return t.image.charAt(0); | |||
} | |||
} | |||
void microsoftExtension() : | |||
@@ -1200,12 +1204,14 @@ void styleRule() : | |||
*/ | |||
String selector() : | |||
{ | |||
String selector; | |||
String selector = null; | |||
char comb; | |||
} | |||
{ | |||
try { | |||
selector=simple_selector(null, ' ') | |||
// the selector can begin either a simple_selector, or a combinatorChar(+, >, ~). | |||
// when beginning with combinatorChar, the next one should be a simple_selector(). | |||
(selector=simple_selector(null, ' ') | (comb=combinatorChar() selector=simple_selector(selector, comb))) | |||
( LOOKAHEAD(2) comb=combinator() | |||
selector=simple_selector(selector, comb) )* (<S>)* | |||
{ | |||
@@ -1265,22 +1271,27 @@ String simple_selector(String selector, char comb) : | |||
if (cond != null) { | |||
simple_current = simple_current + cond; | |||
} | |||
if (selector != null) { | |||
switch (comb) { | |||
StringBuilder builder = new StringBuilder(); | |||
switch (comb) { | |||
case ' ': | |||
selector = selector + comb + simple_current; | |||
if(selector!=null){ | |||
builder.append(selector).append(" "); | |||
} | |||
break; | |||
case '+': | |||
case '>': | |||
case '~': | |||
selector = selector + " " + comb + " " + simple_current; | |||
if(selector!=null){ | |||
builder.append(selector).append(" "); | |||
} | |||
builder.append(comb).append(" "); | |||
break; | |||
default: | |||
throw new ParseException("invalid state. send a bug report"); | |||
} | |||
} else { | |||
selector= simple_current; | |||
} | |||
builder.append(simple_current); | |||
selector = builder.toString(); | |||
if (pseudoElt != null) { | |||
selector = selector + pseudoElt; | |||
} |
@@ -1,3 +1,18 @@ | |||
/* | |||
* 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 | |||
* the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |||
* License for the specific language governing permissions and limitations under | |||
* the License. | |||
*/ | |||
/* Generated By:JavaCC: Do not edit this line. ParserTokenManager.java */ | |||
package com.vaadin.sass.internal.parser; | |||
@@ -5835,21 +5850,6 @@ public class ParserTokenManager implements ParserConstants { | |||
int jjmatchedPos; | |||
int jjmatchedKind; | |||
/* | |||
* 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 the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |||
* License for the specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
/** Get the next Token. */ | |||
public Token getNextToken() { | |||
Token specialToken = null; |
@@ -108,18 +108,39 @@ public class MixinNodeHandler { | |||
} | |||
} | |||
} | |||
int i = 0; | |||
for (final LexicalUnitImpl unit : remainingUnits) { | |||
checkExtraParameters(mixinNode, remainingNodes.size(), | |||
remainingUnits.size()); | |||
for (int i = 0; i < remainingNodes.size() | |||
&& i < remainingUnits.size(); i++) { | |||
LexicalUnitImpl unit = remainingUnits.get(i); | |||
remainingNodes.get(i).setExpr( | |||
(LexicalUnitImpl) DeepCopy.copy(unit)); | |||
i++; | |||
} | |||
} | |||
} | |||
protected static void checkExtraParameters(MixinNode mixinNode, | |||
int remainingNodesSize, int remainingUnitsSize) { | |||
if (remainingUnitsSize > remainingNodesSize) { | |||
String fileName = null; | |||
Node root = mixinNode.getParentNode(); | |||
while (root != null && !(root instanceof ScssStylesheet)) { | |||
root = root.getParentNode(); | |||
} | |||
if (root != null) { | |||
fileName = ((ScssStylesheet) root).getFileName(); | |||
} | |||
StringBuilder builder = new StringBuilder(); | |||
builder.append("More parameters than expected, in Mixin ").append( | |||
mixinNode.getName()); | |||
if (fileName != null) { | |||
builder.append(", in file ").append(fileName); | |||
} | |||
throw new RuntimeException(builder.toString()); | |||
} | |||
} | |||
private static void replaceChildVariables(MixinDefNode mixinDef, Node node) { | |||
for (final Node child : node.getChildren()) { | |||
replaceChildVariables(mixinDef, child); |
@@ -0,0 +1,9 @@ | |||
.v-panel { | |||
display: block; | |||
max-width: 84em; | |||
margin: auto; | |||
} | |||
.v-panel + .abc { | |||
margin-top: 1em; | |||
} |
@@ -0,0 +1,9 @@ | |||
.v-panel { | |||
display: block; | |||
max-width: 84em; | |||
margin: auto; | |||
+ .abc { | |||
margin-top: 1em; | |||
} | |||
} |
@@ -0,0 +1,4 @@ | |||
@mixin test ($p1) { | |||
color: $p1; | |||
} | |||
@include test(foo, bar); |
@@ -0,0 +1,25 @@ | |||
package com.vaadin.sass.testcases.scss; | |||
import org.junit.Assert; | |||
import org.junit.Test; | |||
import com.vaadin.sass.AbstractTestBase; | |||
import com.vaadin.sass.internal.ScssStylesheet; | |||
public class MixinExtraParameters extends AbstractTestBase { | |||
String scss = "/scss/mixin-extra-params.scss"; | |||
@Test | |||
public void testCompiler() { | |||
ScssStylesheet sheet; | |||
try { | |||
sheet = getStyleSheet(scss); | |||
sheet.compile(); | |||
} catch (RuntimeException e) { | |||
Assert.assertEquals(e.getMessage(), | |||
"More parameters than expected, in Mixin test"); | |||
} catch (Exception e) { | |||
Assert.fail(); | |||
} | |||
} | |||
} |
@@ -106,6 +106,10 @@ | |||
<path refid="classpath.runtime.dependencies" /> | |||
</copy> | |||
<!-- Ensure filtered webcontent files are available --> | |||
<antcall target="common.filter.webcontent" /> | |||
<war destfile="${result.war}" duplicate="fail" index="true"> | |||
<fileset refid="common.files.for.all.jars" /> | |||
<fileset dir="${result.dir}"> |
@@ -0,0 +1,37 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |||
<link rel="selenium.base" href="http://localhost:8888/" /> | |||
<title>New Test</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr><td rowspan="1" colspan="3">New Test</td></tr> | |||
</thead><tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.components.absolutelayout.AbsoluteLayoutResizing?restartApplication</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>dragAndDrop</td> | |||
<td>vaadin=runcomvaadintestscomponentsabsolutelayoutAbsoluteLayoutResizing::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VSplitPanelVertical[0]/domChild[0]/domChild[1]/domChild[0]</td> | |||
<td>0,294</td> | |||
</tr> | |||
<tr> | |||
<td>dragAndDrop</td> | |||
<td>vaadin=runcomvaadintestscomponentsabsolutelayoutAbsoluteLayoutResizing::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VSplitPanelVertical[0]/VSplitPanelHorizontal[0]/domChild[0]/domChild[1]/domChild[0]</td> | |||
<td>588,0</td> | |||
</tr> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>resized</td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |
@@ -0,0 +1,44 @@ | |||
package com.vaadin.tests.components.absolutelayout; | |||
import com.vaadin.tests.components.TestBase; | |||
import com.vaadin.ui.AbsoluteLayout; | |||
import com.vaadin.ui.HorizontalSplitPanel; | |||
import com.vaadin.ui.TextArea; | |||
import com.vaadin.ui.VerticalSplitPanel; | |||
public class AbsoluteLayoutResizing extends TestBase { | |||
@Override | |||
protected void setup() { | |||
getLayout().setSizeFull(); | |||
AbsoluteLayout al = new AbsoluteLayout(); | |||
TextArea ta = new TextArea(); | |||
ta.setValue("When resizing the layout this text area should also get resized"); | |||
ta.setSizeFull(); | |||
al.addComponent(ta, "left: 10px; right: 10px; top: 10px; bottom: 10px;"); | |||
HorizontalSplitPanel horizPanel = new HorizontalSplitPanel(); | |||
horizPanel.setSizeFull(); | |||
horizPanel.setFirstComponent(al); | |||
VerticalSplitPanel vertPanel = new VerticalSplitPanel(); | |||
vertPanel.setSizeFull(); | |||
vertPanel.setFirstComponent(horizPanel); | |||
addComponent(vertPanel); | |||
} | |||
@Override | |||
protected String getDescription() { | |||
return "Absolute layout should correctly dynamically resize itself"; | |||
} | |||
@Override | |||
protected Integer getTicketNumber() { | |||
return 10427; | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |||
<link rel="selenium.base" href="http://localhost:8070/" /> | |||
<title>SliderValueFromDataSource</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr><td rowspan="1" colspan="3">SliderValueFromDataSource</td></tr> | |||
</thead><tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/SliderValueFromDataSource?restartApplication</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>assertAttribute</td> | |||
<td>vaadin=runSliderValueFromDataSource::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VProgressIndicator[0]/domChild[0]/domChild[0]@style</td> | |||
<td>regex:.*(width|WIDTH): 50%.*</td> | |||
</tr> | |||
<tr> | |||
<td>assertAttribute</td> | |||
<td>vaadin=runSliderValueFromDataSource::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VSlider[0]/domChild[2]/domChild[0]@style</td> | |||
<td>regex:.*(margin-left|MARGIN-LEFT): 94px.*</td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |
@@ -0,0 +1,59 @@ | |||
package com.vaadin.tests.components.slider; | |||
import com.vaadin.data.Item; | |||
import com.vaadin.data.util.BeanItem; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUI; | |||
import com.vaadin.ui.ProgressIndicator; | |||
import com.vaadin.ui.Slider; | |||
public class SliderValueFromDataSource extends AbstractTestUI { | |||
public static class TestBean { | |||
private double doubleValue = 10.0; | |||
private float floatValue = 0.5f; | |||
public double getDoubleValue() { | |||
return doubleValue; | |||
} | |||
public void setDoubleValue(double doubleValue) { | |||
this.doubleValue = doubleValue; | |||
} | |||
public float getFloatValue() { | |||
return floatValue; | |||
} | |||
public void setFloatValue(float floatValue) { | |||
this.floatValue = floatValue; | |||
} | |||
} | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
Item item = new BeanItem<TestBean>(new TestBean()); | |||
Slider slider = new Slider(0, 20); | |||
slider.setWidth("200px"); | |||
slider.setPropertyDataSource(item.getItemProperty("doubleValue")); | |||
addComponent(slider); | |||
ProgressIndicator pi = new ProgressIndicator(); | |||
pi.setPollingInterval(60 * 1000); | |||
pi.setWidth("200px"); | |||
pi.setPropertyDataSource(item.getItemProperty("floatValue")); | |||
addComponent(pi); | |||
} | |||
@Override | |||
protected String getTestDescription() { | |||
return "Slider and ProgressIndicator do not properly pass a value from data source to the client"; | |||
} | |||
@Override | |||
protected Integer getTicketNumber() { | |||
return 10921; | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |||
<link rel="selenium.base" href="http://localhost:8888/" /> | |||
<title>New Test</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr><td rowspan="1" colspan="3">New Test</td></tr> | |||
</thead><tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.components.textfield.TextFieldMaxLengthRemovedFromDOM?restartApplication</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>assertAttribute</td> | |||
<td>vaadin=runcomvaadintestscomponentstextfieldTextFieldMaxLengthRemovedFromDOM::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTextField[0]@maxlength</td> | |||
<td>11</td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentstextfieldTextFieldMaxLengthRemovedFromDOM::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTextField[0]</td> | |||
<td>118,13</td> | |||
</tr> | |||
<tr> | |||
<td>assertAttribute</td> | |||
<td>vaadin=runcomvaadintestscomponentstextfieldTextFieldMaxLengthRemovedFromDOM::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTextField[0]@maxlength</td> | |||
<td>11</td> | |||
</tr> | |||
<tr> | |||
<td>type</td> | |||
<td>vaadin=runcomvaadintestscomponentstextfieldTextFieldMaxLengthRemovedFromDOM::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTextField[0]</td> | |||
<td>hello</td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentstextfieldTextFieldMaxLengthRemovedFromDOM::/VVerticalLayout[0]/domChild[0]</td> | |||
<td>172,60</td> | |||
</tr> | |||
<tr> | |||
<td>assertAttribute</td> | |||
<td>vaadin=runcomvaadintestscomponentstextfieldTextFieldMaxLengthRemovedFromDOM::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTextField[0]@maxlength</td> | |||
<td>11</td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |
@@ -0,0 +1,37 @@ | |||
package com.vaadin.tests.components.textfield; | |||
import com.vaadin.event.FieldEvents; | |||
import com.vaadin.event.FieldEvents.FocusEvent; | |||
import com.vaadin.tests.components.TestBase; | |||
import com.vaadin.ui.TextField; | |||
public class TextFieldMaxLengthRemovedFromDOM extends TestBase { | |||
@Override | |||
protected void setup() { | |||
final TextField tf = new TextField(); | |||
tf.setMaxLength(11); | |||
tf.setRequired(true); | |||
tf.setImmediate(true); | |||
addComponent(tf); | |||
tf.addFocusListener(new FieldEvents.FocusListener() { | |||
public void focus(FocusEvent event) { | |||
// Resetting Max length should not remove maxlength attribute | |||
tf.setMaxLength(11); | |||
} | |||
}); | |||
} | |||
@Override | |||
protected String getDescription() { | |||
return "Maxlength attribute should not dissappear from the DOM when I focus the text field."; | |||
} | |||
@Override | |||
protected Integer getTicketNumber() { | |||
return 9940; | |||
} | |||
} |
@@ -0,0 +1,31 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |||
<link rel="selenium.base" href="http://localhost:8888/" /> | |||
<title>New Test</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr><td rowspan="1" colspan="3">New Test</td></tr> | |||
</thead><tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.components.textfield.TextFieldWithDataSourceAndInputPrompt?restartApplication</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>assertValue</td> | |||
<td>vaadin=runcomvaadintestscomponentstextfieldTextFieldWithDataSourceAndInputPrompt::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VTextField[0]</td> | |||
<td>Me is input prompt</td> | |||
</tr> | |||
<tr> | |||
<td>assertValue</td> | |||
<td>vaadin=runcomvaadintestscomponentstextfieldTextFieldWithDataSourceAndInputPrompt::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VTextField[0]</td> | |||
<td>Me is input prompt</td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |
@@ -0,0 +1,63 @@ | |||
/* | |||
* Copyright 2012 Vaadin Ltd. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | |||
* use this file except in compliance with the License. You may obtain a copy of | |||
* the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |||
* License for the specific language governing permissions and limitations under | |||
* the License. | |||
*/ | |||
package com.vaadin.tests.components.textfield; | |||
import com.vaadin.data.util.BeanItem; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUI; | |||
import com.vaadin.ui.TextField; | |||
public class TextFieldWithDataSourceAndInputPrompt extends AbstractTestUI { | |||
public static class Pojo { | |||
private String string; | |||
public String getString() { | |||
return string; | |||
} | |||
public void setString(String string) { | |||
this.string = string; | |||
} | |||
} | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
TextField textField = new TextField("TextField with null value"); | |||
textField.setInputPrompt("Me is input prompt"); | |||
textField.setNullRepresentation(null); | |||
textField.setValue(null); | |||
addComponent(textField); | |||
TextField textField2 = new TextField( | |||
"TextField with null data source value"); | |||
textField2.setInputPrompt("Me is input prompt"); | |||
textField2.setNullRepresentation(null); | |||
BeanItem<Pojo> beanItem = new BeanItem<Pojo>(new Pojo()); | |||
textField2.setPropertyDataSource(beanItem.getItemProperty("string")); | |||
addComponent(textField2); | |||
} | |||
@Override | |||
protected String getTestDescription() { | |||
return "Input prompt should be shown when data source provides null"; | |||
} | |||
@Override | |||
protected Integer getTicketNumber() { | |||
return 11021; | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |||
<link rel="selenium.base" href="" /> | |||
<title>TreeTableExtraScrollbar</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr><td rowspan="1" colspan="3">TreeTableExtraScrollbar</td></tr> | |||
</thead><tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.components.treetable.TreeTableExtraScrollbarWithChildren?restartApplication</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>button</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>pause</td> | |||
<td>300</td> | |||
<td></td> | |||
</tr> | |||
<!-- screenCapture should not have a horizontal scrollbar, and the columns should be the same width in body and headers --> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>expanded</td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>button</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>pause</td> | |||
<td>300</td> | |||
<td></td> | |||
</tr> | |||
<!-- screenCapture should not have a horizontal scrollbar, the columns should be back to original width in body and headers, and vertical scrollbar shouldn't have left an empty space --> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>collapsed</td> | |||
</tr> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.components.treetable.TreeTableExtraScrollbarWithChildren</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>pause</td> | |||
<td>300</td> | |||
<td></td> | |||
</tr> | |||
<!-- screenCapture should not have changed --> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>refreshed</td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |
@@ -0,0 +1,92 @@ | |||
package com.vaadin.tests.components.treetable; | |||
import com.vaadin.tests.components.TestBase; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.Button.ClickEvent; | |||
import com.vaadin.ui.Button.ClickListener; | |||
import com.vaadin.ui.HorizontalLayout; | |||
import com.vaadin.ui.Label; | |||
import com.vaadin.ui.Notification; | |||
import com.vaadin.ui.Table; | |||
import com.vaadin.ui.TreeTable; | |||
public class TreeTableExtraScrollbarWithChildren extends TestBase { | |||
@Override | |||
protected String getDescription() { | |||
return "Arrow calculation should not cause a horizontal scrollbar" | |||
+ " if there is enough space for the final contents."; | |||
} | |||
@Override | |||
protected Integer getTicketNumber() { | |||
return 10513; | |||
} | |||
@Override | |||
protected void setup() { | |||
HorizontalLayout layout = new HorizontalLayout(); | |||
layout.setWidth("300px"); | |||
layout.setHeight("300px"); | |||
final TreeTable table = new TreeTable(); | |||
table.setSizeFull(); | |||
table.addGeneratedColumn("parameterId", new HierarchyColumnGenerator()); | |||
table.addGeneratedColumn("wordingTextId", new TypeColumnGenerator()); | |||
table.addGeneratedColumn("parameterTypeId", new TypeColumnGenerator()); | |||
table.setColumnWidth("parameterId", 26); | |||
table.addItem(new TestObject("name 1", "value 1")); | |||
table.addItem(new TestObject("name 2", "value 2")); | |||
table.addItem(new TestObject("name 3", "value 3")); | |||
table.addItem(new TestObject("name 4", "value 4")); | |||
table.addItem(new TestObject("name 5", "value 5")); | |||
final TestObject parent = new TestObject("name 6", "value 6"); | |||
table.addItem(parent); | |||
table.setFooterVisible(true); | |||
for (int i = 1; i <= 10; ++i) { | |||
TestObject child = new TestObject("name 6-" + i, "value 6-" + i); | |||
table.addItem(child); | |||
table.setParent(child, parent); | |||
} | |||
table.setVisibleColumns(new Object[] { "wordingTextId", "parameterId", | |||
"parameterTypeId" }); | |||
table.setColumnHeaders(new String[] { "", "", "" }); | |||
table.setHierarchyColumn("parameterId"); | |||
layout.addComponent(table); | |||
Button button = new Button("Toggle"); | |||
button.setId("button"); | |||
button.addClickListener(new ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
table.setCollapsed(parent, !table.isCollapsed(parent)); | |||
Notification.show("collapsed: " + table.isCollapsed(parent)); | |||
} | |||
}); | |||
addComponent(layout); | |||
addComponent(button); | |||
} | |||
private class HierarchyColumnGenerator implements Table.ColumnGenerator { | |||
public Object generateCell(Table table, Object itemId, Object columnId) { | |||
Label label = new Label("this should be mostly hidden"); | |||
label.setSizeUndefined(); | |||
return label; | |||
} | |||
} | |||
private class TypeColumnGenerator implements Table.ColumnGenerator { | |||
public Object generateCell(Table table, Object itemId, Object columnId) { | |||
if (itemId instanceof TestObject) { | |||
return new Label(((TestObject) itemId).getValue()); | |||
} | |||
return null; | |||
} | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |||
<head profile="http://selenium-ide.openqa.org/profiles/test-case"> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |||
<link rel="selenium.base" href="" /> | |||
<title>New Test</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr><td rowspan="1" colspan="3">New Test</td></tr> | |||
</thead><tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.debug.HierarchyAfterAnalyzeLayouts?restartApplication&debug</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestsdebugHierarchyAfterAnalyzeLayouts::Root/VDebugConsole[0]/FlowPanel[0]/HorizontalPanel[0]/domChild[0]/domChild[0]/domChild[3]/domChild[0]</td> | |||
<td>18,9</td> | |||
</tr> | |||
<tr> | |||
<td>assertTextPresent</td> | |||
<td>Layouts analyzed on server, total top level problems: 0</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>assertElementPresent</td> | |||
<td>vaadin=runcomvaadintestsdebugHierarchyAfterAnalyzeLayouts::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VLabel[0]</td> | |||
<td></td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |
@@ -0,0 +1,40 @@ | |||
/* | |||
* 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 | |||
* the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |||
* License for the specific language governing permissions and limitations under | |||
* the License. | |||
*/ | |||
package com.vaadin.tests.debug; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUI; | |||
import com.vaadin.ui.Label; | |||
public class HierarchyAfterAnalyzeLayouts extends AbstractTestUI { | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
addComponent(new Label("This is a label")); | |||
} | |||
@Override | |||
protected String getTestDescription() { | |||
return "The connector hierarchy should be in order after clicking AL in the debug console"; | |||
} | |||
@Override | |||
protected Integer getTicketNumber() { | |||
return Integer.valueOf(11067); | |||
} | |||
} |
@@ -18,6 +18,7 @@ package com.vaadin.tests.minitutorials.v7a1; | |||
import com.vaadin.annotations.PreserveOnRefresh; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.ui.CssLayout; | |||
import com.vaadin.ui.TextField; | |||
import com.vaadin.ui.UI; | |||
@@ -31,13 +32,12 @@ import com.vaadin.ui.UI; | |||
*/ | |||
@PreserveOnRefresh | |||
public class CreatingPreserveState extends UI { | |||
private static int windowCounter = 0; | |||
private static int instanceCounter = 0; | |||
@Override | |||
public void init(VaadinRequest request) { | |||
TextField tf = new TextField("Window #" + (++windowCounter)); | |||
TextField tf = new TextField("Instance #" + (++instanceCounter)); | |||
tf.setImmediate(true); | |||
setContent(tf); | |||
setContent(new CssLayout(tf)); | |||
} | |||
} |