%s
%s :%s",
- dateColor,
- date,
- textColor,
- text,
- state));
-
- return this;
- }
-
- public String toHex(Color c) {
- int r = c.getRed();
- int g = c.getGreen();
- int b = c.getBlue();
- String hex = String.format("#%02x%02x%02x", r, g, b);
- return hex;
- }
+package envoy.client.ui;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.text.SimpleDateFormat;
+
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+
+import envoy.client.Settings;
+import envoy.schema.Message;
+
+/**
+ * Defines how a message is displayed. %s %s :%s",
+ dateColor,
+ date,
+ textColor,
+ text,
+ state));
+ return this;
+ }
+
+ public String toHex(Color c) {
+ int r = c.getRed();
+ int g = c.getGreen();
+ int b = c.getBlue();
+ String hex = String.format("#%02x%02x%02x", r, g, b);
+ return hex;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/envoy/client/ui/SettingsScreen.java b/src/main/java/envoy/client/ui/SettingsScreen.java
index 6d5c94d..d2b2db3 100644
--- a/src/main/java/envoy/client/ui/SettingsScreen.java
+++ b/src/main/java/envoy/client/ui/SettingsScreen.java
@@ -509,4 +509,5 @@ public class SettingsScreen extends JDialog {
colorsPanel.add(panel);
}
+
}
diff --git a/src/main/java/envoy/client/ui/Startup.java b/src/main/java/envoy/client/ui/Startup.java
index f940191..25af819 100644
--- a/src/main/java/envoy/client/ui/Startup.java
+++ b/src/main/java/envoy/client/ui/Startup.java
@@ -3,6 +3,8 @@ package envoy.client.ui;
import java.awt.EventQueue;
import java.io.IOException;
import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.swing.JOptionPane;
@@ -26,29 +28,35 @@ import envoy.exception.EnvoyException;
*/
public class Startup {
+ private static final Logger logger = Logger.getLogger(Startup.class.getSimpleName());
+
public static void main(String[] args) {
+ logger.setLevel(Level.ALL);
+
Config config = Config.getInstance();
- if (args.length > 0) {
- config.load(args);
- } else {
- ClassLoader loader = Thread.currentThread().getContextClassLoader();
- try {
- Properties configProperties = new Properties();
- configProperties.load(loader.getResourceAsStream("client.properties"));
- config.load(configProperties);
- } catch (IOException e) {
- e.printStackTrace();
- }
+
+ // Load the configuration from client.properties first
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ try {
+ Properties configProperties = new Properties();
+ configProperties.load(loader.getResourceAsStream("client.properties"));
+ config.load(configProperties);
+ } catch (IOException e) {
+ e.printStackTrace();
}
+ // Override configuration values with command line arguments
+ if (args.length > 0) config.load(args);
+
if (!config.isInitialized()) {
- System.err.println("Server or port are not defined. Exiting...");
+ logger.severe("Server or port are not defined. Exiting...");
+ JOptionPane.showMessageDialog(null, "Error loading configuration values.", "Configuration error", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
String userName = JOptionPane.showInputDialog("Please enter your username");
if (userName == null || userName.isEmpty()) {
- System.err.println("User name is not set or empty. Exiting...");
+ logger.severe("User name is not set or empty. Exiting...");
System.exit(1);
}
Client client = new Client(config, userName);
@@ -66,8 +74,9 @@ public class Startup {
EventQueue.invokeLater(() -> {
try {
- ChatWindow frame = new ChatWindow(client, localDB);
- frame.setVisible(true);
+ ChatWindow chatWindow = new ChatWindow(client, localDB);
+ new StatusTrayIcon(chatWindow).show();
+ chatWindow.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
diff --git a/src/main/java/envoy/client/ui/StatusTrayIcon.java b/src/main/java/envoy/client/ui/StatusTrayIcon.java
new file mode 100644
index 0000000..01cc8d7
--- /dev/null
+++ b/src/main/java/envoy/client/ui/StatusTrayIcon.java
@@ -0,0 +1,133 @@
+package envoy.client.ui;
+
+import java.awt.AWTException;
+import java.awt.Image;
+import java.awt.MenuItem;
+import java.awt.PopupMenu;
+import java.awt.SystemTray;
+import java.awt.Toolkit;
+import java.awt.TrayIcon;
+import java.awt.TrayIcon.MessageType;
+import java.awt.Window;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.HashSet;
+import java.util.Set;
+
+import envoy.client.event.Event;
+import envoy.client.event.EventBus;
+import envoy.client.event.EventHandler;
+import envoy.client.event.MessageCreationEvent;
+import envoy.exception.EnvoyException;
+import envoy.schema.Message;
+
+/**
+ * Project: envoy-client %s %s",
- status,
- textColor,
- name));
- break;
-
- case OFFLINE:
- setText(String.format(
- " %s %s",
- status,
- textColor,
- name));
- break;
- }
-
-
-
- return this;
- }
-
- public String toHex(Color c) {
- int r = c.getRed();
- int g = c.getGreen();
- int b = c.getBlue();
- String hex = String.format("#%02x%02x%02x", r, g, b);
- return hex;
- }
+package envoy.client.ui;
+
+import java.awt.Color;
+import java.awt.Component;
+
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+
+import envoy.client.Settings;
+import envoy.schema.User;
+import envoy.schema.User.UserStatus;
+
+/**
+ * Defines how the {@code UserList} is displayed.
+ *
+ * Project: envoy-client %s %s",
+ status,
+ textColor,
+ name));
+ break;
+ case OFFLINE:
+ setText(String.format(
+ " %s %s",
+ status,
+ textColor,
+ name));
+ break;
+ }
+ return this;
+ }
+
+ public String toHex(Color c) {
+ int r = c.getRed();
+ int g = c.getGreen();
+ int b = c.getBlue();
+ String hex = String.format("#%02x%02x%02x", r, g, b);
+ return hex;
+ }
}
\ No newline at end of file
diff --git a/src/main/resources/envoy_logo.png b/src/main/resources/envoy_logo.png
new file mode 100644
index 0000000..1606bd5
Binary files /dev/null and b/src/main/resources/envoy_logo.png differ
diff --git a/src/main/resources/envoy_logo_alpha.png b/src/main/resources/envoy_logo_alpha.png
new file mode 100644
index 0000000..f1040c5
Binary files /dev/null and b/src/main/resources/envoy_logo_alpha.png differ
diff --git a/src/main/resources/envoy_logo_old.png b/src/main/resources/envoy_logo_old.png
new file mode 100644
index 0000000..35ef7d9
Binary files /dev/null and b/src/main/resources/envoy_logo_old.png differ
+ *
+ *
+ * Project: envoy-client
+ * File: UserListRenderer.java
+ * Created: 19 Oct 2019
+ *
+ * @author Kai S. K. Engelbart
+ * @author Maximilian Käfer
+ * @since Envoy v0.1-alpha
+ */
+public class MessageListRenderer extends JLabel implements ListCellRenderer
+ * File: StatusTrayIcon.java
+ * Created: 3 Dec 2019
+ *
+ * @author Kai S. K. Engelbart
+ * @since Envoy v0.2-alpha
+ */
+public class StatusTrayIcon implements EventHandler {
+
+ /**
+ * 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 TrayIcon trayIcon;
+
+ /**
+ * A received {@link Message} is only displayed as a system tray notification if
+ * this variable is set to {@code true}.
+ */
+ private boolean displayMessages = false;
+
+ /**
+ * Creates a {@link StatusTrayIcon} with the Envoy logo, a tool tip and a pop-up
+ * menu.
+ *
+ * @param focusTarget the {@link Window} which focus determines if message
+ * notifications are displayed
+ * @throws EnvoyException if the currently used OS does not support the System
+ * Tray API
+ * @since Envoy v0.2-alpha
+ */
+ public StatusTrayIcon(Window focusTarget) throws EnvoyException {
+ if (!SystemTray.isSupported()) throw new EnvoyException("The Envoy tray icon is not supported.");
+
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ Image img = Toolkit.getDefaultToolkit().createImage(loader.getResource("envoy_logo.png"));
+ trayIcon = new TrayIcon(img, "Envoy Client");
+ trayIcon.setImageAutoSize(true);
+ trayIcon.setToolTip("You are notified if you have unread messages.");
+
+ PopupMenu popup = new PopupMenu();
+
+ MenuItem exitMenuItem = new MenuItem("Exit");
+ exitMenuItem.addActionListener((evt) -> System.exit(0));
+ popup.add(exitMenuItem);
+
+ trayIcon.setPopupMenu(popup);
+
+ // Only display messages if the chat window is not focused
+ focusTarget.addWindowFocusListener(new WindowAdapter() {
+
+ @Override
+ public void windowGainedFocus(WindowEvent e) {
+ displayMessages = false;
+ }
+
+ @Override
+ public void windowLostFocus(WindowEvent e) {
+ displayMessages = true;
+ }
+ });
+
+ // Start processing message events
+ EventBus.getInstance().register(this);
+ }
+
+ /**
+ * Makes this {@link StatusTrayIcon} appear in the system tray.
+ *
+ * @throws EnvoyException if the status icon could not be attaches to the system
+ * tray for system-internal reasons
+ * @since Envoy v0.2-alpha
+ */
+ public void show() throws EnvoyException {
+ try {
+ SystemTray.getSystemTray().add(trayIcon);
+ } catch (AWTException e) {
+ throw new EnvoyException("Could not attach Envoy tray icon to system tray.", e);
+ }
+ }
+
+ /**
+ * Notifies the user of a message by displaying a pop-up every time a new
+ * message is received.
+ *
+ * @since Envoy v0.2-alpha
+ */
+ @Override
+ public void handle(Event> event) {
+ System.out.println("Message received. Displaying message: " + displayMessages);
+ if (displayMessages)
+ trayIcon.displayMessage("New message received", ((MessageCreationEvent) event).get().getContent().get(0).getText(), MessageType.INFO);
+ }
+
+ /**
+ * The {@link StatusTrayIcon} only reacts to {@link MessageCreationEvent}
+ * instances which signify newly received messages.
+ *
+ * @return A set with the single element {@code MessageCreationEvent.class}
+ * @since Envoy v0.2-alpha
+ */
+ @Override
+ public Set
- * File: UserListRenderer.java
- * Created: 12 Oct 2019
- *
- * @author Kai S. K. Engelbart
- * @author Maximilian Käfer
- * @since Envoy v0.1-alpha
- */
-public class UserListRenderer extends JLabel implements ListCellRenderer
+ * File: UserListRenderer.java
+ * Created: 12 Oct 2019
+ *
+ * @author Kai S. K. Engelbart
+ * @author Maximilian Käfer
+ * @since Envoy v0.1-alpha
+ */
+public class UserListRenderer extends JLabel implements ListCellRenderer