diff --git a/src/main/java/envoy/client/LocalDB.java b/src/main/java/envoy/client/LocalDB.java index 7db7200..b5e3971 100644 --- a/src/main/java/envoy/client/LocalDB.java +++ b/src/main/java/envoy/client/LocalDB.java @@ -1,6 +1,7 @@ package envoy.client; -import java.io.*; +import java.io.File; +import java.io.IOException; import java.time.Instant; import java.util.*; import java.util.logging.Logger; @@ -11,6 +12,7 @@ import javax.xml.datatype.DatatypeFactory; import envoy.client.event.EventBus; import envoy.client.event.MessageCreationEvent; import envoy.client.util.EnvoyLog; +import envoy.client.util.SerializationUtils; import envoy.exception.EnvoyException; import envoy.schema.*; import envoy.schema.Message.Metadata.MessageState; @@ -38,7 +40,7 @@ public class LocalDB { private Sync sync = objectFactory.createSync(); private Sync readMessages = objectFactory.createSync(); - private static final Logger logger = EnvoyLog.getLogger(LocalDB.class.getSimpleName()); + private static final Logger logger = EnvoyLog.getLogger(LocalDB.class.getSimpleName()); /** * Constructs an empty local database. To serialize any chats to the file @@ -83,10 +85,10 @@ public class LocalDB { */ public void save() throws IOException { // Save users - write(usersFile, users); + SerializationUtils.write(usersFile, users); // Save chats - write(localDBFile, chats); + SerializationUtils.write(localDBFile, chats); } /** @@ -95,8 +97,7 @@ public class LocalDB { * @throws EnvoyException if the loading process failed * @since Envoy v0.2-alpha */ - @SuppressWarnings("unchecked") - public void loadUsers() throws EnvoyException { users = read(usersFile, HashMap.class); } + public void loadUsers() throws EnvoyException { users = SerializationUtils.read(usersFile, HashMap.class); } /** * Loads all chats saved by Envoy for the client user. @@ -104,31 +105,7 @@ public class LocalDB { * @throws EnvoyException if the loading process failed * @since Envoy v0.1-alpha */ - @SuppressWarnings("unchecked") - public void loadChats() throws EnvoyException { chats = read(localDBFile, ArrayList.class); } - - 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 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(); - } - try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file))) { - out.writeObject(obj); - } catch (IOException e) { - throw e; - } - } + public void loadChats() throws EnvoyException { chats = SerializationUtils.read(localDBFile, ArrayList.class); } /** * Creates a {@link Message} object serializable to XML. @@ -238,8 +215,7 @@ public class LocalDB { // Updating UserStatus of all users in LocalDB for (User user : returnSync.getUsers()) for (Chat chat : getChats()) - if (user.getID() == chat.getRecipient().getID()) - chat.getRecipient().setStatus(user.getStatus()); + if (user.getID() == chat.getRecipient().getID()) chat.getRecipient().setStatus(user.getStatus()); sync.getMessages().clear(); sync.getUsers().clear(); @@ -301,7 +277,8 @@ public class LocalDB { public void clearUnreadMessagesSync() { unreadMessagesSync.getMessages().clear(); } /** - * @return a {@code Map} of all users stored locally with their user names as keys + * @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/Settings.java b/src/main/java/envoy/client/Settings.java index fc60877..e79596c 100644 --- a/src/main/java/envoy/client/Settings.java +++ b/src/main/java/envoy/client/Settings.java @@ -7,6 +7,8 @@ import java.util.prefs.Preferences; import envoy.client.ui.Color; import envoy.client.ui.Theme; +import envoy.client.util.SerializationUtils; +import envoy.exception.EnvoyException; /** * Manages all application settings, which are different objects that can be @@ -25,20 +27,18 @@ import envoy.client.ui.Theme; public class Settings { // Actual settings accessible by the rest of the application - private boolean enterToSend = true; - private Map themes; - private String currentTheme; - private boolean currentOnCloseMode; + private Map> items; + private Map themes; /** - * Required to save the settings. + * Settings are stored in this file. */ - private Preferences prefs = Preferences.userNodeForPackage(Settings.class); + private static final File settingsFile = new File(Config.getInstance().getHomeDirectory(), "settings.ser"); /** * User-defined themes are stored inside this file. */ - private File themeFile = new File(Config.getInstance().getHomeDirectory(), "themes.ser"); + private static final File themeFile = new File(Config.getInstance().getHomeDirectory(), "themes.ser"); /** * Singleton instance of this class. @@ -51,30 +51,21 @@ public class Settings { * * @since Envoy v0.2-alpha */ - private Settings() { load(); } - - /** - * This method is used to ensure that there is only one instance of Settings. - * - * @return the instance of Settings - * @since Envoy v0.2-alpha - */ - public static Settings getInstance() { return settings; } - - @SuppressWarnings("unchecked") - private void load() { - setEnterToSend(prefs.getBoolean("enterToSend", true)); - setCurrentTheme(prefs.get("theme", "dark")); - setCurrentOnCloseMode(prefs.getBoolean("onCloseMode", true)); + private Settings() { + // Load settings from settings file + try { + items = SerializationUtils.read(settingsFile, HashMap.class); + } catch (EnvoyException e) { + items = new HashMap<>(); + } + supplementDefaults(); // Load themes from theme file - try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(themeFile))) { - Object obj = in.readObject(); - if (obj instanceof HashMap) themes = (Map) obj; - } catch (IOException | ClassNotFoundException e) { - themes = new HashMap<>(); - currentTheme = "dark"; - e.printStackTrace(); + try { + themes = SerializationUtils.read(themeFile, HashMap.class); + } catch (EnvoyException e1) { + themes = new HashMap<>(); + setCurrentTheme("dark"); } // Load standard themes not defined in the themes file @@ -86,6 +77,14 @@ public class Settings { Color.black, Color.black)); } + /** + * This method is used to ensure that there is only one instance of Settings. + * + * @return the instance of Settings + * @since Envoy v0.2-alpha + */ + public static Settings getInstance() { return settings; } + /** * Updates the preferences when the save button is clicked. * @@ -94,15 +93,17 @@ public class Settings { * @since Envoy v0.2-alpha */ public void save() throws IOException { - prefs.put("theme", currentTheme); - prefs.putBoolean("enterToSend", isEnterToSend()); - prefs.putBoolean("onCloseMode", currentOnCloseMode); + // Save settings to settings file + SerializationUtils.write(settingsFile, items); // Save themes to theme file - themeFile.createNewFile(); - try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(themeFile))) { - out.writeObject(themes); - } + SerializationUtils.write(themeFile, themes); + } + + private void supplementDefaults() { + items.putIfAbsent("enterToSend", new SettingsItem<>(true, "Enter to send", "Sends a message by pressing the enter key.")); + items.putIfAbsent("onCloseMode", new SettingsItem<>(false, "Hide on close", "Hides the chat window when it is closed.")); + items.putIfAbsent("currentTheme", new SettingsItem<>("dark", null)); } /** @@ -117,7 +118,7 @@ public class Settings { * @return the name of the currently active {@link Theme} * @since Envoy v0.2-alpha */ - public String getCurrentTheme() { return currentTheme; } + public String getCurrentTheme() { return (String) items.get("currentTheme").get(); } /** * Sets the name of the current {@link Theme}. @@ -125,7 +126,8 @@ public class Settings { * @param themeName the name to set * @since Envoy v0.2-alpha */ - public void setCurrentTheme(String themeName) { currentTheme = themeName; } + @SuppressWarnings("unchecked") + public void setCurrentTheme(String themeName) { ((SettingsItem) items.get("currentTheme")).set(themeName); } /** * @return {@code true}, if pressing the {@code Enter} key suffices to send a @@ -133,7 +135,7 @@ public class Settings { * {@code Control} key. * @since Envoy v0.2-alpha */ - public boolean isEnterToSend() { return enterToSend; } + public boolean isEnterToSend() { return (boolean) items.get("enterToSend").get(); } /** * Changes the keystrokes performed by the user to send a message. @@ -143,7 +145,23 @@ public class Settings { * conjunction with the {@code Control} key. * @since Envoy v0.2-alpha */ - public void setEnterToSend(boolean enterToSend) { this.enterToSend = enterToSend; } + @SuppressWarnings("unchecked") + public void setEnterToSend(boolean enterToSend) { ((SettingsItem) items.get("enterToSend")).set(enterToSend); } + + /** + * @return the current on close mode. + * @since Envoy v0.3-alpha + */ + public boolean getCurrentOnCloseMode() { return (boolean) items.get("onCloseMode").get(); } + + /** + * Sets the current on close mode. + * + * @param currentOnCloseMode the on close mode that should be set. + * @since Envoy v0.3-alpha + */ + @SuppressWarnings("unchecked") + public void setCurrentOnCloseMode(boolean currentOnCloseMode) { ((SettingsItem) items.get("onCloseMode")).set(currentOnCloseMode); } /** * @return a {@code Map} of all themes with their names as keys @@ -158,18 +176,4 @@ public class Settings { * @since Envoy v0.2-alpha */ public void setThemes(Map themes) { this.themes = themes; } - - /** - * @return the current on close mode. - * @since Envoy v0.3-alpha - */ - public boolean getCurrentOnCloseMode() { return currentOnCloseMode; } - - /** - * Sets the current on close mode. - * - * @param currentOnCloseMode the on close mode that should be set. - * @since Envoy v0.3-alpha - */ - public void setCurrentOnCloseMode(boolean currentOnCloseMode) { this.currentOnCloseMode = currentOnCloseMode; } } \ No newline at end of file diff --git a/src/main/java/envoy/client/SettingsItem.java b/src/main/java/envoy/client/SettingsItem.java new file mode 100644 index 0000000..23da76a --- /dev/null +++ b/src/main/java/envoy/client/SettingsItem.java @@ -0,0 +1,87 @@ +package envoy.client; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.JComponent; + +import envoy.client.ui.PrimaryToggleSwitch; + +/** + * Project: envoy-clientChess
+ * File: SettingsItem.java
+ * Created: 23.12.2019
+ * + * @author Kai S. K. Engelbart + */ +public class SettingsItem implements Serializable { + + private T value; + private Class componentClass; + private String userFriendlyName, description; + + private static final Map, Class> componentClasses = new HashMap<>(); + + private static final long serialVersionUID = 2146837835556852218L; + + static { + componentClasses.put(boolean.class, PrimaryToggleSwitch.class); + } + + public SettingsItem(T value, String userFriendlyName, String description) { + this(value, componentClasses.get(value.getClass())); + this.userFriendlyName = userFriendlyName; + this.description = description; + } + + public SettingsItem(T value, Class componentClass) { + this.value = value; + this.componentClass = componentClass; + } + + public JComponent getComponent() throws ReflectiveOperationException, SecurityException { + if (componentClass == null) throw new NullPointerException("Component class is null"); + return componentClass.getConstructor(SettingsItem.class).newInstance(this); + } + + /** + * @return the value + */ + public T get() { return value; } + + /** + * @param value the value to set + */ + public void set(T value) { this.value = value; } + + /** + * @return the componentClass + */ + public Class getComponentClass() { return componentClass; } + + /** + * @param componentClass the componentClass to set + */ + public void setComponentClass(Class componentClass) { this.componentClass = componentClass; } + + /** + * @return the userFriendlyName + */ + public String getUserFriendlyName() { return userFriendlyName; } + + /** + * @param userFriendlyName the userFriendlyName to set + */ + public void setUserFriendlyName(String userFriendlyName) { this.userFriendlyName = userFriendlyName; } + + /** + * @return the description + */ + public String getDescription() { return description; } + + /** + * @param description the description to set + */ + public void setDescription(String description) { this.description = description; } +} \ No newline at end of file diff --git a/src/main/java/envoy/client/ui/settings/General.java b/src/main/java/envoy/client/ui/settings/General.java index b128454..235cee9 100644 --- a/src/main/java/envoy/client/ui/settings/General.java +++ b/src/main/java/envoy/client/ui/settings/General.java @@ -29,8 +29,8 @@ import envoy.client.util.EnvoyLog; public class General extends SettingsPanel { private Theme theme; - private boolean onCloseState; - private boolean enterToSend; + private boolean onCloseState = Settings.getInstance().getCurrentOnCloseMode(); + private boolean enterToSend = Settings.getInstance().isEnterToSend(); private PrimaryToggleSwitch toggleSwitch; private JTextPane onCloseModeTextPane = new JTextPane(); @@ -134,8 +134,8 @@ public class General extends SettingsPanel { add(stateText, gbc_stateText); descriptionText.setText(text); - descriptionText.setBackground(theme.getBackgroundColor().invert()); - descriptionText.setForeground(theme.getUserNameColor()); + descriptionText.setBackground(theme.getBackgroundColor()); + descriptionText.setForeground(theme.getBackgroundColor().invert()); descriptionText.setEditable(false); GridBagConstraints gbc_descriptionText = new GridBagConstraints(); diff --git a/src/main/java/envoy/client/util/SerializationUtils.java b/src/main/java/envoy/client/util/SerializationUtils.java new file mode 100644 index 0000000..5a4b842 --- /dev/null +++ b/src/main/java/envoy/client/util/SerializationUtils.java @@ -0,0 +1,38 @@ +package envoy.client.util; + +import java.io.*; + +import envoy.exception.EnvoyException; + +/** + * Project: envoy-clientChess
+ * File: SerializationUtils.javaEvent.java
+ * Created: 23.12.2019
+ * + * @author Kai S. K. Engelbart + */ +public class SerializationUtils { + + private SerializationUtils() {} + + public static 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 new EnvoyException("Could not load serialized object", e); + } + } + + public static void write(File file, Object 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(); + } + try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file))) { + out.writeObject(obj); + } + } +}