diff options
author | Artur Signell <artur@vaadin.com> | 2013-03-25 23:37:45 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2013-04-03 06:42:55 +0000 |
commit | ce2df6d10370c669a512e96f0693fc37cf02aca1 (patch) | |
tree | 5b12cf84ba967b17d96c0a5913030e23a491eeb6 /client | |
parent | 9586a30b64bfd1e8645574d9d7b6568d52dc9e25 (diff) | |
download | vaadin-framework-ce2df6d10370c669a512e96f0693fc37cf02aca1.tar.gz vaadin-framework-ce2df6d10370c669a512e96f0693fc37cf02aca1.zip |
Enable setting loading indicator delays from the server (#7448)
* Refactored LoadingIndicator to a separate class on client side to enable customization and to remove clutter from ApplicationConnection
Change-Id: I12e94294beed9c65a5710bdfe2486bc0f1b92bd9
Diffstat (limited to 'client')
-rw-r--r-- | client/src/com/vaadin/client/ApplicationConnection.java | 104 | ||||
-rw-r--r-- | client/src/com/vaadin/client/VLoadingIndicator.java | 218 | ||||
-rw-r--r-- | client/src/com/vaadin/client/ui/ui/UIConnector.java | 10 |
3 files changed, 249 insertions, 83 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index a043ec6c0b..d59abc892a 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -177,11 +177,6 @@ public class ApplicationConnection { private VContextMenu contextMenu = null; - private Timer loadTimer; - private Timer loadTimer2; - private Timer loadTimer3; - private Element loadElement; - private final UIConnector uIConnector; protected boolean applicationRunning = false; @@ -378,6 +373,8 @@ public class ApplicationConnection { private CommunicationErrorHandler communicationErrorDelegate = null; + private VLoadingIndicator loadingIndicator; + public static class MultiStepDuration extends Duration { private int previousStep = elapsedMillis(); @@ -404,6 +401,8 @@ public class ApplicationConnection { layoutManager = GWT.create(LayoutManager.class); layoutManager.setConnection(this); tooltip = GWT.create(VTooltip.class); + loadingIndicator = GWT.create(VLoadingIndicator.class); + loadingIndicator.setConnection(this); } public void init(WidgetSet widgetSet, ApplicationConfiguration cnf) { @@ -436,7 +435,7 @@ public class ApplicationConnection { tooltip.setOwner(uIConnector.getWidget()); - showLoadingIndicator(); + getLoadingIndicator().trigger(); scheduleHeartbeat(); @@ -987,7 +986,7 @@ public class ApplicationConnection { */ protected boolean isCSSLoaded() { return cssLoaded - || DOM.getElementPropertyInt(loadElement, "offsetHeight") != 0; + || getLoadingIndicator().getElement().getOffsetHeight() != 0; } /** @@ -1085,25 +1084,7 @@ public class ApplicationConnection { } hasActiveRequest = true; requestStartTime = new Date(); - // show initial throbber - if (loadTimer == null) { - loadTimer = new Timer() { - @Override - public void run() { - /* - * IE7 does not properly cancel the event with - * loadTimer.cancel() so we have to check that we really - * should make it visible - */ - if (loadTimer != null) { - showLoadingIndicator(); - } - - } - }; - // First one kicks in at 300ms - } - loadTimer.schedule(300); + loadingIndicator.trigger(); eventBus.fireEvent(new RequestStartingEvent(this)); } @@ -1129,7 +1110,7 @@ public class ApplicationConnection { @Override public void execute() { if (!hasActiveRequest()) { - hideLoadingIndicator(); + getLoadingIndicator().hide(); // If on Liferay and session expiration management is in // use, extend session duration on each request. @@ -1182,54 +1163,6 @@ public class ApplicationConnection { } } - private void showLoadingIndicator() { - // show initial throbber - if (loadElement == null) { - loadElement = DOM.createDiv(); - DOM.setStyleAttribute(loadElement, "position", "absolute"); - DOM.appendChild(uIConnector.getWidget().getElement(), loadElement); - VConsole.log("inserting load indicator"); - } - DOM.setElementProperty(loadElement, "className", "v-loading-indicator"); - DOM.setStyleAttribute(loadElement, "display", "block"); - // Initialize other timers - loadTimer2 = new Timer() { - @Override - public void run() { - DOM.setElementProperty(loadElement, "className", - "v-loading-indicator-delay"); - } - }; - // Second one kicks in at 1500ms from request start - loadTimer2.schedule(1200); - - loadTimer3 = new Timer() { - @Override - public void run() { - DOM.setElementProperty(loadElement, "className", - "v-loading-indicator-wait"); - } - }; - // Third one kicks in at 5000ms from request start - loadTimer3.schedule(4700); - } - - private void hideLoadingIndicator() { - if (loadTimer != null) { - loadTimer.cancel(); - loadTimer = null; - } - if (loadTimer2 != null) { - loadTimer2.cancel(); - loadTimer3.cancel(); - loadTimer2 = null; - loadTimer3 = null; - } - if (loadElement != null) { - DOM.setStyleAttribute(loadElement, "display", "none"); - } - } - /** * Checks if deferred commands are (potentially) still being executed as a * result of an update from the server. Returns true if a deferred command @@ -1252,19 +1185,24 @@ public class ApplicationConnection { } /** + * Returns the loading indicator used by this ApplicationConnection + * + * @return The loading indicator for this ApplicationConnection + */ + public VLoadingIndicator getLoadingIndicator() { + return loadingIndicator; + } + + /** * Determines whether or not the loading indicator is showing. * * @return true if the loading indicator is visible + * @deprecated As of 7.1. Use {@link #getLoadingIndicator()} and + * {@link VLoadingIndicator#isVisible()}.isVisible() instead. */ + @Deprecated public boolean isLoadingIndicatorVisible() { - if (loadElement == null) { - return false; - } - if (loadElement.getStyle().getProperty("display").equals("none")) { - return false; - } - - return true; + return getLoadingIndicator().isVisible(); } private static native ValueMap parseJSONResponse(String jsonText) diff --git a/client/src/com/vaadin/client/VLoadingIndicator.java b/client/src/com/vaadin/client/VLoadingIndicator.java new file mode 100644 index 0000000000..ca29d6a042 --- /dev/null +++ b/client/src/com/vaadin/client/VLoadingIndicator.java @@ -0,0 +1,218 @@ +package com.vaadin.client; + +import com.google.gwt.dom.client.Style.Display; +import com.google.gwt.dom.client.Style.Position; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.Timer; + +/** + * Class representing the loading indicator for Vaadin applications. The loading + * indicator has four states: "triggered", "initial", "delay" and "wait". When + * {@link #trigger()} is called the indicator moves to its "triggered" state and + * then transitions from one state to the next when the timeouts specified using + * the set*StateDelay methods occur. + * + * @author Vaadin Ltd + * @since 7.1 + */ +public class VLoadingIndicator { + + private static final String PRIMARY_STYLE_NAME = "v-loading-indicator"; + + private ApplicationConnection connection; + + private int initialStateDelay = 300; + private int delayStateDelay = 1500; + private int waitStateDelay = 5000; + + private Timer initialTimer = new Timer() { + @Override + public void run() { + show(); + } + }; + private Timer delayStateTimer = new Timer() { + @Override + public void run() { + getElement().setClassName(PRIMARY_STYLE_NAME + "-delay"); + } + }; + private Timer waitStateTimer = new Timer() { + @Override + public void run() { + getElement().setClassName(PRIMARY_STYLE_NAME + "-wait"); + } + }; + + private Element element; + + /** + * Returns the delay (in ms) which must pass before the loading indicator + * moves into the "initial" state and is shown to the user + * + * @return The delay (in ms) until moving into the "initial" state. Counted + * from when {@link #trigger()} is called. + */ + public int getInitialStateDelay() { + return initialStateDelay; + } + + /** + * Sets the delay (in ms) which must pass before the loading indicator moves + * into the "initial" state and is shown to the user + * + * @param initialStateDelay + * The delay (in ms) until moving into the "initial" state. + * Counted from when {@link #trigger()} is called. + */ + public void setInitialStateDelay(int initialStateDelay) { + this.initialStateDelay = initialStateDelay; + } + + /** + * Returns the delay (in ms) which must pass before the loading indicator + * moves to its "delay" state. + * + * @return The delay (in ms) until the loading indicator moves into its + * "delay" state. Counted from when {@link #trigger()} is called. + */ + public int getDelayStateDelay() { + return delayStateDelay; + } + + /** + * Sets the delay (in ms) which must pass before the loading indicator moves + * to its "delay" state. + * + * @param delayStateDelay + * The delay (in ms) until the loading indicator moves into its + * "delay" state. Counted from when {@link #trigger()} is called. + */ + public void setDelayStateDelay(int delayStateDelay) { + this.delayStateDelay = delayStateDelay; + } + + /** + * Returns the delay (in ms) which must pass before the loading indicator + * moves to its "wait" state. + * + * @return The delay (in ms) until the loading indicator moves into its + * "wait" state. Counted from when {@link #trigger()} is called. + */ + public int getWaitStateDelay() { + return waitStateDelay; + } + + /** + * Sets the delay (in ms) which must pass before the loading indicator moves + * to its "wait" state. + * + * @param loadingIndicatorThirdDelay + * The delay (in ms) from the event until changing the loading + * indicator into its "wait" state. Counted from when + * {@link #trigger()} is called. + */ + public void setWaitStateDelay(int loadingIndicatorThirdDelay) { + waitStateDelay = loadingIndicatorThirdDelay; + } + + /** + * Triggers displaying of this loading indicator. The loading indicator will + * actually be shown by {@link #show()} when the initial delay (as specified + * by {@link #getInitialStateDelay()}) has passed. + * <p> + * The loading indicator will be hidden if shown when calling this method. + * </p> + */ + public void trigger() { + hide(); + initialTimer.schedule(getInitialStateDelay()); + } + + /** + * Shows the loading indicator in its standard state and triggers timers for + * transitioning into the "delay" and "wait" states. + */ + public void show() { + // Reset possible style name and display mode + getElement().setClassName(PRIMARY_STYLE_NAME); + getElement().getStyle().setDisplay(Display.BLOCK); + + // Schedule the "delay" loading indicator + int delayStateTimerDelay = getDelayStateDelay() + - getInitialStateDelay(); + if (delayStateTimerDelay >= 0) { + delayStateTimer.schedule(delayStateTimerDelay); + } + + // Schedule the "wait" loading indicator + int waitStateTimerDelay = getWaitStateDelay() - getInitialStateDelay(); + if (waitStateTimerDelay >= 0) { + waitStateTimer.schedule(waitStateTimerDelay); + } + } + + /** + * Returns the {@link ApplicationConnection} which uses this loading + * indicator + * + * @return The ApplicationConnection for this loading indicator + */ + public ApplicationConnection getConnection() { + return connection; + } + + /** + * Sets the {@link ApplicationConnection} which uses this loading indicator. + * Only used internally. + * + * @param connection + * The ApplicationConnection for this loading indicator + */ + void setConnection(ApplicationConnection connection) { + this.connection = connection; + } + + /** + * Hides the loading indicator (if visible). Cancels any possibly running + * timers. + */ + public void hide() { + initialTimer.cancel(); + delayStateTimer.cancel(); + waitStateTimer.cancel(); + + getElement().getStyle().setDisplay(Display.NONE); + } + + /** + * Returns whether or not the loading indicator is showing. + * + * @return true if the loading indicator is visible, false otherwise + */ + public boolean isVisible() { + if (getElement().getStyle().getDisplay() + .equals(Display.NONE.getCssName())) { + return false; + } + + return true; + } + + /** + * Returns the root element of the loading indicator + * + * @return The loading indicator DOM element + */ + public Element getElement() { + if (element == null) { + element = DOM.createDiv(); + element.getStyle().setPosition(Position.ABSOLUTE); + getConnection().getUIConnector().getWidget().getElement() + .appendChild(element); + } + return element; + } + +} diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index b8b7786d21..f4524882fa 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -615,5 +615,15 @@ public class UIConnector extends AbstractSingleComponentContainerConnector getConnection().getVTooltip().setMaxWidth( getState().tooltipConfiguration.maxWidth); } + + if (stateChangeEvent + .hasPropertyChanged("loadingIndicatorConfiguration")) { + getConnection().getLoadingIndicator().setInitialStateDelay( + getState().loadingIndicatorConfiguration.initialDelay); + getConnection().getLoadingIndicator().setWaitStateDelay( + getState().loadingIndicatorConfiguration.waitStateDelay); + getConnection().getLoadingIndicator().setDelayStateDelay( + getState().loadingIndicatorConfiguration.delayStateDelay); + } } } |