From 418a60c0748979c7a6fb1a8965cd08188d608d50 Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sat, 7 Dec 2019 22:48:12 +0100 Subject: [PATCH 01/24] Primary Button Took primaryButton class from corresponding branch. Implemented constructors in ChatWindow. --- src/main/java/envoy/client/ui/ChatWindow.java | 9 ++- .../java/envoy/client/ui/PrimaryButton.java | 61 +++++++++++++++++++ 2 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 src/main/java/envoy/client/ui/PrimaryButton.java diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 6867f5e..7b38a3e 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -15,7 +15,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.DefaultListModel; -import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JOptionPane; @@ -63,8 +62,8 @@ public class ChatWindow extends JFrame { private JScrollPane scrollPane = new JScrollPane(); private JTextPane textPane = new JTextPane(); // private JCheckBox jCbChangeMode; - private JButton postButton = new JButton("Post"); - private JButton settingsButton = new JButton("Settings"); + private PrimaryButton postButton; + private PrimaryButton settingsButton; private static int space = 4; @@ -155,7 +154,7 @@ public class ChatWindow extends JFrame { contentPane.add(messageEnterTextArea, gbc_messageEnterTextfield); // Post Button - postButton.setBorderPainted(false); + postButton = new PrimaryButton("Post"); GridBagConstraints gbc_moveSelectionPostButton = new GridBagConstraints(); gbc_moveSelectionPostButton.fill = GridBagConstraints.BOTH; @@ -168,7 +167,7 @@ public class ChatWindow extends JFrame { contentPane.add(postButton, gbc_moveSelectionPostButton); // Settings Button - settingsButton.setBorderPainted(false); + settingsButton = new PrimaryButton("Settings"); GridBagConstraints gbc_moveSelectionSettingsButton = new GridBagConstraints(); diff --git a/src/main/java/envoy/client/ui/PrimaryButton.java b/src/main/java/envoy/client/ui/PrimaryButton.java new file mode 100644 index 0000000..06df82f --- /dev/null +++ b/src/main/java/envoy/client/ui/PrimaryButton.java @@ -0,0 +1,61 @@ +package envoy.client.ui; + +import java.awt.Graphics; + +import javax.swing.JButton; + +/** + * Project: envoy-clientChess
+ * File: PrimaryButton.javaEvent.java
+ * Created: 07.12.2019
+ * + * @author Kai S. K. Engelbart + */ +public class PrimaryButton extends JButton { + + private static final long serialVersionUID = 3662266120667728364L; + + private int arcSize; + + /** + * Creates a primary button with a white text color and a purple background + * color. + * + * @param title the title of the button + */ + public PrimaryButton(String title) { this(title, 6); } + + /** + * Creates a primary button with a white text color and a purple background + * color. + * + * @param title the title of the button + * @param the size of the arc used to draw the round button edges + */ + public PrimaryButton(String title, int arcSize) { + super(title); + // setForeground(new Color(255, 255, 255)); + // setBackground(new Color(102, 51, 153)); + setBorderPainted(false); + setFocusPainted(false); + setContentAreaFilled(false); + this.arcSize = arcSize; + } + + @Override + protected void paintComponent(Graphics g) { + g.setColor(getBackground()); + g.fillRoundRect(0, 0, getWidth(), getHeight(), arcSize, arcSize); + super.paintComponent(g); + } + + /** + * @return the arcSize + */ + public int getArcSize() { return arcSize; } + + /** + * @param arcSize the arcSize to set + */ + public void setArcSize(int arcSize) { this.arcSize = arcSize; } +} \ No newline at end of file From ecf25664312dd5e552198119d4a16974240cf930 Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sat, 7 Dec 2019 23:23:25 +0100 Subject: [PATCH 02/24] Primary TextArea * Added PrimaryTextArea Class * Implemented PrimaryTextArea in ChatWindow (messageEnterArea) * Made some slight adjustments to the PrimaryButton Class --- src/main/java/envoy/client/ui/ChatWindow.java | 13 ++-- .../java/envoy/client/ui/PrimaryButton.java | 13 ++-- .../java/envoy/client/ui/PrimaryTextArea.java | 67 +++++++++++++++++++ 3 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 src/main/java/envoy/client/ui/PrimaryTextArea.java diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 7b38a3e..14065b0 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -20,7 +20,6 @@ import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; -import javax.swing.JTextArea; import javax.swing.JTextPane; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; @@ -55,7 +54,7 @@ public class ChatWindow extends JFrame { private LocalDB localDB; // GUI components private JPanel contentPane = new JPanel(); - private JTextArea messageEnterTextArea = new JTextArea(); + private PrimaryTextArea messageEnterTextArea; private JList userList = new JList<>(); private Chat currentChat; private JList messageList = new JList<>(); @@ -125,6 +124,9 @@ public class ChatWindow extends JFrame { gbc_scrollPane.insets = new Insets(space, space, space, space); contentPane.add(scrollPane, gbc_scrollPane); + // Checks for changed Message + messageEnterTextArea = new PrimaryTextArea(space); + // Message enter field messageEnterTextArea.addKeyListener(new KeyAdapter() { @@ -137,12 +139,7 @@ public class ChatWindow extends JFrame { } } }); - // Checks for changed Message - messageEnterTextArea.setWrapStyleWord(true); - messageEnterTextArea.setLineWrap(true); - messageEnterTextArea.setBorder(null); - messageEnterTextArea.setFont(new Font("Arial", Font.PLAIN, 17)); - messageEnterTextArea.setBorder(new EmptyBorder(space, space, space, space)); + GridBagConstraints gbc_messageEnterTextfield = new GridBagConstraints(); gbc_messageEnterTextfield.fill = GridBagConstraints.BOTH; diff --git a/src/main/java/envoy/client/ui/PrimaryButton.java b/src/main/java/envoy/client/ui/PrimaryButton.java index 06df82f..2e528db 100644 --- a/src/main/java/envoy/client/ui/PrimaryButton.java +++ b/src/main/java/envoy/client/ui/PrimaryButton.java @@ -5,11 +5,12 @@ import java.awt.Graphics; import javax.swing.JButton; /** - * Project: envoy-clientChess
+ * Project: envoy-client
* File: PrimaryButton.javaEvent.java
* Created: 07.12.2019
* * @author Kai S. K. Engelbart + * @author Maximilian Käfer */ public class PrimaryButton extends JButton { @@ -18,19 +19,19 @@ public class PrimaryButton extends JButton { private int arcSize; /** - * Creates a primary button with a white text color and a purple background - * color. + * Creates a primary button * * @param title the title of the button + * @since Envoy 0.2-alpha */ public PrimaryButton(String title) { this(title, 6); } /** - * Creates a primary button with a white text color and a purple background - * color. + * Creates a primary button * * @param title the title of the button * @param the size of the arc used to draw the round button edges + * @since Envoy 0.2-alpha */ public PrimaryButton(String title, int arcSize) { super(title); @@ -51,11 +52,13 @@ public class PrimaryButton extends JButton { /** * @return the arcSize + * @since Envoy 0.2-alpha */ public int getArcSize() { return arcSize; } /** * @param arcSize the arcSize to set + * @since Envoy 0.2-alpha */ public void setArcSize(int arcSize) { this.arcSize = arcSize; } } \ No newline at end of file diff --git a/src/main/java/envoy/client/ui/PrimaryTextArea.java b/src/main/java/envoy/client/ui/PrimaryTextArea.java new file mode 100644 index 0000000..3f350ed --- /dev/null +++ b/src/main/java/envoy/client/ui/PrimaryTextArea.java @@ -0,0 +1,67 @@ +package envoy.client.ui; + +import java.awt.Font; +import java.awt.Graphics; + +import javax.swing.JTextArea; +import javax.swing.border.EmptyBorder; + +/** + * Project: envoy-client
+ * File: PrimaryTextArea.javaEvent.java
+ * Created: 07.12.2019
+ * + * @author Maximilian Käfer + */ +public class PrimaryTextArea extends JTextArea { + + private static final long serialVersionUID = 1L; + + private int arcSize; + + /** + * Creates TextArea + * + * @param borderSpace + * @since Envoy 0.2-alpha + */ + public PrimaryTextArea(int borderSpace) { this(6, borderSpace); } + + /** + * Creates TextArea + * + * @param arcSize + * @param borderSpace + * @since Envoy 0.2-alpha + */ + public PrimaryTextArea(int arcSize, int borderSpace) { + super(); + setWrapStyleWord(true); + setLineWrap(true); + setBorder(null); + setFont(new Font("Arial", Font.PLAIN, 17)); + setBorder(new EmptyBorder(borderSpace, borderSpace, borderSpace, borderSpace)); + setOpaque(false); + + this.arcSize = arcSize; + } + + @Override + protected void paintComponent(Graphics g) { + g.setColor(getBackground()); + g.fillRoundRect(0, 0, getWidth(), getHeight(), arcSize, arcSize); + super.paintComponent(g); + } + + /** + * @return the arcSize + * @since Envoy 0.2-alpha + */ + public int getArcSize() { return arcSize; } + + /** + * @param arcSize the arcSize to set + * @since Envoy 0.2-alpha + */ + public void setArcSize(int arcSize) { this.arcSize = arcSize; } +} From 0f64ce0a016e137320a4c3e274d9258524eb9ec9 Mon Sep 17 00:00:00 2001 From: kske Date: Wed, 11 Dec 2019 18:52:30 +0100 Subject: [PATCH 03/24] Added offline mode to Client + Saving the user ID in Settings + Loading the user ID from Settings in Client if the server can't be reached --- src/main/java/envoy/client/Client.java | 63 ++++++++++++---------- src/main/java/envoy/client/Settings.java | 25 ++++++--- src/main/java/envoy/client/ui/Startup.java | 21 ++++++-- 3 files changed, 73 insertions(+), 36 deletions(-) diff --git a/src/main/java/envoy/client/Client.java b/src/main/java/envoy/client/Client.java index 8f96739..a6a7f36 100644 --- a/src/main/java/envoy/client/Client.java +++ b/src/main/java/envoy/client/Client.java @@ -10,6 +10,7 @@ import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; +import envoy.exception.EnvoyException; import envoy.schema.ObjectFactory; import envoy.schema.Sync; import envoy.schema.User; @@ -29,14 +30,18 @@ public class Client { private ObjectFactory objectFactory = new ObjectFactory(); private Config config; private User sender, recipient; + private boolean online = false; private static final Logger logger = Logger.getLogger(Client.class.getSimpleName()); - public Client(Config config, String username) { + public Client(Config config, String userName) throws EnvoyException { this.config = config; - sender = getUser(username); - - logger.info("ID: " + sender.getID()); + sender = getUser(userName); + + // Update the user ID in the cache + Settings.getInstance().setUserID(sender.getID()); + + logger.info("Client user ID: " + sender.getID()); } private R post(String uri, T body, Class responseBodyClass) { @@ -48,7 +53,6 @@ public class Client { client.close(); return responseBody; - } /** @@ -63,9 +67,7 @@ public class Client { user.setID(-1); sendSync.getUsers().add(user); - Sync returnSendSync = post( - String - .format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), 0), + Sync returnSendSync = post(String.format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), 0), sendSync, Sync.class); return returnSendSync; @@ -77,29 +79,33 @@ public class Client { * * @param name - the name of the {@link User} * @return a {@link User} with the specified name + * @throws EnvoyException if the server does not return the requested ID * @since Envoy v0.1-alpha */ - private User getUser(String name) { + private User getUser(String name) throws EnvoyException { + // Create a sync with only a user with the requested name Sync senderSync = objectFactory.createSync(); User user = objectFactory.createUser(); user.setName(name); senderSync.getUsers().add(user); - Sync returnSenderSync = post( - String - .format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), 0), - senderSync, - Sync.class); + try { + Sync sync = post(String.format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), 0), + senderSync, + Sync.class); - User returnSender = objectFactory.createUser(); - - if (returnSenderSync.getUsers().size() == 1) { - returnSender = returnSenderSync.getUsers().get(0); - } else { - logger.warning("ERROR exiting..."); + // Expecting a single user with an ID + if (sync.getUsers().size() == 1) { + online = true; + return sync.getUsers().get(0); + } else throw new EnvoyException("Unexpected response from Envoy Server"); + } catch (Exception e) { + logger.warning("Could not connect to server, trying offline mode."); + if (Settings.getInstance().getUserID() != -1) { + user.setID(Settings.getInstance().getUserID()); + return user; + } else throw new EnvoyException("Could not enter offline mode."); } - - return returnSender; } /** @@ -134,7 +140,8 @@ public class Client { * their updated UserStatus to the client.)
* * @param userId the id of the {@link Client} who sends the {@link Sync} - * @param sync the sync object (yet to be converted from java class to sync.xml) + * @param sync the sync object (yet to be converted from java class to + * sync.xml) * @return a returnSync.xml file * @since Envoy v0.1-alpha */ @@ -151,10 +158,7 @@ public class Client { } // Send sync - return post(String - .format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), userId), - sync, - Sync.class); + return post(String.format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), userId), sync, Sync.class); } /** @@ -182,4 +186,9 @@ public class Client { * @since Envoy v0.1-alpha */ public boolean hasRecipient() { return recipient != null; } + + /** + * @return {@code true} if a connection to the server could be established + */ + public boolean isOnline() { return online; } } diff --git a/src/main/java/envoy/client/Settings.java b/src/main/java/envoy/client/Settings.java index 91f696f..851c936 100644 --- a/src/main/java/envoy/client/Settings.java +++ b/src/main/java/envoy/client/Settings.java @@ -27,6 +27,7 @@ public class Settings { // Actual settings accessible by the rest of the application private String username; + private long userID; private String email; private boolean enterToSend = true; private Map themes; @@ -66,6 +67,7 @@ public class Settings { @SuppressWarnings("unchecked") private void load() { setUsername(prefs.get("username", "")); + setUserID(prefs.getLong("userID", -1)); setEmail(prefs.get("email", "")); setEnterToSend(prefs.getBoolean("enterToSend", true)); setCurrentTheme(prefs.get("theme", "dark")); @@ -73,9 +75,9 @@ public class Settings { // Load themes from theme file try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(themeFile))) { Object obj = in.readObject(); - if(obj instanceof HashMap) themes = (Map) obj; + if (obj instanceof HashMap) themes = (Map) obj; } catch (IOException | ClassNotFoundException e) { - themes = new HashMap<>(); + themes = new HashMap<>(); currentTheme = "dark"; e.printStackTrace(); } @@ -90,20 +92,21 @@ public class Settings { } /** - * updates prefs when save button is clicked + * Updates the preferences when the save button is clicked. * * @throws IOException * @since Envoy v0.2-alpha */ - public void save() throws IOException{ + public void save() throws IOException { prefs.put("username", getUsername()); + prefs.putLong("userID", getUserID()); prefs.put("email", getEmail()); prefs.put("theme", currentTheme); prefs.putBoolean("enterToSend", isEnterToSend()); - + // Save themes to theme file themeFile.createNewFile(); - try(ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(themeFile))) { + try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(themeFile))) { out.writeObject(themes); } } @@ -145,6 +148,16 @@ public class Settings { */ public void setUsername(String username) { this.username = username; } + /** + * @return the userID + */ + public long getUserID() { return userID; } + + /** + * @param userID the userID to set + */ + public void setUserID(long userID) { this.userID = userID; } + /** * @return the email associated with that user. * @since Envoy v0.2-alpha diff --git a/src/main/java/envoy/client/ui/Startup.java b/src/main/java/envoy/client/ui/Startup.java index edd5aa2..c8373ed 100644 --- a/src/main/java/envoy/client/ui/Startup.java +++ b/src/main/java/envoy/client/ui/Startup.java @@ -16,7 +16,7 @@ import envoy.exception.EnvoyException; /** * Starts the Envoy client and prompts the user to enter their name. - * + *
* Project: envoy-client
* File: Startup.java
* Created: 12 Oct 2019
@@ -48,19 +48,34 @@ public class Startup { // Override configuration values with command line arguments if (args.length > 0) config.load(args); + // Check if all configuration values have been initialized if (!config.isInitialized()) { logger.severe("Server or port are not defined. Exiting..."); JOptionPane.showMessageDialog(null, "Error loading configuration values.", "Configuration error", JOptionPane.ERROR_MESSAGE); System.exit(1); } + // Ask the user for their user name String userName = JOptionPane.showInputDialog("Please enter your username"); if (userName == null || userName.isEmpty()) { logger.severe("User name is not set or empty. Exiting..."); System.exit(1); } - Client client = new Client(config, userName); - LocalDB localDB = new LocalDB(client.getSender()); + + // Acquire the client user (with ID) either from the server or from the local + // cache (Preferences), which triggers offline mode + Client client; + try { + client = new Client(config, userName); + } catch (Exception e1) { + logger.log(Level.SEVERE, "Failed to acquire client user ID", e1); + JOptionPane.showMessageDialog(null, e1.toString(), "Client error", JOptionPane.ERROR_MESSAGE); + System.exit(1); + return; + } + + // Load the local database + LocalDB localDB = new LocalDB(client.getSender()); try { localDB.initializeDBFile(config.getLocalDB()); } catch (EnvoyException e) { From e69deb9bd68e955d52f6bdfd29ff9fb96e7d184a Mon Sep 17 00:00:00 2001 From: kske Date: Fri, 13 Dec 2019 08:50:15 +0100 Subject: [PATCH 04/24] Moved client.properties loading from Startup to Config --- src/main/java/envoy/client/Config.java | 38 ++++++++++++++-------- src/main/java/envoy/client/ui/Startup.java | 25 +++++--------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/main/java/envoy/client/Config.java b/src/main/java/envoy/client/Config.java index bbd3b72..0c3a000 100644 --- a/src/main/java/envoy/client/Config.java +++ b/src/main/java/envoy/client/Config.java @@ -3,6 +3,8 @@ package envoy.client; import java.io.File; import java.util.Properties; +import envoy.exception.EnvoyException; + /** * Project: envoy-client
* File: Config.java
@@ -29,17 +31,26 @@ public class Config { /** * Defaults to the {@code client.properties} file for information. + * This file contains information about + * the server and port, as well as the path to the local + * database and the synchronization timeout * - * @param properties a {@link Properties} object containing information about - * the server and port, as well as the path to the local - * database and the synchronization timeout + * @throws EnvoyException if the {@code client.properties} file could not be + * loaded * @since Envoy v0.1-alpha */ - public void load(Properties properties) { - if (properties.containsKey("server")) server = properties.getProperty("server"); - if (properties.containsKey("port")) port = Integer.parseInt(properties.getProperty("port")); - localDB = new File(properties.getProperty("localDB", ".\\localDB")); - syncTimeout = Integer.parseInt(properties.getProperty("syncTimeout", "1000")); + public void load() throws EnvoyException { + ClassLoader loader = getClass().getClassLoader(); + try { + Properties properties = new Properties(); + properties.load(loader.getResourceAsStream("client.properties")); + if (properties.containsKey("server")) server = properties.getProperty("server"); + if (properties.containsKey("port")) port = Integer.parseInt(properties.getProperty("port")); + localDB = new File(properties.getProperty("localDB", ".\\localDB")); + syncTimeout = Integer.parseInt(properties.getProperty("syncTimeout", "1000")); + } catch (Exception e) { + throw new EnvoyException("Failed to load client.properties", e); + } } /** @@ -47,9 +58,10 @@ public class Config { * -s, --port / -p and --localDB / -db. * * @param args the command line arguments to parse + * @throws EnvoyException if the command line arguments contain an unknown token * @since Envoy v0.1-alpha */ - public void load(String[] args) { + public void load(String[] args) throws EnvoyException { for (int i = 0; i < args.length; i++) switch (args[i]) { case "--server": @@ -64,6 +76,8 @@ public class Config { case "-db": localDB = new File(args[++i]); break; + default: + throw new EnvoyException("Unknown token " + args[i] + " found"); } } @@ -71,9 +85,7 @@ public class Config { * @return {@code true} if server, port and localDB directory are known. * @since Envoy v0.1-alpha */ - public boolean isInitialized() { - return server != null && !server.isEmpty() && port > 0 && port < 65566 && localDB != null; - } + public boolean isInitialized() { return server != null && !server.isEmpty() && port > 0 && port < 65566 && localDB != null; } /** * @return the host name of the Envoy server @@ -114,7 +126,7 @@ public class Config { /** * Changes the default local database. * Exclusively intended for development purposes. - * + * * @param localDB the file containing the local database * @since Envoy v0.1-alpha **/ diff --git a/src/main/java/envoy/client/ui/Startup.java b/src/main/java/envoy/client/ui/Startup.java index c8373ed..48ce399 100644 --- a/src/main/java/envoy/client/ui/Startup.java +++ b/src/main/java/envoy/client/ui/Startup.java @@ -1,8 +1,6 @@ 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; @@ -35,24 +33,19 @@ public class Startup { Config config = Config.getInstance(); - // 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(); - } + // Load the configuration from client.properties first + config.load(); - // Override configuration values with command line arguments - if (args.length > 0) config.load(args); + // Override configuration values with command line arguments + if (args.length > 0) config.load(args); - // Check if all configuration values have been initialized - if (!config.isInitialized()) { - logger.severe("Server or port are not defined. Exiting..."); - JOptionPane.showMessageDialog(null, "Error loading configuration values.", "Configuration error", JOptionPane.ERROR_MESSAGE); + // Check if all configuration values have been initialized + if (!config.isInitialized()) throw new EnvoyException("Server or port are not defined"); + } catch (Exception e) { + JOptionPane.showMessageDialog(null, "Error loading configuration values: \n" + e.toString(), "Configuration error", JOptionPane.ERROR_MESSAGE); System.exit(1); + e.printStackTrace(); } // Ask the user for their user name From 2b1ece1c48d1f7758b9e4cf878b5c1b4a1590a69 Mon Sep 17 00:00:00 2001 From: kske Date: Sat, 14 Dec 2019 08:44:03 +0100 Subject: [PATCH 05/24] Added user list serialization to LocalDB * Added user list to LocalDB * Removed client user from LocalDB constructor --- src/main/java/envoy/client/LocalDB.java | 108 +++++++++++++----- src/main/java/envoy/client/ui/ChatWindow.java | 2 +- src/main/java/envoy/client/ui/Startup.java | 3 +- 3 files changed, 80 insertions(+), 33 deletions(-) diff --git a/src/main/java/envoy/client/LocalDB.java b/src/main/java/envoy/client/LocalDB.java index f061b28..2ab33ed 100644 --- a/src/main/java/envoy/client/LocalDB.java +++ b/src/main/java/envoy/client/LocalDB.java @@ -34,9 +34,11 @@ import envoy.schema.User; */ public class LocalDB { - private File localDB; - private User sender; - private List chats = new ArrayList<>(); + private File localDBFile, usersFile; + private User user; + private List users = new ArrayList<>(); + private List chats = new ArrayList<>(); + private ObjectFactory objectFactory = new ObjectFactory(); private DatatypeFactory datatypeFactory; @@ -44,16 +46,15 @@ public class LocalDB { private Sync sync = objectFactory.createSync(); private Sync readMessages = objectFactory.createSync(); - private static final Logger logger = Logger.getLogger(LocalDB.class.getSimpleName()); + private static final Logger logger = Logger.getLogger(LocalDB.class.getSimpleName()); /** - * Constructs an empty local database. + * Constructs an empty local database. To serialize any chats to the file + * system, call {@link LocalDB#initializeDBFile(File)}. * - * @param sender the user that is logged in with this client * @since Envoy v0.1-alpha */ - public LocalDB(User sender) { - this.sender = sender; + public LocalDB() { try { datatypeFactory = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException e) { @@ -70,10 +71,17 @@ public class LocalDB { * @since Envoy v0.1-alpha */ public void initializeDBFile(File localDBDir) throws EnvoyException { + if (user == null) throw new NullPointerException("Client user is null"); if (localDBDir.exists() && !localDBDir.isDirectory()) throw new EnvoyException(String.format("LocalDBDir '%s' is not a directory!", localDBDir.getAbsolutePath())); - localDB = new File(localDBDir, sender.getID() + ".db"); - if (localDB.exists()) loadFromLocalDB(); + usersFile = new File(localDBDir, "users.db"); + localDBFile = new File(localDBDir, user.getID() + ".db"); + try { + loadUsers(); + loadChats(); + } catch (ClassNotFoundException | IOException e) { + throw new EnvoyException(e); + } } /** @@ -82,29 +90,46 @@ public class LocalDB { * @throws IOException if something went wrong during saving * @since Envoy v0.1-alpha */ - public void saveToLocalDB() throws IOException { - localDB.getParentFile().mkdirs(); - localDB.createNewFile(); - try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(localDB))) { - out.writeObject(chats); - } catch (IOException ex) { - throw ex; - } + public void save() throws IOException { + // Save users + write(usersFile, users); + + // Save chats + write(localDBFile, chats); } + @SuppressWarnings("unchecked") + private void loadUsers() throws ClassNotFoundException, IOException { users = read(usersFile, ArrayList.class); } + /** * Loads all chats saved by Envoy for the client user. * - * @throws EnvoyException if something fails while loading. + * @throws EnvoyException if something fails while loading. + * @throws IOException + * @throws ClassNotFoundException * @since Envoy v0.1-alpha */ @SuppressWarnings("unchecked") - private void loadFromLocalDB() throws EnvoyException { - try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(localDB))) { - Object obj = in.readObject(); - if (obj instanceof ArrayList) chats = (ArrayList) obj; + private void loadChats() throws ClassNotFoundException, IOException { chats = read(localDBFile, ArrayList.class); } + + private T read(File file, Class serializedClass) throws ClassNotFoundException, IOException { + try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(file))) { + return serializedClass.cast(in.readObject()); } catch (ClassNotFoundException | IOException e) { - throw new EnvoyException(e); + throw e; + } + } + + private void write(File file, T obj) throws IOException { + if (file == null) throw new NullPointerException("File is null"); + if (!file.exists()) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file))) { + out.writeObject(obj); + } catch (IOException e) { + throw e; } } @@ -118,7 +143,7 @@ public class LocalDB { */ public Message createMessage(String textContent, long recipientID) { Message.Metadata metaData = objectFactory.createMessageMetadata(); - metaData.setSender(sender.getID()); + metaData.setSender(user.getID()); metaData.setRecipient(recipientID); metaData.setState(MessageState.WAITING); metaData.setDate(datatypeFactory.newXMLGregorianCalendar(Instant.now().toString())); @@ -134,13 +159,13 @@ public class LocalDB { return message; } - /** + /** * Creates a {@link Sync} object filled with the changes that occurred to the * local database since the last synchronization. * * @param userId the ID of the user that is synchronized by this client * @return {@link Sync} object filled with the current changes - * @since Envoy v0.1-alpha + * @since Envoy v0.1-alpha */ public Sync fillSync(long userId) { addWaitingMessagesToSync(); @@ -156,7 +181,7 @@ public class LocalDB { * Applies the changes carried by a {@link Sync} object to the local database * * @param returnSync the {@link Sync} object to apply - * @since Envoy v0.1-alpha + * @since Envoy v0.1-alpha */ public void applySync(Sync returnSync) { for (int i = 0; i < returnSync.getMessages().size(); i++) { @@ -280,6 +305,16 @@ public class LocalDB { */ public void clearUnreadMessagesSync() { unreadMessagesSync.getMessages().clear(); } + /** + * @return the users + */ + public List getUsers() { return users; } + + /** + * @param users the users to set + */ + public void setUsers(List users) { this.users = users; } + /** * @return all saved {@link Chat} objects that list the client user as the * sender @@ -288,8 +323,19 @@ public class LocalDB { public List getChats() { return chats; } /** - * @return the {@link User} who initialized the local database - * @since Envoy v0.1-alpha + * @param chats the chats to set */ - public User getUser() { return sender; } + public void setChats(List chats) { this.chats = chats; } + + /** + * @return the {@link User} who initialized the local database + * @since Envoy v0.2-alpha + */ + public User getUser() { return user; } + + /** + * @param user the user to set + * @since Envoy v0.2-alpha + */ + public void setUser(User user) { this.user = user; } } diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 6867f5e..ee32bf6 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -86,7 +86,7 @@ public class ChatWindow extends JFrame { @Override public void windowClosing(WindowEvent evt) { try { - localDB.saveToLocalDB(); + localDB.save(); Settings.getInstance().save(); } catch (IOException e1) { e1.printStackTrace(); diff --git a/src/main/java/envoy/client/ui/Startup.java b/src/main/java/envoy/client/ui/Startup.java index 48ce399..f0cf53e 100644 --- a/src/main/java/envoy/client/ui/Startup.java +++ b/src/main/java/envoy/client/ui/Startup.java @@ -68,7 +68,8 @@ public class Startup { } // Load the local database - LocalDB localDB = new LocalDB(client.getSender()); + LocalDB localDB = new LocalDB(); + localDB.setUser(client.getSender()); try { localDB.initializeDBFile(config.getLocalDB()); } catch (EnvoyException e) { From 5b84578a0aac9160dcedfc54ff8617fde6dca445 Mon Sep 17 00:00:00 2001 From: kske Date: Sat, 14 Dec 2019 09:58:25 +0100 Subject: [PATCH 06/24] Removed user id, name and email from Settings --- src/main/java/envoy/client/Client.java | 9 +- src/main/java/envoy/client/Settings.java | 43 --------- .../java/envoy/client/ui/SettingsScreen.java | 91 ++++--------------- src/main/java/envoy/client/ui/Startup.java | 7 +- 4 files changed, 20 insertions(+), 130 deletions(-) diff --git a/src/main/java/envoy/client/Client.java b/src/main/java/envoy/client/Client.java index a6a7f36..fdf371d 100644 --- a/src/main/java/envoy/client/Client.java +++ b/src/main/java/envoy/client/Client.java @@ -38,9 +38,6 @@ public class Client { this.config = config; sender = getUser(userName); - // Update the user ID in the cache - Settings.getInstance().setUserID(sender.getID()); - logger.info("Client user ID: " + sender.getID()); } @@ -100,11 +97,7 @@ public class Client { return sync.getUsers().get(0); } else throw new EnvoyException("Unexpected response from Envoy Server"); } catch (Exception e) { - logger.warning("Could not connect to server, trying offline mode."); - if (Settings.getInstance().getUserID() != -1) { - user.setID(Settings.getInstance().getUserID()); - return user; - } else throw new EnvoyException("Could not enter offline mode."); + throw new EnvoyException("Could not connect to server", e); } } diff --git a/src/main/java/envoy/client/Settings.java b/src/main/java/envoy/client/Settings.java index 851c936..714e5f7 100644 --- a/src/main/java/envoy/client/Settings.java +++ b/src/main/java/envoy/client/Settings.java @@ -26,9 +26,6 @@ import envoy.client.ui.Theme; public class Settings { // Actual settings accessible by the rest of the application - private String username; - private long userID; - private String email; private boolean enterToSend = true; private Map themes; private String currentTheme; @@ -66,9 +63,6 @@ public class Settings { @SuppressWarnings("unchecked") private void load() { - setUsername(prefs.get("username", "")); - setUserID(prefs.getLong("userID", -1)); - setEmail(prefs.get("email", "")); setEnterToSend(prefs.getBoolean("enterToSend", true)); setCurrentTheme(prefs.get("theme", "dark")); @@ -98,9 +92,6 @@ public class Settings { * @since Envoy v0.2-alpha */ public void save() throws IOException { - prefs.put("username", getUsername()); - prefs.putLong("userID", getUserID()); - prefs.put("email", getEmail()); prefs.put("theme", currentTheme); prefs.putBoolean("enterToSend", isEnterToSend()); @@ -136,40 +127,6 @@ public class Settings { */ public void setCurrentTheme(String themeName) { currentTheme = themeName; } - /** - * @return the user name - * @since Envoy v0.2-alpha - */ - public String getUsername() { return username; } - - /** - * @param username the user name to set - * @since Envoy v0.2-alpha - */ - public void setUsername(String username) { this.username = username; } - - /** - * @return the userID - */ - public long getUserID() { return userID; } - - /** - * @param userID the userID to set - */ - public void setUserID(long userID) { this.userID = userID; } - - /** - * @return the email associated with that user. - * @since Envoy v0.2-alpha - */ - public String getEmail() { return email; } - - /** - * @param email the email to set - * @since Envoy v0.2-alpha - */ - public void setEmail(String email) { this.email = email; } - /** * @return true, if "enter" suffices to send a message, else it has to be "ctrl" * + "enter" diff --git a/src/main/java/envoy/client/ui/SettingsScreen.java b/src/main/java/envoy/client/ui/SettingsScreen.java index bd80c2e..fdc12dc 100644 --- a/src/main/java/envoy/client/ui/SettingsScreen.java +++ b/src/main/java/envoy/client/ui/SettingsScreen.java @@ -101,8 +101,7 @@ public class SettingsScreen extends JDialog { createNewThemeButton.setEnabled(false); - temporaryTheme = new Theme("temporaryTheme", - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); + temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); // Content pane GridBagLayout gbl_contentPanel = new GridBagLayout(); @@ -200,20 +199,8 @@ public class SettingsScreen extends JDialog { colorsPanel.setLayout(new BoxLayout(colorsPanel, BoxLayout.Y_AXIS)); colorsPanel.setAlignmentX(Component.LEFT_ALIGNMENT); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getBackgroundColor(), - "Background", - 1); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getCellColor(), - "Cells", - 2); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getBackgroundColor(), "Background", 1); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getCellColor(), "Cells", 2); buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), @@ -228,41 +215,11 @@ public class SettingsScreen extends JDialog { theme.getInteractableBackgroundColor(), "Interactable Background", 4); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getMessageColorChat(), - "Messages Chat", - 5); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getDateColorChat(), - "Date Chat", - 6); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getSelectionColor(), - "Selection", - 7); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getTypingMessageColor(), - "Typing Message", - 8); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getUserNameColor(), - "User Names", - 9); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getMessageColorChat(), "Messages Chat", 5); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getDateColorChat(), "Date Chat", 6); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getSelectionColor(), "Selection", 7); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getTypingMessageColor(), "Typing Message", 8); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getUserNameColor(), "User Names", 9); GridBagConstraints gbc_colorsPanel = new GridBagConstraints(); gbc_colorsPanel.fill = GridBagConstraints.HORIZONTAL; @@ -283,16 +240,14 @@ public class SettingsScreen extends JDialog { String s = JOptionPane.showInputDialog("Enter a name for the new theme"); System.out.println(s); Settings.getInstance() - .addNewThemeToMap(new Theme(s, temporaryTheme.getBackgroundColor(), - temporaryTheme.getCellColor(), temporaryTheme.getInteractableForegroundColor(), - temporaryTheme.getInteractableBackgroundColor(), temporaryTheme.getMessageColorChat(), - temporaryTheme.getDateColorChat(), temporaryTheme.getSelectionColor(), + .addNewThemeToMap(new Theme(s, temporaryTheme.getBackgroundColor(), temporaryTheme.getCellColor(), + temporaryTheme.getInteractableForegroundColor(), temporaryTheme.getInteractableBackgroundColor(), + temporaryTheme.getMessageColorChat(), temporaryTheme.getDateColorChat(), temporaryTheme.getSelectionColor(), temporaryTheme.getTypingMessageColor(), temporaryTheme.getUserNameColor())); themeArray = Arrays.copyOf(themeArray, themeArray.length + 1); themeArray[themeArray.length - 1] = Settings.getInstance().getThemes().get(s).getThemeName(); - temporaryTheme = new Theme("temporaryTheme", - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); + temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); createNewThemeButton.setEnabled(false); themes.addItem(themeArray[themeArray.length - 1]); @@ -348,10 +303,6 @@ public class SettingsScreen extends JDialog { getRootPane().setDefaultButton(okButton); okButton.addActionListener((evt) -> { try { - Settings.getInstance().setUsername(Settings.getInstance().getUsername());// still temporary - - Settings.getInstance().setEmail(Settings.getInstance().getEmail());// still temporary value - Settings.getInstance().setEnterToSend(Settings.getInstance().isEnterToSend());// still temporary Settings.getInstance().setCurrentTheme(selectedTheme.getThemeName()); @@ -412,21 +363,12 @@ public class SettingsScreen extends JDialog { temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getBackgroundColor(), Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor(), - Settings.getInstance() - .getThemes() - .get(Settings.getInstance().getCurrentTheme()) - .getInteractableForegroundColor(), - Settings.getInstance() - .getThemes() - .get(Settings.getInstance().getCurrentTheme()) - .getInteractableBackgroundColor(), + Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getInteractableForegroundColor(), + Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getInteractableBackgroundColor(), Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageColorChat(), Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getDateColorChat(), Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getSelectionColor(), - Settings.getInstance() - .getThemes() - .get(Settings.getInstance().getCurrentTheme()) - .getTypingMessageColor(), + Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getTypingMessageColor(), Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor()); colorsPanel.removeAll(); @@ -513,8 +455,7 @@ public class SettingsScreen extends JDialog { private void setContent(JPanel content, GridBagConstraints layout) { contentPanel.add(content, layout); } - private void buildCustomizeElement(JPanel panel, JButton button, JTextPane textPane, Theme theme, Color color, - String name, int yIndex) { + private void buildCustomizeElement(JPanel panel, JButton button, JTextPane textPane, Theme theme, Color color, String name, int yIndex) { textPane.setFont(new Font("Arial", Font.PLAIN, 14)); textPane.setBackground(theme.getBackgroundColor()); textPane.setForeground(theme.getUserNameColor()); diff --git a/src/main/java/envoy/client/ui/Startup.java b/src/main/java/envoy/client/ui/Startup.java index f0cf53e..b9d08c4 100644 --- a/src/main/java/envoy/client/ui/Startup.java +++ b/src/main/java/envoy/client/ui/Startup.java @@ -9,7 +9,6 @@ import javax.swing.JOptionPane; import envoy.client.Client; import envoy.client.Config; import envoy.client.LocalDB; -import envoy.client.Settings; import envoy.exception.EnvoyException; /** @@ -43,7 +42,8 @@ public class Startup { // Check if all configuration values have been initialized if (!config.isInitialized()) throw new EnvoyException("Server or port are not defined"); } catch (Exception e) { - JOptionPane.showMessageDialog(null, "Error loading configuration values: \n" + e.toString(), "Configuration error", JOptionPane.ERROR_MESSAGE); + JOptionPane + .showMessageDialog(null, "Error loading configuration values: \n" + e.toString(), "Configuration error", JOptionPane.ERROR_MESSAGE); System.exit(1); e.printStackTrace(); } @@ -56,7 +56,7 @@ public class Startup { } // Acquire the client user (with ID) either from the server or from the local - // cache (Preferences), which triggers offline mode + // database, which triggers offline mode Client client; try { client = new Client(config, userName); @@ -79,7 +79,6 @@ public class Startup { "Local DB error", JOptionPane.WARNING_MESSAGE); } - Settings.getInstance().setUsername(userName); EventQueue.invokeLater(() -> { try { From ea3ad85611c596c055f528b0cd4186c21662b3d7 Mon Sep 17 00:00:00 2001 From: kske Date: Sat, 14 Dec 2019 10:53:20 +0100 Subject: [PATCH 07/24] Implemented offline mode for Client and LocalDB --- src/main/java/envoy/client/Client.java | 28 +++++---- src/main/java/envoy/client/LocalDB.java | 34 +++++------ src/main/java/envoy/client/ui/ChatWindow.java | 31 ++++------ src/main/java/envoy/client/ui/Startup.java | 57 ++++++++++++++----- 4 files changed, 87 insertions(+), 63 deletions(-) diff --git a/src/main/java/envoy/client/Client.java b/src/main/java/envoy/client/Client.java index fdf371d..356dc24 100644 --- a/src/main/java/envoy/client/Client.java +++ b/src/main/java/envoy/client/Client.java @@ -1,6 +1,7 @@ package envoy.client; -import java.util.logging.Logger; +import java.util.HashMap; +import java.util.Map; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; @@ -32,13 +33,11 @@ public class Client { private User sender, recipient; private boolean online = false; - private static final Logger logger = Logger.getLogger(Client.class.getSimpleName()); + public Client(Config config) { this.config = config; } - public Client(Config config, String userName) throws EnvoyException { - this.config = config; - sender = getUser(userName); - - logger.info("Client user ID: " + sender.getID()); + public void onlineInit(String userName) throws EnvoyException { + sender = getUser(userName); + online = true; } private R post(String uri, T body, Class responseBodyClass) { @@ -53,22 +52,25 @@ public class Client { } /** - * Returns a {@link Sync} with all users on the server. + * Returns a {@code Map} of all users on the server with their + * user names as keys. * * @return Sync - List of all users on the server. - * @since Envoy v0.1-alpha + * @since Envoy v0.2-alpha */ - public Sync getUsersListXml() { + public Map getUsers() { Sync sendSync = objectFactory.createSync(); User user = objectFactory.createUser(); user.setID(-1); sendSync.getUsers().add(user); - Sync returnSendSync = post(String.format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), 0), + Sync returnSync = post(String.format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), 0), sendSync, Sync.class); - return returnSendSync; + Map users = new HashMap<>(); + returnSync.getUsers().forEach(u -> users.put(u.getName(), u)); + return users; } /** @@ -160,6 +162,8 @@ public class Client { */ public User getSender() { return sender; } + public void setSender(User sender) { this.sender = sender; } + /** * @return the current recipient of the current chat. * @since Envoy v0.1-alpha diff --git a/src/main/java/envoy/client/LocalDB.java b/src/main/java/envoy/client/LocalDB.java index 2ab33ed..f22c7c7 100644 --- a/src/main/java/envoy/client/LocalDB.java +++ b/src/main/java/envoy/client/LocalDB.java @@ -8,7 +8,9 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.time.Instant; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.logging.Logger; import javax.xml.datatype.DatatypeConfigurationException; @@ -34,9 +36,9 @@ import envoy.schema.User; */ public class LocalDB { - private File localDBFile, usersFile; + private File localDBDir, localDBFile, usersFile; private User user; - private List users = new ArrayList<>(); + private Map users = new HashMap<>(); private List chats = new ArrayList<>(); private ObjectFactory objectFactory = new ObjectFactory(); @@ -54,12 +56,19 @@ public class LocalDB { * * @since Envoy v0.1-alpha */ - public LocalDB() { + public LocalDB(File localDBDir) throws IOException { + this.localDBDir = localDBDir; + try { datatypeFactory = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException e) { e.printStackTrace(); } + + // Initialize local database directory + if (localDBDir.exists() && !localDBDir.isDirectory()) + throw new IOException(String.format("LocalDBDir '%s' is not a directory!", localDBDir.getAbsolutePath())); + usersFile = new File(localDBDir, "users.db"); } /** @@ -70,18 +79,9 @@ public class LocalDB { * @throws EnvoyException if the directory selected is not an actual directory. * @since Envoy v0.1-alpha */ - public void initializeDBFile(File localDBDir) throws EnvoyException { + public void initializeDBFile() throws EnvoyException { if (user == null) throw new NullPointerException("Client user is null"); - if (localDBDir.exists() && !localDBDir.isDirectory()) - throw new EnvoyException(String.format("LocalDBDir '%s' is not a directory!", localDBDir.getAbsolutePath())); - usersFile = new File(localDBDir, "users.db"); localDBFile = new File(localDBDir, user.getID() + ".db"); - try { - loadUsers(); - loadChats(); - } catch (ClassNotFoundException | IOException e) { - throw new EnvoyException(e); - } } /** @@ -99,7 +99,7 @@ public class LocalDB { } @SuppressWarnings("unchecked") - private void loadUsers() throws ClassNotFoundException, IOException { users = read(usersFile, ArrayList.class); } + public void loadUsers() throws ClassNotFoundException, IOException { users = read(usersFile, HashMap.class); } /** * Loads all chats saved by Envoy for the client user. @@ -110,7 +110,7 @@ public class LocalDB { * @since Envoy v0.1-alpha */ @SuppressWarnings("unchecked") - private void loadChats() throws ClassNotFoundException, IOException { chats = read(localDBFile, ArrayList.class); } + public void loadChats() throws ClassNotFoundException, IOException { chats = read(localDBFile, ArrayList.class); } private T read(File file, Class serializedClass) throws ClassNotFoundException, IOException { try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(file))) { @@ -308,12 +308,12 @@ public class LocalDB { /** * @return the users */ - public List getUsers() { return users; } + public Map getUsers() { return users; } /** * @param users the users to set */ - public void setUsers(List users) { this.users = users; } + public void setUsers(Map users) { this.users = users; } /** * @return all saved {@link Chat} objects that list the client user as the diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index ee32bf6..0c85abb 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -34,7 +34,6 @@ import envoy.client.Config; import envoy.client.LocalDB; import envoy.client.Settings; import envoy.schema.Message; -import envoy.schema.Sync; import envoy.schema.User; /** @@ -132,8 +131,7 @@ public class ChatWindow extends JFrame { @Override public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER - && ((Settings.getInstance().isEnterToSend() && e.getModifiersEx() == 0) - || (e.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK))) { + && ((Settings.getInstance().isEnterToSend() && e.getModifiersEx() == 0) || (e.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK))) { postMessage(messageList); } } @@ -181,8 +179,8 @@ public class ChatWindow extends JFrame { settingsButton.addActionListener((evt) -> { try { SettingsScreen.open(); - changeChatWindowColors(Settings.getInstance().getCurrentTheme()); - } catch (Exception e) { + changeChatWindowColors(Settings.getInstance().getCurrentTheme()); + } catch (Exception e) { SettingsScreen.open(); logger.log(Level.WARNING, "An error occured while opening the settings screen", e); e.printStackTrace(); @@ -235,7 +233,7 @@ public class ChatWindow extends JFrame { gbc_userList.insets = new Insets(space, space, space, space); changeChatWindowColors(Settings.getInstance().getCurrentTheme()); - + contentPane.add(userList, gbc_userList); contentPane.revalidate(); @@ -244,7 +242,6 @@ public class ChatWindow extends JFrame { contentPane.revalidate(); } - /** * Used to immediately reload the ChatWindow when settings were changed. @@ -287,18 +284,14 @@ public class ChatWindow extends JFrame { private void postMessage(JList messageList) { if (!client.hasRecipient()) { - JOptionPane.showMessageDialog(this, - "Please select a recipient!", - "Cannot send message", - JOptionPane.INFORMATION_MESSAGE); + JOptionPane.showMessageDialog(this, "Please select a recipient!", "Cannot send message", JOptionPane.INFORMATION_MESSAGE); return; } if (!messageEnterTextArea.getText().isEmpty()) try { // Create and send message object - final Message message = localDB.createMessage(messageEnterTextArea.getText(), - currentChat.getRecipient().getID()); + final Message message = localDB.createMessage(messageEnterTextArea.getText(), currentChat.getRecipient().getID()); currentChat.appendMessage(message); messageList.setModel(currentChat.getModel()); @@ -322,9 +315,8 @@ public class ChatWindow extends JFrame { */ private void loadUsersAndChats() { new Thread(() -> { - Sync users = client.getUsersListXml(); - DefaultListModel userListModel = new DefaultListModel<>(); - users.getUsers().forEach(user -> { + DefaultListModel userListModel = new DefaultListModel<>(); + localDB.getUsers().values().forEach(user -> { userListModel.addElement(user); // Check if user exists in local DB @@ -348,8 +340,7 @@ public class ChatWindow extends JFrame { new Thread(() -> { // Synchronize - localDB.applySync( - client.sendSync(client.getSender().getID(), localDB.fillSync(client.getSender().getID()))); + localDB.applySync(client.sendSync(client.getSender().getID(), localDB.fillSync(client.getSender().getID()))); // Process unread messages localDB.addUnreadMessagesToLocalDB(); @@ -359,8 +350,7 @@ public class ChatWindow extends JFrame { readCurrentChat(); // Update UI - SwingUtilities - .invokeLater(() -> { updateUserStates(); contentPane.revalidate(); contentPane.repaint(); }); + SwingUtilities.invokeLater(() -> { updateUserStates(); contentPane.revalidate(); contentPane.repaint(); }); }).start(); }).start(); } @@ -377,4 +367,3 @@ public class ChatWindow extends JFrame { */ private void readCurrentChat() { if (currentChat != null) { localDB.setMessagesToRead(currentChat); } } } - diff --git a/src/main/java/envoy/client/ui/Startup.java b/src/main/java/envoy/client/ui/Startup.java index b9d08c4..e2f6b5e 100644 --- a/src/main/java/envoy/client/ui/Startup.java +++ b/src/main/java/envoy/client/ui/Startup.java @@ -1,6 +1,7 @@ package envoy.client.ui; import java.awt.EventQueue; +import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; @@ -10,6 +11,7 @@ import envoy.client.Client; import envoy.client.Config; import envoy.client.LocalDB; import envoy.exception.EnvoyException; +import envoy.schema.User; /** * Starts the Envoy client and prompts the user to enter their name. @@ -54,32 +56,61 @@ public class Startup { logger.severe("User name is not set or empty. Exiting..."); System.exit(1); } - - // Acquire the client user (with ID) either from the server or from the local - // database, which triggers offline mode - Client client; + + // Initialize the local database + LocalDB localDB; try { - client = new Client(config, userName); - } catch (Exception e1) { - logger.log(Level.SEVERE, "Failed to acquire client user ID", e1); - JOptionPane.showMessageDialog(null, e1.toString(), "Client error", JOptionPane.ERROR_MESSAGE); + localDB = new LocalDB(config.getLocalDB()); + } catch (IOException e3) { + logger.log(Level.SEVERE, "Could not initialize local database", e3); + JOptionPane.showMessageDialog(null, "Could not initialize local database!\n" + e3.toString()); System.exit(1); return; } - // Load the local database - LocalDB localDB = new LocalDB(); - localDB.setUser(client.getSender()); + // Acquire the client user (with ID) either from the server or from the local + // database, which triggers offline mode + Client client = new Client(config); try { - localDB.initializeDBFile(config.getLocalDB()); - } catch (EnvoyException e) { + // Try entering online mode first + client.onlineInit(userName); + } catch (Exception e1) { + logger.warning("Could not connect to server. Trying offline mode..."); + try { + // Try entering offline mode + localDB.loadUsers(); + User clientUser = localDB.getUsers().get(userName); + if(clientUser == null) + throw new EnvoyException("Could not enter offline mode: user name unknown"); + client.setSender(clientUser); + } catch(Exception e2) { + JOptionPane.showMessageDialog(null, e1.toString(), "Client error", JOptionPane.ERROR_MESSAGE); + System.exit(1); + return; + } + } + + // Set client user in local database + localDB.setUser(client.getSender()); + + // Initialize chats in local database + try { + localDB.initializeDBFile(); + localDB.loadChats(); + } catch (EnvoyException | ClassNotFoundException | IOException e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "Error while loading local database: " + e.toString() + "\nChats will not be stored locally.", "Local DB error", JOptionPane.WARNING_MESSAGE); } + + logger.info("Client user ID: " + client.getSender().getID()); + // Save all users to the local database + if(client.isOnline()) + localDB.setUsers(client.getUsers()); + EventQueue.invokeLater(() -> { try { ChatWindow chatWindow = new ChatWindow(client, localDB); From 0123935cea4a8e873d42b251f70345912b511745 Mon Sep 17 00:00:00 2001 From: kske Date: Sat, 14 Dec 2019 11:02:01 +0100 Subject: [PATCH 08/24] Not starting the sync thread in offline mode --- src/main/java/envoy/client/ui/ChatWindow.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 0c85abb..ab0cbb7 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -238,7 +238,9 @@ public class ChatWindow extends JFrame { contentPane.revalidate(); loadUsersAndChats(); - startSyncThread(Config.getInstance().getSyncTimeout()); + + if(client.isOnline()) + startSyncThread(Config.getInstance().getSyncTimeout()); contentPane.revalidate(); } From 89b75b00c88f4390aa8963478114c8497fecd641 Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sat, 14 Dec 2019 11:22:37 +0100 Subject: [PATCH 09/24] Fixes bugs with the incorrect applying of the changed colors. Fixes #50 --- src/main/java/envoy/client/Settings.java | 2 +- .../java/envoy/client/ui/SettingsScreen.java | 60 ++++++++----------- src/main/java/envoy/client/ui/Theme.java | 23 +------ 3 files changed, 28 insertions(+), 57 deletions(-) diff --git a/src/main/java/envoy/client/Settings.java b/src/main/java/envoy/client/Settings.java index 91f696f..3bd54f1 100644 --- a/src/main/java/envoy/client/Settings.java +++ b/src/main/java/envoy/client/Settings.java @@ -116,7 +116,7 @@ public class Settings { */ public void addNewThemeToMap(Theme theme) { settings.getThemes().put(theme.getThemeName(), theme); - currentTheme = theme.getThemeName(); + // currentTheme = theme.getThemeName(); } /** diff --git a/src/main/java/envoy/client/ui/SettingsScreen.java b/src/main/java/envoy/client/ui/SettingsScreen.java index bd80c2e..f96eac1 100644 --- a/src/main/java/envoy/client/ui/SettingsScreen.java +++ b/src/main/java/envoy/client/ui/SettingsScreen.java @@ -206,63 +206,63 @@ public class SettingsScreen extends JDialog { theme, theme.getBackgroundColor(), "Background", - 1); + 0); buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getCellColor(), "Cells", - 2); + 1); buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getInteractableForegroundColor(), "Interactable Foreground", - 3); + 2); buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getInteractableBackgroundColor(), "Interactable Background", - 4); + 3); buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getMessageColorChat(), "Messages Chat", - 5); + 4); buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getDateColorChat(), "Date Chat", - 6); + 5); buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getSelectionColor(), "Selection", - 7); + 6); buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getTypingMessageColor(), "Typing Message", - 8); + 7); buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getUserNameColor(), "User Names", - 9); + 8); GridBagConstraints gbc_colorsPanel = new GridBagConstraints(); gbc_colorsPanel.fill = GridBagConstraints.HORIZONTAL; @@ -438,7 +438,7 @@ public class SettingsScreen extends JDialog { theme, theme.getBackgroundColor(), "Background", - 1); + 0); buildCustomizeElement(new JPanel(), new JButton(), @@ -446,7 +446,7 @@ public class SettingsScreen extends JDialog { theme, theme.getCellColor(), "Cells", - 2); + 1); buildCustomizeElement(new JPanel(), new JButton(), @@ -454,7 +454,7 @@ public class SettingsScreen extends JDialog { theme, theme.getInteractableForegroundColor(), "Interactable Foreground", - 3); + 2); buildCustomizeElement(new JPanel(), new JButton(), @@ -462,7 +462,7 @@ public class SettingsScreen extends JDialog { theme, theme.getInteractableBackgroundColor(), "Interactable Background", - 4); + 3); buildCustomizeElement(new JPanel(), new JButton(), @@ -470,7 +470,7 @@ public class SettingsScreen extends JDialog { theme, theme.getMessageColorChat(), "Messages Chat", - 5); + 4); buildCustomizeElement(new JPanel(), new JButton(), @@ -478,7 +478,7 @@ public class SettingsScreen extends JDialog { theme, theme.getDateColorChat(), "Date Chat", - 6); + 5); buildCustomizeElement(new JPanel(), new JButton(), @@ -486,7 +486,7 @@ public class SettingsScreen extends JDialog { theme, theme.getSelectionColor(), "Selection", - 7); + 6); buildCustomizeElement(new JPanel(), new JButton(), @@ -494,7 +494,7 @@ public class SettingsScreen extends JDialog { theme, theme.getTypingMessageColor(), "Typing Message", - 8); + 7); buildCustomizeElement(new JPanel(), new JButton(), @@ -502,7 +502,7 @@ public class SettingsScreen extends JDialog { theme, theme.getUserNameColor(), "User Names", - 9); + 8); GridBagConstraints gbc_createNewTheme = new GridBagConstraints(); gbc_createNewTheme.gridx = 0; @@ -532,18 +532,11 @@ public class SettingsScreen extends JDialog { System.out.println(color.getRGB()); // TODO: When Theme changed in same settings screen, color variable doesnt // update. - Color[] colorsArray = temporaryTheme.getAllColors(); - for (int i = 0; i < colorsArray.length; i++) { - if (color.getRGB() == colorsArray[i].getRGB()) { - temporaryTheme.setColor(i, newColor); - colorChanged = true; - createNewThemeButton.setEnabled(true); - break; - } - - } + temporaryTheme.setColor(yIndex, newColor); + colorChanged = true; + createNewThemeButton.setEnabled(true); + } button.setBackground(newColor); - } } catch (Exception e) { logger.info("An error occured while opening Color Chooser: " + e); @@ -551,12 +544,9 @@ public class SettingsScreen extends JDialog { } }); - panel.add(textPane); - panel.add(button); - panel.setBackground(theme.getCellColor()); - panel.setAlignmentX(Component.LEFT_ALIGNMENT); + panel.add(textPane);panel.add(button);panel.setBackground(theme.getCellColor());panel.setAlignmentX(Component.LEFT_ALIGNMENT); - colorsPanel.add(panel); - } + colorsPanel.add(panel); +} } diff --git a/src/main/java/envoy/client/ui/Theme.java b/src/main/java/envoy/client/ui/Theme.java index a0ef259..9dcda1e 100644 --- a/src/main/java/envoy/client/ui/Theme.java +++ b/src/main/java/envoy/client/ui/Theme.java @@ -44,8 +44,8 @@ public class Theme implements Serializable { } public Theme(String name, Theme other) { - this(name, other.backgroundColor, other.cellColor, other.interactableBackgroundColor, - other.interactableForegroundColor, other.messageColorChat, other.dateColorChat, other.selectionColor, + this(name, other.backgroundColor, other.cellColor, other.interactableForegroundColor, + other.interactableBackgroundColor, other.messageColorChat, other.dateColorChat, other.selectionColor, other.typingMessageColor, other.userNameColor); } @@ -109,25 +109,6 @@ public class Theme implements Serializable { */ public Color getUserNameColor() { return userNameColor; } - /** - * @return a color array containing all colors of this theme - * @since Envoy v0.2-alpha - */ - public Color[] getAllColors() { - Color[] c = new Color[9]; - c[0] = backgroundColor; - c[1] = cellColor; - c[2] = interactableForegroundColor; - c[3] = interactableBackgroundColor; - c[4] = messageColorChat; - c[5] = dateColorChat; - c[6] = selectionColor; - c[7] = typingMessageColor; - c[8] = userNameColor; - - return c; - } - /** * Sets the a specific {@link Color} in this theme to a new {@link Color} * From ac7b7fa3d6bd1787c4dfb6b5956a7f1c7e30a55b Mon Sep 17 00:00:00 2001 From: kske Date: Sat, 14 Dec 2019 11:30:00 +0100 Subject: [PATCH 10/24] Added documentation, refined exception handling --- src/main/java/envoy/client/Client.java | 35 ++++++++++--- src/main/java/envoy/client/LocalDB.java | 49 +++++++++++-------- src/main/java/envoy/client/ui/ChatWindow.java | 11 +++-- src/main/java/envoy/client/ui/Startup.java | 2 +- 4 files changed, 65 insertions(+), 32 deletions(-) diff --git a/src/main/java/envoy/client/Client.java b/src/main/java/envoy/client/Client.java index 356dc24..b7cc83c 100644 --- a/src/main/java/envoy/client/Client.java +++ b/src/main/java/envoy/client/Client.java @@ -33,8 +33,23 @@ public class Client { private User sender, recipient; private boolean online = false; + /** + * Initializes the client. At this state, the client user has yet to be + * initialized, which can be done by calling {@link Client#onlineInit(String). + * + * @param config The {@link Config} instance to use in this client + * @since Envoy v0.2-alpha + */ public Client(Config config) { this.config = config; } + /** + * Enters the online mode by acquiring a user ID from the server. + * + * @param userName the name of the client user + * @throws EnvoyException if the online mode could not be entered or the request + * failed for some other reason + * @since Envoy v0.2-alpha + */ public void onlineInit(String userName) throws EnvoyException { sender = getUser(userName); online = true; @@ -52,10 +67,8 @@ public class Client { } /** - * Returns a {@code Map} of all users on the server with their - * user names as keys. - * - * @return Sync - List of all users on the server. + * @return a {@code Map} of all users on the server with their + * user names as keys * @since Envoy v0.2-alpha */ public Map getUsers() { @@ -138,9 +151,12 @@ public class Client { * @param sync the sync object (yet to be converted from java class to * sync.xml) * @return a returnSync.xml file + * @throws EnvoyException if the client is not in online mode * @since Envoy v0.1-alpha */ - public Sync sendSync(long userId, Sync sync) { + public Sync sendSync(long userId, Sync sync) throws EnvoyException { + if(!isOnline()) + throw new EnvoyException("Client is not in online mode"); // Print sync XML to console JAXBContext jc; try { @@ -162,6 +178,12 @@ public class Client { */ public User getSender() { return sender; } + /** + * Sets the client user which is used to send messages. + * + * @param sender the client user to set + * @since Envoy v0.2-alpha + */ public void setSender(User sender) { this.sender = sender; } /** @@ -173,7 +195,7 @@ public class Client { /** * Sets the recipient. * - * @param recipient - the recipient to set + * @param recipient the recipient to set * @since Envoy v0.1-alpha */ public void setRecipient(User recipient) { this.recipient = recipient; } @@ -186,6 +208,7 @@ public class Client { /** * @return {@code true} if a connection to the server could be established + * @since Envoy v0.2-alpha */ public boolean isOnline() { return online; } } diff --git a/src/main/java/envoy/client/LocalDB.java b/src/main/java/envoy/client/LocalDB.java index f22c7c7..60de119 100644 --- a/src/main/java/envoy/client/LocalDB.java +++ b/src/main/java/envoy/client/LocalDB.java @@ -36,10 +36,10 @@ import envoy.schema.User; */ public class LocalDB { - private File localDBDir, localDBFile, usersFile; - private User user; + private File localDBDir, localDBFile, usersFile; + private User user; private Map users = new HashMap<>(); - private List chats = new ArrayList<>(); + private List chats = new ArrayList<>(); private ObjectFactory objectFactory = new ObjectFactory(); private DatatypeFactory datatypeFactory; @@ -54,38 +54,38 @@ public class LocalDB { * Constructs an empty local database. To serialize any chats to the file * system, call {@link LocalDB#initializeDBFile(File)}. * + * @param localDBDir the directory in which to store users and chats * @since Envoy v0.1-alpha */ public LocalDB(File localDBDir) throws IOException { this.localDBDir = localDBDir; - + try { datatypeFactory = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException e) { e.printStackTrace(); } - + // Initialize local database directory if (localDBDir.exists() && !localDBDir.isDirectory()) throw new IOException(String.format("LocalDBDir '%s' is not a directory!", localDBDir.getAbsolutePath())); - usersFile = new File(localDBDir, "users.db"); + usersFile = new File(localDBDir, "users.db"); } /** - * Initializes the local database and fills it with values - * if the user has already sent or received messages. + * Creates a database file for a user-specific list of chats. * - * @param localDBDir the directory where we wish to save/load the database from. - * @throws EnvoyException if the directory selected is not an actual directory. + * @throws NullPointerException if the client user is not yet specified * @since Envoy v0.1-alpha */ - public void initializeDBFile() throws EnvoyException { + public void initializeDBFile() { if (user == null) throw new NullPointerException("Client user is null"); - localDBFile = new File(localDBDir, user.getID() + ".db"); + localDBFile = new File(localDBDir, user.getID() + ".db"); } /** - * Saves the database into a file for future use. + * Stores all users to the local database. If the client user is specified, the + * chats related to this user are stored as well. * * @throws IOException if something went wrong during saving * @since Envoy v0.1-alpha @@ -98,30 +98,36 @@ public class LocalDB { write(localDBFile, chats); } + /** + * Loads all users that are stored in the local database. + * + * @throws EnvoyException if the loading process failed + * @since Envoy v0.2-alpha + */ @SuppressWarnings("unchecked") - public void loadUsers() throws ClassNotFoundException, IOException { users = read(usersFile, HashMap.class); } + public void loadUsers() throws EnvoyException { users = read(usersFile, HashMap.class); } /** * Loads all chats saved by Envoy for the client user. * - * @throws EnvoyException if something fails while loading. - * @throws IOException - * @throws ClassNotFoundException + * @throws EnvoyException if the loading process failed * @since Envoy v0.1-alpha */ @SuppressWarnings("unchecked") - public void loadChats() throws ClassNotFoundException, IOException { chats = read(localDBFile, ArrayList.class); } + public void loadChats() throws EnvoyException { chats = read(localDBFile, ArrayList.class); } - private T read(File file, Class serializedClass) throws ClassNotFoundException, IOException { + private T read(File file, Class serializedClass) throws EnvoyException { + if (file == null) throw new NullPointerException("File is null"); try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(file))) { return serializedClass.cast(in.readObject()); } catch (ClassNotFoundException | IOException e) { - throw e; + throw new EnvoyException("Could not load serialized object", e); } } private void write(File file, T obj) throws IOException { if (file == null) throw new NullPointerException("File is null"); + if (obj == null) throw new NullPointerException("Object to serialize is null"); if (!file.exists()) { file.getParentFile().mkdirs(); file.createNewFile(); @@ -306,7 +312,8 @@ public class LocalDB { public void clearUnreadMessagesSync() { unreadMessagesSync.getMessages().clear(); } /** - * @return the users + * @return a {@code Map} of all users stored locally with their user names as keys + * @since Envoy v0.2-alpha */ public Map getUsers() { return users; } diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index ab0cbb7..45d607b 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -238,9 +238,8 @@ public class ChatWindow extends JFrame { contentPane.revalidate(); loadUsersAndChats(); - - if(client.isOnline()) - startSyncThread(Config.getInstance().getSyncTimeout()); + + if (client.isOnline()) startSyncThread(Config.getInstance().getSyncTimeout()); contentPane.revalidate(); } @@ -342,7 +341,11 @@ public class ChatWindow extends JFrame { new Thread(() -> { // Synchronize - localDB.applySync(client.sendSync(client.getSender().getID(), localDB.fillSync(client.getSender().getID()))); + try { + localDB.applySync(client.sendSync(client.getSender().getID(), localDB.fillSync(client.getSender().getID()))); + } catch (Exception e) { + logger.log(Level.SEVERE, "Could not perform sync", e); + } // Process unread messages localDB.addUnreadMessagesToLocalDB(); diff --git a/src/main/java/envoy/client/ui/Startup.java b/src/main/java/envoy/client/ui/Startup.java index e2f6b5e..933890d 100644 --- a/src/main/java/envoy/client/ui/Startup.java +++ b/src/main/java/envoy/client/ui/Startup.java @@ -97,7 +97,7 @@ public class Startup { try { localDB.initializeDBFile(); localDB.loadChats(); - } catch (EnvoyException | ClassNotFoundException | IOException e) { + } catch (EnvoyException e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "Error while loading local database: " + e.toString() + "\nChats will not be stored locally.", From a0e72a6e5668ccf916c7a11aec9a14baf6716d87 Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sat, 14 Dec 2019 12:54:32 +0100 Subject: [PATCH 11/24] Changed colors management in the displaying of the themes settings screen. --- .../java/envoy/client/ui/SettingsScreen.java | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/main/java/envoy/client/ui/SettingsScreen.java b/src/main/java/envoy/client/ui/SettingsScreen.java index f96eac1..ef1dadc 100644 --- a/src/main/java/envoy/client/ui/SettingsScreen.java +++ b/src/main/java/envoy/client/ui/SettingsScreen.java @@ -138,11 +138,6 @@ public class SettingsScreen extends JDialog { Theme theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()); - options.setSelectionForeground(theme.getUserNameColor()); - options.setSelectionBackground(theme.getSelectionColor()); - options.setForeground(theme.getUserNameColor()); - options.setBackground(theme.getCellColor()); - GridBagConstraints gbc_optionsList = new GridBagConstraints(); gbc_optionsList.fill = GridBagConstraints.BOTH; gbc_optionsList.gridx = 0; @@ -164,9 +159,6 @@ public class SettingsScreen extends JDialog { GridBagLayout gbl_themeLayout = new GridBagLayout(); - themeContent.setForeground(theme.getUserNameColor()); - themeContent.setBackground(theme.getCellColor()); - gbl_themeLayout.columnWidths = new int[] { 1, 1 }; gbl_themeLayout.rowHeights = new int[] { 1, 1 }; gbl_themeLayout.columnWeights = new double[] { 1.0, 1.0 }; @@ -174,8 +166,6 @@ public class SettingsScreen extends JDialog { themeContent.setLayout(gbl_themeLayout); - themes.setBackground(theme.getUserNameColor()); - themes.setForeground(theme.getBackgroundColor()); themes.setSelectedItem(Settings.getInstance().getCurrentTheme()); themes.addItemListener(new ItemListener() { @@ -300,8 +290,6 @@ public class SettingsScreen extends JDialog { contentPanel.revalidate(); contentPanel.repaint(); - // TODO: Create new Theme - } catch (Exception e) { logger.info("New theme couldn't be created! " + e); e.printStackTrace(); @@ -397,8 +385,8 @@ public class SettingsScreen extends JDialog { themeContent.setForeground(theme.getUserNameColor()); themeContent.setBackground(theme.getCellColor()); // themes - themes.setBackground(theme.getUserNameColor()); - themes.setForeground(theme.getBackgroundColor()); + themes.setBackground(theme.getBackgroundColor()); + themes.setForeground(getInvertedColor(theme.getBackgroundColor())); createNewThemeButton.setBackground(theme.getInteractableBackgroundColor()); createNewThemeButton.setForeground(theme.getInteractableForegroundColor()); @@ -517,7 +505,7 @@ public class SettingsScreen extends JDialog { String name, int yIndex) { textPane.setFont(new Font("Arial", Font.PLAIN, 14)); textPane.setBackground(theme.getBackgroundColor()); - textPane.setForeground(theme.getUserNameColor()); + textPane.setForeground(getInvertedColor(theme.getBackgroundColor())); textPane.setText(name); textPane.setEditable(false); @@ -532,11 +520,11 @@ public class SettingsScreen extends JDialog { System.out.println(color.getRGB()); // TODO: When Theme changed in same settings screen, color variable doesnt // update. - temporaryTheme.setColor(yIndex, newColor); - colorChanged = true; - createNewThemeButton.setEnabled(true); - } - button.setBackground(newColor); + temporaryTheme.setColor(yIndex, newColor); + colorChanged = true; + createNewThemeButton.setEnabled(true); + } + button.setBackground(newColor); } catch (Exception e) { logger.info("An error occured while opening Color Chooser: " + e); @@ -544,9 +532,16 @@ public class SettingsScreen extends JDialog { } }); - panel.add(textPane);panel.add(button);panel.setBackground(theme.getCellColor());panel.setAlignmentX(Component.LEFT_ALIGNMENT); + panel.add(textPane); + panel.add(button); + panel.setBackground(theme.getCellColor()); + panel.setAlignmentX(Component.LEFT_ALIGNMENT); - colorsPanel.add(panel); -} + colorsPanel.add(panel); + } + + private Color getInvertedColor(Color color) { + return new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue()); + } } From 4ba1f6360ce9244b98f5b05eb5aa7e44fbb3816f Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sat, 14 Dec 2019 13:46:19 +0100 Subject: [PATCH 12/24] Revised code according to reviews by @delvh and @CyB3RC0nN0R --- src/main/java/envoy/client/ui/ChatWindow.java | 40 +++++++++---------- .../java/envoy/client/ui/PrimaryButton.java | 3 +- .../java/envoy/client/ui/PrimaryTextArea.java | 9 +++-- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 14065b0..1434148 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -53,16 +53,16 @@ public class ChatWindow extends JFrame { private Client client; private LocalDB localDB; // GUI components - private JPanel contentPane = new JPanel(); - private PrimaryTextArea messageEnterTextArea; - private JList userList = new JList<>(); + private JPanel contentPane = new JPanel(); + private PrimaryTextArea messageEnterTextArea = new PrimaryTextArea(space); + private JList userList = new JList<>(); private Chat currentChat; - private JList messageList = new JList<>(); - private JScrollPane scrollPane = new JScrollPane(); - private JTextPane textPane = new JTextPane(); + private JList messageList = new JList<>(); + private JScrollPane scrollPane = new JScrollPane(); + private JTextPane textPane = new JTextPane(); // private JCheckBox jCbChangeMode; - private PrimaryButton postButton; - private PrimaryButton settingsButton; + private PrimaryButton postButton = new PrimaryButton("Post"); + private PrimaryButton settingsButton = new PrimaryButton("Settings"); private static int space = 4; @@ -76,7 +76,8 @@ public class ChatWindow extends JFrame { setBounds(100, 100, 600, 800); setTitle("Envoy"); setLocationRelativeTo(null); - setIconImage(Toolkit.getDefaultToolkit().createImage(getClass().getClassLoader().getResource("envoy_logo.png"))); + setIconImage( + Toolkit.getDefaultToolkit().createImage(getClass().getClassLoader().getResource("envoy_logo.png"))); // Save chats when window closes addWindowListener(new WindowAdapter() { @@ -124,9 +125,6 @@ public class ChatWindow extends JFrame { gbc_scrollPane.insets = new Insets(space, space, space, space); contentPane.add(scrollPane, gbc_scrollPane); - // Checks for changed Message - messageEnterTextArea = new PrimaryTextArea(space); - // Message enter field messageEnterTextArea.addKeyListener(new KeyAdapter() { @@ -140,7 +138,6 @@ public class ChatWindow extends JFrame { } }); - GridBagConstraints gbc_messageEnterTextfield = new GridBagConstraints(); gbc_messageEnterTextfield.fill = GridBagConstraints.BOTH; gbc_messageEnterTextfield.gridx = 1; @@ -151,7 +148,6 @@ public class ChatWindow extends JFrame { contentPane.add(messageEnterTextArea, gbc_messageEnterTextfield); // Post Button - postButton = new PrimaryButton("Post"); GridBagConstraints gbc_moveSelectionPostButton = new GridBagConstraints(); gbc_moveSelectionPostButton.fill = GridBagConstraints.BOTH; @@ -164,8 +160,6 @@ public class ChatWindow extends JFrame { contentPane.add(postButton, gbc_moveSelectionPostButton); // Settings Button - settingsButton = new PrimaryButton("Settings"); - GridBagConstraints gbc_moveSelectionSettingsButton = new GridBagConstraints(); gbc_moveSelectionSettingsButton.fill = GridBagConstraints.BOTH; @@ -177,8 +171,8 @@ public class ChatWindow extends JFrame { settingsButton.addActionListener((evt) -> { try { SettingsScreen.open(); - changeChatWindowColors(Settings.getInstance().getCurrentTheme()); - } catch (Exception e) { + changeChatWindowColors(Settings.getInstance().getCurrentTheme()); + } catch (Exception e) { SettingsScreen.open(); logger.log(Level.WARNING, "An error occured while opening the settings screen", e); e.printStackTrace(); @@ -207,7 +201,11 @@ public class ChatWindow extends JFrame { final User user = selectedUserList.getSelectedValue(); client.setRecipient(user); - currentChat = localDB.getChats().stream().filter(chat -> chat.getRecipient().getID() == user.getID()).findFirst().get(); + currentChat = localDB.getChats() + .stream() + .filter(chat -> chat.getRecipient().getID() == user.getID()) + .findFirst() + .get(); // Set all unread messages in the chat to read readCurrentChat(); @@ -231,7 +229,7 @@ public class ChatWindow extends JFrame { gbc_userList.insets = new Insets(space, space, space, space); changeChatWindowColors(Settings.getInstance().getCurrentTheme()); - + contentPane.add(userList, gbc_userList); contentPane.revalidate(); @@ -240,7 +238,6 @@ public class ChatWindow extends JFrame { contentPane.revalidate(); } - /** * Used to immediately reload the ChatWindow when settings were changed. @@ -373,4 +370,3 @@ public class ChatWindow extends JFrame { */ private void readCurrentChat() { if (currentChat != null) { localDB.setMessagesToRead(currentChat); } } } - diff --git a/src/main/java/envoy/client/ui/PrimaryButton.java b/src/main/java/envoy/client/ui/PrimaryButton.java index 2e528db..fe93571 100644 --- a/src/main/java/envoy/client/ui/PrimaryButton.java +++ b/src/main/java/envoy/client/ui/PrimaryButton.java @@ -11,6 +11,7 @@ import javax.swing.JButton; * * @author Kai S. K. Engelbart * @author Maximilian Käfer + * @since Envoy v0.2-alpha */ public class PrimaryButton extends JButton { @@ -35,8 +36,6 @@ public class PrimaryButton extends JButton { */ public PrimaryButton(String title, int arcSize) { super(title); - // setForeground(new Color(255, 255, 255)); - // setBackground(new Color(102, 51, 153)); setBorderPainted(false); setFocusPainted(false); setContentAreaFilled(false); diff --git a/src/main/java/envoy/client/ui/PrimaryTextArea.java b/src/main/java/envoy/client/ui/PrimaryTextArea.java index 3f350ed..e4d6fa1 100644 --- a/src/main/java/envoy/client/ui/PrimaryTextArea.java +++ b/src/main/java/envoy/client/ui/PrimaryTextArea.java @@ -12,6 +12,7 @@ import javax.swing.border.EmptyBorder; * Created: 07.12.2019
* * @author Maximilian Käfer + * @since Envoy v0.2-alpha */ public class PrimaryTextArea extends JTextArea { @@ -20,7 +21,7 @@ public class PrimaryTextArea extends JTextArea { private int arcSize; /** - * Creates TextArea + * Creates the text area * * @param borderSpace * @since Envoy 0.2-alpha @@ -28,10 +29,10 @@ public class PrimaryTextArea extends JTextArea { public PrimaryTextArea(int borderSpace) { this(6, borderSpace); } /** - * Creates TextArea + * Creates the text area * * @param arcSize - * @param borderSpace + * @param borderSpace - the insets of the border on all four sides * @since Envoy 0.2-alpha */ public PrimaryTextArea(int arcSize, int borderSpace) { @@ -54,7 +55,7 @@ public class PrimaryTextArea extends JTextArea { } /** - * @return the arcSize + * @return the arcSize - the diameter of the arc at the four corners. * @since Envoy 0.2-alpha */ public int getArcSize() { return arcSize; } From 4d35129a67001e24f805da078924a313ffc27555 Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sat, 14 Dec 2019 13:52:47 +0100 Subject: [PATCH 13/24] Formatted --- src/main/java/envoy/client/LocalDB.java | 8 +- src/main/java/envoy/client/Settings.java | 10 +-- src/main/java/envoy/client/ui/ChatWindow.java | 40 +++------ .../envoy/client/ui/MessageListRenderer.java | 12 +-- .../java/envoy/client/ui/PrimaryTextArea.java | 9 +- .../java/envoy/client/ui/SettingsScreen.java | 87 ++++--------------- src/main/java/envoy/client/ui/Theme.java | 12 ++- .../envoy/client/ui/UserListRenderer.java | 19 ++-- 8 files changed, 58 insertions(+), 139 deletions(-) diff --git a/src/main/java/envoy/client/LocalDB.java b/src/main/java/envoy/client/LocalDB.java index f061b28..5ca7a04 100644 --- a/src/main/java/envoy/client/LocalDB.java +++ b/src/main/java/envoy/client/LocalDB.java @@ -44,7 +44,7 @@ public class LocalDB { private Sync sync = objectFactory.createSync(); private Sync readMessages = objectFactory.createSync(); - private static final Logger logger = Logger.getLogger(LocalDB.class.getSimpleName()); + private static final Logger logger = Logger.getLogger(LocalDB.class.getSimpleName()); /** * Constructs an empty local database. @@ -134,13 +134,13 @@ public class LocalDB { return message; } - /** + /** * Creates a {@link Sync} object filled with the changes that occurred to the * local database since the last synchronization. * * @param userId the ID of the user that is synchronized by this client * @return {@link Sync} object filled with the current changes - * @since Envoy v0.1-alpha + * @since Envoy v0.1-alpha */ public Sync fillSync(long userId) { addWaitingMessagesToSync(); @@ -156,7 +156,7 @@ public class LocalDB { * Applies the changes carried by a {@link Sync} object to the local database * * @param returnSync the {@link Sync} object to apply - * @since Envoy v0.1-alpha + * @since Envoy v0.1-alpha */ public void applySync(Sync returnSync) { for (int i = 0; i < returnSync.getMessages().size(); i++) { diff --git a/src/main/java/envoy/client/Settings.java b/src/main/java/envoy/client/Settings.java index 91f696f..fe5d769 100644 --- a/src/main/java/envoy/client/Settings.java +++ b/src/main/java/envoy/client/Settings.java @@ -73,9 +73,9 @@ public class Settings { // Load themes from theme file try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(themeFile))) { Object obj = in.readObject(); - if(obj instanceof HashMap) themes = (Map) obj; + if (obj instanceof HashMap) themes = (Map) obj; } catch (IOException | ClassNotFoundException e) { - themes = new HashMap<>(); + themes = new HashMap<>(); currentTheme = "dark"; e.printStackTrace(); } @@ -95,15 +95,15 @@ public class Settings { * @throws IOException * @since Envoy v0.2-alpha */ - public void save() throws IOException{ + public void save() throws IOException { prefs.put("username", getUsername()); prefs.put("email", getEmail()); prefs.put("theme", currentTheme); prefs.putBoolean("enterToSend", isEnterToSend()); - + // Save themes to theme file themeFile.createNewFile(); - try(ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(themeFile))) { + try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(themeFile))) { out.writeObject(themes); } } diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 1434148..ade7bcd 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -53,15 +53,15 @@ public class ChatWindow extends JFrame { private Client client; private LocalDB localDB; // GUI components - private JPanel contentPane = new JPanel(); - private PrimaryTextArea messageEnterTextArea = new PrimaryTextArea(space); - private JList userList = new JList<>(); + private JPanel contentPane = new JPanel(); + private PrimaryTextArea messageEnterTextArea = new PrimaryTextArea(space); + private JList userList = new JList<>(); private Chat currentChat; - private JList messageList = new JList<>(); - private JScrollPane scrollPane = new JScrollPane(); - private JTextPane textPane = new JTextPane(); + private JList messageList = new JList<>(); + private JScrollPane scrollPane = new JScrollPane(); + private JTextPane textPane = new JTextPane(); // private JCheckBox jCbChangeMode; - private PrimaryButton postButton = new PrimaryButton("Post"); + private PrimaryButton postButton = new PrimaryButton("Post"); private PrimaryButton settingsButton = new PrimaryButton("Settings"); private static int space = 4; @@ -76,8 +76,7 @@ public class ChatWindow extends JFrame { setBounds(100, 100, 600, 800); setTitle("Envoy"); setLocationRelativeTo(null); - setIconImage( - Toolkit.getDefaultToolkit().createImage(getClass().getClassLoader().getResource("envoy_logo.png"))); + setIconImage(Toolkit.getDefaultToolkit().createImage(getClass().getClassLoader().getResource("envoy_logo.png"))); // Save chats when window closes addWindowListener(new WindowAdapter() { @@ -131,8 +130,7 @@ public class ChatWindow extends JFrame { @Override public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER - && ((Settings.getInstance().isEnterToSend() && e.getModifiersEx() == 0) - || (e.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK))) { + && ((Settings.getInstance().isEnterToSend() && e.getModifiersEx() == 0) || (e.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK))) { postMessage(messageList); } } @@ -201,11 +199,7 @@ public class ChatWindow extends JFrame { final User user = selectedUserList.getSelectedValue(); client.setRecipient(user); - currentChat = localDB.getChats() - .stream() - .filter(chat -> chat.getRecipient().getID() == user.getID()) - .findFirst() - .get(); + currentChat = localDB.getChats().stream().filter(chat -> chat.getRecipient().getID() == user.getID()).findFirst().get(); // Set all unread messages in the chat to read readCurrentChat(); @@ -280,18 +274,14 @@ public class ChatWindow extends JFrame { private void postMessage(JList messageList) { if (!client.hasRecipient()) { - JOptionPane.showMessageDialog(this, - "Please select a recipient!", - "Cannot send message", - JOptionPane.INFORMATION_MESSAGE); + JOptionPane.showMessageDialog(this, "Please select a recipient!", "Cannot send message", JOptionPane.INFORMATION_MESSAGE); return; } if (!messageEnterTextArea.getText().isEmpty()) try { // Create and send message object - final Message message = localDB.createMessage(messageEnterTextArea.getText(), - currentChat.getRecipient().getID()); + final Message message = localDB.createMessage(messageEnterTextArea.getText(), currentChat.getRecipient().getID()); currentChat.appendMessage(message); messageList.setModel(currentChat.getModel()); @@ -341,8 +331,7 @@ public class ChatWindow extends JFrame { new Thread(() -> { // Synchronize - localDB.applySync( - client.sendSync(client.getSender().getID(), localDB.fillSync(client.getSender().getID()))); + localDB.applySync(client.sendSync(client.getSender().getID(), localDB.fillSync(client.getSender().getID()))); // Process unread messages localDB.addUnreadMessagesToLocalDB(); @@ -352,8 +341,7 @@ public class ChatWindow extends JFrame { readCurrentChat(); // Update UI - SwingUtilities - .invokeLater(() -> { updateUserStates(); contentPane.revalidate(); contentPane.repaint(); }); + SwingUtilities.invokeLater(() -> { updateUserStates(); contentPane.revalidate(); contentPane.repaint(); }); }).start(); }).start(); } diff --git a/src/main/java/envoy/client/ui/MessageListRenderer.java b/src/main/java/envoy/client/ui/MessageListRenderer.java index 2e6b65f..9be79c5 100644 --- a/src/main/java/envoy/client/ui/MessageListRenderer.java +++ b/src/main/java/envoy/client/ui/MessageListRenderer.java @@ -42,22 +42,18 @@ public class MessageListRenderer extends JLabel implements ListCellRenderer

%s

%s :%s", + setText(String.format("

%s

%s :%s", dateColor, date, textColor, diff --git a/src/main/java/envoy/client/ui/PrimaryTextArea.java b/src/main/java/envoy/client/ui/PrimaryTextArea.java index e4d6fa1..1fd5584 100644 --- a/src/main/java/envoy/client/ui/PrimaryTextArea.java +++ b/src/main/java/envoy/client/ui/PrimaryTextArea.java @@ -16,9 +16,8 @@ import javax.swing.border.EmptyBorder; */ public class PrimaryTextArea extends JTextArea { - private static final long serialVersionUID = 1L; - - private int arcSize; + private static final long serialVersionUID = -5829028696155434913L; + private int arcSize; /** * Creates the text area @@ -31,8 +30,8 @@ public class PrimaryTextArea extends JTextArea { /** * Creates the text area * - * @param arcSize - * @param borderSpace - the insets of the border on all four sides + * @param arcSize is the diameter of the arc at the four corners. + * @param borderSpace is the insets of the border on all four sides. * @since Envoy 0.2-alpha */ public PrimaryTextArea(int arcSize, int borderSpace) { diff --git a/src/main/java/envoy/client/ui/SettingsScreen.java b/src/main/java/envoy/client/ui/SettingsScreen.java index bd80c2e..1f57199 100644 --- a/src/main/java/envoy/client/ui/SettingsScreen.java +++ b/src/main/java/envoy/client/ui/SettingsScreen.java @@ -101,8 +101,7 @@ public class SettingsScreen extends JDialog { createNewThemeButton.setEnabled(false); - temporaryTheme = new Theme("temporaryTheme", - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); + temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); // Content pane GridBagLayout gbl_contentPanel = new GridBagLayout(); @@ -200,20 +199,8 @@ public class SettingsScreen extends JDialog { colorsPanel.setLayout(new BoxLayout(colorsPanel, BoxLayout.Y_AXIS)); colorsPanel.setAlignmentX(Component.LEFT_ALIGNMENT); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getBackgroundColor(), - "Background", - 1); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getCellColor(), - "Cells", - 2); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getBackgroundColor(), "Background", 1); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getCellColor(), "Cells", 2); buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), @@ -228,41 +215,11 @@ public class SettingsScreen extends JDialog { theme.getInteractableBackgroundColor(), "Interactable Background", 4); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getMessageColorChat(), - "Messages Chat", - 5); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getDateColorChat(), - "Date Chat", - 6); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getSelectionColor(), - "Selection", - 7); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getTypingMessageColor(), - "Typing Message", - 8); - buildCustomizeElement(new JPanel(), - new JButton(), - new JTextPane(), - theme, - theme.getUserNameColor(), - "User Names", - 9); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getMessageColorChat(), "Messages Chat", 5); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getDateColorChat(), "Date Chat", 6); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getSelectionColor(), "Selection", 7); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getTypingMessageColor(), "Typing Message", 8); + buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getUserNameColor(), "User Names", 9); GridBagConstraints gbc_colorsPanel = new GridBagConstraints(); gbc_colorsPanel.fill = GridBagConstraints.HORIZONTAL; @@ -283,16 +240,14 @@ public class SettingsScreen extends JDialog { String s = JOptionPane.showInputDialog("Enter a name for the new theme"); System.out.println(s); Settings.getInstance() - .addNewThemeToMap(new Theme(s, temporaryTheme.getBackgroundColor(), - temporaryTheme.getCellColor(), temporaryTheme.getInteractableForegroundColor(), - temporaryTheme.getInteractableBackgroundColor(), temporaryTheme.getMessageColorChat(), - temporaryTheme.getDateColorChat(), temporaryTheme.getSelectionColor(), + .addNewThemeToMap(new Theme(s, temporaryTheme.getBackgroundColor(), temporaryTheme.getCellColor(), + temporaryTheme.getInteractableForegroundColor(), temporaryTheme.getInteractableBackgroundColor(), + temporaryTheme.getMessageColorChat(), temporaryTheme.getDateColorChat(), temporaryTheme.getSelectionColor(), temporaryTheme.getTypingMessageColor(), temporaryTheme.getUserNameColor())); themeArray = Arrays.copyOf(themeArray, themeArray.length + 1); themeArray[themeArray.length - 1] = Settings.getInstance().getThemes().get(s).getThemeName(); - temporaryTheme = new Theme("temporaryTheme", - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); + temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); createNewThemeButton.setEnabled(false); themes.addItem(themeArray[themeArray.length - 1]); @@ -412,21 +367,12 @@ public class SettingsScreen extends JDialog { temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getBackgroundColor(), Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor(), - Settings.getInstance() - .getThemes() - .get(Settings.getInstance().getCurrentTheme()) - .getInteractableForegroundColor(), - Settings.getInstance() - .getThemes() - .get(Settings.getInstance().getCurrentTheme()) - .getInteractableBackgroundColor(), + Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getInteractableForegroundColor(), + Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getInteractableBackgroundColor(), Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageColorChat(), Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getDateColorChat(), Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getSelectionColor(), - Settings.getInstance() - .getThemes() - .get(Settings.getInstance().getCurrentTheme()) - .getTypingMessageColor(), + Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getTypingMessageColor(), Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor()); colorsPanel.removeAll(); @@ -513,8 +459,7 @@ public class SettingsScreen extends JDialog { private void setContent(JPanel content, GridBagConstraints layout) { contentPanel.add(content, layout); } - private void buildCustomizeElement(JPanel panel, JButton button, JTextPane textPane, Theme theme, Color color, - String name, int yIndex) { + private void buildCustomizeElement(JPanel panel, JButton button, JTextPane textPane, Theme theme, Color color, String name, int yIndex) { textPane.setFont(new Font("Arial", Font.PLAIN, 14)); textPane.setBackground(theme.getBackgroundColor()); textPane.setForeground(theme.getUserNameColor()); diff --git a/src/main/java/envoy/client/ui/Theme.java b/src/main/java/envoy/client/ui/Theme.java index a0ef259..7de0ea9 100644 --- a/src/main/java/envoy/client/ui/Theme.java +++ b/src/main/java/envoy/client/ui/Theme.java @@ -26,9 +26,8 @@ public class Theme implements Serializable { private Color selectionColor; private Color typingMessageColor; - public Theme(String themeName, Color backgroundColor, Color cellColor, Color interactableForegroundColor, - Color interactableBackgroundColor, Color messageColorChat, Color dateColorChat, Color selectionColor, - Color typingMessageColor, Color userNameColor) { + public Theme(String themeName, Color backgroundColor, Color cellColor, Color interactableForegroundColor, Color interactableBackgroundColor, + Color messageColorChat, Color dateColorChat, Color selectionColor, Color typingMessageColor, Color userNameColor) { this.themeName = themeName; @@ -42,11 +41,10 @@ public class Theme implements Serializable { this.typingMessageColor = typingMessageColor; this.userNameColor = userNameColor; } - + public Theme(String name, Theme other) { - this(name, other.backgroundColor, other.cellColor, other.interactableBackgroundColor, - other.interactableForegroundColor, other.messageColorChat, other.dateColorChat, other.selectionColor, - other.typingMessageColor, other.userNameColor); + this(name, other.backgroundColor, other.cellColor, other.interactableBackgroundColor, other.interactableForegroundColor, + other.messageColorChat, other.dateColorChat, other.selectionColor, other.typingMessageColor, other.userNameColor); } /** diff --git a/src/main/java/envoy/client/ui/UserListRenderer.java b/src/main/java/envoy/client/ui/UserListRenderer.java index c730e74..b145f28 100644 --- a/src/main/java/envoy/client/ui/UserListRenderer.java +++ b/src/main/java/envoy/client/ui/UserListRenderer.java @@ -44,23 +44,16 @@ public class UserListRenderer extends JLabel implements ListCellRenderer { final UserStatus status = value.getStatus(); // Getting the UserNameColor of the current theme - String textColor = null; - textColor = toHex( - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor()); + String textColor = null; + textColor = toHex(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor()); switch (status) { case ONLINE: - setText(String.format( - "

%s

%s", - status, - textColor, - name)); + setText(String + .format("

%s

%s", status, textColor, name)); break; case OFFLINE: - setText(String.format( - "

%s

%s", - status, - textColor, - name)); + setText(String + .format("

%s

%s", status, textColor, name)); break; } return this; From f0353c8c72738647647e8793bf601a6f70aecbfa Mon Sep 17 00:00:00 2001 From: kske Date: Sat, 14 Dec 2019 14:17:24 +0100 Subject: [PATCH 14/24] Added background execution --- src/main/java/envoy/client/ui/Startup.java | 6 +++++- src/main/java/envoy/client/ui/StatusTrayIcon.java | 11 +++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/envoy/client/ui/Startup.java b/src/main/java/envoy/client/ui/Startup.java index 933890d..53cbbc0 100644 --- a/src/main/java/envoy/client/ui/Startup.java +++ b/src/main/java/envoy/client/ui/Startup.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; +import javax.swing.JFrame; import javax.swing.JOptionPane; import envoy.client.Client; @@ -84,7 +85,7 @@ public class Startup { throw new EnvoyException("Could not enter offline mode: user name unknown"); client.setSender(clientUser); } catch(Exception e2) { - JOptionPane.showMessageDialog(null, e1.toString(), "Client error", JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(null, e2.toString(), "Client error", JOptionPane.ERROR_MESSAGE); System.exit(1); return; } @@ -118,6 +119,9 @@ public class Startup { try { new StatusTrayIcon(chatWindow).show(); + + // If the tray icon is supported, hide the chat window on close + chatWindow.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); } catch (EnvoyException e) { logger.warning("The StatusTrayIcon is not supported on this platform!"); } diff --git a/src/main/java/envoy/client/ui/StatusTrayIcon.java b/src/main/java/envoy/client/ui/StatusTrayIcon.java index 01cc8d7..03380c2 100644 --- a/src/main/java/envoy/client/ui/StatusTrayIcon.java +++ b/src/main/java/envoy/client/ui/StatusTrayIcon.java @@ -75,16 +75,15 @@ public class StatusTrayIcon implements EventHandler { focusTarget.addWindowFocusListener(new WindowAdapter() { @Override - public void windowGainedFocus(WindowEvent e) { - displayMessages = false; - } + public void windowGainedFocus(WindowEvent e) { displayMessages = false; } @Override - public void windowLostFocus(WindowEvent e) { - displayMessages = true; - } + public void windowLostFocus(WindowEvent e) { displayMessages = true; } }); + // Show the window if the user clicks on the icon + trayIcon.addActionListener((evt) -> { focusTarget.setVisible(true); focusTarget.requestFocus(); }); + // Start processing message events EventBus.getInstance().register(this); } From 4a2d6f913bfe2e6b64fa154fdd0f8e74fb558543 Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sat, 14 Dec 2019 19:10:45 +0100 Subject: [PATCH 15/24] Custom scroll bar * Added PrimaryScrollBar class * Implemented PrimaryScrollBar in ChatWindow for the ScrollPanes vertical scroll bar --- src/main/java/envoy/client/ui/ChatWindow.java | 11 +++ .../envoy/client/ui/PrimaryScrollBar.java | 95 +++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 src/main/java/envoy/client/ui/PrimaryScrollBar.java diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 1c562b6..a6510ec 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -1,5 +1,6 @@ package envoy.client.ui; +import java.awt.Color; import java.awt.ComponentOrientation; import java.awt.Font; import java.awt.GridBagConstraints; @@ -252,6 +253,16 @@ public class ChatWindow extends JFrame { // scrollPane scrollPane.setForeground(theme.getBackgroundColor()); scrollPane.setBackground(theme.getCellColor()); + // scrollPane.getVerticalScrollBar() + // .setBackground( + // new Color(theme.getBackgroundColor().getRed() + 50, + // theme.getBackgroundColor().getGreen() + 50, + // theme.getBackgroundColor().getBlue() + 50)); + scrollPane.getVerticalScrollBar().setBackground(theme.getCellColor()); + scrollPane.getVerticalScrollBar() + .setUI(new PrimaryScrollBar(5, theme.getInteractableBackgroundColor(), + new Color(theme.getInteractableBackgroundColor().getRGB() - 50), + new Color(theme.getInteractableBackgroundColor().getRGB() + 170))); // messageEnterTextArea messageEnterTextArea.setCaretColor(theme.getTypingMessageColor()); messageEnterTextArea.setForeground(theme.getTypingMessageColor()); diff --git a/src/main/java/envoy/client/ui/PrimaryScrollBar.java b/src/main/java/envoy/client/ui/PrimaryScrollBar.java new file mode 100644 index 0000000..aaaa0a0 --- /dev/null +++ b/src/main/java/envoy/client/ui/PrimaryScrollBar.java @@ -0,0 +1,95 @@ +package envoy.client.ui; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.plaf.basic.BasicScrollBarUI; + +import envoy.client.Settings; + +/** + * Project: envoy-client
+ * File: PrimaryScrollBar.javaEvent.java
+ * Created: 14.12.2019
+ * + * @author Maximilian Käfer + * @since Envoy v0.2-alpha + */ +public class PrimaryScrollBar extends BasicScrollBarUI{ + + private final Dimension d = new Dimension(); + private int arcSize; + private Color scrollBarColor; + private Color hoverColor; + private Color draggingColor; + + public PrimaryScrollBar(int arcSize, Color scrollBarColor, Color hoverColor, Color draggingColor) { + this.arcSize = arcSize; + this.scrollBarColor = scrollBarColor; + this.hoverColor = hoverColor; + this.draggingColor = draggingColor; + } + + @Override + protected JButton createDecreaseButton(int orientation) { + return new JButton() { + private static final long serialVersionUID = 1032443171070235890L; + + @Override + public Dimension getPreferredSize() { + return d; + } + }; + } + + @Override + protected JButton createIncreaseButton (int orientation) { + return new JButton() { + + private static final long serialVersionUID = 7575774542623215803L; + + @Override + public Dimension getPreferredSize() { + return d; + } + }; + } + @Override + protected void paintTrack(Graphics g, JComponent c, Rectangle r) { + } + + @Override + protected void paintThumb(Graphics g, JComponent c, Rectangle r) { + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + Color color = null; + JScrollBar sb = (JScrollBar) c; + if (!sb.isEnabled() || r.width > r.height) { + return; + } else if (isDragging) { + color = draggingColor; + } else if (isThumbRollover()) { + color = hoverColor; + } else { + color = scrollBarColor; + } + g2.setPaint(color); + g2.fillRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); + g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); + g2.drawRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); + g2.dispose(); + } + + @Override + protected void setThumbBounds(int x, int y, int width, int height) { + super.setThumbBounds(x, y, width, height); + scrollbar.repaint(); + } +} From 6bfa3c2b79426c01f5f85c418a5c77ce4eb51ffb Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sun, 15 Dec 2019 00:34:44 +0100 Subject: [PATCH 16/24] Horizontal Scroll Bar Implemented primaryScrollBar support for horizontal scroll bar as well. --- src/main/java/envoy/client/ui/ChatWindow.java | 10 ++++++- .../envoy/client/ui/PrimaryScrollBar.java | 26 ++++++++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index a6510ec..6968f5c 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -262,7 +262,15 @@ public class ChatWindow extends JFrame { scrollPane.getVerticalScrollBar() .setUI(new PrimaryScrollBar(5, theme.getInteractableBackgroundColor(), new Color(theme.getInteractableBackgroundColor().getRGB() - 50), - new Color(theme.getInteractableBackgroundColor().getRGB() + 170))); + new Color(theme.getInteractableBackgroundColor().getRGB() + 170), true)); + scrollPane.getHorizontalScrollBar().setBackground(theme.getCellColor()); + scrollPane.getHorizontalScrollBar() + .setUI(new PrimaryScrollBar(5, theme.getInteractableBackgroundColor(), new Color(theme.getInteractableBackgroundColor().getRGB() - 50), + new Color(theme.getInteractableBackgroundColor().getRGB() + 170), false)); + // int currentVerticalScrollBarValue = + // scrollPane.getVerticalScrollBar().getValue() + + // scrollPane.getVerticalScrollBar().getVisibleAmount(); Work in Progress for + // autoscroll // messageEnterTextArea messageEnterTextArea.setCaretColor(theme.getTypingMessageColor()); messageEnterTextArea.setForeground(theme.getTypingMessageColor()); diff --git a/src/main/java/envoy/client/ui/PrimaryScrollBar.java b/src/main/java/envoy/client/ui/PrimaryScrollBar.java index aaaa0a0..546119b 100644 --- a/src/main/java/envoy/client/ui/PrimaryScrollBar.java +++ b/src/main/java/envoy/client/ui/PrimaryScrollBar.java @@ -29,12 +29,14 @@ public class PrimaryScrollBar extends BasicScrollBarUI{ private Color scrollBarColor; private Color hoverColor; private Color draggingColor; + private boolean isVertical; - public PrimaryScrollBar(int arcSize, Color scrollBarColor, Color hoverColor, Color draggingColor) { + public PrimaryScrollBar(int arcSize, Color scrollBarColor, Color hoverColor, Color draggingColor, boolean isVertical) { this.arcSize = arcSize; this.scrollBarColor = scrollBarColor; this.hoverColor = hoverColor; this.draggingColor = draggingColor; + this.isVertical = isVertical; } @Override @@ -71,7 +73,7 @@ public class PrimaryScrollBar extends BasicScrollBarUI{ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Color color = null; JScrollBar sb = (JScrollBar) c; - if (!sb.isEnabled() || r.width > r.height) { + if (!sb.isEnabled() || (isVertical == true && r.width > r.height) || (isVertical == false && r.width < r.height)) { return; } else if (isDragging) { color = draggingColor; @@ -80,11 +82,21 @@ public class PrimaryScrollBar extends BasicScrollBarUI{ } else { color = scrollBarColor; } - g2.setPaint(color); - g2.fillRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); - g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); - g2.drawRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); - g2.dispose(); + + if (isVertical == true) { + g2.setPaint(color); + g2.fillRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); + g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); + g2.drawRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); + g2.dispose(); + } + if (isVertical == false) { + g2.setPaint(color); + g2.fillRoundRect(r.x, r.y + 9, r.width, r.height - 10, arcSize, arcSize); + g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); + g2.drawRoundRect(r.x, r.y + 9, r.width, r.height - 10, arcSize, arcSize); + g2.dispose(); + } } @Override From 3fefeb1082fef1091bf899c1ef2cddd5cc3e392b Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sun, 15 Dec 2019 12:48:40 +0100 Subject: [PATCH 17/24] Autoscroll * Implemented functionality to automatically scroll down when user is on the bottom of the chat and then there are new messages added. * When chat is opened, the vertical scroll bar starts at the bottom. * When rereading messages, the chat doesn't scroll down if new messages are added. (Besides see first point) --- src/main/java/envoy/client/ui/ChatWindow.java | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 6968f5c..134734f 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -63,6 +63,8 @@ public class ChatWindow extends JFrame { // private JCheckBox jCbChangeMode; private PrimaryButton postButton = new PrimaryButton("Post"); private PrimaryButton settingsButton = new PrimaryButton("Settings"); + private int verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum(); + private boolean chatOpened = false; private static int space = 4; @@ -208,6 +210,7 @@ public class ChatWindow extends JFrame { textPane.setText(currentChat.getRecipient().getName()); messageList.setModel(currentChat.getModel()); + chatOpened = true; contentPane.revalidate(); } }); @@ -253,11 +256,8 @@ public class ChatWindow extends JFrame { // scrollPane scrollPane.setForeground(theme.getBackgroundColor()); scrollPane.setBackground(theme.getCellColor()); - // scrollPane.getVerticalScrollBar() - // .setBackground( - // new Color(theme.getBackgroundColor().getRed() + 50, - // theme.getBackgroundColor().getGreen() + 50, - // theme.getBackgroundColor().getBlue() + 50)); + + // Scroll Bar Styling scrollPane.getVerticalScrollBar().setBackground(theme.getCellColor()); scrollPane.getVerticalScrollBar() .setUI(new PrimaryScrollBar(5, theme.getInteractableBackgroundColor(), @@ -267,10 +267,26 @@ public class ChatWindow extends JFrame { scrollPane.getHorizontalScrollBar() .setUI(new PrimaryScrollBar(5, theme.getInteractableBackgroundColor(), new Color(theme.getInteractableBackgroundColor().getRGB() - 50), new Color(theme.getInteractableBackgroundColor().getRGB() + 170), false)); - // int currentVerticalScrollBarValue = - // scrollPane.getVerticalScrollBar().getValue() + - // scrollPane.getVerticalScrollBar().getVisibleAmount(); Work in Progress for - // autoscroll + + // Autoscroll + scrollPane.getVerticalScrollBar().addAdjustmentListener(e -> { + if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0) { + return; + } + + if (chatOpened == true) { + e.getAdjustable().setValue(e.getAdjustable().getMaximum()); + verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum(); + chatOpened = false; + return; + } + if (scrollPane.getVerticalScrollBar().getValue() + + scrollPane.getVerticalScrollBar().getVisibleAmount() + 100 >= scrollPane.getVerticalScrollBar().getMaximum()) { + e.getAdjustable().setValue(e.getAdjustable().getMaximum()); + verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum(); + } + }); + // messageEnterTextArea messageEnterTextArea.setCaretColor(theme.getTypingMessageColor()); messageEnterTextArea.setForeground(theme.getTypingMessageColor()); From 4f777412f38c3bea6f742ed480b24ff1cee9d519 Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sun, 15 Dec 2019 12:53:01 +0100 Subject: [PATCH 18/24] Cold style improvement Changed if query with isVertical in PrimaryScrollBar to short form. --- src/main/java/envoy/client/ui/PrimaryScrollBar.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/envoy/client/ui/PrimaryScrollBar.java b/src/main/java/envoy/client/ui/PrimaryScrollBar.java index 546119b..a7dc073 100644 --- a/src/main/java/envoy/client/ui/PrimaryScrollBar.java +++ b/src/main/java/envoy/client/ui/PrimaryScrollBar.java @@ -83,14 +83,14 @@ public class PrimaryScrollBar extends BasicScrollBarUI{ color = scrollBarColor; } - if (isVertical == true) { + if (isVertical) { g2.setPaint(color); g2.fillRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); g2.drawRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); g2.dispose(); } - if (isVertical == false) { + if (!isVertical) { g2.setPaint(color); g2.fillRoundRect(r.x, r.y + 9, r.width, r.height - 10, arcSize, arcSize); g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); From adb5c417c541ed85bdce5b6d1583faed96127d97 Mon Sep 17 00:00:00 2001 From: kske Date: Sun, 15 Dec 2019 16:26:11 +0100 Subject: [PATCH 19/24] Improved code style and formatting --- src/main/java/envoy/client/ui/ChatWindow.java | 33 ++++---- .../envoy/client/ui/PrimaryScrollBar.java | 83 ++++++++----------- 2 files changed, 48 insertions(+), 68 deletions(-) diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 134734f..2e263da 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -49,22 +49,22 @@ public class ChatWindow extends JFrame { private static final long serialVersionUID = 6865098428255463649L; - // user specific objects + // User specific objects private Client client; private LocalDB localDB; + // GUI components - private JPanel contentPane = new JPanel(); - private PrimaryTextArea messageEnterTextArea = new PrimaryTextArea(space); - private JList userList = new JList<>(); + private JPanel contentPane = new JPanel(); + private PrimaryTextArea messageEnterTextArea = new PrimaryTextArea(space); + private JList userList = new JList<>(); private Chat currentChat; - private JList messageList = new JList<>(); - private JScrollPane scrollPane = new JScrollPane(); - private JTextPane textPane = new JTextPane(); - // private JCheckBox jCbChangeMode; - private PrimaryButton postButton = new PrimaryButton("Post"); - private PrimaryButton settingsButton = new PrimaryButton("Settings"); + private JList messageList = new JList<>(); + private JScrollPane scrollPane = new JScrollPane(); private int verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum(); private boolean chatOpened = false; + private JTextPane textPane = new JTextPane(); + private PrimaryButton postButton = new PrimaryButton("Post"); + private PrimaryButton settingsButton = new PrimaryButton("Settings"); private static int space = 4; @@ -239,7 +239,7 @@ public class ChatWindow extends JFrame { /** * Used to immediately reload the ChatWindow when settings were changed. - * + * * @since Envoy v0.1-alpha */ public void changeChatWindowColors(String key) { @@ -260,8 +260,7 @@ public class ChatWindow extends JFrame { // Scroll Bar Styling scrollPane.getVerticalScrollBar().setBackground(theme.getCellColor()); scrollPane.getVerticalScrollBar() - .setUI(new PrimaryScrollBar(5, theme.getInteractableBackgroundColor(), - new Color(theme.getInteractableBackgroundColor().getRGB() - 50), + .setUI(new PrimaryScrollBar(5, theme.getInteractableBackgroundColor(), new Color(theme.getInteractableBackgroundColor().getRGB() - 50), new Color(theme.getInteractableBackgroundColor().getRGB() + 170), true)); scrollPane.getHorizontalScrollBar().setBackground(theme.getCellColor()); scrollPane.getHorizontalScrollBar() @@ -270,9 +269,7 @@ public class ChatWindow extends JFrame { // Autoscroll scrollPane.getVerticalScrollBar().addAdjustmentListener(e -> { - if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0) { - return; - } + if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0) { return; } if (chatOpened == true) { e.getAdjustable().setValue(e.getAdjustable().getMaximum()); @@ -280,8 +277,8 @@ public class ChatWindow extends JFrame { chatOpened = false; return; } - if (scrollPane.getVerticalScrollBar().getValue() - + scrollPane.getVerticalScrollBar().getVisibleAmount() + 100 >= scrollPane.getVerticalScrollBar().getMaximum()) { + if (scrollPane.getVerticalScrollBar().getValue() + scrollPane.getVerticalScrollBar().getVisibleAmount() + + 100 >= scrollPane.getVerticalScrollBar().getMaximum()) { e.getAdjustable().setValue(e.getAdjustable().getMaximum()); verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum(); } diff --git a/src/main/java/envoy/client/ui/PrimaryScrollBar.java b/src/main/java/envoy/client/ui/PrimaryScrollBar.java index a7dc073..845448c 100644 --- a/src/main/java/envoy/client/ui/PrimaryScrollBar.java +++ b/src/main/java/envoy/client/ui/PrimaryScrollBar.java @@ -16,23 +16,23 @@ import envoy.client.Settings; /** * Project: envoy-client
- * File: PrimaryScrollBar.javaEvent.java
+ * File: PrimaryScrollBar.java
* Created: 14.12.2019
- * + * * @author Maximilian Käfer * @since Envoy v0.2-alpha */ -public class PrimaryScrollBar extends BasicScrollBarUI{ - +public class PrimaryScrollBar extends BasicScrollBarUI { + private final Dimension d = new Dimension(); - private int arcSize; - private Color scrollBarColor; - private Color hoverColor; - private Color draggingColor; - private boolean isVertical; - + private final int arcSize; + private final Color scrollBarColor; + private final Color hoverColor; + private final Color draggingColor; + private final boolean isVertical; + public PrimaryScrollBar(int arcSize, Color scrollBarColor, Color hoverColor, Color draggingColor, boolean isVertical) { - this.arcSize = arcSize; + this.arcSize = arcSize; this.scrollBarColor = scrollBarColor; this.hoverColor = hoverColor; this.draggingColor = draggingColor; @@ -41,62 +41,45 @@ public class PrimaryScrollBar extends BasicScrollBarUI{ @Override protected JButton createDecreaseButton(int orientation) { - return new JButton() { - private static final long serialVersionUID = 1032443171070235890L; - - @Override - public Dimension getPreferredSize() { - return d; - } - }; + JButton button = new JButton(); + button.setPreferredSize(d); + return button; } - + @Override - protected JButton createIncreaseButton (int orientation) { - return new JButton() { - - private static final long serialVersionUID = 7575774542623215803L; - - @Override - public Dimension getPreferredSize() { - return d; - } - }; + protected JButton createIncreaseButton(int orientation) { + JButton button = new JButton(); + button.setPreferredSize(d); + return button; } + @Override - protected void paintTrack(Graphics g, JComponent c, Rectangle r) { - } - + protected void paintTrack(Graphics g, JComponent c, Rectangle r) {} + @Override protected void paintThumb(Graphics g, JComponent c, Rectangle r) { Graphics2D g2 = (Graphics2D) g.create(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - Color color = null; - JScrollBar sb = (JScrollBar) c; - if (!sb.isEnabled() || (isVertical == true && r.width > r.height) || (isVertical == false && r.width < r.height)) { - return; - } else if (isDragging) { - color = draggingColor; - } else if (isThumbRollover()) { - color = hoverColor; - } else { - color = scrollBarColor; - } + Color color; + JScrollBar sb = (JScrollBar) c; + if (!sb.isEnabled() || (isVertical && r.width > r.height) || (!isVertical && r.width < r.height)) return; + + if (isDragging) color = draggingColor; + else if (isThumbRollover()) color = hoverColor; + else color = scrollBarColor; + + g2.setPaint(color); if (isVertical) { - g2.setPaint(color); g2.fillRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); g2.drawRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); - g2.dispose(); - } - if (!isVertical) { - g2.setPaint(color); + } else { g2.fillRoundRect(r.x, r.y + 9, r.width, r.height - 10, arcSize, arcSize); g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); g2.drawRoundRect(r.x, r.y + 9, r.width, r.height - 10, arcSize, arcSize); - g2.dispose(); } + g2.dispose(); } @Override From acc7424503740bf054b21d3ef39099674ec3b454 Mon Sep 17 00:00:00 2001 From: kske Date: Sun, 15 Dec 2019 17:44:13 +0100 Subject: [PATCH 20/24] Added PrimaryScrollPane class with default scroll pane UI settings --- src/main/java/envoy/client/ui/ChatWindow.java | 55 ++++--------------- .../envoy/client/ui/PrimaryScrollBar.java | 5 ++ .../envoy/client/ui/PrimaryScrollPane.java | 48 ++++++++++++++++ 3 files changed, 64 insertions(+), 44 deletions(-) create mode 100644 src/main/java/envoy/client/ui/PrimaryScrollPane.java diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 2e263da..3a28754 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -1,6 +1,5 @@ package envoy.client.ui; -import java.awt.Color; import java.awt.ComponentOrientation; import java.awt.Font; import java.awt.GridBagConstraints; @@ -20,7 +19,6 @@ import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; -import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; @@ -54,17 +52,15 @@ public class ChatWindow extends JFrame { private LocalDB localDB; // GUI components - private JPanel contentPane = new JPanel(); - private PrimaryTextArea messageEnterTextArea = new PrimaryTextArea(space); - private JList userList = new JList<>(); - private Chat currentChat; - private JList messageList = new JList<>(); - private JScrollPane scrollPane = new JScrollPane(); - private int verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum(); - private boolean chatOpened = false; - private JTextPane textPane = new JTextPane(); - private PrimaryButton postButton = new PrimaryButton("Post"); - private PrimaryButton settingsButton = new PrimaryButton("Settings"); + private JPanel contentPane = new JPanel(); + private PrimaryTextArea messageEnterTextArea = new PrimaryTextArea(space); + private JList userList = new JList<>(); + private Chat currentChat; + private JList messageList = new JList<>(); + private PrimaryScrollPane scrollPane = new PrimaryScrollPane(); + private JTextPane textPane = new JTextPane(); + private PrimaryButton postButton = new PrimaryButton("Post"); + private PrimaryButton settingsButton = new PrimaryButton("Settings"); private static int space = 4; @@ -115,7 +111,6 @@ public class ChatWindow extends JFrame { messageList.setBorder(new EmptyBorder(space, space, space, space)); scrollPane.setViewportView(messageList); - scrollPane.setBorder(null); GridBagConstraints gbc_scrollPane = new GridBagConstraints(); gbc_scrollPane.fill = GridBagConstraints.BOTH; @@ -210,7 +205,7 @@ public class ChatWindow extends JFrame { textPane.setText(currentChat.getRecipient().getName()); messageList.setModel(currentChat.getModel()); - chatOpened = true; + scrollPane.setChatOpened(true); contentPane.revalidate(); } }); @@ -254,35 +249,7 @@ public class ChatWindow extends JFrame { messageList.setForeground(theme.getMessageColorChat()); messageList.setBackground(theme.getCellColor()); // scrollPane - scrollPane.setForeground(theme.getBackgroundColor()); - scrollPane.setBackground(theme.getCellColor()); - - // Scroll Bar Styling - scrollPane.getVerticalScrollBar().setBackground(theme.getCellColor()); - scrollPane.getVerticalScrollBar() - .setUI(new PrimaryScrollBar(5, theme.getInteractableBackgroundColor(), new Color(theme.getInteractableBackgroundColor().getRGB() - 50), - new Color(theme.getInteractableBackgroundColor().getRGB() + 170), true)); - scrollPane.getHorizontalScrollBar().setBackground(theme.getCellColor()); - scrollPane.getHorizontalScrollBar() - .setUI(new PrimaryScrollBar(5, theme.getInteractableBackgroundColor(), new Color(theme.getInteractableBackgroundColor().getRGB() - 50), - new Color(theme.getInteractableBackgroundColor().getRGB() + 170), false)); - - // Autoscroll - scrollPane.getVerticalScrollBar().addAdjustmentListener(e -> { - if ((verticalScrollBarMaximumValue - e.getAdjustable().getMaximum()) == 0) { return; } - - if (chatOpened == true) { - e.getAdjustable().setValue(e.getAdjustable().getMaximum()); - verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum(); - chatOpened = false; - return; - } - if (scrollPane.getVerticalScrollBar().getValue() + scrollPane.getVerticalScrollBar().getVisibleAmount() - + 100 >= scrollPane.getVerticalScrollBar().getMaximum()) { - e.getAdjustable().setValue(e.getAdjustable().getMaximum()); - verticalScrollBarMaximumValue = scrollPane.getVerticalScrollBar().getMaximum(); - } - }); + scrollPane.applyTheme(theme); // messageEnterTextArea messageEnterTextArea.setCaretColor(theme.getTypingMessageColor()); diff --git a/src/main/java/envoy/client/ui/PrimaryScrollBar.java b/src/main/java/envoy/client/ui/PrimaryScrollBar.java index 845448c..6853d8f 100644 --- a/src/main/java/envoy/client/ui/PrimaryScrollBar.java +++ b/src/main/java/envoy/client/ui/PrimaryScrollBar.java @@ -39,6 +39,11 @@ public class PrimaryScrollBar extends BasicScrollBarUI { this.isVertical = isVertical; } + public PrimaryScrollBar(Theme theme, boolean isVertical) { + this(5, theme.getInteractableBackgroundColor(), new Color(theme.getInteractableBackgroundColor().getRGB() - 50), + new Color(theme.getInteractableBackgroundColor().getRGB() + 170), isVertical); + } + @Override protected JButton createDecreaseButton(int orientation) { JButton button = new JButton(); diff --git a/src/main/java/envoy/client/ui/PrimaryScrollPane.java b/src/main/java/envoy/client/ui/PrimaryScrollPane.java new file mode 100644 index 0000000..d4e0b28 --- /dev/null +++ b/src/main/java/envoy/client/ui/PrimaryScrollPane.java @@ -0,0 +1,48 @@ +package envoy.client.ui; + +import javax.swing.JScrollPane; + +/** + * Project: envoy-client
+ * File: PrimaryScrollPane.java
+ * Created: 15 Dec 2019
+ * + * @author Kai S. K. Engelbart + */ +public class PrimaryScrollPane extends JScrollPane { + + private static final long serialVersionUID = -4786837444056228439L; + + private int verticalScrollBarMaximum = getVerticalScrollBar().getMaximum(); + private boolean chatOpened = false; + + public PrimaryScrollPane() { setBorder(null); } + + public void applyTheme(Theme theme) { + setForeground(theme.getBackgroundColor()); + setBackground(theme.getCellColor()); + + getVerticalScrollBar().setBackground(theme.getCellColor()); + getVerticalScrollBar().setUI(new PrimaryScrollBar(theme, true)); + getHorizontalScrollBar().setBackground(theme.getCellColor()); + getHorizontalScrollBar().setUI(new PrimaryScrollBar(theme, false)); + + // Automatic scrolling to the bottom + getVerticalScrollBar().addAdjustmentListener(e -> { + if (verticalScrollBarMaximum == e.getAdjustable().getMaximum()) return; + + if (chatOpened) { + e.getAdjustable().setValue(e.getAdjustable().getMaximum()); + verticalScrollBarMaximum = getVerticalScrollBar().getMaximum(); + chatOpened = false; + return; + } + if (getVerticalScrollBar().getValue() + getVerticalScrollBar().getVisibleAmount() + 100 >= getVerticalScrollBar().getMaximum()) { + e.getAdjustable().setValue(e.getAdjustable().getMaximum()); + verticalScrollBarMaximum = getVerticalScrollBar().getMaximum(); + } + }); + } + + public void setChatOpened(boolean chatOpened) { this.chatOpened = chatOpened; } +} From f6bd6ab754310acd0ccdd23089c4e9a2dfa53a83 Mon Sep 17 00:00:00 2001 From: DieGurke <55625494+DieGurke@users.noreply.github.com> Date: Sun, 15 Dec 2019 20:18:43 +0100 Subject: [PATCH 21/24] Formatting * Split applyTheme method in applyTheme and autoscroll. * Added Javadoc --- src/main/java/envoy/client/ui/ChatWindow.java | 1 + .../envoy/client/ui/PrimaryScrollPane.java | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 3a28754..9595d43 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -250,6 +250,7 @@ public class ChatWindow extends JFrame { messageList.setBackground(theme.getCellColor()); // scrollPane scrollPane.applyTheme(theme); + scrollPane.autoscroll(); // messageEnterTextArea messageEnterTextArea.setCaretColor(theme.getTypingMessageColor()); diff --git a/src/main/java/envoy/client/ui/PrimaryScrollPane.java b/src/main/java/envoy/client/ui/PrimaryScrollPane.java index d4e0b28..904806a 100644 --- a/src/main/java/envoy/client/ui/PrimaryScrollPane.java +++ b/src/main/java/envoy/client/ui/PrimaryScrollPane.java @@ -8,6 +8,7 @@ import javax.swing.JScrollPane; * Created: 15 Dec 2019
* * @author Kai S. K. Engelbart + * @author Maximilian Käfer */ public class PrimaryScrollPane extends JScrollPane { @@ -18,6 +19,12 @@ public class PrimaryScrollPane extends JScrollPane { public PrimaryScrollPane() { setBorder(null); } + /** + * Styles the vertical and horizontal scroll bars. + * + * @param theme + * @since Envoy v0.2-alpha + */ public void applyTheme(Theme theme) { setForeground(theme.getBackgroundColor()); setBackground(theme.getCellColor()); @@ -26,7 +33,22 @@ public class PrimaryScrollPane extends JScrollPane { getVerticalScrollBar().setUI(new PrimaryScrollBar(theme, true)); getHorizontalScrollBar().setBackground(theme.getCellColor()); getHorizontalScrollBar().setUI(new PrimaryScrollBar(theme, false)); + } + /** + * Implements autoscroll functionality for the vertical scroll bar.
+ *
+ * Functionality to automatically scroll down when user views
+ * the bottom of the chat while there are new messages added.
+ *
+ * When chat is opened, the vertical scroll bar starts at the bottom.
+ *
+ * When rereading messages, the chat doesn't scroll down if new messages
+ * are added. (Besides see first point) + * + * @since Envoy v0.2-alpha + */ + public void autoscroll() { // Automatic scrolling to the bottom getVerticalScrollBar().addAdjustmentListener(e -> { if (verticalScrollBarMaximum == e.getAdjustable().getMaximum()) return; From 396686bfdcf53e29e1739f87376c4612c814e266 Mon Sep 17 00:00:00 2001 From: kske Date: Mon, 16 Dec 2019 09:41:21 +0100 Subject: [PATCH 22/24] Added ThemeChangeEvent, improved EventHandler declaration --- src/main/java/envoy/client/event/Event.java | 6 +-- .../java/envoy/client/event/EventBus.java | 40 +++++++++------ .../java/envoy/client/event/EventHandler.java | 11 +--- .../envoy/client/event/ThemeChangeEvent.java | 20 ++++++++ src/main/java/envoy/client/ui/ChatWindow.java | 11 ++-- .../java/envoy/client/ui/SettingsScreen.java | 50 +++++++------------ .../java/envoy/client/ui/StatusTrayIcon.java | 38 ++------------ 7 files changed, 79 insertions(+), 97 deletions(-) create mode 100644 src/main/java/envoy/client/event/ThemeChangeEvent.java diff --git a/src/main/java/envoy/client/event/Event.java b/src/main/java/envoy/client/event/Event.java index 9db2477..4a3264d 100644 --- a/src/main/java/envoy/client/event/Event.java +++ b/src/main/java/envoy/client/event/Event.java @@ -1,10 +1,10 @@ package envoy.client.event; /** - * Project: envoy-clientChess
- * File: Event.javaEvent.java
+ * Project: envoy-client
+ * File: Event.java
* Created: 04.12.2019
- * + * * @author Kai S. K. Engelbart * @since Envoy v0.2-alpha */ diff --git a/src/main/java/envoy/client/event/EventBus.java b/src/main/java/envoy/client/event/EventBus.java index f6da3f5..06b385f 100644 --- a/src/main/java/envoy/client/event/EventBus.java +++ b/src/main/java/envoy/client/event/EventBus.java @@ -1,8 +1,9 @@ package envoy.client.event; import java.util.ArrayList; -import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * This class handles events by allowing {@link EventHandler} object to register @@ -10,11 +11,12 @@ import java.util.List; * bus.
*
* The event bus is a singleton and can be used across the entire application to - * guarantee the propagation of events. + * guarantee the propagation of events.
+ * * Project: envoy-client
* File: EventBus.java
* Created: 04.12.2019
- * + * * @author Kai S. K. Engelbart * @since Envoy v0.2-alpha */ @@ -22,9 +24,10 @@ public class EventBus { /** * Contains all {@link EventHandler} instances registered at this - * {@link EventBus}. + * {@link EventBus} as values mapped to by their supported {@link Event} + * classes. */ - private List handlers = new ArrayList<>(); + private Map>, List> handlers = new HashMap<>(); /** * The singleton instance of this {@link EventBus} that is used across the @@ -46,26 +49,33 @@ public class EventBus { public static EventBus getInstance() { return eventBus; } /** - * Registers a list of {@link EventHandler} objects to be notified when a - * {@link Event} is dispatched that they are subscribed to. - * - * @param handlers the {@link EventHandler} objects to register + * Registers an {@link EventHandler} to be notified when a + * {@link Event} of a certain type is dispatched. + * + * @param eventClass the class which the {@link EventHandler} is subscribed to + * @param handler the {@link EventHandler} to register * @since Envoy v0.2-alpha */ - public void register(EventHandler... handlers) { this.handlers.addAll(Arrays.asList(handlers)); } + public void register(Class> eventClass, EventHandler handler) { + if (!handlers.containsKey(eventClass)) handlers.put(eventClass, new ArrayList<>()); + handlers.get(eventClass).add(handler); + } /** * Dispatches a {@link Event} to every {@link EventHandler} subscribed to it. - * + * * @param event the {@link Event} to dispatch * @since Envoy v0.2-alpha */ - public void dispatch(Event event) { handlers.stream().filter(h -> h.supports().contains(event.getClass())).forEach(h -> h.handle(event)); } + public void dispatch(Event event) { + handlers.keySet().stream().filter(event.getClass()::isAssignableFrom).map(handlers::get).flatMap(List::stream).forEach(h -> h.handle(event)); + } /** - * @return a list of all {@link EventHandler} instances currently registered at - * this {@link EventBus} + * @return a map of all {@link EventHandler} instances currently registered at + * this {@link EventBus} with the {@link Event} classes they are + * subscribed to as keys * @since Envoy v0.2-alpha */ - public List getHandlers() { return handlers; } + public Map>, List> getHandlers() { return handlers; } } diff --git a/src/main/java/envoy/client/event/EventHandler.java b/src/main/java/envoy/client/event/EventHandler.java index a6e5b81..ef3daea 100644 --- a/src/main/java/envoy/client/event/EventHandler.java +++ b/src/main/java/envoy/client/event/EventHandler.java @@ -1,25 +1,18 @@ package envoy.client.event; -import java.util.Set; - /** * Project: envoy-clientChess
* File: EventHandler.javaEvent.java
* Created: 04.12.2019
- * + * * @author Kai S. K. Engelbart */ public interface EventHandler { /** * Consumes an event dispatched by the event bus. - * + * * @param event The event dispatched by the event bus, only of supported type */ void handle(Event event); - - /** - * @return A set of classes this class is supposed to handle in events - */ - Set>> supports(); } diff --git a/src/main/java/envoy/client/event/ThemeChangeEvent.java b/src/main/java/envoy/client/event/ThemeChangeEvent.java new file mode 100644 index 0000000..d3ba96b --- /dev/null +++ b/src/main/java/envoy/client/event/ThemeChangeEvent.java @@ -0,0 +1,20 @@ +package envoy.client.event; + +import envoy.client.ui.Theme; + +/** + * Project: envoy-client
+ * File: ThemeChangeEvent.java
+ * Created: 15 Dec 2019
+ * + * @author Kai S. K. Engelbart + */ +public class ThemeChangeEvent implements Event { + + private final Theme theme; + + public ThemeChangeEvent(Theme theme) { this.theme = theme; } + + @Override + public Theme get() { return theme; } +} diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 9595d43..49c73df 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -30,6 +30,8 @@ import envoy.client.Client; import envoy.client.Config; import envoy.client.LocalDB; import envoy.client.Settings; +import envoy.client.event.EventBus; +import envoy.client.event.ThemeChangeEvent; import envoy.schema.Message; import envoy.schema.User; @@ -166,7 +168,6 @@ public class ChatWindow extends JFrame { settingsButton.addActionListener((evt) -> { try { SettingsScreen.open(); - changeChatWindowColors(Settings.getInstance().getCurrentTheme()); } catch (Exception e) { SettingsScreen.open(); logger.log(Level.WARNING, "An error occured while opening the settings screen", e); @@ -220,11 +221,13 @@ public class ChatWindow extends JFrame { gbc_userList.anchor = GridBagConstraints.PAGE_START; gbc_userList.insets = new Insets(space, space, space, space); - changeChatWindowColors(Settings.getInstance().getCurrentTheme()); + changeChatWindowColors(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); contentPane.add(userList, gbc_userList); contentPane.revalidate(); + EventBus.getInstance().register(ThemeChangeEvent.class, (evt) -> changeChatWindowColors((Theme) evt.get())); + loadUsersAndChats(); if (client.isOnline()) startSyncThread(Config.getInstance().getSyncTimeout()); @@ -237,9 +240,7 @@ public class ChatWindow extends JFrame { * * @since Envoy v0.1-alpha */ - public void changeChatWindowColors(String key) { - Theme theme = Settings.getInstance().getThemes().get(key); - + private void changeChatWindowColors(Theme theme) { // contentPane contentPane.setBackground(theme.getBackgroundColor()); contentPane.setForeground(theme.getUserNameColor()); diff --git a/src/main/java/envoy/client/ui/SettingsScreen.java b/src/main/java/envoy/client/ui/SettingsScreen.java index 161365d..fc0ebda 100644 --- a/src/main/java/envoy/client/ui/SettingsScreen.java +++ b/src/main/java/envoy/client/ui/SettingsScreen.java @@ -27,14 +27,16 @@ import javax.swing.ListSelectionModel; import envoy.client.LocalDB; import envoy.client.Settings; +import envoy.client.event.EventBus; +import envoy.client.event.ThemeChangeEvent; /** * This class provides the GUI to change the user specific settings. - * + * * Project: envoy-client
* File: SettingsScreen.java
* Created: 31 Oct 2019
- * + * * @author Leon Hofmeister * @author Maximilian Käfer * @author Kai S. K. Engelbart @@ -45,12 +47,12 @@ public class SettingsScreen extends JDialog { private final JPanel contentPanel = new JPanel(); private DefaultListModel optionsListModel = new DefaultListModel<>(); - private final JList options = new JList(); + private final JList options = new JList<>(); private JPanel buttonPane = new JPanel(); private JPanel themeContent = new JPanel(); private String[] themeArray = Settings.getInstance().getThemes().keySet().toArray(new String[0]); - private JComboBox themes = new JComboBox(themeArray); + private JComboBox themes = new JComboBox<>(themeArray); private GridBagConstraints gbc_themeContent = new GridBagConstraints(); @@ -63,8 +65,7 @@ public class SettingsScreen extends JDialog { private JButton cancelButton = new JButton("Cancel"); private static int space = 5; - private boolean colorChanged = false; - private Theme temporaryTheme; + private Theme temporaryTheme; private static final Logger logger = Logger.getLogger(LocalDB.class.getSimpleName()); @@ -77,7 +78,7 @@ public class SettingsScreen extends JDialog { /** * Opens the settings screen.
- * + * * @since Envoy v0.1-alpha */ public static void open() { @@ -89,7 +90,7 @@ public class SettingsScreen extends JDialog { /** * Builds the settings screen. - * + * * @since Envoy v0.1-alpha */ private SettingsScreen() { @@ -296,9 +297,10 @@ public class SettingsScreen extends JDialog { Settings.getInstance().setCurrentTheme(selectedTheme.getThemeName()); System.out.println(selectedTheme.getThemeName()); - changeSettingsScreenColors(Settings.getInstance().getCurrentTheme()); - updateColorVariables(Settings.getInstance().getCurrentTheme()); - + final Theme currentTheme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()); + changeSettingsScreenColors(currentTheme); + updateColorVariables(currentTheme); + EventBus.getInstance().dispatch(new ThemeChangeEvent(currentTheme)); Settings.getInstance().save(); revalidate(); @@ -310,11 +312,10 @@ public class SettingsScreen extends JDialog { }); } } - changeSettingsScreenColors(Settings.getInstance().getCurrentTheme()); + changeSettingsScreenColors(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); } - private void changeSettingsScreenColors(String key) { - Theme theme = Settings.getInstance().getThemes().get(key); + private void changeSettingsScreenColors(Theme theme) { // whole JDialog setBackground(theme.getBackgroundColor()); // contentPanel @@ -345,19 +346,8 @@ public class SettingsScreen extends JDialog { } - private void updateColorVariables(String key) { - Theme theme = Settings.getInstance().getThemes().get(key); - - temporaryTheme = new Theme("temporaryTheme", - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getBackgroundColor(), - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor(), - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getInteractableForegroundColor(), - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getInteractableBackgroundColor(), - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageColorChat(), - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getDateColorChat(), - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getSelectionColor(), - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getTypingMessageColor(), - Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor()); + private void updateColorVariables(Theme theme) { + temporaryTheme = new Theme("temporaryTheme", theme); colorsPanel.removeAll(); @@ -462,7 +452,6 @@ public class SettingsScreen extends JDialog { // TODO: When Theme changed in same settings screen, color variable doesnt // update. temporaryTheme.setColor(yIndex, newColor); - colorChanged = true; createNewThemeButton.setEnabled(true); } button.setBackground(newColor); @@ -481,8 +470,5 @@ public class SettingsScreen extends JDialog { colorsPanel.add(panel); } - private Color getInvertedColor(Color color) { - return new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue()); - } - + private Color getInvertedColor(Color color) { return new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue()); } } diff --git a/src/main/java/envoy/client/ui/StatusTrayIcon.java b/src/main/java/envoy/client/ui/StatusTrayIcon.java index 03380c2..4670377 100644 --- a/src/main/java/envoy/client/ui/StatusTrayIcon.java +++ b/src/main/java/envoy/client/ui/StatusTrayIcon.java @@ -11,12 +11,8 @@ 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; @@ -29,7 +25,7 @@ import envoy.schema.Message; * @author Kai S. K. Engelbart * @since Envoy v0.2-alpha */ -public class StatusTrayIcon implements EventHandler { +public class StatusTrayIcon { /** * The {@link TrayIcon} provided by the System Tray API for controlling the @@ -85,7 +81,10 @@ public class StatusTrayIcon implements EventHandler { trayIcon.addActionListener((evt) -> { focusTarget.setVisible(true); focusTarget.requestFocus(); }); // Start processing message events - EventBus.getInstance().register(this); + EventBus.getInstance().register(MessageCreationEvent.class, (evt) -> { + if (displayMessages) + trayIcon.displayMessage("New message received", ((MessageCreationEvent) evt).get().getContent().get(0).getText(), MessageType.INFO); + }); } /** @@ -102,31 +101,4 @@ public class StatusTrayIcon implements EventHandler { 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>> supports() { - Set>> supportedEvents = new HashSet<>(); - supportedEvents.add(MessageCreationEvent.class); - return supportedEvents; - } } From 69153005cd661544a39005df4c2574b9c8ebe809 Mon Sep 17 00:00:00 2001 From: kske Date: Tue, 17 Dec 2019 08:17:22 +0100 Subject: [PATCH 23/24] Fixed vertical scroll bar drawing on 4K monitors --- src/main/java/envoy/client/ui/ChatWindow.java | 1 - src/main/java/envoy/client/ui/PrimaryScrollBar.java | 6 +++--- src/main/java/envoy/client/ui/PrimaryScrollPane.java | 5 +++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index 49c73df..910180c 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -195,7 +195,6 @@ public class ChatWindow extends JFrame { @SuppressWarnings("unchecked") final JList selectedUserList = (JList) listSelectionEvent.getSource(); final User user = selectedUserList.getSelectedValue(); - client.setRecipient(user); currentChat = localDB.getChats().stream().filter(chat -> chat.getRecipient().getID() == user.getID()).findFirst().get(); diff --git a/src/main/java/envoy/client/ui/PrimaryScrollBar.java b/src/main/java/envoy/client/ui/PrimaryScrollBar.java index 6853d8f..20bed6c 100644 --- a/src/main/java/envoy/client/ui/PrimaryScrollBar.java +++ b/src/main/java/envoy/client/ui/PrimaryScrollBar.java @@ -68,7 +68,7 @@ public class PrimaryScrollBar extends BasicScrollBarUI { Color color; JScrollBar sb = (JScrollBar) c; - if (!sb.isEnabled() || (isVertical && r.width > r.height) || (!isVertical && r.width < r.height)) return; + if (!sb.isEnabled()) return; if (isDragging) color = draggingColor; else if (isThumbRollover()) color = hoverColor; @@ -76,9 +76,9 @@ public class PrimaryScrollBar extends BasicScrollBarUI { g2.setPaint(color); if (isVertical) { - g2.fillRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); + g2.fillRoundRect(r.x - 9, r.y, r.width, r.height, arcSize, arcSize); g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); - g2.drawRoundRect(r.x + 9, r.y, r.width - 10, r.height, arcSize, arcSize); + g2.drawRoundRect(r.x - 9, r.y, r.width, r.height, arcSize, arcSize); } else { g2.fillRoundRect(r.x, r.y + 9, r.width, r.height - 10, arcSize, arcSize); g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); diff --git a/src/main/java/envoy/client/ui/PrimaryScrollPane.java b/src/main/java/envoy/client/ui/PrimaryScrollPane.java index 904806a..61c348a 100644 --- a/src/main/java/envoy/client/ui/PrimaryScrollPane.java +++ b/src/main/java/envoy/client/ui/PrimaryScrollPane.java @@ -21,7 +21,7 @@ public class PrimaryScrollPane extends JScrollPane { /** * Styles the vertical and horizontal scroll bars. - * + * * @param theme * @since Envoy v0.2-alpha */ @@ -31,6 +31,7 @@ public class PrimaryScrollPane extends JScrollPane { getVerticalScrollBar().setBackground(theme.getCellColor()); getVerticalScrollBar().setUI(new PrimaryScrollBar(theme, true)); + getHorizontalScrollBar().setBackground(theme.getCellColor()); getHorizontalScrollBar().setUI(new PrimaryScrollBar(theme, false)); } @@ -45,7 +46,7 @@ public class PrimaryScrollPane extends JScrollPane { *
* When rereading messages, the chat doesn't scroll down if new messages
* are added. (Besides see first point) - * + * * @since Envoy v0.2-alpha */ public void autoscroll() { From 500555c8dbfb6ebdc64a8221dd65731529a93328 Mon Sep 17 00:00:00 2001 From: kske Date: Wed, 18 Dec 2019 22:07:05 +0100 Subject: [PATCH 24/24] Added Javadoc requested by @delvh --- .../java/envoy/client/ui/PrimaryButton.java | 10 +- .../envoy/client/ui/PrimaryScrollBar.java | 210 ++++++++++-------- .../envoy/client/ui/PrimaryScrollPane.java | 12 + 3 files changed, 132 insertions(+), 100 deletions(-) diff --git a/src/main/java/envoy/client/ui/PrimaryButton.java b/src/main/java/envoy/client/ui/PrimaryButton.java index fe93571..65c52a0 100644 --- a/src/main/java/envoy/client/ui/PrimaryButton.java +++ b/src/main/java/envoy/client/ui/PrimaryButton.java @@ -8,7 +8,7 @@ import javax.swing.JButton; * Project: envoy-client
* File: PrimaryButton.javaEvent.java
* Created: 07.12.2019
- * + * * @author Kai S. K. Engelbart * @author Maximilian Käfer * @since Envoy v0.2-alpha @@ -21,7 +21,7 @@ public class PrimaryButton extends JButton { /** * Creates a primary button - * + * * @param title the title of the button * @since Envoy 0.2-alpha */ @@ -29,9 +29,9 @@ public class PrimaryButton extends JButton { /** * Creates a primary button - * - * @param title the title of the button - * @param the size of the arc used to draw the round button edges + * + * @param title the title of the button + * @param arcSize the size of the arc used to draw the round button edges * @since Envoy 0.2-alpha */ public PrimaryButton(String title, int arcSize) { diff --git a/src/main/java/envoy/client/ui/PrimaryScrollBar.java b/src/main/java/envoy/client/ui/PrimaryScrollBar.java index 20bed6c..a7cb8fc 100644 --- a/src/main/java/envoy/client/ui/PrimaryScrollBar.java +++ b/src/main/java/envoy/client/ui/PrimaryScrollBar.java @@ -1,95 +1,115 @@ -package envoy.client.ui; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; - -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JScrollBar; -import javax.swing.plaf.basic.BasicScrollBarUI; - -import envoy.client.Settings; - -/** - * Project: envoy-client
- * File: PrimaryScrollBar.java
- * Created: 14.12.2019
- * - * @author Maximilian Käfer - * @since Envoy v0.2-alpha - */ -public class PrimaryScrollBar extends BasicScrollBarUI { - - private final Dimension d = new Dimension(); - private final int arcSize; - private final Color scrollBarColor; - private final Color hoverColor; - private final Color draggingColor; - private final boolean isVertical; - - public PrimaryScrollBar(int arcSize, Color scrollBarColor, Color hoverColor, Color draggingColor, boolean isVertical) { - this.arcSize = arcSize; - this.scrollBarColor = scrollBarColor; - this.hoverColor = hoverColor; - this.draggingColor = draggingColor; - this.isVertical = isVertical; - } - - public PrimaryScrollBar(Theme theme, boolean isVertical) { - this(5, theme.getInteractableBackgroundColor(), new Color(theme.getInteractableBackgroundColor().getRGB() - 50), - new Color(theme.getInteractableBackgroundColor().getRGB() + 170), isVertical); - } - - @Override - protected JButton createDecreaseButton(int orientation) { - JButton button = new JButton(); - button.setPreferredSize(d); - return button; - } - - @Override - protected JButton createIncreaseButton(int orientation) { - JButton button = new JButton(); - button.setPreferredSize(d); - return button; - } - - @Override - protected void paintTrack(Graphics g, JComponent c, Rectangle r) {} - - @Override - protected void paintThumb(Graphics g, JComponent c, Rectangle r) { - Graphics2D g2 = (Graphics2D) g.create(); - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - Color color; - JScrollBar sb = (JScrollBar) c; - - if (!sb.isEnabled()) return; - - if (isDragging) color = draggingColor; - else if (isThumbRollover()) color = hoverColor; - else color = scrollBarColor; - - g2.setPaint(color); - if (isVertical) { - g2.fillRoundRect(r.x - 9, r.y, r.width, r.height, arcSize, arcSize); - g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); - g2.drawRoundRect(r.x - 9, r.y, r.width, r.height, arcSize, arcSize); - } else { - g2.fillRoundRect(r.x, r.y + 9, r.width, r.height - 10, arcSize, arcSize); - g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); - g2.drawRoundRect(r.x, r.y + 9, r.width, r.height - 10, arcSize, arcSize); - } - g2.dispose(); - } - - @Override - protected void setThumbBounds(int x, int y, int width, int height) { - super.setThumbBounds(x, y, width, height); - scrollbar.repaint(); - } -} +package envoy.client.ui; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.plaf.basic.BasicScrollBarUI; + +import envoy.client.Settings; + +/** + * Project: envoy-client
+ * File: PrimaryScrollBar.java
+ * Created: 14.12.2019
+ * + * @author Maximilian Käfer + * @since Envoy v0.2-alpha + */ +public class PrimaryScrollBar extends BasicScrollBarUI { + + private final Dimension d = new Dimension(); + private final int arcSize; + private final Color scrollBarColor; + private final Color hoverColor; + private final Color draggingColor; + private final boolean isVertical; + + /** + * Initializes a {@link PrimaryScrollBar} with a color scheme. + * + * @param arcSize the size of the arc used to draw the round scroll bar + * edges + * @param scrollBarColor the default color + * @param hoverColor the color while hovering + * @param draggingColor the color while dragging + * @param isVertical indicates whether this is a vertical + * {@link PrimaryScrollBar} + */ + public PrimaryScrollBar(int arcSize, Color scrollBarColor, Color hoverColor, Color draggingColor, boolean isVertical) { + this.arcSize = arcSize; + this.scrollBarColor = scrollBarColor; + this.hoverColor = hoverColor; + this.draggingColor = draggingColor; + this.isVertical = isVertical; + } + + /** + * Initializes a {@link PrimaryScrollBar} using a color scheme specified in a + * {@link Theme} + * + * @param theme the {@link Theme} to be applied to this + * {@link PrimaryScrollBar} + * @param isVertical indicates whether this is a vertical + * {@link PrimaryScrollBar} + */ + public PrimaryScrollBar(Theme theme, boolean isVertical) { + this(5, theme.getInteractableBackgroundColor(), new Color(theme.getInteractableBackgroundColor().getRGB() - 50), + new Color(theme.getInteractableBackgroundColor().getRGB() + 170), isVertical); + } + + @Override + protected JButton createDecreaseButton(int orientation) { + JButton button = new JButton(); + button.setPreferredSize(d); + return button; + } + + @Override + protected JButton createIncreaseButton(int orientation) { + JButton button = new JButton(); + button.setPreferredSize(d); + return button; + } + + @Override + protected void paintTrack(Graphics g, JComponent c, Rectangle r) {} + + @Override + protected void paintThumb(Graphics g, JComponent c, Rectangle r) { + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + Color color; + JScrollBar sb = (JScrollBar) c; + + if (!sb.isEnabled()) return; + + if (isDragging) color = draggingColor; + else if (isThumbRollover()) color = hoverColor; + else color = scrollBarColor; + + g2.setPaint(color); + if (isVertical) { + g2.fillRoundRect(r.x - 9, r.y, r.width, r.height, arcSize, arcSize); + g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); + g2.drawRoundRect(r.x - 9, r.y, r.width, r.height, arcSize, arcSize); + } else { + g2.fillRoundRect(r.x, r.y + 9, r.width, r.height - 10, arcSize, arcSize); + g2.setPaint(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor()); + g2.drawRoundRect(r.x, r.y + 9, r.width, r.height - 10, arcSize, arcSize); + } + g2.dispose(); + } + + @Override + protected void setThumbBounds(int x, int y, int width, int height) { + super.setThumbBounds(x, y, width, height); + scrollbar.repaint(); + } +} diff --git a/src/main/java/envoy/client/ui/PrimaryScrollPane.java b/src/main/java/envoy/client/ui/PrimaryScrollPane.java index 61c348a..8b78a99 100644 --- a/src/main/java/envoy/client/ui/PrimaryScrollPane.java +++ b/src/main/java/envoy/client/ui/PrimaryScrollPane.java @@ -17,6 +17,11 @@ public class PrimaryScrollPane extends JScrollPane { private int verticalScrollBarMaximum = getVerticalScrollBar().getMaximum(); private boolean chatOpened = false; + /** + * Initializes a {@link JScrollPane} with the primary Envoy design scheme + * + * @since Envoy v0.2-alpha + */ public PrimaryScrollPane() { setBorder(null); } /** @@ -67,5 +72,12 @@ public class PrimaryScrollPane extends JScrollPane { }); } + /** + * Indicates a chat being opened by the user to this {@link PrimaryScrollPane} + * triggering it to automatically scroll down. + * + * @param chatOpened indicates the chat opening status + * @since Envoy v0.2-alpha + */ public void setChatOpened(boolean chatOpened) { this.chatOpened = chatOpened; } }