diff options
Diffstat (limited to 'server')
23 files changed, 415 insertions, 114 deletions
diff --git a/server/src/main/java/com/vaadin/annotations/PreserveOnRefresh.java b/server/src/main/java/com/vaadin/annotations/PreserveOnRefresh.java index 7f4ef3ffe5..86723b97fc 100644 --- a/server/src/main/java/com/vaadin/annotations/PreserveOnRefresh.java +++ b/server/src/main/java/com/vaadin/annotations/PreserveOnRefresh.java @@ -17,6 +17,7 @@ package com.vaadin.annotations; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -45,6 +46,7 @@ import com.vaadin.ui.UI; */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) +@Inherited public @interface PreserveOnRefresh { // Empty marker annotation } diff --git a/server/src/main/java/com/vaadin/annotations/Push.java b/server/src/main/java/com/vaadin/annotations/Push.java index b6a28c1560..736bc4488b 100644 --- a/server/src/main/java/com/vaadin/annotations/Push.java +++ b/server/src/main/java/com/vaadin/annotations/Push.java @@ -17,6 +17,7 @@ package com.vaadin.annotations; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -38,6 +39,7 @@ import com.vaadin.ui.UI; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface Push { /** * Returns the {@link PushMode} to use for the annotated UI. The default diff --git a/server/src/main/java/com/vaadin/annotations/Theme.java b/server/src/main/java/com/vaadin/annotations/Theme.java index 61c47389ad..03fa1179bc 100644 --- a/server/src/main/java/com/vaadin/annotations/Theme.java +++ b/server/src/main/java/com/vaadin/annotations/Theme.java @@ -17,6 +17,7 @@ package com.vaadin.annotations; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -28,6 +29,7 @@ import com.vaadin.ui.UI; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface Theme { /** * @return simple name of the theme diff --git a/server/src/main/java/com/vaadin/annotations/Title.java b/server/src/main/java/com/vaadin/annotations/Title.java index 38a3d75f17..07eaf17e33 100644 --- a/server/src/main/java/com/vaadin/annotations/Title.java +++ b/server/src/main/java/com/vaadin/annotations/Title.java @@ -17,6 +17,7 @@ package com.vaadin.annotations; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -28,6 +29,7 @@ import com.vaadin.ui.UI; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface Title { /** * Gets the HTML title that should be used if the UI is used on it's own. diff --git a/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java b/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java index 00af38ecc1..907f2c3a0c 100644 --- a/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java +++ b/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java @@ -18,6 +18,7 @@ package com.vaadin.annotations; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -44,6 +45,7 @@ import com.vaadin.ui.UI; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface VaadinServletConfiguration { /** * Defines the init parameter name for methods in diff --git a/server/src/main/java/com/vaadin/annotations/Widgetset.java b/server/src/main/java/com/vaadin/annotations/Widgetset.java index c6ef6a7194..2dcf93af13 100644 --- a/server/src/main/java/com/vaadin/annotations/Widgetset.java +++ b/server/src/main/java/com/vaadin/annotations/Widgetset.java @@ -17,6 +17,7 @@ package com.vaadin.annotations; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -28,6 +29,7 @@ import com.vaadin.ui.UI; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) +@Inherited public @interface Widgetset { /** * @return name of the widgetset diff --git a/server/src/main/java/com/vaadin/server/UIProvider.java b/server/src/main/java/com/vaadin/server/UIProvider.java index d3d834cad7..4ed86b9c31 100644 --- a/server/src/main/java/com/vaadin/server/UIProvider.java +++ b/server/src/main/java/com/vaadin/server/UIProvider.java @@ -18,6 +18,7 @@ package com.vaadin.server; import java.io.Serializable; import java.lang.annotation.Annotation; +import java.lang.annotation.Inherited; import com.vaadin.annotations.PreserveOnRefresh; import com.vaadin.annotations.Push; @@ -43,8 +44,15 @@ public abstract class UIProvider implements Serializable { /** * Helper to get an annotation for a class. If the annotation is not present - * on the target class, its super classes and implemented interfaces are - * also searched for the annotation. + * on the target class, its super classes and directly implemented + * interfaces are also searched for the annotation. Interfaces implemented + * by superclasses are not taken into account. + * <p> + * Note that searching implemented interfaces for {@code @Inherited} + * annotations and searching for superclasses for non-inherited annotations + * do not follow the standard semantics and are supported for backwards + * compatibility. Future versions of the framework might only support the + * standard semantics of {@code @Inherited}. * * @param clazz * the class from which the annotation should be found @@ -55,18 +63,26 @@ public abstract class UIProvider implements Serializable { */ protected static <T extends Annotation> T getAnnotationFor(Class<?> clazz, Class<T> annotationType) { - // Find from the class hierarchy - Class<?> currentType = clazz; - while (currentType != Object.class) { - T annotation = currentType.getAnnotation(annotationType); + // Don't discover hierarchy if annotation is inherited + if (annotationType.getAnnotation(Inherited.class) != null) { + T annotation = clazz.getAnnotation(annotationType); if (annotation != null) { return annotation; - } else { - currentType = currentType.getSuperclass(); + } + } else { + // Find from the class hierarchy + Class<?> currentType = clazz; + while (currentType != Object.class) { + T annotation = currentType.getAnnotation(annotationType); + if (annotation != null) { + return annotation; + } else { + currentType = currentType.getSuperclass(); + } } } - // Find from an implemented interface + // Find from a directly implemented interface for (Class<?> iface : clazz.getInterfaces()) { T annotation = iface.getAnnotation(annotationType); if (annotation != null) { diff --git a/server/src/main/java/com/vaadin/server/VaadinPortlet.java b/server/src/main/java/com/vaadin/server/VaadinPortlet.java index 043f95fd7b..5c91b6669c 100644 --- a/server/src/main/java/com/vaadin/server/VaadinPortlet.java +++ b/server/src/main/java/com/vaadin/server/VaadinPortlet.java @@ -180,6 +180,14 @@ public class VaadinPortlet extends GenericPortlet implements Constants, */ public static class VaadinLiferayRequest extends VaadinHttpAndPortletRequest { + /** + * The PortalUtil class to use. Set to either + * {@link #LIFERAY_6_PORTAL_UTIL} or {@link #LIFERAY_7_PORTAL_UTIL} the + * first time it is needed. + */ + private static String portalUtilClass = null; + private static final String LIFERAY_6_PORTAL_UTIL = "com.liferay.portal.util.PortalUtil"; + private static final String LIFERAY_7_PORTAL_UTIL = "com.liferay.portal.kernel.util.PortalUtil"; public VaadinLiferayRequest(PortletRequest request, VaadinPortletService vaadinService) { @@ -247,19 +255,28 @@ public class VaadinPortlet extends GenericPortlet implements Constants, @Override protected HttpServletRequest getServletRequest(PortletRequest request) { + if (portalUtilClass == null) { + try { + invokeStaticLiferayMethod(LIFERAY_7_PORTAL_UTIL, + "getHttpServletRequest", request, + "javax.portlet.PortletRequest"); + portalUtilClass = LIFERAY_7_PORTAL_UTIL; + } catch (Exception e) { + // Liferay 6 or older + portalUtilClass = LIFERAY_6_PORTAL_UTIL; + } + } try { // httpRequest = PortalUtil.getHttpServletRequest(request); HttpServletRequest httpRequest = (HttpServletRequest) invokeStaticLiferayMethod( - "com.liferay.portal.util.PortalUtil", - "getHttpServletRequest", request, + portalUtilClass, "getHttpServletRequest", request, "javax.portlet.PortletRequest"); // httpRequest = // PortalUtil.getOriginalServletRequest(httpRequest); httpRequest = (HttpServletRequest) invokeStaticLiferayMethod( - "com.liferay.portal.util.PortalUtil", - "getOriginalServletRequest", httpRequest, - "javax.servlet.http.HttpServletRequest"); + portalUtilClass, "getOriginalServletRequest", + httpRequest, "javax.servlet.http.HttpServletRequest"); return httpRequest; } catch (Exception e) { throw new IllegalStateException("Liferay request not detected", diff --git a/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java index 593b1f544f..3503a2d8b1 100644 --- a/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java +++ b/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java @@ -316,7 +316,7 @@ public class ServerRpcHandler implements Serializable { * 6 semantics for components and add-ons that do not use Vaadin 7 RPC * directly. * - * @param uI + * @param ui * the UI receiving the invocations data * @param lastSyncIdSeenByClient * the most recent sync id the client has seen at the time the @@ -324,20 +324,21 @@ public class ServerRpcHandler implements Serializable { * @param invocationsData * JSON containing all information needed to execute all * requested RPC calls. + * @since */ - private void handleInvocations(UI uI, int lastSyncIdSeenByClient, + protected void handleInvocations(UI ui, int lastSyncIdSeenByClient, JsonArray invocationsData) { // TODO PUSH Refactor so that this is not needed - LegacyCommunicationManager manager = uI.getSession() + LegacyCommunicationManager manager = ui.getSession() .getCommunicationManager(); try { - ConnectorTracker connectorTracker = uI.getConnectorTracker(); + ConnectorTracker connectorTracker = ui.getConnectorTracker(); Set<Connector> enabledConnectors = new HashSet<Connector>(); List<MethodInvocation> invocations = parseInvocations( - uI.getConnectorTracker(), invocationsData, + ui.getConnectorTracker(), invocationsData, lastSyncIdSeenByClient); for (MethodInvocation invocation : invocations) { final ClientConnector connector = connectorTracker @@ -404,35 +405,11 @@ public class ServerRpcHandler implements Serializable { } if (invocation instanceof ServerRpcMethodInvocation) { - try { - ServerRpcManager.applyInvocation(connector, - (ServerRpcMethodInvocation) invocation); - } catch (RpcInvocationException e) { - manager.handleConnectorRelatedException(connector, e); - } + handleInvocation(ui, connector, + (ServerRpcMethodInvocation) invocation); } else { - - // All code below is for legacy variable changes LegacyChangeVariablesInvocation legacyInvocation = (LegacyChangeVariablesInvocation) invocation; - Map<String, Object> changes = legacyInvocation - .getVariableChanges(); - try { - if (connector instanceof VariableOwner) { - // The source parameter is never used anywhere - changeVariables(null, (VariableOwner) connector, - changes); - } else { - throw new IllegalStateException( - "Received legacy variable change for " - + connector.getClass().getName() - + " (" - + connector.getConnectorId() - + ") which is not a VariableOwner. The client-side connector sent these legacy varaibles: " - + changes.keySet()); - } - } catch (Exception e) { - manager.handleConnectorRelatedException(connector, e); - } + handleInvocation(ui, connector, legacyInvocation); } } } catch (JsonException e) { @@ -444,6 +421,63 @@ public class ServerRpcHandler implements Serializable { } /** + * Handles the given RPC method invocation for the given connector + * + * @since + * @param ui + * the UI containing the connector + * @param connector + * the connector the RPC is targeted to + * @param invocation + * information about the rpc to invoke + */ + protected void handleInvocation(UI ui, ClientConnector connector, + ServerRpcMethodInvocation invocation) { + try { + ServerRpcManager.applyInvocation(connector, invocation); + } catch (RpcInvocationException e) { + ui.getSession().getCommunicationManager() + .handleConnectorRelatedException(connector, e); + } + + } + + /** + * Handles the given Legacy variable change RPC method invocation for the + * given connector + * + * @since + * @param ui + * the UI containing the connector + * @param connector + * the connector the RPC is targeted to + * @param invocation + * information about the rpc to invoke + */ + protected void handleInvocation(UI ui, ClientConnector connector, + LegacyChangeVariablesInvocation legacyInvocation) { + Map<String, Object> changes = legacyInvocation.getVariableChanges(); + try { + if (connector instanceof VariableOwner) { + // The source parameter is never used anywhere + changeVariables(null, (VariableOwner) connector, changes); + } else { + throw new IllegalStateException( + "Received legacy variable change for " + + connector.getClass().getName() + + " (" + + connector.getConnectorId() + + ") which is not a VariableOwner. The client-side connector sent these legacy varaibles: " + + changes.keySet()); + } + } catch (Exception e) { + ui.getSession().getCommunicationManager() + .handleConnectorRelatedException(connector, e); + } + + } + + /** * Parse JSON from the client into a list of MethodInvocation instances. * * @param connectorTracker diff --git a/server/src/main/java/com/vaadin/server/communication/UidlRequestHandler.java b/server/src/main/java/com/vaadin/server/communication/UidlRequestHandler.java index dda3d81453..db18bb9e1e 100644 --- a/server/src/main/java/com/vaadin/server/communication/UidlRequestHandler.java +++ b/server/src/main/java/com/vaadin/server/communication/UidlRequestHandler.java @@ -51,9 +51,20 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements public static final String UIDL_PATH = "UIDL/"; - private ServerRpcHandler rpcHandler = new ServerRpcHandler(); + private ServerRpcHandler rpcHandler; public UidlRequestHandler() { + rpcHandler = createRpcHandler(); + } + + /** + * Creates the ServerRpcHandler to use + * + * @since + * @return the ServerRpcHandler to use + */ + protected ServerRpcHandler createRpcHandler() { + return new ServerRpcHandler(); } @Override diff --git a/server/src/main/java/com/vaadin/server/communication/UidlWriter.java b/server/src/main/java/com/vaadin/server/communication/UidlWriter.java index b117cb4b4d..8a4e62fb24 100644 --- a/server/src/main/java/com/vaadin/server/communication/UidlWriter.java +++ b/server/src/main/java/com/vaadin/server/communication/UidlWriter.java @@ -352,9 +352,12 @@ public class UidlWriter implements Serializable { * @throws IOException */ private void writePerformanceData(UI ui, Writer writer) throws IOException { - writer.write(String.format(", \"timings\":[%d, %d]", ui.getSession() - .getCumulativeRequestDuration(), ui.getSession() - .getLastRequestDuration())); + if (!ui.getSession().getService().getDeploymentConfiguration() + .isProductionMode()) { + writer.write(String.format(", \"timings\":[%d, %d]", ui + .getSession().getCumulativeRequestDuration(), ui + .getSession().getLastRequestDuration())); + } } private static final Logger getLogger() { diff --git a/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java b/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java index 063f4f5346..255f34d936 100644 --- a/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java +++ b/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java @@ -495,7 +495,24 @@ public class ClassPathExplorer { * @return URL */ public static URL getDefaultSourceDirectory() { + return getWidgetsetSourceDirectory(null); + } + /** + * Find and return the source directory which contains the given widgetset + * file. + * + * If not applicable or widgetsetFileName is null, return the first + * directory (not a JAR file etc.) on the classpath. + * + * TODO this could be done better... + * + * @param widgetsetFileName + * relative path for the widgetset + * + * @return URL + */ + public static URL getWidgetsetSourceDirectory(String widgetsetFileName) { if (debug) { debug("classpathLocations values:"); ArrayList<String> locations = new ArrayList<String>( @@ -505,6 +522,7 @@ public class ClassPathExplorer { } } + URL firstDirectory = null; Iterator<String> it = rawClasspathEntries.iterator(); while (it.hasNext()) { String entry = it.next(); @@ -513,13 +531,18 @@ public class ClassPathExplorer { if (directory.exists() && !directory.isHidden() && directory.isDirectory()) { try { - return new URL("file://" + directory.getCanonicalPath()); - } catch (MalformedURLException e) { - // ignore: continue to the next classpath entry - if (debug) { - e.printStackTrace(); + URL directoryUrl = directory.toURI().toURL(); + + // Store the first directory encountered. + if (firstDirectory == null) { + firstDirectory = directoryUrl; } - } catch (IOException e) { + + if (widgetsetFileName == null + || new File(directory, widgetsetFileName).exists()) { + return directoryUrl; + } + } catch (MalformedURLException e) { // ignore: continue to the next classpath entry if (debug) { e.printStackTrace(); @@ -527,7 +550,8 @@ public class ClassPathExplorer { } } } - return null; + + return firstDirectory; } /** diff --git a/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java b/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java index f810a63a38..b0d8cdd004 100644 --- a/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java +++ b/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java @@ -61,16 +61,17 @@ public class WidgetSetBuilder { Map<String, URL> availableWidgetSets = ClassPathExplorer .getAvailableWidgetSets(); + String widgetsetFileName = widgetset.replace(".", "/") + ".gwt.xml"; URL sourceUrl = availableWidgetSets.get(widgetset); if (sourceUrl == null) { // find first/default source directory - sourceUrl = ClassPathExplorer.getDefaultSourceDirectory(); + sourceUrl = ClassPathExplorer + .getWidgetsetSourceDirectory(widgetsetFileName); } - String widgetsetfilename = sourceUrl.getFile() + "/" - + widgetset.replace(".", "/") + ".gwt.xml"; + String wsFullPath = sourceUrl.getFile() + "/" + widgetsetFileName; - File widgetsetFile = new File(widgetsetfilename); + File widgetsetFile = new File(wsFullPath); if (!widgetsetFile.exists()) { // create empty gwt module file File parent = widgetsetFile.getParentFile(); @@ -137,7 +138,7 @@ public class WidgetSetBuilder { changed = changed || !content.equals(originalContent); if (changed) { - commitChanges(widgetsetfilename, content); + commitChanges(wsFullPath, content); } } else { System.out diff --git a/server/src/main/java/com/vaadin/ui/AbstractOrderedLayout.java b/server/src/main/java/com/vaadin/ui/AbstractOrderedLayout.java index e0dbcb004b..f517ab0af5 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractOrderedLayout.java +++ b/server/src/main/java/com/vaadin/ui/AbstractOrderedLayout.java @@ -31,7 +31,6 @@ import com.vaadin.server.Sizeable; import com.vaadin.shared.Connector; import com.vaadin.shared.EventId; import com.vaadin.shared.MouseEventDetails; -import com.vaadin.shared.ui.AlignmentInfo; import com.vaadin.shared.ui.MarginInfo; import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutServerRpc; import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState; @@ -486,22 +485,8 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements Component newChild = designContext.readDesign(childComponent); addComponent(newChild); // handle alignment - int bitMask = 0; - if (attr.hasKey(":middle")) { - bitMask += AlignmentInfo.Bits.ALIGNMENT_VERTICAL_CENTER; - } else if (attr.hasKey(":bottom")) { - bitMask += AlignmentInfo.Bits.ALIGNMENT_BOTTOM; - } else { - bitMask += AlignmentInfo.Bits.ALIGNMENT_TOP; - } - if (attr.hasKey(":center")) { - bitMask += AlignmentInfo.Bits.ALIGNMENT_HORIZONTAL_CENTER; - } else if (attr.hasKey(":right")) { - bitMask += AlignmentInfo.Bits.ALIGNMENT_RIGHT; - } else { - bitMask += AlignmentInfo.Bits.ALIGNMENT_LEFT; - } - setComponentAlignment(newChild, new Alignment(bitMask)); + setComponentAlignment(newChild, + DesignAttributeHandler.readAlignment(attr)); // handle expand ratio if (attr.hasKey(":expand")) { String value = attr.get(":expand"); diff --git a/server/src/main/java/com/vaadin/ui/AbstractSelect.java b/server/src/main/java/com/vaadin/ui/AbstractSelect.java index 9babf7e876..2714e0cbf5 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractSelect.java +++ b/server/src/main/java/com/vaadin/ui/AbstractSelect.java @@ -532,13 +532,16 @@ public abstract class AbstractSelect extends AbstractField<Object> implements } else { final Object id = itemIdMapper .get(clientSideSelectedKeys[0]); - if (!isNullSelectionAllowed() && id == null) { - markAsDirty(); - } else if (id != null - && id.equals(getNullSelectionItemId())) { - setValue(null, true); + + if (id != null) { + if (isNullSelectionAllowed() + && id.equals(getNullSelectionItemId())) { + setValue(null, true); + } else { + setValue(id, true); + } } else { - setValue(id, true); + markAsDirty(); } } } diff --git a/server/src/main/java/com/vaadin/ui/DragAndDropWrapper.java b/server/src/main/java/com/vaadin/ui/DragAndDropWrapper.java index 90b3b56ef6..29179ddca7 100644 --- a/server/src/main/java/com/vaadin/ui/DragAndDropWrapper.java +++ b/server/src/main/java/com/vaadin/ui/DragAndDropWrapper.java @@ -40,6 +40,7 @@ import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.ui.dd.HorizontalDropLocation; import com.vaadin.shared.ui.dd.VerticalDropLocation; import com.vaadin.shared.ui.draganddropwrapper.DragAndDropWrapperConstants; +import com.vaadin.shared.ui.draganddropwrapper.DragAndDropWrapperServerRpc; import com.vaadin.ui.declarative.DesignContext; @SuppressWarnings("serial") @@ -111,6 +112,14 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget, } + private final DragAndDropWrapperServerRpc rpc = new DragAndDropWrapperServerRpc() { + + @Override + public void poll() { + // #19616 RPC to poll the server for changes + } + }; + private Map<String, ProxyReceiver> receivers = new HashMap<String, ProxyReceiver>(); public class WrapperTargetDetails extends TargetDetailsImpl { @@ -197,6 +206,7 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget, @Deprecated public DragAndDropWrapper() { super(); + registerRpc(rpc); } /** diff --git a/server/src/main/java/com/vaadin/ui/FormLayout.java b/server/src/main/java/com/vaadin/ui/FormLayout.java index f6f711d658..c817300e53 100644 --- a/server/src/main/java/com/vaadin/ui/FormLayout.java +++ b/server/src/main/java/com/vaadin/ui/FormLayout.java @@ -36,7 +36,7 @@ public class FormLayout extends AbstractOrderedLayout { public FormLayout() { super(); setSpacing(true); - setMargin(new MarginInfo(true, false, true, false)); + setMargin(new MarginInfo(true, false)); setWidth(100, UNITS_PERCENTAGE); } diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java index 4074672675..036fe8b756 100644 --- a/server/src/main/java/com/vaadin/ui/Grid.java +++ b/server/src/main/java/com/vaadin/ui/Grid.java @@ -4855,8 +4855,13 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, } /** - * Sets the grid data source. - * + * Sets the grid data source.<p> + * + * <strong>Note</strong> Grid columns are based on properties and try to detect a correct converter for + * the data type. The columns are not reinitialized automatically if the container is changed, and if the same + * properties are present after container change, the columns are reused. + * Properties with same names, but different data types will lead to unpredictable behaviour. + * * @param container * The container data source. Cannot be null. * @throws IllegalArgumentException diff --git a/server/src/main/java/com/vaadin/ui/GridLayout.java b/server/src/main/java/com/vaadin/ui/GridLayout.java index 8517962e91..148fd85fff 100644 --- a/server/src/main/java/com/vaadin/ui/GridLayout.java +++ b/server/src/main/java/com/vaadin/ui/GridLayout.java @@ -1330,7 +1330,7 @@ public class GridLayout extends AbstractLayout implements } } setRows(Math.max(rows.size(), 1)); - + Map<Component, Alignment> alignments = new HashMap<Component, Alignment>(); List<Integer> columnExpandRatios = new ArrayList<Integer>(); for (int row = 0; row < rowElements.size(); ++row) { Element rowElement = rowElements.get(row); @@ -1357,7 +1357,10 @@ public class GridLayout extends AbstractLayout implements Component child = null; if (col.children().size() > 0) { - child = designContext.readDesign(col.child(0)); + Element childElement = col.child(0); + child = designContext.readDesign(childElement); + alignments.put(child, DesignAttributeHandler + .readAlignment(childElement.attributes())); // TODO: Currently ignoring any extra children. // Needs Error handling? } // Else: Empty placeholder. No child component. @@ -1441,6 +1444,7 @@ public class GridLayout extends AbstractLayout implements // Add component with area addComponent(child, j, i, j + colspan, i + rowspan); + setComponentAlignment(child, alignments.get(child)); } } // Set cursor position explicitly @@ -1511,16 +1515,8 @@ public class GridLayout extends AbstractLayout implements ChildComponentData coords = childData.get(child); Alignment alignment = getComponentAlignment(child); - if (alignment.isMiddle()) { - childElement.attr(":middle", true); - } else if (alignment.isBottom()) { - childElement.attr(":bottom", true); - } - if (alignment.isCenter()) { - childElement.attr(":center", true); - } else if (alignment.isRight()) { - childElement.attr(":right", true); - } + DesignAttributeHandler.writeAlignment(childElement, + alignment); col.appendChild(childElement); if (coords.row1 != coords.row2) { diff --git a/server/src/main/java/com/vaadin/ui/Window.java b/server/src/main/java/com/vaadin/ui/Window.java index b5cd384f53..70399ae566 100644 --- a/server/src/main/java/com/vaadin/ui/Window.java +++ b/server/src/main/java/com/vaadin/ui/Window.java @@ -1051,7 +1051,9 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, @Override public void handleAction(Object sender, Object target) { - window.close(); + if (window.isClosable()) { + window.close(); + } } public boolean equals(int keyCode, int... modifiers) { diff --git a/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java b/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java index cee2ebe381..bbfd90b2cc 100644 --- a/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java +++ b/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java @@ -37,7 +37,9 @@ import org.jsoup.nodes.Element; import org.jsoup.nodes.Node; import com.vaadin.data.util.converter.Converter; +import com.vaadin.shared.ui.AlignmentInfo; import com.vaadin.shared.util.SharedUtil; +import com.vaadin.ui.Alignment; /** * Default attribute handler implementation used when parsing designs to @@ -452,4 +454,55 @@ public class DesignAttributeHandler implements Serializable { return (methods != null && methods.length > 1) ? methods[1] : null; } } + + /** + * Read the alignment from the given child component attributes. + * + * @since 7.6.4 + * @param attr + * the child component attributes + * @return the component alignment + */ + public static Alignment readAlignment(Attributes attr) { + int bitMask = 0; + if (attr.hasKey(":middle")) { + bitMask += AlignmentInfo.Bits.ALIGNMENT_VERTICAL_CENTER; + } else if (attr.hasKey(":bottom")) { + bitMask += AlignmentInfo.Bits.ALIGNMENT_BOTTOM; + } else { + bitMask += AlignmentInfo.Bits.ALIGNMENT_TOP; + } + if (attr.hasKey(":center")) { + bitMask += AlignmentInfo.Bits.ALIGNMENT_HORIZONTAL_CENTER; + } else if (attr.hasKey(":right")) { + bitMask += AlignmentInfo.Bits.ALIGNMENT_RIGHT; + } else { + bitMask += AlignmentInfo.Bits.ALIGNMENT_LEFT; + } + + return new Alignment(bitMask); + } + + /** + * Writes the alignment to the given child element attributes. + * + * @since 7.6.4 + * @param childElement + * the child element + * @param alignment + * the component alignment + */ + public static void writeAlignment(Element childElement, Alignment alignment) { + if (alignment.isMiddle()) { + childElement.attr(":middle", true); + } else if (alignment.isBottom()) { + childElement.attr(":bottom", true); + } + if (alignment.isCenter()) { + childElement.attr(":center", true); + } else if (alignment.isRight()) { + childElement.attr(":right", true); + } + } + } diff --git a/server/src/test/java/com/vaadin/server/UIProviderTest.java b/server/src/test/java/com/vaadin/server/UIProviderTest.java new file mode 100644 index 0000000000..579a3f1858 --- /dev/null +++ b/server/src/test/java/com/vaadin/server/UIProviderTest.java @@ -0,0 +1,113 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.server; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.annotations.Theme; +import com.vaadin.annotations.Widgetset; + +/** + * Tests for {@link UIProvider} class. + * + * @author Vaadin Ltd + */ +public class UIProviderTest { + + @Test + public void getAnnotationFor_widgetsetAnnotationForSubclass_annotationFound() { + Assert.assertNotNull("Widgetset annotation is not found for subclass", + UIProvider.getAnnotationFor(TestClass.class, Widgetset.class)); + } + + @Test + public void getAnnotationFor_themeAnnotationForSubclass_annotationFound() { + Assert.assertNotNull("Theme annotation is not found for subclass", + UIProvider.getAnnotationFor(TestClass.class, Theme.class)); + } + + @Test + public void getAnnotationFor_themeAnnotationForSubclass_annotationOverridden() { + Assert.assertEquals( + "Theme annotation is not overridden correctly in subclass", + "c", UIProvider.getAnnotationFor(TestClass.class, Theme.class) + .value()); + } + + @Test + public void getAnnotationFor_notInheritedAnnotationForSubclass_annotationFound() { + Assert.assertNotNull( + "TestAnnotation annotation is not found for subclass", + UIProvider.getAnnotationFor(TestClass.class, + TestAnnotation.class)); + } + + @Test + public void getAnnotationFor_directAnnotationForSubclass_annotationFound() { + Assert.assertNotNull( + "TestAnnotation1 annotation is not found for subclass", + UIProvider.getAnnotationFor(TestClass.class, + TestAnnotation1.class)); + } + + @Test + public void getAnnotationFor_annotationInheritedFromInterface_annotationFound() { + Assert.assertNotNull( + "Theme annotation is not inherited from interface", UIProvider + .getAnnotationFor(ClassImplementingInterface.class, + Theme.class)); + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface TestAnnotation { + + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + public @interface TestAnnotation1 { + + } + + @Widgetset("a") + @Theme("b") + @TestAnnotation + public static class TestSuperClass { + + } + + @TestAnnotation1 + @Theme("c") + public static class TestClass extends TestSuperClass { + + } + + @Theme("d") + public interface InterfaceWithAnnotation { + } + + public static class ClassImplementingInterface implements + InterfaceWithAnnotation { + } + +} diff --git a/server/src/test/java/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java b/server/src/test/java/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java index 0e4293481e..e3975e41a8 100644 --- a/server/src/test/java/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java +++ b/server/src/test/java/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java @@ -70,7 +70,7 @@ public class GridLayoutDeclarativeTest extends @Test public void testOneBigComponentGridLayout() { - Button b1 = new Button("Button 0,0 -> 1,1"); + Button b1 = new Button("Button 0,0 -> 1,1"); b1.setCaptionAsHtml(true); String design = "<vaadin-grid-layout><row>" // + "<column colspan=2 rowspan=2>" + writeChild(b1) + "</column>" // @@ -86,19 +86,19 @@ public class GridLayoutDeclarativeTest extends @Test public void testMultipleSpannedComponentsGridLayout() { GridLayout gl = new GridLayout(5, 5); - Button b1 = new Button("Button 0,0 -> 0,2"); + Button b1 = new Button("Button 0,0 -> 0,2"); b1.setCaptionAsHtml(true); gl.addComponent(b1, 0, 0, 2, 0); - Button b2 = new Button("Button 0,3 -> 3,3"); + Button b2 = new Button("Button 0,3 -> 3,3"); b2.setCaptionAsHtml(true); gl.addComponent(b2, 3, 0, 3, 3); - Button b3 = new Button("Button 0,4 -> 1,4"); + Button b3 = new Button("Button 0,4 -> 1,4"); b3.setCaptionAsHtml(true); gl.addComponent(b3, 4, 0, 4, 1); - Button b4 = new Button("Button 1,0 -> 3,1"); + Button b4 = new Button("Button 1,0 -> 3,1"); b4.setCaptionAsHtml(true); gl.addComponent(b4, 0, 1, 1, 3); @@ -106,11 +106,11 @@ public class GridLayoutDeclarativeTest extends b5.setCaptionAsHtml(true); gl.addComponent(b5, 2, 2); - Button b6 = new Button("Button 3,4 -> 4,4"); + Button b6 = new Button("Button 3,4 -> 4,4"); b6.setCaptionAsHtml(true); gl.addComponent(b6, 4, 3, 4, 4); - Button b7 = new Button("Button 4,1 -> 4,2"); + Button b7 = new Button("Button 4,1 -> 4,2"); b7.setCaptionAsHtml(true); gl.addComponent(b7, 2, 4, 3, 4); @@ -146,7 +146,7 @@ public class GridLayoutDeclarativeTest extends @Test public void testManyExtraGridLayoutSlots() { GridLayout gl = new GridLayout(5, 5); - Button b1 = new Button("Button 0,4 -> 4,4"); + Button b1 = new Button("Button 0,4 -> 4,4"); b1.setCaptionAsHtml(true); gl.addComponent(b1, 4, 0, 4, 4); gl.setColumnExpandRatio(2, 2.0f); @@ -166,7 +166,7 @@ public class GridLayoutDeclarativeTest extends @Test public void testManyEmptyColumnsWithOneExpand() { GridLayout gl = new GridLayout(5, 5); - Button b1 = new Button("Button 0,4 -> 4,4"); + Button b1 = new Button("Button 0,4 -> 4,4"); b1.setCaptionAsHtml(true); gl.addComponent(b1, 0, 0, 0, 4); gl.setColumnExpandRatio(4, 2.0f); @@ -202,13 +202,29 @@ public class GridLayoutDeclarativeTest extends GridLayout result = super.testRead(design, expected); for (int row = 0; row < expected.getRows(); ++row) { - Assert.assertTrue(Math.abs(expected.getRowExpandRatio(row) - - result.getRowExpandRatio(row)) < 0.00001); + Assert.assertEquals(expected.getRowExpandRatio(row), + result.getRowExpandRatio(row), 0.00001); } for (int col = 0; col < expected.getColumns(); ++col) { - Assert.assertTrue(Math.abs(expected.getColumnExpandRatio(col) - - result.getColumnExpandRatio(col)) < 0.00001); + Assert.assertEquals(expected.getColumnExpandRatio(col), + result.getColumnExpandRatio(col), 0.00001); } + for (int row = 0; row < expected.getRows(); ++row) { + for (int col = 0; col < expected.getColumns(); ++col) { + Component eC = expected.getComponent(col, row); + Component rC = result.getComponent(col, row); + + assertEquals(eC, rC); + if (eC == null) { + continue; + } + + Assert.assertEquals(expected.getComponentAlignment(eC), + result.getComponentAlignment(rC)); + + } + } + return result; } |