From bb05ac27ba751cfbf45fa89fe4770f2791961a84 Mon Sep 17 00:00:00 2001 From: Marc Englund Date: Mon, 5 Nov 2007 15:25:43 +0000 Subject: [PATCH] Notifications API. + small fix for richtextarea svn changeset:2712/svn branch:trunk --- WebContent/WEB-INF/web.xml | 14 + .../itmill/toolkit/demo/NotificationDemo.java | 82 +++++ .../terminal/gwt/client/ui/Notification.java | 229 ++++++++++++++ .../client/ui/richtextarea/IRichTextArea.java | 22 +- .../terminal/gwt/public/default/styles.css | 1 + .../public/default/window/notification.css | 38 +++ src/com/itmill/toolkit/ui/Window.java | 296 ++++++++++++++---- 7 files changed, 618 insertions(+), 64 deletions(-) create mode 100644 src/com/itmill/toolkit/demo/NotificationDemo.java create mode 100644 src/com/itmill/toolkit/terminal/gwt/client/ui/Notification.java create mode 100644 src/com/itmill/toolkit/terminal/gwt/public/default/window/notification.css diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index 1a96230438..ede3cfa876 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -297,6 +297,15 @@ + + NotificationDemo + com.itmill.toolkit.terminal.gwt.server.ApplicationServlet + + application + com.itmill.toolkit.demo.NotificationDemo + + + TestForNativeWindowing @@ -433,6 +442,11 @@ CachingDemo /CachingDemo/* + + + NotificationDemo + /NotificationDemo/* + index.jsp diff --git a/src/com/itmill/toolkit/demo/NotificationDemo.java b/src/com/itmill/toolkit/demo/NotificationDemo.java new file mode 100644 index 0000000000..00cfd182dc --- /dev/null +++ b/src/com/itmill/toolkit/demo/NotificationDemo.java @@ -0,0 +1,82 @@ +package com.itmill.toolkit.demo; + +import com.itmill.toolkit.data.Item; +import com.itmill.toolkit.ui.Button; +import com.itmill.toolkit.ui.NativeSelect; +import com.itmill.toolkit.ui.RichTextArea; +import com.itmill.toolkit.ui.Select; +import com.itmill.toolkit.ui.TextField; +import com.itmill.toolkit.ui.Window; +import com.itmill.toolkit.ui.Button.ClickEvent; +import com.itmill.toolkit.ui.Button.ClickListener; + +/** + * Demonstrates the use of Notifications. + * + * @author IT Mill Ltd. + * @see com.itmill.toolkit.ui.Window + */ +public class NotificationDemo extends com.itmill.toolkit.Application { + + NativeSelect type; + TextField caption; + TextField message; + + /** + * The initialization method that is the only requirement for inheriting the + * com.itmill.toolkit.service.Application class. It will be automatically + * called by the framework when a user accesses the application. + */ + public void init() { + + /* + * - Create new window for the application - Give the window a visible + * title - Set the window to be the main window of the application + */ + Window main = new Window("Notification demo"); + setMainWindow(main); + + Window conf = new Window("Show Notification"); + conf.setWidth(450); + conf.setHeight(340); + main.addWindow(conf); + + type = new NativeSelect("Notification type"); + type.addContainerProperty("caption", String.class, null); + type.setNullSelectionAllowed(false); + type.setItemCaptionMode(Select.ITEM_CAPTION_MODE_PROPERTY); + type.setItemCaptionPropertyId("caption"); + Item i = type.addItem(new Integer( + Window.Notification.TYPE_HUMANIZED_MESSAGE)); + i.getItemProperty("caption").setValue("Humanized message"); + i = type.addItem(new Integer(Window.Notification.TYPE_WARNING_MESSAGE)); + i.getItemProperty("caption").setValue("Warning message"); + i = type.addItem(new Integer(Window.Notification.TYPE_ERROR_MESSAGE)); + i.getItemProperty("caption").setValue("Error message"); + i = type + .addItem(new Integer(Window.Notification.TYPE_TRAY_NOTIFICATION)); + i.getItemProperty("caption").setValue("Tray notification"); + type.setValue(new Integer(Window.Notification.TYPE_HUMANIZED_MESSAGE)); + conf.addComponent(type); + + caption = new TextField("Caption"); + caption.setValue("Saved!"); + caption.setColumns(20); + conf.addComponent(caption); + + message = new RichTextArea(); + message.setCaption("Message"); + message.setValue("Your stuff has been saved in MyDocuments."); + conf.addComponent(message); + + Button b = new Button("Show notification", new ClickListener() { + public void buttonClick(ClickEvent event) { + getMainWindow().showNotification((String) caption.getValue(), + (String) message.getValue(), + ((Integer) type.getValue()).intValue()); + } + + }); + conf.addComponent(b); + } +} diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/Notification.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/Notification.java new file mode 100644 index 0000000000..cd4740007e --- /dev/null +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/Notification.java @@ -0,0 +1,229 @@ +package com.itmill.toolkit.terminal.gwt.client.ui; + +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.EventPreview; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.PopupPanel; +import com.google.gwt.user.client.ui.Widget; + +public class Notification extends PopupPanel { + + public static final int CENTERED = 1; + public static final int CENTERED_TOP = 2; + public static final int CENTERED_BOTTOM = 3; + public static final int TOP_LEFT = 4; + public static final int TOP_RIGHT = 5; + public static final int BOTTOM_LEFT = 6; + public static final int BOTTOM_RIGHT = 7; + + public static final int DELAY_FOREVER = -1; + public static final int DELAY_NONE = 0; + + private static final String STYLENAME = "i-Notification"; + private static final int mouseMoveThreshold = 7; + private static final int Z_INDEX_BASE = 20000; + + private int startOpacity = 90; + private int fadeMsec = 400; + private int delayMsec = 1000; + + private Timer fader; + private Timer delay; + private EventPreview eventPreview; + + private String temporaryStyle; + + public Notification() { + setStylePrimaryName(STYLENAME); + sinkEvents(Event.ONCLICK); + DOM.setStyleAttribute(getElement(), "zIndex", "" + Z_INDEX_BASE); + } + + public Notification(int delayMsec) { + this(); + this.delayMsec = delayMsec; + } + + public Notification(int delayMsec, int fadeMsec, int startOpacity) { + this(delayMsec); + this.fadeMsec = fadeMsec; + this.startOpacity = startOpacity; + } + + public void startDelay() { + DOM.removeEventPreview(eventPreview); + if (delayMsec > 0) { + delay = new Timer() { + public void run() { + fade(); + } + }; + delay.scheduleRepeating(delayMsec); + } else if (delayMsec == 0) { + fade(); + } + } + + public void show() { + show(CENTERED); + } + + public void show(String style) { + show(CENTERED, style); + } + + public void show(int position) { + show(position, null); + } + + public void show(Widget widget, int position, String style) { + setWidget(widget); + show(position, style); + } + + public void show(String html, int position, String style) { + setWidget(new HTML(html)); + show(position, style); + } + + public void show(int position, String style) { + hide(); + setOpacity(getElement(), startOpacity); + if (style != null) { + this.temporaryStyle = style; + addStyleName(style); + } + super.show(); + setPosition(position); + + if (eventPreview == null) { + eventPreview = new EventPreview() { + int x = -1; + int y = -1; + + public boolean onEventPreview(Event event) { + switch (DOM.eventGetType(event)) { + case Event.ONMOUSEMOVE: + if (x < 0) { + x = DOM.eventGetClientX(event); + y = DOM.eventGetClientY(event); + } else if (Math.abs(DOM.eventGetClientX(event) - x) > mouseMoveThreshold + || Math.abs(DOM.eventGetClientY(event) - y) > mouseMoveThreshold) { + startDelay(); + } + break; + case Event.KEYEVENTS: + case Event.ONCLICK: + case Event.ONDBLCLICK: + case Event.ONSCROLL: + default: + startDelay(); + } + return true; + } + }; + } + + DOM.addEventPreview(eventPreview); + } + + public void hide() { + DOM.removeEventPreview(eventPreview); + cancelDelay(); + cancelFade(); + if (this.temporaryStyle != null) { + removeStyleName(this.temporaryStyle); + this.temporaryStyle = null; + } + super.hide(); + } + + public void fade() { + cancelDelay(); + fader = new Timer() { + int opacity = startOpacity; + + public void run() { + opacity -= 5; + setOpacity(getElement(), opacity); + if (opacity <= 0) { + cancel(); + hide(); + } + } + }; + int msec = fadeMsec / (startOpacity / 5); + fader.scheduleRepeating(msec); + } + + public void setPosition(int position) { + Element el = getElement(); + DOM.setStyleAttribute(el, "top", null); + DOM.setStyleAttribute(el, "left", null); + DOM.setStyleAttribute(el, "bottom", null); + DOM.setStyleAttribute(el, "right", null); + switch (position) { + case TOP_LEFT: + DOM.setStyleAttribute(el, "top", "0px"); + DOM.setStyleAttribute(el, "left", "0px"); + break; + case TOP_RIGHT: + DOM.setStyleAttribute(el, "top", "0px"); + DOM.setStyleAttribute(el, "right", "0px"); + break; + case BOTTOM_RIGHT: + DOM.setStyleAttribute(el, "position", "absolute"); + DOM.setStyleAttribute(el, "bottom", "0px"); + DOM.setStyleAttribute(el, "right", "0px"); + break; + case BOTTOM_LEFT: + DOM.setStyleAttribute(el, "bottom", "0px"); + DOM.setStyleAttribute(el, "left", "0px"); + break; + case CENTERED_TOP: + center(); + DOM.setStyleAttribute(el, "top", "0px"); + break; + case CENTERED_BOTTOM: + center(); + DOM.setStyleAttribute(el, "top", null); + DOM.setStyleAttribute(el, "bottom", "0px"); + break; + default: + case CENTERED: + center(); + break; + } + } + + private void cancelFade() { + if (fader != null) { + fader.cancel(); + fader = null; + } + } + + private void cancelDelay() { + if (delay != null) { + delay.cancel(); + delay = null; + } + } + + private void setOpacity(Element el, int opacity) { + DOM.setStyleAttribute(el, "opacity", "" + (opacity / 100.0)); + DOM.setStyleAttribute(el, "filter", "Alpha(opacity=" + opacity + ")"); + + } + + public void onBrowserEvent(Event event) { + DOM.removeEventPreview(eventPreview); + if (fader == null) { + fade(); + } + } + +} diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/IRichTextArea.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/IRichTextArea.java index e2af2fd2b8..03c73e9e9d 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/IRichTextArea.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/richtextarea/IRichTextArea.java @@ -29,18 +29,18 @@ public class IRichTextArea extends Composite implements Paintable, protected ApplicationConnection client; private boolean immediate = false; - + RichTextArea rta = new RichTextArea(); - + RichTextToolbar formatter = new RichTextToolbar(rta); public IRichTextArea() { FlowPanel fp = new FlowPanel(); fp.add(formatter); - + rta.setWidth("100%"); rta.addFocusListener(this); - + fp.add(rta); initWidget(fp); @@ -51,28 +51,30 @@ public class IRichTextArea extends Composite implements Paintable, this.client = client; id = uidl.getId(); - if (client.updateComponent(this, uidl, true)) + if (client.updateComponent(this, uidl, true)) { return; + } immediate = uidl.getBooleanAttribute("immediate"); - - rta.setText(uidl.getStringAttribute("text")); + + rta.setHTML(uidl.getStringVariable("text")); } public void onChange(Widget sender) { - if (client != null && id != null) + if (client != null && id != null) { client.updateVariable(id, "text", rta.getText(), immediate); + } } public void onFocus(Widget sender) { - + } public void onLostFocus(Widget sender) { String html = rta.getHTML(); client.updateVariable(id, "text", html, immediate); - + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/public/default/styles.css b/src/com/itmill/toolkit/terminal/gwt/public/default/styles.css index e5e037f988..3935cf07aa 100644 --- a/src/com/itmill/toolkit/terminal/gwt/public/default/styles.css +++ b/src/com/itmill/toolkit/terminal/gwt/public/default/styles.css @@ -8,6 +8,7 @@ @import "table/table.css"; @import "slider/slider.css"; @import "window/window.css"; +@import "window/notification.css"; @import "caption/caption.css"; @import "tree/tree.css"; @import "splitpanel/splitpanel.css"; diff --git a/src/com/itmill/toolkit/terminal/gwt/public/default/window/notification.css b/src/com/itmill/toolkit/terminal/gwt/public/default/window/notification.css new file mode 100644 index 0000000000..3156f387b0 --- /dev/null +++ b/src/com/itmill/toolkit/terminal/gwt/public/default/window/notification.css @@ -0,0 +1,38 @@ + +.i-Notification { + font-family: "Trebuchet MS", geneva, helvetica, arial, tahoma, verdana, sans-serif; + background-color: #ffffff; + color: #cccccc; + border: 10px solid #cccccc; + padding: 0.2em; + cursor: pointer; +} +.i-Notification H1, +.i-Notification p, +.i-Notification.error H1, +.i-Notification.error p, +.i-Notification.warning H1, +.i-Notification.warning p { + display: inline; + padding: 0.1em; +} +.i-Notification.tray H1, +.i-Notification.tray p { + display: block; + font-size: 1em; + line-height: 0.5em; +} + +.i-Notification.warning { + border-color: #f14c1a; + color: #f14c1a; +} + +.i-Notification.error { + color: #ff0a0a; + border-color: #ff0a0a; +} +.i-Notification.tray { + color: #000000; + border-bottom: none; +} diff --git a/src/com/itmill/toolkit/ui/Window.java b/src/com/itmill/toolkit/ui/Window.java index 411f977f81..376e056756 100644 --- a/src/com/itmill/toolkit/ui/Window.java +++ b/src/com/itmill/toolkit/ui/Window.java @@ -28,18 +28,6 @@ package com.itmill.toolkit.ui; -import com.itmill.toolkit.Application; -import com.itmill.toolkit.Application.WindowAttachEvent; -import com.itmill.toolkit.Application.WindowAttachListener; -import com.itmill.toolkit.terminal.DownloadStream; -import com.itmill.toolkit.terminal.PaintException; -import com.itmill.toolkit.terminal.PaintTarget; -import com.itmill.toolkit.terminal.ParameterHandler; -import com.itmill.toolkit.terminal.Resource; -import com.itmill.toolkit.terminal.Sizeable; -import com.itmill.toolkit.terminal.Terminal; -import com.itmill.toolkit.terminal.URIHandler; - import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.net.MalformedURLException; @@ -47,11 +35,21 @@ import java.net.URL; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedList; import java.util.Map; -import java.util.Iterator; import java.util.Set; +import com.itmill.toolkit.Application; +import com.itmill.toolkit.terminal.DownloadStream; +import com.itmill.toolkit.terminal.PaintException; +import com.itmill.toolkit.terminal.PaintTarget; +import com.itmill.toolkit.terminal.ParameterHandler; +import com.itmill.toolkit.terminal.Resource; +import com.itmill.toolkit.terminal.Sizeable; +import com.itmill.toolkit.terminal.Terminal; +import com.itmill.toolkit.terminal.URIHandler; + /** * Application window component. * @@ -98,7 +96,7 @@ public class Window extends Panel implements URIHandler, ParameterHandler { private LinkedList parameterHandlerList = null; /** Set of subwindows */ - private HashSet subwindows = new HashSet(); + private final HashSet subwindows = new HashSet(); /** * Explicitly specified theme of this window. If null, application theme is @@ -109,7 +107,7 @@ public class Window extends Panel implements URIHandler, ParameterHandler { /** * Resources to be opened automatically on next repaint. */ - private LinkedList openList = new LinkedList(); + private final LinkedList openList = new LinkedList(); /** * The name of the window. @@ -148,6 +146,8 @@ public class Window extends Panel implements URIHandler, ParameterHandler { */ private int scrollLeft = 0; + private LinkedList notifications; + /* ********************************************************************* */ /** @@ -240,8 +240,9 @@ public class Window extends Panel implements URIHandler, ParameterHandler { * @return the parent application of the component. */ public final Application getApplication() { - if (getParent() == null) + if (getParent() == null) { return this.application; + } return ((Window) getParent()).getApplication(); } @@ -300,11 +301,13 @@ public class Window extends Panel implements URIHandler, ParameterHandler { public void addURIHandler(URIHandler handler) { // TODO Subwindow support - if (uriHandlerList == null) + if (uriHandlerList == null) { uriHandlerList = new LinkedList(); + } synchronized (uriHandlerList) { - if (!uriHandlerList.contains(handler)) + if (!uriHandlerList.contains(handler)) { uriHandlerList.addLast(handler); + } } } @@ -317,12 +320,14 @@ public class Window extends Panel implements URIHandler, ParameterHandler { public void removeURIHandler(URIHandler handler) { // TODO Subwindow support - if (handler == null || uriHandlerList == null) + if (handler == null || uriHandlerList == null) { return; + } synchronized (uriHandlerList) { uriHandlerList.remove(handler); - if (uriHandlerList.isEmpty()) + if (uriHandlerList.isEmpty()) { uriHandlerList = null; + } } } @@ -345,10 +350,11 @@ public class Window extends Panel implements URIHandler, ParameterHandler { DownloadStream ds = ((URIHandler) handlers[i]).handleURI( context, relativeUri); if (ds != null) { - if (result != null) + if (result != null) { throw new RuntimeException("handleURI for " + context + " uri: '" + relativeUri + "' returns ambigious result."); + } result = ds; } } @@ -366,11 +372,13 @@ public class Window extends Panel implements URIHandler, ParameterHandler { */ public void addParameterHandler(ParameterHandler handler) { // TODO Subwindow support - if (parameterHandlerList == null) + if (parameterHandlerList == null) { parameterHandlerList = new LinkedList(); + } synchronized (parameterHandlerList) { - if (!parameterHandlerList.contains(handler)) + if (!parameterHandlerList.contains(handler)) { parameterHandlerList.addLast(handler); + } } } @@ -382,12 +390,14 @@ public class Window extends Panel implements URIHandler, ParameterHandler { */ public void removeParameterHandler(ParameterHandler handler) { // TODO Subwindow support - if (handler == null || parameterHandlerList == null) + if (handler == null || parameterHandlerList == null) { return; + } synchronized (parameterHandlerList) { parameterHandlerList.remove(handler); - if (parameterHandlerList.isEmpty()) + if (parameterHandlerList.isEmpty()) { parameterHandlerList = null; + } } } @@ -398,8 +408,9 @@ public class Window extends Panel implements URIHandler, ParameterHandler { synchronized (parameterHandlerList) { handlers = parameterHandlerList.toArray(); } - for (int i = 0; i < handlers.length; i++) + for (int i = 0; i < handlers.length; i++) { ((ParameterHandler) handlers[i]).handleParameters(parameters); + } } } @@ -419,14 +430,18 @@ public class Window extends Panel implements URIHandler, ParameterHandler { * returned */ public String getTheme() { - if (getParent() != null) + if (getParent() != null) { return ((Window) getParent()).getTheme(); - if (theme != null) + } + if (theme != null) { return theme; - if ((application != null) && (application.getTheme() != null)) + } + if ((application != null) && (application.getTheme() != null)) { return application.getTheme(); - if (terminal != null) + } + if (terminal != null) { return terminal.getDefaultTheme(); + } return null; } @@ -439,9 +454,10 @@ public class Window extends Panel implements URIHandler, ParameterHandler { * the New theme for this window. Null implies the default theme. */ public void setTheme(String theme) { - if (getParent() != null) + if (getParent() != null) { throw new UnsupportedOperationException( "Setting theme for sub-windws is not supported."); + } this.theme = theme; requestRepaint(); } @@ -467,14 +483,16 @@ public class Window extends Panel implements URIHandler, ParameterHandler { // Marks the main window if (getApplication() != null - && this == getApplication().getMainWindow()) + && this == getApplication().getMainWindow()) { target.addAttribute("main", true); + } // Open requested resource synchronized (openList) { if (!openList.isEmpty()) { - for (Iterator i = openList.iterator(); i.hasNext();) + for (Iterator i = openList.iterator(); i.hasNext();) { ((OpenResource) i.next()).paintContent(target); + } openList.clear(); } } @@ -494,11 +512,12 @@ public class Window extends Panel implements URIHandler, ParameterHandler { target.addVariable(this, "close", false); // Sets the focused component - if (this.focusedComponent != null) + if (this.focusedComponent != null) { target.addVariable(this, "focused", "" + this.focusedComponent.getFocusableId()); - else + } else { target.addVariable(this, "focused", ""); + } // Paint subwindows for (Iterator i = subwindows.iterator(); i.hasNext();) { @@ -506,6 +525,29 @@ public class Window extends Panel implements URIHandler, ParameterHandler { w.paint(target); } + // Paint notifications + if (this.notifications != null) { + target.startTag("notifications"); + for (Iterator it = this.notifications.iterator(); it.hasNext();) { + Notification n = (Notification) it.next(); + target.startTag("notification"); + if (n.getCaption() != null) { + target.addAttribute("caption", n.getCaption()); + } + if (n.getMessage() != null) { + target.addAttribute("message", n.getMessage()); + } + target.addAttribute("position", n.getPosition()); + target.addAttribute("delay", n.getDelayMsec()); + if (n.getStyleName() != null) { + target.addAttribute("style", n.getStyleName()); + } + target.endTag("notification"); + } + target.endTag("notifications"); + this.notifications = null; + } + } /* ********************************************************************* */ @@ -517,9 +559,10 @@ public class Window extends Panel implements URIHandler, ParameterHandler { */ public void open(Resource resource) { synchronized (openList) { - if (!openList.contains(resource)) + if (!openList.contains(resource)) { openList.add(new OpenResource(resource, null, -1, -1, BORDER_DEFAULT)); + } } requestRepaint(); } @@ -538,9 +581,10 @@ public class Window extends Panel implements URIHandler, ParameterHandler { */ public void open(Resource resource, String windowName) { synchronized (openList) { - if (!openList.contains(resource)) + if (!openList.contains(resource)) { openList.add(new OpenResource(resource, windowName, -1, -1, BORDER_DEFAULT)); + } } requestRepaint(); } @@ -561,9 +605,10 @@ public class Window extends Panel implements URIHandler, ParameterHandler { public void open(Resource resource, String windowName, int width, int height, int border) { synchronized (openList) { - if (!openList.contains(resource)) + if (!openList.contains(resource)) { openList.add(new OpenResource(resource, windowName, width, height, border)); + } } requestRepaint(); } @@ -578,8 +623,9 @@ public class Window extends Panel implements URIHandler, ParameterHandler { */ public URL getURL() { - if (application == null) + if (application == null) { return null; + } try { return new URL(application.getURL(), getName() + "/"); @@ -651,8 +697,9 @@ public class Window extends Panel implements URIHandler, ParameterHandler { public void setApplication(Application application) { // If the application is not changed, dont do nothing - if (application == this.application) + if (application == this.application) { return; + } // Sends detach event if the window is connected to application if (this.application != null) { @@ -663,8 +710,9 @@ public class Window extends Panel implements URIHandler, ParameterHandler { this.application = application; // Sends the attach event if connected to a window - if (application != null) + if (application != null) { attach(); + } } /** @@ -684,10 +732,11 @@ public class Window extends Panel implements URIHandler, ParameterHandler { public void setName(String name) { // The name can not be changed in application - if (getApplication() != null) + if (getApplication() != null) { throw new IllegalStateException( "Window name can not be changed while " + "the window is in application"); + } this.name = name; } @@ -709,8 +758,9 @@ public class Window extends Panel implements URIHandler, ParameterHandler { * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits() */ public void setHeightUnits(int units) { - if (units != Sizeable.UNITS_PIXELS) + if (units != Sizeable.UNITS_PIXELS) { throw new IllegalArgumentException("Only pixels are supported"); + } } /** @@ -719,8 +769,9 @@ public class Window extends Panel implements URIHandler, ParameterHandler { * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits() */ public void setWidthUnits(int units) { - if (units != Sizeable.UNITS_PIXELS) + if (units != Sizeable.UNITS_PIXELS) { throw new IllegalArgumentException("Only pixels are supported"); + } } /** @@ -728,15 +779,15 @@ public class Window extends Panel implements URIHandler, ParameterHandler { */ private class OpenResource { - private Resource resource; + private final Resource resource; - private String name; + private final String name; - private int width; + private final int width; - private int height; + private final int height; - private int border; + private final int border; /** * Creates a new open resource. @@ -767,12 +818,15 @@ public class Window extends Panel implements URIHandler, ParameterHandler { private void paintContent(PaintTarget target) throws PaintException { target.startTag("open"); target.addAttribute("src", resource); - if (name != null && name.length() > 0) + if (name != null && name.length() > 0) { target.addAttribute("name", name); - if (width >= 0) + } + if (width >= 0) { target.addAttribute("width", width); - if (height >= 0) + } + if (height >= 0) { target.addAttribute("height", height); + } switch (border) { case Window.BORDER_MINIMAL: target.addAttribute("border", "minimal"); @@ -1052,12 +1106,14 @@ public class Window extends Panel implements URIHandler, ParameterHandler { public void addWindow(Window window) throws IllegalArgumentException, NullPointerException { - if (getParent() != null) + if (getParent() != null) { throw new IllegalArgumentException( "You can only add windows inside application-level windows"); + } - if (window == null) + if (window == null) { throw new NullPointerException("Argument must not be null"); + } subwindows.add(window); window.setParent(this); @@ -1124,4 +1180,136 @@ public class Window extends Panel implements URIHandler, ParameterHandler { this.scrollLeft = scrollLeft; } + public void showNotification(String message) { + addNotification(new Notification(message)); + } + + public void showNotification(String message, int type) { + addNotification(new Notification(message, type)); + } + + public void showNotification(String caption, String message, int type) { + addNotification(new Notification(caption, message, type)); + } + + public void showNotification(Notification notification) { + addNotification(notification); + } + + private void addNotification(Notification notification) { + if (this.notifications == null) { + this.notifications = new LinkedList(); + } + this.notifications.add(notification); + requestRepaint(); + } + + public class Notification { + public static final int TYPE_HUMANIZED_MESSAGE = 1; + public static final int TYPE_WARNING_MESSAGE = 2; + public static final int TYPE_ERROR_MESSAGE = 3; + public static final int TYPE_TRAY_NOTIFICATION = 4; + + public static final int POSITION_CENTERED = 1; + public static final int POSITION_CENTERED_TOP = 2; + public static final int POSITION_CENTERED_BOTTOM = 3; + public static final int POSITION_TOP_LEFT = 4; + public static final int POSITION_TOP_RIGHT = 5; + public static final int POSITION_BOTTOM_LEFT = 6; + public static final int POSITION_BOTTOM_RIGHT = 7; + + public static final int DELAY_FOREVER = -1; + public static final int DELAY_NONE = 0; + + private String caption; + private String message; + private Resource icon; + private int position = POSITION_CENTERED; + private int delayMsec = 0; + private String styleName; + + public Notification(String message) { + this(null, message, TYPE_HUMANIZED_MESSAGE); + } + + public Notification(String message, int type) { + this(null, message, type); + } + + public Notification(String caption, String message, int type) { + this.caption = caption; + this.message = message; + setType(type); + } + + private void setType(int type) { + switch (type) { + case TYPE_WARNING_MESSAGE: + delayMsec = 1500; + styleName = "warning"; + break; + case TYPE_ERROR_MESSAGE: + delayMsec = -1; + styleName = "error"; + break; + case TYPE_TRAY_NOTIFICATION: + delayMsec = 3000; + position = POSITION_BOTTOM_RIGHT; + styleName = "tray"; + + case TYPE_HUMANIZED_MESSAGE: + default: + break; + } + + } + + public String getCaption() { + return caption; + } + + public void setCaption(String caption) { + this.caption = caption; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + } + + public Resource getIcon() { + return icon; + } + + public void setIcon(Resource icon) { + this.icon = icon; + } + + public int getDelayMsec() { + return delayMsec; + } + + public void setDelayMsec(int delayMsec) { + this.delayMsec = delayMsec; + } + + public void setStyleName(String styleName) { + this.styleName = styleName; + } + + public String getStyleName() { + return this.styleName; + } + } } -- 2.39.5