diff --git a/client/src/main/java/envoy/client/ui/StatusTrayIcon.java b/client/src/main/java/envoy/client/ui/StatusTrayIcon.java
index cf0fcb0..aac73db 100644
--- a/client/src/main/java/envoy/client/ui/StatusTrayIcon.java
+++ b/client/src/main/java/envoy/client/ui/StatusTrayIcon.java
@@ -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
+ *
+ * - Changing the user status
+ * - Logging out
+ * - Quitting Envoy
+ *
+ *
* @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;
+ }
}