3
* ********************************************************************
4
* This is a conditional block for preventing the DoxyGen documentation
5
* tool to include this license header within the description of each
6
* source code file. If you want to include this block, please define
7
* the LICENSE parameter into the provided DoxyFile.
8
* ********************************************************************
10
* JCarrierPigeon - A notification library
11
* Copyright (c) 2010, Paulo Roberto Massa Cereda
12
* All rights reserved.
14
* Redistribution and use in source and binary forms, with or
15
* without modification, are permitted provided that the following
18
* 1. Redistributions of source code must retain the above copyright
19
* notice, this list of conditions and the following disclaimer.
21
* 2. Redistributions in binary form must reproduce the above copyright
22
* notice, this list of conditions and the following disclaimer in
23
* the documentation and/or other materials provided with the
26
* 3. Neither the name of the project's author nor the names of its
27
* contributors may be used to endorse or promote products derived
28
* from this software without specific prior written permission.
30
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
36
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
37
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
40
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42
* ********************************************************************
43
* End of the LICENSE conditional block
44
* ********************************************************************
47
* <b>Notification.java</b>: provides the notification features to any
48
* <code>javax.swing.JFrame</code> or <code>javax.swing.JWindow</code>
49
* object. Please note that this new class introduced in version 1.3 is
50
* the new replacement for <b>net.sf.jcarrierpigeon.CarrierPigeon</b>,
51
* assigned as deprecated.
54
package net.sf.jcarrierpigeon;
56
import java.awt.GraphicsEnvironment;
57
import java.awt.Rectangle;
58
import javax.swing.JFrame;
59
import javax.swing.JWindow;
60
import org.jdesktop.animation.timing.Animator;
61
import org.jdesktop.animation.timing.TimingTarget;
64
* Provides the notification features to any <code>javax.swing.JFrame</code>
65
* or <code>javax.swing.JWindow</code> object. In order to achieve a greater
66
* effect, it's highly recommended to remove the window border of the provided
67
* <code>javax.swing.JFrame</code>. You don't need to worry with that when
68
* using <code>javax.swing.JWindow</code>, since it has no borders at all.
69
* Please note that this new class introduced in version 1.3 is the new
70
* replacement for <b>net.sf.jcarrierpigeon.CarrierPigeon</b>, assigned
71
* as deprecated. If you are using <b>net.sf.jcarrierpigeon.CarrierPigeon</b>,
72
* please change your code to use this class together with the new
73
* <b>net.sf.jcarrierpigeon.NotificationQueue</b>. Check the following example:
75
* JWindow window = new JWindow();
76
* Notification note = new Notification(window, WindowPosition.BOTTOMRIGHT, 25, 25, 1000);
77
* NotificationQueue queue = new NotificationQueue();
80
* Note that <b>net.sf.jcarrierpigeon.Notification</b> takes the very same
81
* parameters of the deprecated <b>net.sf.jcarrierpigeon.CarrierPigeon</b>
82
* class. Aside from the addition of <b>net.sf.jcarrierpigeon.NotificationQueue</b>,
83
* there is not so much change in code.
85
* @author Paulo Roberto Massa Cereda
89
public class Notification implements TimingTarget {
91
private WindowPosition windowPosition;
92
private WindowType windowType;
93
private int thisHeight;
94
private int thisWidth;
96
private JFrame windowJFrame;
97
private JWindow windowJWindow;
99
private double borderX, borderY;
100
private double boundX, boundY;
101
private double positionX, positionY;
103
private int duration;
104
private AnimationFrame animationFrame;
105
// animators, each one representing one state
106
// on AnimationFrame class
107
private Animator animatorHandlerOnShow;
108
private Animator animatorHandlerOnDisplay;
109
private Animator animatorHandlerOnClose;
110
// time in milliseconds to animate windows
111
// on show and close events
112
private int timeToAnimate = 500;
115
* Constructor method for a basic <code>javax.swing.JFrame</code> object.
116
* It basically builds the notification model according to the provided
117
* parameters. Just keep in mind the provided <code>javax.swing.JFrame</code>
118
* is <b>disposed</b> after the notification being displayed. Check the
121
* JFrame window = new JFrame();
122
* Notification note = new Notification(window, WindowPosition.BOTTOMRIGHT, 25, 25, 1000);
123
* NotificationQueue queue = new NotificationQueue();
126
* @param window The window to act as a notification. Please, remove the borders
127
* in order to achieve a greater effect.
128
* @param windowPosition The window position on screen. You may choose one amongst
129
* four states, each one representing the screen corners.
130
* @param borderX The distance in pixels the window must keep from the X axis border. If
131
* the notification is right-aligned, this border will be from the right side, and so forth.
132
* Usually 50 pixels or less is an acceptable value for this parameter.
133
* @param borderY The distance in pixels the window must keep from the Y axis border. If
134
* the notification is aligned from the top, this border will be from the top itself, and so forth.
135
* Usually 50 pixels or less is an acceptable value for this parameter.
136
* @param duration The notification display duration in milliseconds. So if you want 2 seconds, you need
137
* to multiply it by 1000; 2 seconds times 1000 = 2000 milliseconds.
139
public Notification(JFrame window, WindowPosition windowPosition, int borderX, int borderY, int duration) {
142
this.windowType = WindowType.JFRAME;
143
this.windowJWindow = null;
145
// setting some attributes
146
this.windowPosition = windowPosition;
147
this.windowJFrame = window;
148
this.borderX = borderX;
149
this.borderY = borderY;
152
this.thisHeight = windowJFrame.getHeight();
153
this.thisWidth = windowJFrame.getWidth();
155
// set the animation duration
156
this.duration = duration;
159
// retrieve the screen resolution and set some attributes
160
Rectangle rect = getScreenResolution();
161
this.boundX = rect.getWidth();
162
this.boundY = rect.getHeight();
165
// second calculation: based on the window position and the provided
166
// values, calculate positions on screen and the global payload for
167
// that specific region
168
switch (this.windowPosition) {
170
this.positionX = this.boundX - (this.thisWidth + this.borderX);
171
this.positionY = this.boundY - (this.thisHeight + this.borderY);
174
this.positionX = this.borderX;
175
this.positionY = this.boundY - (this.thisHeight + this.borderY);
178
this.positionX = this.boundX - (this.thisWidth + this.borderX);
179
this.positionY = this.borderY;
182
this.positionX = this.borderX;
183
this.positionY = this.borderY;
189
* Constructor method for a basic <code>javax.swing.JWindow</code> object.
190
* It basically builds the notification model according to the provided
191
* parameters. Just keep in mind the provided <code>javax.swing.JWindow</code>
192
* is <b>disposed</b> after the notification being displayed. Check the
195
* JWindow window = new JWindow();
196
* Notification note = new Notification(window, WindowPosition.BOTTOMRIGHT, 25, 25, 1000);
197
* NotificationQueue queue = new NotificationQueue();
200
* @param window The window to act as a notification. Note that a <code>javax.swing.JWindow</code>
201
* object has no borders by default, so there is no need of removing them.
202
* @param windowPosition The window position on screen. You may choose one amongst
203
* four states, each one representing the screen corners.
204
* @param borderX The distance in pixels the window must keep from the X axis border. If
205
* the notification is right-aligned, this border will be from the right side, and so forth.
206
* Usually 50 pixels or less is an acceptable value for this parameter.
207
* @param borderY The distance in pixels the window must keep from the Y axis border. If
208
* the notification is aligned from the top, this border will be from the top itself, and so forth.
209
* Usually 50 pixels or less is an acceptable value for this parameter.
210
* @param duration The notification display duration in milliseconds. So if you want 2 seconds, you need
211
* to multiply it by 1000; 2 seconds times 1000 = 2000 milliseconds.
213
public Notification(JWindow window, WindowPosition windowPosition, int borderX, int borderY, int duration) {
216
this.windowType = WindowType.JWINDOW;
217
this.windowJFrame = null;
219
// setting some attributes
220
this.windowPosition = windowPosition;
221
this.windowJWindow = window;
222
this.borderX = borderX;
223
this.borderY = borderY;
226
this.thisHeight = windowJWindow.getHeight();
227
this.thisWidth = windowJWindow.getWidth();
229
// set the animation duration
230
this.duration = duration;
233
// retrieve the screen resolution and set some attributes
234
Rectangle rect = getScreenResolution();
235
this.boundX = rect.getWidth();
236
this.boundY = rect.getHeight();
239
// second calculation: based on the window position and the provided
240
// values, calculate positions on screen and the global payload for
241
// that specific region
242
switch (this.windowPosition) {
244
this.positionX = this.boundX - (this.thisWidth + this.borderX);
245
this.positionY = this.boundY - (this.thisHeight + this.borderY);
248
this.positionX = this.borderX;
249
this.positionY = this.boundY - (this.thisHeight + this.borderY);
252
this.positionX = this.boundX - (this.thisWidth + this.borderX);
253
this.positionY = this.borderY;
256
this.positionX = this.borderX;
257
this.positionY = this.borderY;
263
* Calculates the screen size.
264
* @return A <code>java.awt.Rectangle</code> with the exact size of the screen.
266
private Rectangle getScreenResolution() {
267
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
268
return environment.getMaximumWindowBounds();
272
* Calculates the current window position based on the Y axis and the
273
* fraction of elapsed time.
274
* @param x Fraction of elapsed time. This value is on a continuum interval, 0 <= x <= 1.
275
* @return An <code>int</code> value representing the current Y value according to the
278
private int calculateCurrentPositionOnY(float x) {
282
// checks if the animation is the beginning
283
if (animationFrame == AnimationFrame.ONSHOW) {
285
// calculates the position, using the following math function
286
switch (windowPosition) {
289
result = (int) (positionY + ((boundY - positionY) * (1 - x)));
293
result = (int) (positionY - ((thisHeight + borderY) * (1 - x)));
299
// animation is now closing
300
if (animationFrame == AnimationFrame.ONCLOSE) {
302
// calculates the position, now using the inverse math function
303
switch (windowPosition) {
306
result = (int) (positionY + ((boundY - positionY) * (x)));
310
result = (int) (positionY - ((thisHeight + borderY) * (x)));
316
// seems animation is now on display, then just return the very
318
result = (int) positionY;
327
* Implements the <code>timingEvent</code> method from <code>org.jdesktop.animation.timing.TimingTarget</code>.
328
* Please don't call this function directly.
329
* @param f The continnum interval referring to the animation.
331
public void timingEvent(float f) {
333
// animate the window based on the Y axis
334
setCurrentWindowBounds((int) positionX, calculateCurrentPositionOnY(f), thisWidth, thisHeight);
339
* Implements the <code>begin</code> method from <code>org.jdesktop.animation.timing.TimingTarget</code>.
340
* This method is called before animation begins. Please don't call this function directly.
342
public void begin() {
347
* Implements the <code>end</code> method from <code>org.jdesktop.animation.timing.TimingTarget</code>.
348
* This method is called after the animation finishes. Please don't call this function directly.
352
// checks if animation just finished the presenting state
353
if (animationFrame == AnimationFrame.ONSHOW) {
355
// create a new animation handler
356
animatorHandlerOnDisplay = new Animator(duration, 1, Animator.RepeatBehavior.LOOP, this);
358
// sets the current animation state
359
animationFrame = AnimationFrame.ONDISPLAY;
362
animatorHandlerOnDisplay.start();
365
// now checking if animation just finished displaying
366
if (animationFrame == AnimationFrame.ONDISPLAY) {
368
// create a new animation handler
369
animatorHandlerOnClose = new Animator(timeToAnimate, 1, Animator.RepeatBehavior.LOOP, this);
371
// sets the current animation state
372
animationFrame = AnimationFrame.ONCLOSE;
375
animatorHandlerOnClose.start();
378
// animation is done, so hide and dispose window
379
setCurrentWindowVisible(false);
380
disposeCurrentWindow();
389
* Implements the <code>repeat</code> method from <code>org.jdesktop.animation.timing.TimingTarget</code>.
390
* This function is called on every animation repetition. Please don't call this function directly.
392
public void repeat() {
397
* Performs the animation itself based on the parameters provided in the
398
* constructor method. Keep in mind this method is synchronized. Check
399
* the following example:
401
* JWindow window = new JWindow();
402
* Notification note = new Notification(window, WindowPosition.BOTTOMRIGHT, 25, 25, 1000);
405
* Wherever possible, please use the new notification queue manager
406
* <b>net.sf.jcarrierpigeon.NotificationQueue</b>.
408
public synchronized void animate() {
410
// set the animation state
411
animationFrame = AnimationFrame.ONSHOW;
413
// define some window properties
414
setCurrentWindowAlwaysOnTop(true);
415
setCurrentWindowVisible(true);
417
// defines the animator handler from Timing Framework
418
// first animator handler
419
animatorHandlerOnShow = new Animator(timeToAnimate, 1, Animator.RepeatBehavior.LOOP, this);
422
animatorHandlerOnShow.start();
426
* Checks if the notification process is still running. It basically calls the
427
* <code>isRunning</code> method from <code>org.jdesktop.animation.timing.Animator</code>.
428
* @return <code>true</code> if the notification is still running, or <code>false</code>
431
public boolean isRunning() {
432
if ((animatorHandlerOnShow.isRunning())
433
|| (animatorHandlerOnDisplay.isRunning())
434
|| (animatorHandlerOnClose).isRunning()) {
442
* Sets the bounds of the current window. It's basically a call to the
443
* inner window <code>setBounds</code> method.
444
* @param x Coordinate X
445
* @param y Coordinate Y
447
* @param height Height
449
private void setCurrentWindowBounds(int x, int y, int width, int height) {
450
switch (windowType) {
452
windowJFrame.setBounds(x, y, width, height);
455
windowJWindow.setBounds(x, y, width, height);
461
* Sets the visibility of the current window. It's basically a call to the
462
* inner window <code>setVisible</code> method.
463
* @param value <code>true</code> if window should be visible, or <code>false</code>
466
private void setCurrentWindowVisible(boolean value) {
467
switch (windowType) {
469
windowJFrame.setVisible(value);
472
windowJWindow.setVisible(value);
478
* Sets the window parameter of being on top of other windows. It's basically
479
* a call to the inner window <code>setAlwaysOnTop</code> method.
480
* @param value <code>true</code> if window should be on top of other windows, or
481
* <code>false</code> otherwise.
483
private void setCurrentWindowAlwaysOnTop(boolean value) {
484
switch (windowType) {
486
windowJFrame.setAlwaysOnTop(value);
489
windowJWindow.setAlwaysOnTop(value);
495
* Dispose the current window. It's basically a call to the inner window
496
* <code>dispose</code> method.
498
private void disposeCurrentWindow() {
499
switch (windowType) {
501
windowJFrame.dispose();
504
windowJWindow.dispose();
510
* Sets the animation speed. This method was rewritten and the name was
511
* replaced by a more meaningful one. Check the following example:
513
* JWindow window = new JWindow();
514
* Notification note = new Notification(window, WindowPosition.BOTTOMRIGHT, 25, 25, 1000);
515
* note.setAnimationSpeed(500);
516
* NotificationQueue queue = new NotificationQueue();
519
* @param milliseconds The notification effects duration in milliseconds.
520
* Usually 500 milliseconds or less is an acceptable value for this parameter.
522
public void setAnimationSpeed(int milliseconds) {
523
this.timeToAnimate = milliseconds;