ResizeAnimation class
An {@link Animation} used to enlarge the popup into view.
class ResizeAnimation extends Animation { /** * The {@link PopupPanel} being affected. */ PopupPanel curPanel = null; /** * Indicates whether or not the {@link PopupPanel} is in the process of * unloading. If the popup is unloading, then the animation just does * cleanup. */ bool isUnloading = false; /** * The offset height and width of the current {@link PopupPanel}. */ int offsetHeight, offsetWidth = -1; /** * A bool indicating whether we are showing or hiding the popup. */ bool showing = false; /** * The timer used to delay the show animation. */ Timer showTimer; /** * A bool indicating whether the glass element is currently attached. */ bool glassShowing = false; //HandlerRegistration resizeRegistration; /** * Create a new {@link ResizeAnimation}. * * @param panel the panel to affect */ ResizeAnimation(PopupPanel panel) { this.curPanel = panel; } /** * Open or close the content. This method always called immediately after * the PopupPanel showing state has changed, so we base the animation on the * current state. * * @param showing true if the popup is showing, false if not */ void setState(bool showing, bool isUnloading) { // Immediately complete previous open/close animation this.isUnloading = isUnloading; cancel(); // If there is a pending timer to start a show animation, then just cancel // the timer and complete the show operation. if (showTimer != null) { showTimer.cancel(); showTimer = null; onComplete(); } // Update the logical state. curPanel.showing = showing; curPanel.updateHandlers(); // Determine if we need to animate bool animate = !isUnloading && curPanel._isAnimationEnabled; if (curPanel.animType != AnimationType.CENTER && !showing) { animate = false; } // Open the new item this.showing = showing; if (animate) { // impl.onShow takes some time to complete, so we do it before starting // the animation. If we move this to onStart, the animation will look // choppy or not run at all. if (showing) { maybeShowGlass(); // Set the position attribute, and then attach to the Dom. Otherwise, // the PopupPanel will appear to 'jump' from its static/relative // position to its absolute position (issue #1231). Dom.setStyleAttribute(curPanel.getElement(), "position", "absolute"); if (curPanel.topPosition != -1) { curPanel.setPopupPosition(curPanel.leftPosition, curPanel.topPosition); } PopupPanel.impl.setClip(curPanel.getElement(), getRectString(0, 0, 0, 0)); RootPanel.get().add(curPanel); PopupPanel.impl.onShow(curPanel.getElement()); // Wait for the popup panel and iframe to be attached before running // the animation. We use a Timer instead of a DeferredCommand so we // can cancel it if the popup is hidden synchronously. showTimer = new Timer.get(() { showTimer = null; run(PopupPanel.ANIMATION_DURATION); }); showTimer.schedule(1); } else { run(PopupPanel.ANIMATION_DURATION); } } else { onInstantaneousRun(); } } void onComplete() { if (!showing) { maybeShowGlass(); if (!isUnloading) { RootPanel.get().remove(curPanel); } PopupPanel.impl.onHide(curPanel.getElement()); } PopupPanel.impl.setClip(curPanel.getElement(), "rect(auto, auto, auto, auto)"); Dom.setStyleAttribute(curPanel.getElement(), "overflow", "visible"); } void onStart() { offsetHeight = curPanel.getOffsetHeight(); offsetWidth = curPanel.getOffsetWidth(); Dom.setStyleAttribute(curPanel.getElement(), "overflow", "hidden"); super.onStart(); } void onUpdate(double progress) { if (!showing) { progress = 1.0 - progress; } // Determine the clipping size int top = 0; int left = 0; int right = 0; int bottom = 0; int height = (progress * offsetHeight).toInt(); int width = (progress * offsetWidth).toInt(); switch (curPanel.animType) { case AnimationType.ROLL_DOWN: right = offsetWidth; bottom = height; break; case AnimationType.CENTER: top = (offsetHeight - height) >> 1; left = (offsetWidth - width) >> 1; right = left + width; bottom = top + height; break; case AnimationType.ONE_WAY_CORNER: if (LocaleInfo.getCurrentLocale().isRTL()) { left = offsetWidth - width; } right = left + width; bottom = top + height; break; } // Set the rect clipping PopupPanel.impl.setClip(curPanel.getElement(), getRectString(top, right, bottom, left)); } /** * Returns a rect string. */ String getRectString(int top, int right, int bottom, int left) { return "rect(${top}px, ${right}px, ${bottom}px, ${left}px)"; } /** * Show or hide the glass. */ void maybeShowGlass() { if (showing) { if (curPanel._isGlassEnabled) { dart_html.document.body.append(curPanel.glass); PopupPanel.impl.onShow(curPanel.glass); // resizeRegistration = dart_html.document.window.addResizeHandler(curPanel.glassResizer); curPanel.glassResizer.onResize(null); glassShowing = true; } } else if (glassShowing) { //dart_html.document.body.removeChild(curPanel.glass); curPanel.glass.remove(); PopupPanel.impl.onHide(curPanel.glass); // resizeRegistration.removeHandler(); // resizeRegistration = null; glassShowing = false; } } void onInstantaneousRun() { maybeShowGlass(); if (showing) { // Set the position attribute, and then attach to the Dom. Otherwise, // the PopupPanel will appear to 'jump' from its static/relative // position to its absolute position (issue #1231). Dom.setStyleAttribute(curPanel.getElement(), "position", "absolute"); if (curPanel.topPosition != -1) { curPanel.setPopupPosition(curPanel.leftPosition, curPanel.topPosition); } RootPanel.get().add(curPanel); PopupPanel.impl.onShow(curPanel.getElement()); } else { if (!isUnloading) { RootPanel.get().remove(curPanel); } PopupPanel.impl.onHide(curPanel.getElement()); } Dom.setStyleAttribute(curPanel.getElement(), "overflow", "visible"); } }
Extends
Animation > ResizeAnimation
Constructors
new ResizeAnimation(PopupPanel panel) #
Create a new {@link ResizeAnimation}.
@param panel the panel to affect
ResizeAnimation(PopupPanel panel) { this.curPanel = panel; }
Properties
PopupPanel curPanel #
The {@link PopupPanel} being affected.
PopupPanel curPanel = null
int duration #
The duration of the {@link Animation} in milliseconds.
int duration = -1
bool glassShowing #
A bool indicating whether the glass element is currently attached.
bool glassShowing = false
bool isStarted #
Has the {@link Animation} actually started.
bool isStarted = false
bool isUnloading #
Indicates whether or not the {@link PopupPanel} is in the process of unloading. If the popup is unloading, then the animation just does cleanup.
bool isUnloading = false
int offsetHeight #
The offset height and width of the current {@link PopupPanel}.
int offsetHeight
int offsetWidth #
The offset height and width of the current {@link PopupPanel}.
int offsetHeight, offsetWidth = -1
AnimationHandle requestHandle #
The ID of the pending animation request.
AnimationHandle requestHandle
int runId #
The unique ID of the current run. Used to handle cases where an animation is restarted within an execution block.
int runId = -1
bool running #
Is the animation running, even if it hasn't started yet.
bool running = false
bool showing #
A bool indicating whether we are showing or hiding the popup.
bool showing = false
Methods
void cancel() #
Immediately cancel this animation. If the animation is running or is scheduled to run, {@link #onCancel()} will be called.
void cancel() { // Ignore if the animation is not currently running. if (!running) { return; } // Reset the state. wasStarted = isStarted; // Used by onCancel. element = null; running = false; isStarted = false; // Cancel the animation request. if (requestHandle != null) { requestHandle.cancel(); requestHandle = null; } onCancel(); }
String getRectString(int top, int right, int bottom, int left) #
Returns a rect string.
String getRectString(int top, int right, int bottom, int left) { return "rect(${top}px, ${right}px, ${bottom}px, ${left}px)"; }
double interpolate(double progress) #
Interpolate the linear progress into a more natural easing function.
Depending on the {@link Animation}, the return value of this method can be less than 0.0 or greater than 1.0.
@param progress the linear progress, between 0.0 and 1.0 @return the interpolated progress
double interpolate(double progress) { return (1 + dart_math.cos(dart_math.PI + progress * dart_math.PI)) / 2; }
bool isRunning(int curRunId) #
Check if the specified run ID is still being run.
@param curRunId the current run ID to check @return true if running, false if canceled or restarted
bool isRunning(int curRunId) { return running && (runId == curRunId); }
void maybeShowGlass() #
Show or hide the glass.
void maybeShowGlass() { if (showing) { if (curPanel._isGlassEnabled) { dart_html.document.body.append(curPanel.glass); PopupPanel.impl.onShow(curPanel.glass); // resizeRegistration = dart_html.document.window.addResizeHandler(curPanel.glassResizer); curPanel.glassResizer.onResize(null); glassShowing = true; } } else if (glassShowing) { //dart_html.document.body.removeChild(curPanel.glass); curPanel.glass.remove(); PopupPanel.impl.onHide(curPanel.glass); // resizeRegistration.removeHandler(); // resizeRegistration = null; glassShowing = false; } }
void onCancel() #
Called immediately after the animation is canceled. The default implementation of this method calls {@link #onComplete()} only if the animation has actually started running.
void onCancel() { if (wasStarted) { onComplete(); } }
void onComplete() #
Called immediately after the animation completes.
void onComplete() { if (!showing) { maybeShowGlass(); if (!isUnloading) { RootPanel.get().remove(curPanel); } PopupPanel.impl.onHide(curPanel.getElement()); } PopupPanel.impl.setClip(curPanel.getElement(), "rect(auto, auto, auto, auto)"); Dom.setStyleAttribute(curPanel.getElement(), "overflow", "visible"); }
void onInstantaneousRun() #
void onInstantaneousRun() { maybeShowGlass(); if (showing) { // Set the position attribute, and then attach to the Dom. Otherwise, // the PopupPanel will appear to 'jump' from its static/relative // position to its absolute position (issue #1231). Dom.setStyleAttribute(curPanel.getElement(), "position", "absolute"); if (curPanel.topPosition != -1) { curPanel.setPopupPosition(curPanel.leftPosition, curPanel.topPosition); } RootPanel.get().add(curPanel); PopupPanel.impl.onShow(curPanel.getElement()); } else { if (!isUnloading) { RootPanel.get().remove(curPanel); } PopupPanel.impl.onHide(curPanel.getElement()); } Dom.setStyleAttribute(curPanel.getElement(), "overflow", "visible"); }
void onStart() #
Called immediately before the animation starts.
void onStart() { offsetHeight = curPanel.getOffsetHeight(); offsetWidth = curPanel.getOffsetWidth(); Dom.setStyleAttribute(curPanel.getElement(), "overflow", "hidden"); super.onStart(); }
void onUpdate(double progress) #
Called when the animation should be updated.
The value of progress is between 0.0 and 1.0 (inclusive) (unless you override the {@link #interpolate(double)} method to provide a wider range of values). You can override {@link #onStart()} and {@link #onComplete()} to perform setup and tear down procedures.
@param progress a double, normally between 0.0 and 1.0 (inclusive)
void onUpdate(double progress) { if (!showing) { progress = 1.0 - progress; } // Determine the clipping size int top = 0; int left = 0; int right = 0; int bottom = 0; int height = (progress * offsetHeight).toInt(); int width = (progress * offsetWidth).toInt(); switch (curPanel.animType) { case AnimationType.ROLL_DOWN: right = offsetWidth; bottom = height; break; case AnimationType.CENTER: top = (offsetHeight - height) >> 1; left = (offsetWidth - width) >> 1; right = left + width; bottom = top + height; break; case AnimationType.ONE_WAY_CORNER: if (LocaleInfo.getCurrentLocale().isRTL()) { left = offsetWidth - width; } right = left + width; bottom = top + height; break; } // Set the rect clipping PopupPanel.impl.setClip(curPanel.getElement(), getRectString(top, right, bottom, left)); }
void run(int duration, {int startTime: null, Element element: null}) #
Run this animation at the given startTime. If the startTime has already passed, the animation will run synchronously as if it started at the specified start time. If the animation is already running, it will be canceled first. <p> If the element is not <code>null</code>, the {@link #onUpdate(double)} method might be called only if the element may be visible (generally left at the appreciation of the browser). Otherwise, it will be called unconditionally.
@param duration the duration of the animation in milliseconds @param startTime the synchronized start time in milliseconds @param element the element that visually bounds the entire animation
void run(int duration, {int startTime:null, dart_html.Element element:null}) { // Cancel the animation if it is running cancel(); if (startTime == null) { startTime = (new DateTime.now()).millisecondsSinceEpoch; } // Save the duration and startTime running = true; isStarted = false; this.duration = duration; this.startTime = startTime; this.element = element; ++runId; // Execute the first callback. callback.execute((new DateTime.now()).millisecondsSinceEpoch); }
void setState(bool showing, bool isUnloading) #
Open or close the content. This method always called immediately after the PopupPanel showing state has changed, so we base the animation on the current state.
@param showing true if the popup is showing, false if not
void setState(bool showing, bool isUnloading) { // Immediately complete previous open/close animation this.isUnloading = isUnloading; cancel(); // If there is a pending timer to start a show animation, then just cancel // the timer and complete the show operation. if (showTimer != null) { showTimer.cancel(); showTimer = null; onComplete(); } // Update the logical state. curPanel.showing = showing; curPanel.updateHandlers(); // Determine if we need to animate bool animate = !isUnloading && curPanel._isAnimationEnabled; if (curPanel.animType != AnimationType.CENTER && !showing) { animate = false; } // Open the new item this.showing = showing; if (animate) { // impl.onShow takes some time to complete, so we do it before starting // the animation. If we move this to onStart, the animation will look // choppy or not run at all. if (showing) { maybeShowGlass(); // Set the position attribute, and then attach to the Dom. Otherwise, // the PopupPanel will appear to 'jump' from its static/relative // position to its absolute position (issue #1231). Dom.setStyleAttribute(curPanel.getElement(), "position", "absolute"); if (curPanel.topPosition != -1) { curPanel.setPopupPosition(curPanel.leftPosition, curPanel.topPosition); } PopupPanel.impl.setClip(curPanel.getElement(), getRectString(0, 0, 0, 0)); RootPanel.get().add(curPanel); PopupPanel.impl.onShow(curPanel.getElement()); // Wait for the popup panel and iframe to be attached before running // the animation. We use a Timer instead of a DeferredCommand so we // can cancel it if the popup is hidden synchronously. showTimer = new Timer.get(() { showTimer = null; run(PopupPanel.ANIMATION_DURATION); }); showTimer.schedule(1); } else { run(PopupPanel.ANIMATION_DURATION); } } else { onInstantaneousRun(); } }
bool update(int curTime) #
Update the {@link Animation}.
@param curTime the current time @return true if the animation should run again, false if it is complete
bool update(int curTime) { /* * Save the run id. If the runId is incremented during this execution block, * we know that this run has been canceled. */ int curRunId = runId; bool finished = curTime >= startTime + duration; if (isStarted && !finished) { // Animation is in progress. double progress = (curTime - startTime) / duration; onUpdate(interpolate(progress)); return isRunning(curRunId); // Check if this run was canceled. } if (!isStarted && curTime >= startTime) { /* * Start the animation. We do not call onUpdate() because onStart() calls * onUpdate() by default. */ isStarted = true; onStart(); if (!isRunning(curRunId)) { // This run was canceled. return false; } // Intentional fall through to possibly end the animation. } if (finished) { // Animation is complete. running = false; isStarted = false; onComplete(); return false; } return true; }