diff options
13 files changed, 471 insertions, 189 deletions
diff --git a/all/src/main/templates/release-notes.html b/all/src/main/templates/release-notes.html index 327dae38b3..02806e7346 100644 --- a/all/src/main/templates/release-notes.html +++ b/all/src/main/templates/release-notes.html @@ -86,6 +86,7 @@ <li>Separate row heights for header, body and footer in Grid</li> <li>Support for item descriptions (tooltips) in CheckBoxGroup, RadioButtonGroup and Tree</li> <li>Binder supports removing bindings</li> + <li>Notification supports CloseListener</li> </ul> </p> @@ -109,8 +110,9 @@ <li><tt>ErrorLevel</tt> is removed from <tt>ErrorMessage</tt> and now <tt>com.vaadin.shared.ui.ErrorLevel</tt> should be used.</li> <li>Error indicators are now <tt><span class="v-errorindicator"></span></tt> elements.</li> <li><tt>Embedded</tt> is not a <tt>LegacyComponent</tt> anymore.</li> + <li><tt>Notification</tt> method <tt>show</tt> returns <tt>Notification</tt>, instead of <tt>void</tt>.</li> - <h2>For incompatible or behaviour-altering changes in 8.1, please see <a href="https://vaadin.com/download/release/8.1/8.1.0/release-notes.html#incompatible">8.1 release notes</a></h2> + <h2>For incompatible or behavior-altering changes in 8.1, please see <a href="https://vaadin.com/download/release/8.1/8.1.0/release-notes.html#incompatible">8.1 release notes</a></h2> <h3 id="knownissues">Known Issues and Limitations</h3> diff --git a/client/src/main/java/com/vaadin/client/ui/VNotification.java b/client/src/main/java/com/vaadin/client/ui/VNotification.java index 8f98b6bd08..5fc14e7ae2 100644 --- a/client/src/main/java/com/vaadin/client/ui/VNotification.java +++ b/client/src/main/java/com/vaadin/client/ui/VNotification.java @@ -18,6 +18,7 @@ package com.vaadin.client.ui; import java.util.ArrayList; import java.util.EventObject; +import java.util.List; import com.google.gwt.aria.client.Roles; import com.google.gwt.core.client.GWT; @@ -36,12 +37,10 @@ import com.vaadin.client.AnimationUtil; import com.vaadin.client.AnimationUtil.AnimationEndListener; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.BrowserInfo; -import com.vaadin.client.UIDL; import com.vaadin.client.WidgetUtil; import com.vaadin.client.ui.aria.AriaHelper; import com.vaadin.shared.Position; import com.vaadin.shared.ui.ui.NotificationRole; -import com.vaadin.shared.ui.ui.UIConstants; import com.vaadin.shared.ui.ui.UIState.NotificationTypeConfiguration; public class VNotification extends VOverlay { @@ -80,7 +79,7 @@ public class VNotification extends VOverlay { private static final int Z_INDEX_BASE = 20000; public static final String STYLE_SYSTEM = "system"; - private static final ArrayList<VNotification> notifications = new ArrayList<>(); + private static final List<VNotification> notifications = new ArrayList<>(); private boolean infiniteDelay = false; private int hideDelay = 0; @@ -92,7 +91,7 @@ public class VNotification extends VOverlay { private String temporaryStyle; - private ArrayList<EventListener> listeners; + private List<EventListener> listeners; private static final int TOUCH_DEVICE_IDLE_DELAY = 1000; /** @@ -197,8 +196,8 @@ public class VNotification extends VOverlay { && !styleSetup.prefix.isEmpty(); } - public void show(String html, Position position, String style) { - NotificationTypeConfiguration styleSetup = getUiState(style); + public void show(String html, Position position, String styleName) { + NotificationTypeConfiguration styleSetup = getUiState(styleName); String assistiveDeviceOnlyStyle = AriaHelper.ASSISTIVE_DEVICE_ONLY_STYLE; setWaiAriaRole(styleSetup); @@ -217,7 +216,7 @@ public class VNotification extends VOverlay { } setWidget(new HTML(type + html + usage)); - show(position, style); + show(position, styleName); } private NotificationTypeConfiguration getUiState(String style) { @@ -478,54 +477,58 @@ public class VNotification extends VOverlay { } } - public static void showNotification(ApplicationConnection client, - final UIDL notification) { - boolean onlyPlainText = notification.hasAttribute( - UIConstants.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED); + /** + * Creates and shows a {@code Notification} with the specified parameters. + * + * @param client + * The client connection, cannot be {@code null}. + * @param caption + * The Notification caption, can be {@code null}. + * @param description + * The Notification description, can be {@code null}. + * @param htmlContentAllowed + * Whether {@code caption} and {@code description} + * are interpreted as HTML or not. + * @param iconUri + * The icon URI, can be {@code null}. + * @param styleName + * The Notification style name, can be {@code null}. + * @param position + * The desired {@link Position}, can not be {@code null}. + * @param delayMsec + * The delay in milliseconds before disappearing, -1 for forever. + * + * @since + */ + public static VNotification showNotification(ApplicationConnection client, + String caption, String description, boolean htmlContentAllowed, + String iconUri, String styleName, Position position, int delayMsec) { String html = ""; - if (notification - .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_ICON)) { - String iconUri = notification.getStringAttribute( - UIConstants.ATTRIBUTE_NOTIFICATION_ICON); + if (iconUri != null) { html += client.getIcon(iconUri).getElement().getString(); } - if (notification - .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_CAPTION)) { - String caption = notification.getStringAttribute( - UIConstants.ATTRIBUTE_NOTIFICATION_CAPTION); - if (onlyPlainText) { + if (caption != null) { + if (!htmlContentAllowed) { caption = WidgetUtil.escapeHTML(caption); caption = caption.replaceAll("\\n", "<br />"); } html += "<h1 class='" + getDependentStyle(client, CAPTION) + "'>" + caption + "</h1>"; } - if (notification - .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_MESSAGE)) { - String message = notification.getStringAttribute( - UIConstants.ATTRIBUTE_NOTIFICATION_MESSAGE); - if (onlyPlainText) { - message = WidgetUtil.escapeHTML(message); - message = message.replaceAll("\\n", "<br />"); + if (description != null) { + if (!htmlContentAllowed) { + description = WidgetUtil.escapeHTML(description); + description = description.replaceAll("\\n", "<br />"); } html += "<p class='" + getDependentStyle(client, DESCRIPTION) + "'>" - + message + "</p>"; + + description + "</p>"; } - final String style = notification - .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_STYLE) - ? notification.getStringAttribute( - UIConstants.ATTRIBUTE_NOTIFICATION_STYLE) - : null; - - final int pos = notification - .getIntAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_POSITION); - Position position = Position.values()[pos]; + VNotification vNotification = createNotification(delayMsec, + client.getUIConnector().getWidget()); - final int delay = notification - .getIntAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_DELAY); - createNotification(delay, client.getUIConnector().getWidget()) - .show(html, position, style); + vNotification.show(html, position, styleName); + return vNotification; } /** diff --git a/client/src/main/java/com/vaadin/client/ui/notification/NotificationConnector.java b/client/src/main/java/com/vaadin/client/ui/notification/NotificationConnector.java new file mode 100644 index 0000000000..45f72375d6 --- /dev/null +++ b/client/src/main/java/com/vaadin/client/ui/notification/NotificationConnector.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2016 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.client.ui.notification; + +import com.google.gwt.event.logical.shared.CloseEvent; +import com.google.gwt.event.logical.shared.CloseHandler; +import com.google.gwt.user.client.ui.PopupPanel; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.extensions.AbstractExtensionConnector; +import com.vaadin.client.ui.VNotification; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.notification.NotificationServerRpc; +import com.vaadin.shared.ui.notification.NotificationState; +import com.vaadin.ui.Notification; + +/** + * The client-side connector for the {@code Notification}. + * + * @author Vaadin Ltd. + * + * @since + */ +@Connect(value = Notification.class) +public class NotificationConnector extends AbstractExtensionConnector { + + @Override + public NotificationState getState() { + return (NotificationState) super.getState(); + } + + @Override + protected void extend(ServerConnector target) { + NotificationState state = getState(); + VNotification n = VNotification.showNotification( + target.getConnection(), + state.caption, state.description, + state.htmlContentAllowed, getResourceUrl("icon"), + state.styleName, state.position, state.delay); + + n.addCloseHandler(new CloseHandler<PopupPanel>() { + + @Override + public void onClose(CloseEvent<PopupPanel> event) { + NotificationServerRpc rpc = + getRpcProxy(NotificationServerRpc.class); + rpc.closed(); + } + }); + } + +} diff --git a/client/src/main/java/com/vaadin/client/ui/ui/UIConnector.java b/client/src/main/java/com/vaadin/client/ui/ui/UIConnector.java index 44f0b4253a..c808ea6c9d 100644 --- a/client/src/main/java/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/ui/UIConnector.java @@ -75,7 +75,6 @@ import com.vaadin.client.ui.AbstractConnector; import com.vaadin.client.ui.AbstractSingleComponentContainerConnector; import com.vaadin.client.ui.ClickEventHandler; import com.vaadin.client.ui.ShortcutActionHandler; -import com.vaadin.client.ui.VNotification; import com.vaadin.client.ui.VOverlay; import com.vaadin.client.ui.VUI; import com.vaadin.client.ui.VWindow; @@ -376,12 +375,6 @@ public class UIConnector extends AbstractSingleComponentContainerConnector getWidget().id, client); } getWidget().actionHandler.updateActionMap(childUidl); - } else if (tag == "notifications") { - for (final Iterator<?> it = childUidl.getChildIterator(); it - .hasNext();) { - final UIDL notification = (UIDL) it.next(); - VNotification.showNotification(client, notification); - } } else if (tag == "css-injections") { injectCSS(childUidl); } diff --git a/server/src/main/java/com/vaadin/server/Page.java b/server/src/main/java/com/vaadin/server/Page.java index 3e95de0c4b..d458839e4c 100644 --- a/server/src/main/java/com/vaadin/server/Page.java +++ b/server/src/main/java/com/vaadin/server/Page.java @@ -311,12 +311,6 @@ public class Page implements Serializable { private final LinkedList<OpenResource> openList = new LinkedList<>(); /** - * A list of notifications that are waiting to be sent to the client. - * Cleared (set to null) when the notifications have been sent. - */ - private List<Notification> notifications; - - /** * Event fired when the URI fragment of a <code>Page</code> changes. * * @see Page#addUriFragmentChangedListener(UriFragmentChangedListener) @@ -937,45 +931,6 @@ public class Page implements Serializable { openList.clear(); } - // Paint notifications - if (notifications != null) { - target.startTag("notifications"); - for (final Notification n : notifications) { - target.startTag("notification"); - if (n.getCaption() != null) { - target.addAttribute( - UIConstants.ATTRIBUTE_NOTIFICATION_CAPTION, - n.getCaption()); - } - if (n.getDescription() != null) { - target.addAttribute( - UIConstants.ATTRIBUTE_NOTIFICATION_MESSAGE, - n.getDescription()); - } - if (n.getIcon() != null) { - target.addAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_ICON, - n.getIcon()); - } - if (!n.isHtmlContentAllowed()) { - target.addAttribute( - UIConstants.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED, - true); - } - target.addAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_POSITION, - n.getPosition().ordinal()); - target.addAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_DELAY, - n.getDelayMsec()); - if (n.getStyleName() != null) { - target.addAttribute( - UIConstants.ATTRIBUTE_NOTIFICATION_STYLE, - n.getStyleName()); - } - target.endTag("notification"); - } - target.endTag("notifications"); - notifications = null; - } - if (newPushState != null) { target.addAttribute(UIConstants.ATTRIBUTE_PUSH_STATE, newPushState); newPushState = null; @@ -1342,20 +1297,6 @@ public class Page implements Serializable { } /** - * Internal helper method to actually add a notification. - * - * @param notification - * the notification to add - */ - private void addNotification(Notification notification) { - if (notifications == null) { - notifications = new LinkedList<>(); - } - notifications.add(notification); - uI.markAsDirty(); - } - - /** * Shows a notification message. * * @see Notification @@ -1367,7 +1308,7 @@ public class Page implements Serializable { */ @Deprecated public void showNotification(Notification notification) { - addNotification(notification); + notification.show(this); } /** @@ -1469,11 +1410,22 @@ public class Page implements Serializable { * @since 8.1 */ public Collection<Dependency> getPendingDependencies() { - ArrayList<Dependency> copy = new ArrayList<>(); + List<Dependency> copy = new ArrayList<>(); if (pendingDependencies != null) { copy.addAll(pendingDependencies); } pendingDependencies = null; return copy; } + + /** + * Returns the {@link UI} of this {@link Page}. + * + * @return the {@link UI} of this {@link Page}. + * + * @since + */ + public UI getUI() { + return uI; + } } diff --git a/server/src/main/java/com/vaadin/server/PaintTarget.java b/server/src/main/java/com/vaadin/server/PaintTarget.java index 6d531abc2c..0719fb26aa 100644 --- a/server/src/main/java/com/vaadin/server/PaintTarget.java +++ b/server/src/main/java/com/vaadin/server/PaintTarget.java @@ -39,7 +39,7 @@ public interface PaintTarget extends Serializable { * @param sectionTagName * the name of the tag. * @param sectionData - * the scetion data. + * the section data. * @throws PaintException * if the paint operation failed. */ @@ -145,7 +145,7 @@ public interface PaintTarget extends Serializable { public void endTag(String tagName) throws PaintException; /** - * Adds a boolean attribute to component. Atributes must be added before any + * Adds a boolean attribute to component. Attributes must be added before any * content is written. * * @param name @@ -159,7 +159,7 @@ public interface PaintTarget extends Serializable { public void addAttribute(String name, boolean value) throws PaintException; /** - * Adds a integer attribute to component. Atributes must be added before any + * Adds a integer attribute to component. Attributes must be added before any * content is written. * * @param name @@ -173,7 +173,7 @@ public interface PaintTarget extends Serializable { public void addAttribute(String name, int value) throws PaintException; /** - * Adds a resource attribute to component. Atributes must be added before + * Adds a resource attribute to component. Attributes must be added before * any content is written. * * @param name @@ -222,7 +222,7 @@ public interface PaintTarget extends Serializable { StreamVariable value) throws PaintException; /** - * Adds a long attribute to component. Atributes must be added before any + * Adds a long attribute to component. Attributes must be added before any * content is written. * * @param name @@ -236,7 +236,7 @@ public interface PaintTarget extends Serializable { public void addAttribute(String name, long value) throws PaintException; /** - * Adds a float attribute to component. Atributes must be added before any + * Adds a float attribute to component. Attributes must be added before any * content is written. * * @param name @@ -250,7 +250,7 @@ public interface PaintTarget extends Serializable { public void addAttribute(String name, float value) throws PaintException; /** - * Adds a double attribute to component. Atributes must be added before any + * Adds a double attribute to component. Attributes must be added before any * content is written. * * @param name @@ -264,7 +264,7 @@ public interface PaintTarget extends Serializable { public void addAttribute(String name, double value) throws PaintException; /** - * Adds a string attribute to component. Atributes must be added before any + * Adds a string attribute to component. Attributes must be added before any * content is written. * * @param name @@ -318,7 +318,7 @@ public interface PaintTarget extends Serializable { throws PaintException; /** - * Adds a int type variable. + * Adds an int type variable. * * @param owner * the Listener for variable changes. @@ -434,7 +434,7 @@ public interface PaintTarget extends Serializable { throws PaintException; /** - * Adds a upload stream type variable. + * Adds an upload stream type variable. * * @param owner * the Listener for variable changes. diff --git a/server/src/main/java/com/vaadin/ui/Notification.java b/server/src/main/java/com/vaadin/ui/Notification.java index 9ec031799f..15637ef3b0 100644 --- a/server/src/main/java/com/vaadin/ui/Notification.java +++ b/server/src/main/java/com/vaadin/ui/Notification.java @@ -17,10 +17,17 @@ package com.vaadin.ui; import java.io.Serializable; +import java.lang.reflect.Method; +import com.vaadin.event.ConnectorEvent; +import com.vaadin.server.AbstractExtension; import com.vaadin.server.Page; import com.vaadin.server.Resource; +import com.vaadin.server.ResourceReference; import com.vaadin.shared.Position; +import com.vaadin.shared.Registration; +import com.vaadin.shared.ui.notification.NotificationServerRpc; +import com.vaadin.shared.ui.notification.NotificationState; /** * A notification message, used to display temporary messages to the user - for @@ -61,7 +68,15 @@ import com.vaadin.shared.Position; * </p> * */ -public class Notification implements Serializable { +public class Notification extends AbstractExtension implements Serializable { + + /** + * The server RPC. + */ + protected NotificationServerRpc rpc = () -> { + fireEvent(new CloseEvent(Notification.this)); + }; + public enum Type { HUMANIZED_MESSAGE("humanized"), WARNING_MESSAGE( "warning"), ERROR_MESSAGE("error"), TRAY_NOTIFICATION("tray"), @@ -113,14 +128,6 @@ public class Notification implements Serializable { public static final int DELAY_FOREVER = -1; public static final int DELAY_NONE = 0; - private String caption; - private String description; - private Resource icon; - private Position position = Position.MIDDLE_CENTER; - private int delayMsec = 0; - private String styleName; - private boolean htmlContentAllowed; - /** * Creates a "humanized" notification message. * @@ -199,28 +206,29 @@ public class Notification implements Serializable { */ public Notification(String caption, String description, Type type, boolean htmlContentAllowed) { - this.caption = caption; - this.description = description; - this.htmlContentAllowed = htmlContentAllowed; + registerRpc(rpc); + setCaption(caption); + setDescription(description); + setHtmlContentAllowed(htmlContentAllowed); setType(type); } private void setType(Type type) { - styleName = type.getStyle(); + setStyleName(type.getStyle()); switch (type) { case WARNING_MESSAGE: - delayMsec = 1500; + setDelayMsec(1500); break; case ERROR_MESSAGE: - delayMsec = -1; + setDelayMsec(DELAY_FOREVER); break; case TRAY_NOTIFICATION: - delayMsec = 3000; - position = Position.BOTTOM_RIGHT; + setDelayMsec(3000); + setPosition(Position.BOTTOM_RIGHT); break; case ASSISTIVE_NOTIFICATION: - delayMsec = 3000; - position = Position.ASSISTIVE; + setDelayMsec(3000); + setPosition(Position.ASSISTIVE); break; case HUMANIZED_MESSAGE: default: @@ -234,35 +242,36 @@ public class Notification implements Serializable { * @return The message caption */ public String getCaption() { - return caption; + return getState(false).caption; } /** - * Sets the caption part of the notification message + * Sets the caption part of the notification message. * * @param caption * The message caption */ public void setCaption(String caption) { - this.caption = caption; + getState().caption = caption; } /** * Gets the description part of the notification message. * - * @return The message description. + * @return The message description */ public String getDescription() { - return description; + return getState(false).description; } /** * Sets the description part of the notification message. * * @param description + * The message description */ public void setDescription(String description) { - this.description = description; + getState().description = description; } /** @@ -271,17 +280,21 @@ public class Notification implements Serializable { * @return The position */ public Position getPosition() { - return position; + return getState(false).position; } /** * Sets the position of the notification message. * * @param position - * The desired notification position + * The desired notification position, + * not {@code null} */ public void setPosition(Position position) { - this.position = position; + if (position == null) { + throw new IllegalArgumentException("Position can not be null"); + } + getState().position = position; } /** @@ -290,7 +303,7 @@ public class Notification implements Serializable { * @return The message icon */ public Resource getIcon() { - return icon; + return getResource("icon"); } /** @@ -300,46 +313,47 @@ public class Notification implements Serializable { * The desired message icon */ public void setIcon(Resource icon) { - this.icon = icon; + setResource("icon", icon); } /** * Gets the delay before the notification disappears. * - * @return the delay in msec, -1 indicates the message has to be clicked. + * @return the delay in milliseconds, {@value #DELAY_FOREVER} + * indicates the message has to be clicked. */ public int getDelayMsec() { - return delayMsec; + return getState(false).delay; } /** * Sets the delay before the notification disappears. * * @param delayMsec - * the desired delay in msec, -1 to require the user to click the - * message + * the desired delay in milliseconds, {@value #DELAY_FOREVER} + * to require the user to click the message */ public void setDelayMsec(int delayMsec) { - this.delayMsec = delayMsec; + getState().delay = delayMsec; } /** * Sets the style name for the notification message. * * @param styleName - * The desired style name. + * The desired style name */ public void setStyleName(String styleName) { - this.styleName = styleName; + getState().styleName = styleName; } /** * Gets the style name for the notification message. * - * @return + * @return The style name */ public String getStyleName() { - return styleName; + return getState(false).styleName; } /** @@ -353,18 +367,19 @@ public class Notification implements Serializable { * text */ public void setHtmlContentAllowed(boolean htmlContentAllowed) { - this.htmlContentAllowed = htmlContentAllowed; + getState().htmlContentAllowed = htmlContentAllowed; } /** - * Checks whether caption and description are interpreted as html or plain + * Checks whether caption and description are interpreted as HTML or plain * text. * - * @return true if the texts are used as html, false if used as plain text + * @return {@code true} if the texts are used as HTML, + * {@code false} if used as plain text * @see #setHtmlContentAllowed(boolean) */ public boolean isHtmlContentAllowed() { - return htmlContentAllowed; + return getState(false).htmlContentAllowed; } /** @@ -374,8 +389,17 @@ public class Notification implements Serializable { * The page on which the notification should be shown */ public void show(Page page) { - // TODO Can avoid deprecated API when Notification extends Extension - page.showNotification(this); + extend(page.getUI()); + } + + @Override + protected NotificationState getState() { + return (NotificationState) super.getState(); + } + + @Override + protected NotificationState getState(boolean markAsDirty) { + return (NotificationState) super.getState(markAsDirty); } /** @@ -389,16 +413,20 @@ public class Notification implements Serializable { * * @param caption * The message + * @return + * The Notification */ - public static void show(String caption) { - new Notification(caption).show(Page.getCurrent()); + public static Notification show(String caption) { + Notification notification = new Notification(caption); + notification.extend(UI.getCurrent()); + return notification; } /** * Shows a notification message the current page. The position and behavior * of the message depends on the type, which is one of the basic types * defined in {@link Notification}, for instance - * Notification.TYPE_WARNING_MESSAGE. + * {@link Type#WARNING_MESSAGE}. * * The caption is rendered as plain text with HTML automatically escaped. * @@ -409,9 +437,13 @@ public class Notification implements Serializable { * The message * @param type * The message type + * @return + * The Notification */ - public static void show(String caption, Type type) { - new Notification(caption, type).show(Page.getCurrent()); + public static Notification show(String caption, Type type) { + Notification notification = new Notification(caption, type); + notification.extend(UI.getCurrent()); + return notification; } /** @@ -431,8 +463,73 @@ public class Notification implements Serializable { * The message description * @param type * The message type + * @return + * The Notification */ - public static void show(String caption, String description, Type type) { - new Notification(caption, description, type).show(Page.getCurrent()); + public static Notification show(String caption, String description, Type type) { + Notification notification = new Notification(caption, description, type); + notification.extend(UI.getCurrent()); + return notification; } + + /** + * Adds a CloseListener to the Notification. + * + * @param listener + * the CloseListener to add, not {@code null} + * @since + */ + public Registration addCloseListener(CloseListener listener) { + return addListener(CloseEvent.class, listener, CLOSE_METHOD); + } + + private static final Method CLOSE_METHOD; + static { + try { + CLOSE_METHOD = CloseListener.class + .getDeclaredMethod("notificationClose", CloseEvent.class); + } catch (final NoSuchMethodException e) { + // This should never happen + throw new RuntimeException( + "Internal error, notification close method not found"); + } + } + + public static class CloseEvent extends ConnectorEvent { + + /** + * @param source + */ + public CloseEvent(Notification source) { + super(source); + } + + /** + * Gets the Notification. + * + * @return The Notification + */ + public Notification getNotification() { + return (Notification) getSource(); + } + } + + /** + * An interface used for listening to Notification close events. Add the + * CloseListener to a Notification and + * {@link CloseListener#notificationClose(CloseEvent)} will be called whenever the + * Notification is closed. + */ + @FunctionalInterface + public interface CloseListener extends Serializable { + /** + * Use {@link CloseEvent#getNotification()} to get a reference to the + * {@link Notification} that was closed. + * + * @param e + * The triggered event + */ + public void notificationClose(CloseEvent e); + } + } diff --git a/server/src/main/java/com/vaadin/ui/Window.java b/server/src/main/java/com/vaadin/ui/Window.java index 5a9b19f421..cd0840e517 100644 --- a/server/src/main/java/com/vaadin/ui/Window.java +++ b/server/src/main/java/com/vaadin/ui/Window.java @@ -504,7 +504,7 @@ public class Window extends Panel * {@link Window} that was closed. * * @param e - * Event containing + * The triggered event */ public void windowClose(CloseEvent e); } diff --git a/shared/src/main/java/com/vaadin/shared/ui/notification/NotificationServerRpc.java b/shared/src/main/java/com/vaadin/shared/ui/notification/NotificationServerRpc.java new file mode 100644 index 0000000000..bf10a8c879 --- /dev/null +++ b/shared/src/main/java/com/vaadin/shared/ui/notification/NotificationServerRpc.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2016 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.shared.ui.notification; + +import com.vaadin.shared.communication.ServerRpc; + +/** + * Client to server RPC interface for Notification. + * + * @author Vaadin Ltd. + * + * @since + */ +public interface NotificationServerRpc extends ServerRpc { + + void closed(); +} diff --git a/shared/src/main/java/com/vaadin/shared/ui/notification/NotificationState.java b/shared/src/main/java/com/vaadin/shared/ui/notification/NotificationState.java new file mode 100644 index 0000000000..19f923ee87 --- /dev/null +++ b/shared/src/main/java/com/vaadin/shared/ui/notification/NotificationState.java @@ -0,0 +1,61 @@ +/* + * Copyright 2000-2016 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.shared.ui.notification; + +import com.vaadin.shared.Position; +import com.vaadin.shared.communication.SharedState; + +/** + * Shared state for {@link com.vaadin.ui.Notification}. + * + * @author Vaadin Ltd. + * + * @since + */ +public class NotificationState extends SharedState { + + /** + * The {@link com.vaadin.ui.Notification} caption, can be {@code null}. + */ + public String caption; + + /** + * The description, can be {@code null}. + */ + public String description; + + /** + * Whether texts are interpreted as HTML ({@code true}) or not ({@code false}). + */ + public boolean htmlContentAllowed; + + /** + * The style name, can be {@code null}. + */ + public String styleName; + + /** + * The {@link Position} of the {@link com.vaadin.ui.Notification}, + * can not be {@code null}. + */ + public Position position = Position.MIDDLE_CENTER; + + /** + * The delay in milliseconds before disappearing, {@code -1} for forever. + */ + public int delay; +} diff --git a/shared/src/main/java/com/vaadin/shared/ui/ui/UIConstants.java b/shared/src/main/java/com/vaadin/shared/ui/ui/UIConstants.java index 086164e750..54da337189 100644 --- a/shared/src/main/java/com/vaadin/shared/ui/ui/UIConstants.java +++ b/shared/src/main/java/com/vaadin/shared/ui/ui/UIConstants.java @@ -25,27 +25,11 @@ public class UIConstants implements Serializable { public static final String RESIZE_LAZY = "rL"; @Deprecated - public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain"; - - @Deprecated public static final String ATTRIBUTE_PUSH_STATE = "ps"; @Deprecated public static final String ATTRIBUTE_REPLACE_STATE = "rs"; - @Deprecated - public static final String ATTRIBUTE_NOTIFICATION_STYLE = "style"; - @Deprecated - public static final String ATTRIBUTE_NOTIFICATION_CAPTION = "caption"; - @Deprecated - public static final String ATTRIBUTE_NOTIFICATION_MESSAGE = "message"; - @Deprecated - public static final String ATTRIBUTE_NOTIFICATION_ICON = "icon"; - @Deprecated - public static final String ATTRIBUTE_NOTIFICATION_POSITION = "position"; - @Deprecated - public static final String ATTRIBUTE_NOTIFICATION_DELAY = "delay"; - /** * Name of the parameter used to transmit UI ids back and forth */ diff --git a/uitest/src/main/java/com/vaadin/tests/extensions/NotificationCloseListener.java b/uitest/src/main/java/com/vaadin/tests/extensions/NotificationCloseListener.java new file mode 100644 index 0000000000..2528f935b2 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/extensions/NotificationCloseListener.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.extensions; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.Notification; + +/** + * UI used to validate Notification closes works. + */ +public class NotificationCloseListener extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + CheckBox checkBox = new CheckBox(); + addComponent(checkBox); + + Notification notification = Notification.show("something"); + notification.addCloseListener(e -> checkBox.setValue(true)); + } + + @Override + protected String getTestDescription() { + return "Notification Close listener is called."; + } + + @Override + protected Integer getTicketNumber() { + return 10027; + } + +} diff --git a/uitest/src/test/java/com/vaadin/tests/extensions/NotificationCloseListenerTest.java b/uitest/src/test/java/com/vaadin/tests/extensions/NotificationCloseListenerTest.java new file mode 100644 index 0000000000..3b241a49d8 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/extensions/NotificationCloseListenerTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2016 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.extensions; + +import org.junit.Test; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.support.ui.ExpectedCondition; + +import com.vaadin.testbench.elements.CheckBoxElement; +import com.vaadin.testbench.elements.NotificationElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class NotificationCloseListenerTest extends MultiBrowserTest { + + @Test + public void closeListenerCalled() throws Exception { + openTestURL(); + + $(NotificationElement.class).first().close(); + + waitUntil(new ExpectedCondition<Boolean>() { + + @Override + public Boolean apply(WebDriver input) { + try { + return $(CheckBoxElement.class).first().isChecked(); + } + catch (Exception e) { + e.printStackTrace(); + return false; + } + } + }); + } +} |