source: trunk/src/org/expeditee/gui/PopupManager.java@ 1175

Last change on this file since 1175 was 1175, checked in by bln4, 6 years ago

org.expeditee.gui.PopupManager ->

Temporarily comments out the code to paint popups while that system is not functional.

File size: 7.7 KB
Line 
1/**
2 * PopupManager.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.gui;
20
21import java.util.LinkedList;
22import java.util.List;
23
24import org.expeditee.core.Point;
25import org.expeditee.core.bounds.AxisAlignedBoxBounds;
26import org.expeditee.gio.EcosystemManager;
27import org.expeditee.gio.EcosystemManager.Ecosystem;
28
29/**
30 * A centralised container for all custom pop-ups in expeditee.
31 *
32 * @author Brook Novak
33 */
34public final class PopupManager implements DisplayObserver
35{
36 /** Singleton */
37 private static PopupManager _instance = null;
38
39 /**
40 * @return The singleton instance.
41 */
42 public static PopupManager getInstance()
43 {
44 // Only valid for Swing ecosystems
45 if (EcosystemManager.getType() != Ecosystem.Swing) {
46 return null;
47 }
48
49 // Construct the instance
50 if (_instance == null) {
51 _instance = new PopupManager();
52 }
53
54 return _instance;
55 }
56
57 /** Singleton */
58 private PopupManager()
59 {
60 }
61
62 private LinkedList<Popup> _popups = new LinkedList<Popup>();
63
64 /** Time its takes for a maximise/minimise to animate, in milliseconds. */
65 //private final int ANIMATION_DURATION = 180;
66 /** in milliseconds. TODO: Expand. cts16 */
67 //private final int ANIMATION_RATE = 30;
68
69 public void add(Popup p)
70 {
71 if (p == null) {
72 return;
73 }
74
75 synchronized(_popups) {
76 if (!_popups.contains(p)) {
77 _popups.add(p);
78 }
79 }
80 }
81
82 public void remove(Popup p)
83 {
84 if (p == null) {
85 return;
86 }
87
88 synchronized(_popups) {
89 if (_popups.contains(p)) {
90 _popups.remove(p);
91 }
92 }
93 }
94
95 public List<Popup> getPopups()
96 {
97 synchronized(_popups) {
98 return new LinkedList<Popup>(_popups);
99 }
100 }
101
102 /**
103 * Determines whether a given point is over a pop-up.
104 *
105 * @param p
106 *
107 * @return True if p is over a pop-up
108 *
109 * @throws NullPointerException
110 * If p is null
111 */
112 public boolean isPointOverPopup(Point p)
113 {
114 if (p == null) {
115 throw new NullPointerException("p");
116 }
117
118 synchronized(_popups) {
119 for (Popup popup : _popups) {
120 if (popup.getBounds().contains(p)) {
121 return true;
122 }
123 }
124 }
125
126 return false;
127 }
128
129 /**
130 * Use this instead of isVisible to determine if the popup is showing or not,
131 * since it considers animation.
132 *
133 * @return
134 * True if this popup is showing. <b>IMPORTANT:</b> This includes
135 * if the popup is not yet visible, but in an animation sequence for showing...
136 *
137 * @throws NullPointerException
138 * If p is null
139 */
140 public boolean isShowing(Popup p)
141 {
142 if (p == null) {
143 throw new NullPointerException("p");
144 }
145
146 synchronized(_popups) {
147 return _popups.contains(p) && p.isShowing();
148 }
149 }
150
151 /**
152 * @return
153 * True if a pop-up is showing. False otherwise.
154 */
155 public boolean isAnyPopupsShowing()
156 {
157 synchronized(_popups) {
158 return !_popups.isEmpty();
159 }
160 }
161
162 public void hideAutoHidePopups()
163 {
164 synchronized(_popups) {
165 for (Popup p : _popups) {
166 if (p.doesAutoHide()) {
167 p.hide();
168 }
169 }
170 }
171 }
172
173 /**
174 * @return
175 * True if the mouse click event for going back a frame should be consumed
176 * due to a pop-up requesting this event to be consumed currently showing.
177 */
178 public boolean shouldConsumeBackClick()
179 {
180 synchronized(_popups) {
181 for (Popup p : _popups) {
182 if (p.shouldConsumeBackClick()) {
183 return true;
184 }
185 }
186 }
187
188 return false;
189 }
190
191 @Override
192 public void frameChanged()
193 {
194 }
195
196 /**
197 * Paints current popup animations to the expeditee browser content pane.
198 */
199 public void paint()
200 {
201 //Bryce: popups temporarly disabled due to them not working and interfering in things.
202// synchronized (_popups) {
203// for (Popup popup : _popups) {
204// popup.update();
205// popup.paint();
206// }
207// }
208 }
209
210 /**
211 * Provides animations for a popup when hiding or when showing.
212 *
213 * Note that {@link PopupAnimator#paint(Graphics)} and {@link PopupAnimator#update(float)}
214 * will always be invoked at seperate times - so do not have to worry about thread-safety.
215 *
216 * These should only be used once... one per popup at a time.
217 *
218 * @author Brook Novak
219 */
220 public static abstract class PopupAnimator
221 {
222 /** True if animating to show the popup, false if to hide. */
223 private boolean _showing = true;
224
225 /** Whether the animation is currently paused. */
226 private boolean _paused = true;
227
228 private long _startTime;
229 private long _duration;
230 private long _animationCurrentTime;
231
232 public PopupAnimator()
233 {
234 _animationCurrentTime = _startTime = System.currentTimeMillis();
235 _duration = getDurationMillis();
236 }
237
238 /**
239 * @return False if the animation has finished, true if further updates are required.
240 */
241 public boolean update()
242 {
243 long currentTime = System.currentTimeMillis();
244
245 if (currentTime > _startTime + _duration) {
246 currentTime = _startTime + _duration;
247 }
248
249 // If paused, make sure elapsed time stays constant
250 if (_paused) {
251 _startTime += currentTime - _animationCurrentTime;
252 }
253
254 _animationCurrentTime = currentTime;
255
256 return !isFinished();
257 }
258
259 public void hide()
260 {
261 if (!_showing) {
262 return;
263 }
264
265 _showing = false;
266 complementAnimationProgress();
267 }
268
269 public void show()
270 {
271 if (_showing) {
272 return;
273 }
274
275 _showing = true;
276 complementAnimationProgress();
277 }
278
279 public boolean isShowing()
280 {
281 return _showing;
282 }
283
284 public void start()
285 {
286 _animationCurrentTime = _startTime = System.currentTimeMillis();
287 unpause();
288 }
289
290 public void pause()
291 {
292 pause(true);
293 }
294
295 public void unpause()
296 {
297 pause(false);
298 }
299
300 public void pause(boolean pause)
301 {
302 _paused = pause;
303 }
304
305 private void complementAnimationProgress()
306 {
307 _startTime = _animationCurrentTime - ((_startTime + _duration) - _animationCurrentTime);
308 }
309
310 public float getProgress()
311 {
312 return (_animationCurrentTime - _startTime) / ((float) _duration);
313 }
314
315 public boolean isFinished()
316 {
317 return _animationCurrentTime != _startTime + _duration;
318 }
319
320 public abstract long getDurationMillis();
321
322 public abstract AxisAlignedBoxBounds getAnimatedBounds(AxisAlignedBoxBounds fullBounds);
323
324 }
325
326 public static class ExpandShrinkAnimator extends PopupAnimator
327 {
328 public static final long DURATION_MS = 2000;
329
330 public AxisAlignedBoxBounds _initialBounds = null;
331
332 public ExpandShrinkAnimator()
333 {
334 }
335
336 public ExpandShrinkAnimator(AxisAlignedBoxBounds initialBounds)
337 {
338 setInitialBounds(initialBounds);
339 }
340
341 public void setInitialBounds(AxisAlignedBoxBounds initialBounds)
342 {
343 _initialBounds = initialBounds;
344 }
345
346 @Override
347 public long getDurationMillis() { return DURATION_MS; }
348
349 @Override
350 public AxisAlignedBoxBounds getAnimatedBounds(AxisAlignedBoxBounds fullBounds)
351 {
352 if (_initialBounds == null) {
353 setInitialBounds(fullBounds.clone());
354 _initialBounds.getTopLeft().setY(_initialBounds.getTopLeft().getY() + _initialBounds.getSize().height);
355 _initialBounds.getSize().height = 0;
356 }
357
358 float percentShown = getProgress();
359 if (!isShowing()) {
360 percentShown = 1 - percentShown;
361 }
362
363 return AxisAlignedBoxBounds.lerp(_initialBounds, fullBounds, percentShown);
364 }
365 }
366}
Note: See TracBrowser for help on using the repository browser.