-
Notifications
You must be signed in to change notification settings - Fork 0
/
Notification.java
396 lines (344 loc) · 14.8 KB
/
Notification.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
package CAM;
/*
* Copyright (c) 2013 by Gerrit Grunwald
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Popup;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
/**
* Created by
* User: hansolo
* Date: 01.07.13
* Time: 07:10
*/
public class Notification {
public static final Image INFO_ICON = new Image(Notifier.class.getResourceAsStream("info.png"));
public static final Image WARNING_ICON = new Image(Notifier.class.getResourceAsStream("warning.png"));
public static final Image SUCCESS_ICON = new Image(Notifier.class.getResourceAsStream("success.png"));
public static final Image ERROR_ICON = new Image(Notifier.class.getResourceAsStream("error.png"));
public final String TITLE;
public final String MESSAGE;
public final Image IMAGE;
// ******************** Constructors **************************************
public Notification(final String TITLE, final String MESSAGE) {
this(TITLE, MESSAGE, null);
}
public Notification(final String MESSAGE, final Image IMAGE) {
this("", MESSAGE, IMAGE);
}
public Notification(final String TITLE, final String MESSAGE, final Image IMAGE) {
this.TITLE = TITLE;
this.MESSAGE = MESSAGE;
this.IMAGE = IMAGE;
}
// ******************** Inner Classes *************************************
public enum Notifier {
INSTANCE;
private static final double ICON_WIDTH = 24;
private static final double ICON_HEIGHT = 24;
private static double width = 350;
private static double height = 80;
private static double offsetX = 0;
private static double offsetY = 25;
private static double spacingY = 5;
private static Pos popupLocation = Pos.CENTER;
// private static Stage stageRef = null;
private Duration popupLifetime;
private Stage stage;
private Scene scene;
private ObservableList<Popup> popups;
// ******************** Constructor ***************************************
private Notifier() {
init();
initGraphics();
}
// ******************** Initialization ************************************
private void init() {
popupLifetime = Duration.millis(5000);
popups = FXCollections.observableArrayList();
}
private void initGraphics()
{
// scene = new Scene(new Region());
// //scene.setFill(null);
// scene.getStylesheets().add(getClass().getResource("Rec.css").toExternalForm());
//
// stage = new Stage();
// stage.initStyle(StageStyle.TRANSPARENT);
// stage.setScene(scene);
}
// ******************** Methods *******************************************
/**
* @param STAGE_REF The Notification will be positioned relative to the given Stage.<br>
* If null then the Notification will be positioned relative to the primary Screen.
* @param POPUP_LOCATION The default is TOP_RIGHT of primary Screen.
*/
public static void setPopupLocation(final Stage STAGE_REF, final Pos POPUP_LOCATION) {
if (null != STAGE_REF) {
INSTANCE.stage.initOwner(STAGE_REF);
// Notifier.stageRef = STAGE_REF;
}
Notifier.popupLocation = POPUP_LOCATION;
}
/**
* Sets the Notification's owner stage so that when the owner
* stage is closed Notifications will be shut down as well.<br>
* This is only needed if <code>setPopupLocation</code> is called
* <u>without</u> a stage reference.
* @param OWNER
*/
public static void setNotificationOwner(final Stage OWNER) {
INSTANCE.stage.initOwner(OWNER);
}
/**
* @param OFFSET_X The horizontal shift required.
* <br> The default is 0 px.
*/
public static void setOffsetX(final double OFFSET_X) {
Notifier.offsetX = OFFSET_X;
}
/**
* @param OFFSET_Y The vertical shift required.
* <br> The default is 25 px.
*/
public static void setOffsetY(final double OFFSET_Y) {
Notifier.offsetY = OFFSET_Y;
}
/**
* @param WIDTH The default is 300 px.
*/
public static void setWidth(final double WIDTH) {
Notifier.width = WIDTH;
}
/**
* @param HEIGHT The default is 80 px.
*/
public static void setHeight(final double HEIGHT) {
Notifier.height = HEIGHT;
}
/**
* @param SPACING_Y The spacing between multiple Notifications.
* <br> The default is 5 px.
*/
public static void setSpacingY(final double SPACING_Y) {
Notifier.spacingY = SPACING_Y;
}
public void stop() {
popups.clear();
stage.close();
}
/**
* Returns the Duration that the notification will stay on screen before it
* will fade out.
* @return the Duration the popup notification will stay on screen
*/
public Duration getPopupLifetime() {
return popupLifetime;
}
/**
* Defines the Duration that the popup notification will stay on screen before it
* will fade out. The parameter is limited to values between 2 and 20 seconds.
* @param POPUP_LIFETIME
*/
public void setPopupLifetime(final Duration POPUP_LIFETIME) {
popupLifetime = Duration.millis(clamp(2000, 20000, POPUP_LIFETIME.toMillis()));
}
/**
* Show the given Notification on the screen
* @param NOTIFICATION
*/
public void notify(final Notification NOTIFICATION) {
preOrder();
showPopup(NOTIFICATION);
}
/**
* Show a Notification with the given parameters on the screen
* @param TITLE
* @param MESSAGE
* @param IMAGE
*/
public void notify(final String TITLE, final String MESSAGE, final Image IMAGE) {
notify(new Notification(TITLE, MESSAGE, IMAGE));
}
/**
* Show a Notification with the given title and message and an Info icon
* @param TITLE
* @param MESSAGE
*/
public void notifyInfo(final String TITLE, final String MESSAGE) {
notify(new Notification(TITLE, MESSAGE, Notification.INFO_ICON));
}
/**
* Show a Notification with the given title and message and a Warning icon
* @param TITLE
* @param MESSAGE
*/
public void notifyWarning(final String TITLE, final String MESSAGE) {
notify(new Notification(TITLE, MESSAGE, Notification.WARNING_ICON));
}
/**
* Show a Notification with the given title and message and a Checkmark icon
* @param TITLE
* @param MESSAGE
*/
public void notifySuccess(final String TITLE, final String MESSAGE) {
notify(new Notification(TITLE, MESSAGE, Notification.SUCCESS_ICON));
}
/**
* Show a Notification with the given title and message and an Error icon
* @param TITLE
* @param MESSAGE
*/
public void notifyError(final String TITLE, final String MESSAGE) {
notify(new Notification(TITLE, MESSAGE, Notification.ERROR_ICON));
}
/**
* Makes sure that the given VALUE is within the range of MIN to MAX
* @param MIN
* @param MAX
* @param VALUE
* @return
*/
private double clamp(final double MIN, final double MAX, final double VALUE) {
if (VALUE < MIN) return MIN;
if (VALUE > MAX) return MAX;
return VALUE;
}
/**
* Reorder the popup Notifications on screen so that the latest Notification will stay on top
*/
private void preOrder() {
if (popups.isEmpty()) return;
for (int i = 0 ; i < popups.size() ; i++) {
switch (popupLocation) {
case TOP_LEFT: case TOP_CENTER: case TOP_RIGHT: popups.get(i).setY(popups.get(i).getY() + height + spacingY); break;
default: popups.get( i ).setY( popups.get( i ).getY() - height - spacingY);
}
}
}
/**
* Creates and shows a popup with the data from the given Notification object
* @param NOTIFICATION
*/
private void showPopup(final Notification NOTIFICATION) {
Label title = new Label(NOTIFICATION.TITLE);
title.setStyle("-fx-font-size:1.083333em;-fx-font-weight:bold;-fx-text-fill:black;");
//title.getStyleClass().add("title");
ImageView icon = new ImageView(NOTIFICATION.IMAGE);
icon.setFitWidth(ICON_WIDTH);
icon.setFitHeight(ICON_HEIGHT);
Label message = new Label(NOTIFICATION.MESSAGE, icon);
message.setStyle("-fx-font-size:1.0em; -fx-content-display:left;-fx-graphic-text-gap:10;-fx-text-fill:black;");
// message.getStyleClass().add("message");
VBox popupLayout = new VBox();
popupLayout.setSpacing(10);
popupLayout.setPadding(new Insets(10, 10, 10, 10));
popupLayout.getChildren().addAll(title, message);
StackPane popupContent = new StackPane();
popupContent.setPrefSize(width, height);
//popupContent.getStyleClass().add("notification");
//popupContent.setStyle("-fx-background-color : rgba(208, 222, 111, 0.8);-fx-background-radius: 5;-fx-effect: innershadow(two-pass-box, rgba(255, 255, 255, 0.6), 5.0, 0.25, 0, 0);-foreground-color: white;-icon-color: white;");
if(NOTIFICATION.TITLE.endsWith("Info"))
{
popupContent.setStyle("-fx-background-color : rgba(77, 143, 178, 0.8);-fx-background-radius: 5;");
}
else if(NOTIFICATION.TITLE.endsWith("Error"))
{
popupContent.setStyle("-fx-background-color : rgba(191, 86, 86, 0.8);-fx-background-radius: 5;");
}
else if(NOTIFICATION.TITLE.endsWith("Warning"))
{
popupContent.setStyle("-fx-background-color : rgba(214, 155, 58, 0.8);-fx-background-radius: 5;");
}
else if(NOTIFICATION.TITLE.endsWith("Success"))
{
popupContent.setStyle("-fx-background-color : rgba(123, 153, 79, 0.8);-fx-background-radius: 5;");
}
popupContent.getChildren().addAll(popupLayout);
final Popup POPUP = new Popup();
POPUP.setX( getX() );
POPUP.setY( getY() );
POPUP.getContent().add(popupContent);
popups.add(POPUP);
// Add a timeline for popup fade out
KeyValue fadeOutBegin = new KeyValue(POPUP.opacityProperty(), 1.0);
KeyValue fadeOutEnd = new KeyValue(POPUP.opacityProperty(), 0.0);
KeyFrame kfBegin = new KeyFrame(Duration.ZERO, fadeOutBegin);
KeyFrame kfEnd = new KeyFrame(Duration.millis(500), fadeOutEnd);
Timeline timeline = new Timeline(kfBegin, kfEnd);
timeline.setDelay(popupLifetime);
timeline.setOnFinished(actionEvent -> Platform.runLater(() -> {
POPUP.hide();
popups.remove(POPUP);
//@-dxÔö¼ÓnotiÔËÐбêÖ¾-¸´Î»
//ScreensFramework.Noti_RunFlag=false;
}));
// Move popup to the right during fade out
//POPUP.opacityProperty().addListener((observableValue, oldOpacity, opacity) -> popup.setX(popup.getX() + (1.0 - opacity.doubleValue()) * popup.getWidth()) );
// if (stage.isShowing()) {
// stage.toFront();
// } else {
// stage.show();
// }
POPUP.show(ScreensFramework.MK3_Stage);
timeline.play();
}
private double getX() {
// if (null == stageRef) return calcX( 0.0, Screen.getPrimary().getBounds().getWidth() );
//
// return calcX(stageRef.getX(), stageRef.getWidth());
return calcX( 0.0, Screen.getPrimary().getBounds().getWidth() );
}
private double getY() {
// if (null == stageRef) return calcY( 0.0, Screen.getPrimary().getBounds().getHeight() );
//
// return calcY(stageRef.getY(), stageRef.getHeight());
return calcY( 0.0, Screen.getPrimary().getBounds().getHeight() );
}
private double calcX(final double LEFT, final double TOTAL_WIDTH) {
switch (popupLocation) {
case TOP_LEFT : case CENTER_LEFT : case BOTTOM_LEFT : return LEFT + offsetX;
case TOP_CENTER: case CENTER : case BOTTOM_CENTER: return LEFT + (TOTAL_WIDTH - width) * 0.5 - offsetX;
case TOP_RIGHT : case CENTER_RIGHT: case BOTTOM_RIGHT : return LEFT + TOTAL_WIDTH - width - offsetX;
default: return 0.0;
}
}
private double calcY(final double TOP, final double TOTAL_HEIGHT ) {
switch (popupLocation) {
case TOP_LEFT : case TOP_CENTER : case TOP_RIGHT : return TOP + offsetY;
case CENTER_LEFT: case CENTER : case CENTER_RIGHT: return TOP + (TOTAL_HEIGHT- height)/2 - offsetY;
case BOTTOM_LEFT: case BOTTOM_CENTER: case BOTTOM_RIGHT: return TOP + TOTAL_HEIGHT - height - offsetY;
default: return 0.0;
}
}
}
}