Display Current User Status and Unread Message Amount in Status Tray Icon #103
@ -2,37 +2,58 @@ package envoy.client.ui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.TrayIcon.MessageType;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import envoy.client.event.OwnStatusChange;
|
||||
import envoy.client.helper.ShutdownHelper;
|
||||
import envoy.client.util.*;
|
||||
import envoy.data.Message;
|
||||
import envoy.data.User.UserStatus;
|
||||
|
||||
import dev.kske.eventbus.*;
|
||||
import dev.kske.eventbus.Event;
|
||||
|
||||
import envoy.data.Message;
|
||||
import envoy.data.User.UserStatus;
|
||||
|
||||
import envoy.client.data.Context;
|
||||
import envoy.client.event.OwnStatusChange;
|
||||
import envoy.client.helper.ShutdownHelper;
|
||||
import envoy.client.util.*;
|
||||
|
||||
/**
|
||||
* A tray icon with the Envoy logo, a "Envoy" tool tip and a pop-up menu with menu items for
|
||||
* <ul>
|
||||
* <li>Changing the user status</li>
|
||||
* <li>Logging out</li>
|
||||
* <li>Quitting Envoy</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Kai S. K. Engelbart
|
||||
* @since Envoy Client v0.2-alpha
|
||||
*/
|
||||
public final class StatusTrayIcon implements EventListener {
|
||||
|
||||
/**
|
||||
* The {@link TrayIcon} provided by the System Tray API for controlling the
|
||||
* system tray. This includes displaying the icon, but also creating
|
||||
* notifications when new messages are received.
|
||||
* The {@link TrayIcon} provided by the System Tray API for controlling the system tray. This
|
||||
* includes displaying the icon, but also creating notifications when new messages are received.
|
||||
*/
|
||||
private final TrayIcon trayIcon;
|
||||
|
||||
/**
|
||||
* A received {@link Message} is only displayed as a system tray notification if
|
||||
* this variable is set to {@code true}.
|
||||
* A received {@link Message} is only displayed as a system tray notification if this variable
|
||||
* is set to {@code true}.
|
||||
*/
|
||||
private boolean displayMessages;
|
||||
private boolean displayMessageNotification;
|
||||
|
||||
/**
|
||||
* The Envoy logo on which the current user status and unread message count will be drawn to
|
||||
* compose the tray icon.
|
||||
*/
|
||||
private final Image logo = IconUtil.loadAWTCompatible("/icons/envoy_logo.png")
|
||||
.getScaledInstance(size, size, BufferedImage.SCALE_SMOOTH);
|
||||
|
||||
/**
|
||||
* The size of the tray icon, as defined by the system tray.
|
||||
*/
|
||||
private static final int size = (int) SystemTray.getSystemTray().getTrayIconSize().getWidth();
|
||||
|
||||
/**
|
||||
* @return {@code true} if the status tray icon is supported on this platform
|
||||
@ -41,18 +62,12 @@ public final class StatusTrayIcon implements EventListener {
|
||||
public static boolean isSupported() { return SystemTray.isSupported(); }
|
||||
|
||||
/**
|
||||
* Creates a {@link StatusTrayIcon} with the Envoy logo, a tool tip and a pop-up
|
||||
* menu.
|
||||
* Creates a {@link StatusTrayIcon} with the Envoy logo, a tool tip and a pop-up menu.
|
||||
*
|
||||
* @param stage the stage whose focus determines if message
|
||||
* notifications are displayed
|
||||
* @param stage the stage whose focus determines if message notifications are displayed
|
||||
* @since Envoy Client v0.2-beta
|
||||
*/
|
||||
public StatusTrayIcon(Stage stage) {
|
||||
trayIcon = new TrayIcon(IconUtil.loadAWTCompatible("/icons/envoy_logo.png"), "Envoy");
|
||||
trayIcon.setImageAutoSize(true);
|
||||
trayIcon.setToolTip("You are notified if you have unread messages.");
|
||||
|
||||
final var popup = new PopupMenu();
|
||||
|
||||
// Adding the exit menu item
|
||||
@ -62,26 +77,37 @@ public final class StatusTrayIcon implements EventListener {
|
||||
|
||||
// Adding the logout menu item
|
||||
final var logoutMenuItem = new MenuItem("Logout");
|
||||
logoutMenuItem.addActionListener(evt -> { hide(); Platform.runLater(UserUtil::logout); });
|
||||
logoutMenuItem.addActionListener(evt -> {
|
||||
hide();
|
||||
Platform.runLater(UserUtil::logout);
|
||||
});
|
||||
popup.add(logoutMenuItem);
|
||||
|
||||
// Adding the status change items
|
||||
final var statusSubMenu = new Menu("Change status");
|
||||
for (final var status : UserStatus.values()) {
|
||||
final var statusMenuItem = new MenuItem(status.toString().toLowerCase());
|
||||
statusMenuItem.addActionListener(evt -> Platform.runLater(() -> UserUtil.changeStatus(status)));
|
||||
statusMenuItem
|
||||
.addActionListener(evt -> Platform.runLater(() -> UserUtil.changeStatus(status)));
|
||||
statusSubMenu.add(statusMenuItem);
|
||||
}
|
||||
popup.add(statusSubMenu);
|
||||
|
||||
trayIcon.setPopupMenu(popup);
|
||||
// Initialize the icon
|
||||
trayIcon = new TrayIcon(createImage(), "Envoy", popup);
|
||||
|
||||
// Only display messages if the stage is not focused and the current user status
|
||||
// is not BUSY (if BUSY, displayMessages will be false)
|
||||
stage.focusedProperty().addListener((ov, wasFocused, isFocused) -> displayMessages = !displayMessages && wasFocused ? false : !isFocused);
|
||||
// is not BUSY (if BUSY, displayMessageNotification will be false)
|
||||
stage.focusedProperty()
|
||||
.addListener((ov, wasFocused, isFocused) -> displayMessageNotification =
|
||||
!displayMessageNotification && wasFocused ? false : !isFocused);
|
||||
|
||||
// Show the window if the user clicks on the icon
|
||||
trayIcon.addActionListener(evt -> Platform.runLater(() -> { stage.setIconified(false); stage.toFront(); stage.requestFocus(); }));
|
||||
trayIcon.addActionListener(evt -> Platform.runLater(() -> {
|
||||
stage.setIconified(false);
|
||||
stage.toFront();
|
||||
stage.requestFocus();
|
||||
}));
|
||||
|
||||
// Start processing message events
|
||||
EventBus.getInstance().registerListener(this);
|
||||
@ -95,7 +121,7 @@ public final class StatusTrayIcon implements EventListener {
|
||||
public void show() {
|
||||
try {
|
||||
SystemTray.getSystemTray().add(trayIcon);
|
||||
} catch (final AWTException e) {}
|
||||
} catch (AWTException e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,15 +129,60 @@ public final class StatusTrayIcon implements EventListener {
|
||||
*
|
||||
* @since Envoy Client v0.2-beta
|
||||
*/
|
||||
public void hide() { SystemTray.getSystemTray().remove(trayIcon); }
|
||||
public void hide() {
|
||||
SystemTray.getSystemTray().remove(trayIcon);
|
||||
}
|
||||
|
||||
@Event
|
||||
private void onOwnStatusChange(OwnStatusChange statusChange) { displayMessages = !statusChange.get().equals(UserStatus.BUSY); }
|
||||
private void onOwnStatusChange(OwnStatusChange statusChange) {
|
||||
displayMessageNotification = !statusChange.get().equals(UserStatus.BUSY);
|
||||
trayIcon.getImage().flush();
|
||||
trayIcon.setImage(createImage());
|
||||
}
|
||||
|
||||
@Event
|
||||
private void onMessage(Message message) {
|
||||
if (displayMessages) trayIcon
|
||||
.displayMessage(message.hasAttachment() ? "New " + message.getAttachment().getType().toString().toLowerCase() + " message received"
|
||||
if (displayMessageNotification)
|
||||
trayIcon
|
||||
.displayMessage(message.hasAttachment()
|
||||
? "New " + message.getAttachment().getType().toString().toLowerCase()
|
||||
+ " message received"
|
||||
: "New message received", message.getText(), MessageType.INFO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes an icon that displays the current user status and the amount of unread messages, if
|
||||
* any are present.
|
||||
*
|
||||
* @since Envoy Client v0.3-beta
|
||||
*/
|
||||
private BufferedImage createImage() {
|
||||
|
||||
// Create a new image with the dimensions of the logo
|
||||
var img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
// Obtain the draw graphics of the image and copy the logo
|
||||
var g = img.createGraphics();
|
||||
g.drawImage(logo, 0, 0, null);
|
||||
|
||||
// Draw the current user status
|
||||
switch (Context.getInstance().getLocalDB().getUser().getStatus()) {
|
||||
case ONLINE:
|
||||
g.setColor(Color.GREEN);
|
||||
break;
|
||||
case AWAY:
|
||||
g.setColor(Color.YELLOW);
|
||||
break;
|
||||
case BUSY:
|
||||
g.setColor(Color.RED);
|
||||
break;
|
||||
case OFFLINE:
|
||||
g.setColor(Color.GRAY);
|
||||
}
|
||||
g.fillOval(size / 2, size / 2, size / 2, size / 2);
|
||||
|
||||
// Finish drawing
|
||||
g.dispose();
|
||||
return img;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user