1 /*******************************************************************************
2  * Copyright (c) 2004, 2020 Tasktop Technologies and others.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v. 2.0 which is available at
6  * https://www.eclipse.org/legal/epl-2.0
7  *
8  * SPDX-License-Identifier: EPL-2.0
9  *
10  * Contributors:
11  *     Tasktop Technologies - initial API and implementation
12  *     SAP SE - port to platform.ui
13  *******************************************************************************/
14 
15 package org.eclipse.jface.notifications.internal;
16 
17 import org.eclipse.core.runtime.IProgressMonitor;
18 import org.eclipse.core.runtime.IStatus;
19 import org.eclipse.core.runtime.Status;
20 import org.eclipse.core.runtime.jobs.Job;
21 import org.eclipse.swt.widgets.Display;
22 import org.eclipse.swt.widgets.Shell;
23 
24 public class AnimationUtil {
25 
26 	public static final long FADE_RESCHEDULE_DELAY = 80;
27 
28 	public static final int FADE_IN_INCREMENT = 15;
29 
30 	public static final int FADE_OUT_INCREMENT = -20;
31 
fastFadeIn(Shell shell, IFadeListener listener)32 	public static FadeJob fastFadeIn(Shell shell, IFadeListener listener) {
33 		return new FadeJob(shell, 2 * FADE_IN_INCREMENT, FADE_RESCHEDULE_DELAY, listener);
34 	}
35 
fadeIn(Shell shell, IFadeListener listener)36 	public static FadeJob fadeIn(Shell shell, IFadeListener listener) {
37 		return new FadeJob(shell, FADE_IN_INCREMENT, FADE_RESCHEDULE_DELAY, listener);
38 	}
39 
fadeOut(Shell shell, IFadeListener listener)40 	public static FadeJob fadeOut(Shell shell, IFadeListener listener) {
41 		return new FadeJob(shell, FADE_OUT_INCREMENT, FADE_RESCHEDULE_DELAY, listener);
42 	}
43 
44 	public static class FadeJob extends Job {
45 
46 		private final Shell shell;
47 
48 		private final int increment;
49 
50 		private volatile boolean stopped;
51 
52 		private volatile int currentAlpha;
53 
54 		private final long delay;
55 
56 		private final IFadeListener fadeListener;
57 
FadeJob(Shell shell, int increment, long delay, IFadeListener fadeListener)58 		public FadeJob(Shell shell, int increment, long delay, IFadeListener fadeListener) {
59 			super(Messages.AnimationUtil_FadeJobTitle);
60 			if (increment < -255 || increment == 0 || increment > 255) {
61 				throw new IllegalArgumentException("-255 <= increment <= 255 && increment != 0"); //$NON-NLS-1$
62 			}
63 			if (delay < 1) {
64 				throw new IllegalArgumentException("delay must be > 0"); //$NON-NLS-1$
65 			}
66 			this.currentAlpha = shell.getAlpha();
67 			this.shell = shell;
68 			this.increment = increment;
69 			this.delay = delay;
70 			this.fadeListener = fadeListener;
71 
72 			setSystem(true);
73 			schedule(delay);
74 		}
75 
76 		@Override
canceling()77 		protected void canceling() {
78 			this.stopped = true;
79 		}
80 
reschedule()81 		private void reschedule() {
82 			if (this.stopped) {
83 				return;
84 			}
85 			schedule(this.delay);
86 		}
87 
cancelAndWait(final boolean setAlpha)88 		public void cancelAndWait(final boolean setAlpha) {
89 			if (this.stopped) {
90 				return;
91 			}
92 			cancel();
93 			Display.getDefault().syncExec(new Runnable() {
94 				@Override
95 				public void run() {
96 					if (setAlpha) {
97 						FadeJob.this.shell.setAlpha(getLastAlpha());
98 					}
99 				}
100 			});
101 		}
102 
103 		@Override
run(IProgressMonitor monitor)104 		protected IStatus run(IProgressMonitor monitor) {
105 			if (this.stopped) {
106 				return Status.OK_STATUS;
107 			}
108 
109 			this.currentAlpha += this.increment;
110 			if (this.currentAlpha <= 0) {
111 				this.currentAlpha = 0;
112 			} else if (this.currentAlpha >= 255) {
113 				this.currentAlpha = 255;
114 			}
115 
116 			Display.getDefault().syncExec(new Runnable() {
117 				@Override
118 				public void run() {
119 					if (FadeJob.this.stopped) {
120 						return;
121 					}
122 
123 					if (FadeJob.this.shell.isDisposed()) {
124 						FadeJob.this.stopped = true;
125 						return;
126 					}
127 
128 					FadeJob.this.shell.setAlpha(FadeJob.this.currentAlpha);
129 
130 					if (FadeJob.this.fadeListener != null) {
131 						FadeJob.this.fadeListener.faded(FadeJob.this.shell, FadeJob.this.currentAlpha);
132 					}
133 				}
134 			});
135 
136 			if (this.currentAlpha == 0 || this.currentAlpha == 255) {
137 				this.stopped = true;
138 			}
139 
140 			reschedule();
141 			return Status.OK_STATUS;
142 		}
143 
getLastAlpha()144 		private int getLastAlpha() {
145 			return (this.increment < 0) ? 0 : 255;
146 		}
147 
148 	}
149 
150 	public static interface IFadeListener {
151 
faded(Shell shell, int alpha)152 		public void faded(Shell shell, int alpha);
153 
154 	}
155 
156 }
157