Saving settings in a file, added SettingsItem class
This commit is contained in:
		| @@ -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> T read(File file, Class<T> 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 <T> 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<String, User>} of all users stored locally with their user names as keys | ||||
| 	 * @return a {@code Map<String, User>} of all users stored locally with their | ||||
| 	 *         user names as keys | ||||
| 	 * @since Envoy v0.2-alpha | ||||
| 	 */ | ||||
| 	public Map<String, User> getUsers() { return users; } | ||||
|   | ||||
| @@ -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<String, Theme>	themes; | ||||
| 	private String				currentTheme; | ||||
| 	private boolean				currentOnCloseMode; | ||||
| 	private Map<String, SettingsItem<?>>	items; | ||||
| 	private Map<String, Theme>				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<String, Theme>) 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<String>) 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<Boolean>) 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<Boolean>) items.get("onCloseMode")).set(currentOnCloseMode); } | ||||
|  | ||||
| 	/** | ||||
| 	 * @return a {@code Map<String, Theme>} of all themes with their names as keys | ||||
| @@ -158,18 +176,4 @@ public class Settings { | ||||
| 	 * @since Envoy v0.2-alpha | ||||
| 	 */ | ||||
| 	public void setThemes(Map<String, Theme> 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; } | ||||
| } | ||||
							
								
								
									
										87
									
								
								src/main/java/envoy/client/SettingsItem.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/main/java/envoy/client/SettingsItem.java
									
									
									
									
									
										Normal file
									
								
							| @@ -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: <strong>envoy-clientChess</strong><br> | ||||
|  * File: <strong>SettingsItem.java</strong><br> | ||||
|  * Created: <strong>23.12.2019</strong><br> | ||||
|  *  | ||||
|  * @author Kai S. K. Engelbart | ||||
|  */ | ||||
| public class SettingsItem<T> implements Serializable { | ||||
|  | ||||
| 	private T							value; | ||||
| 	private Class<? extends JComponent>	componentClass; | ||||
| 	private String						userFriendlyName, description; | ||||
|  | ||||
| 	private static final Map<Class<?>, Class<? extends JComponent>> 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<? extends JComponent> 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<? extends JComponent> getComponentClass() { return componentClass; } | ||||
|  | ||||
| 	/** | ||||
| 	 * @param componentClass the componentClass to set | ||||
| 	 */ | ||||
| 	public void setComponentClass(Class<? extends JComponent> 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; } | ||||
| } | ||||
| @@ -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(); | ||||
|   | ||||
							
								
								
									
										38
									
								
								src/main/java/envoy/client/util/SerializationUtils.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/main/java/envoy/client/util/SerializationUtils.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| package envoy.client.util; | ||||
|  | ||||
| import java.io.*; | ||||
|  | ||||
| import envoy.exception.EnvoyException; | ||||
|  | ||||
| /** | ||||
|  * Project: <strong>envoy-clientChess</strong><br> | ||||
|  * File: <strong>SerializationUtils.javaEvent.java</strong><br> | ||||
|  * Created: <strong>23.12.2019</strong><br> | ||||
|  *  | ||||
|  * @author Kai S. K. Engelbart | ||||
|  */ | ||||
| public class SerializationUtils { | ||||
|  | ||||
| 	private SerializationUtils() {} | ||||
|  | ||||
| 	public static <T extends Serializable> T read(File file, Class<T> 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); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user