Refined theme customization mechanism
* Created abstract SettingsPanel class for defining settings screen pages * Moves theme customization related settings to new class ThemeCustomizationPanel * Changes Theme to use a map internally
This commit is contained in:
		| @@ -29,6 +29,7 @@ import envoy.client.LocalDB; | |||||||
| import envoy.client.Settings; | import envoy.client.Settings; | ||||||
| import envoy.client.event.EventBus; | import envoy.client.event.EventBus; | ||||||
| import envoy.client.event.ThemeChangeEvent; | import envoy.client.event.ThemeChangeEvent; | ||||||
|  | import envoy.client.ui.settings.SettingsScreen; | ||||||
| import envoy.client.util.EnvoyLog; | import envoy.client.util.EnvoyLog; | ||||||
| import envoy.schema.Message; | import envoy.schema.Message; | ||||||
| import envoy.schema.User; | import envoy.schema.User; | ||||||
| @@ -157,7 +158,6 @@ public class ChatWindow extends JFrame { | |||||||
| 		settingsButton.addActionListener((evt) -> { | 		settingsButton.addActionListener((evt) -> { | ||||||
| 			try { | 			try { | ||||||
| 				new SettingsScreen().setVisible(true); | 				new SettingsScreen().setVisible(true); | ||||||
| 				changeChatWindowColors(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); |  | ||||||
| 			} catch (Exception e) { | 			} catch (Exception e) { | ||||||
| 				logger.log(Level.WARNING, "An error occured while opening the settings screen", e); | 				logger.log(Level.WARNING, "An error occured while opening the settings screen", e); | ||||||
| 				e.printStackTrace(); | 				e.printStackTrace(); | ||||||
|   | |||||||
| @@ -1,458 +0,0 @@ | |||||||
| package envoy.client.ui; |  | ||||||
|  |  | ||||||
| import java.awt.BorderLayout; |  | ||||||
| import java.awt.Color; |  | ||||||
| import java.awt.Component; |  | ||||||
| import java.awt.Dimension; |  | ||||||
| import java.awt.Font; |  | ||||||
| import java.awt.GridBagConstraints; |  | ||||||
| import java.awt.GridBagLayout; |  | ||||||
| import java.awt.Insets; |  | ||||||
| import java.awt.event.ItemEvent; |  | ||||||
| import java.awt.event.ItemListener; |  | ||||||
| import java.util.Arrays; |  | ||||||
| import java.util.logging.Level; |  | ||||||
| import java.util.logging.Logger; |  | ||||||
|  |  | ||||||
| import javax.swing.BoxLayout; |  | ||||||
| import javax.swing.DefaultListModel; |  | ||||||
| import javax.swing.JButton; |  | ||||||
| import javax.swing.JColorChooser; |  | ||||||
| import javax.swing.JComboBox; |  | ||||||
| import javax.swing.JDialog; |  | ||||||
| import javax.swing.JList; |  | ||||||
| import javax.swing.JOptionPane; |  | ||||||
| import javax.swing.JPanel; |  | ||||||
| import javax.swing.JTextPane; |  | ||||||
| import javax.swing.ListSelectionModel; |  | ||||||
|  |  | ||||||
| import envoy.client.Settings; |  | ||||||
| import envoy.client.util.EnvoyLog; |  | ||||||
| import envoy.client.event.EventBus; |  | ||||||
| import envoy.client.event.ThemeChangeEvent; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * This class provides the GUI to change the user specific settings. |  | ||||||
|  * |  | ||||||
|  * Project: <strong>envoy-client</strong><br> |  | ||||||
|  * File: <strong>SettingsScreen.java</strong><br> |  | ||||||
|  * Created: <strong>31 Oct 2019</strong><br> |  | ||||||
|  * |  | ||||||
|  * @author Leon Hofmeister |  | ||||||
|  * @author Maximilian Käfer |  | ||||||
|  * @author Kai S. K. Engelbart |  | ||||||
|  */ |  | ||||||
| public class SettingsScreen extends JDialog { |  | ||||||
|  |  | ||||||
| 	private static final long	serialVersionUID	= -4476913491263077107L; |  | ||||||
| 	private final JPanel		contentPanel		= new JPanel(); |  | ||||||
|  |  | ||||||
| 	private DefaultListModel<String>	optionsListModel	= new DefaultListModel<>(); |  | ||||||
| 	private final JList<String>			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<String>	themes			= new JComboBox<>(themeArray); |  | ||||||
|  |  | ||||||
| 	private GridBagConstraints gbc_themeContent = new GridBagConstraints(); |  | ||||||
|  |  | ||||||
| 	private JButton	createNewThemeButton	= new JButton("Create New Theme"); |  | ||||||
| 	private JPanel	colorsPanel				= new JPanel(); |  | ||||||
| 	private JButton	okButton				= new JButton("Save"); |  | ||||||
| 	private JButton	cancelButton			= new JButton("Cancel"); |  | ||||||
|  |  | ||||||
| 	private static int	space			= 5; |  | ||||||
|  |  | ||||||
| 	private Theme temporaryTheme, selectedTheme; |  | ||||||
|  |  | ||||||
| 	private static final Logger logger = EnvoyLog.getLogger(SettingsScreen.class.getSimpleName()); |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Builds the settings screen. |  | ||||||
| 	 * |  | ||||||
| 	 * @since Envoy v0.1-alpha |  | ||||||
| 	 */ |  | ||||||
| 	public SettingsScreen() { |  | ||||||
| 		logger.info(Settings.getInstance().getCurrentTheme()); |  | ||||||
|  |  | ||||||
| 		setBounds(10, 10, 450, 650); |  | ||||||
| 		getContentPane().setLayout(new BorderLayout()); |  | ||||||
| 		{ |  | ||||||
|  |  | ||||||
| 			createNewThemeButton.setEnabled(false); |  | ||||||
|  |  | ||||||
| 			temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); |  | ||||||
|  |  | ||||||
| 			// Content pane |  | ||||||
| 			GridBagLayout gbl_contentPanel = new GridBagLayout(); |  | ||||||
|  |  | ||||||
| 			gbl_contentPanel.columnWidths	= new int[] { 1, 1 }; |  | ||||||
| 			gbl_contentPanel.rowHeights		= new int[] { 1 }; |  | ||||||
| 			gbl_contentPanel.columnWeights	= new double[] { 0.05, 1.0 }; |  | ||||||
| 			gbl_contentPanel.rowWeights		= new double[] { 1.0 }; |  | ||||||
|  |  | ||||||
| 			getContentPane().add(contentPanel, BorderLayout.CENTER); |  | ||||||
| 			contentPanel.setLayout(gbl_contentPanel); |  | ||||||
|  |  | ||||||
| 			options.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); |  | ||||||
|  |  | ||||||
| 			options.addListSelectionListener((listSelectionEvent) -> { |  | ||||||
| 				if (!listSelectionEvent.getValueIsAdjusting()) { |  | ||||||
| 					@SuppressWarnings("unchecked") |  | ||||||
| 					final JList<String>	selectedOption	= (JList<String>) listSelectionEvent.getSource(); |  | ||||||
| 					final String		option			= selectedOption.getSelectedValue(); |  | ||||||
| 					logger.log(Level.FINEST, option); |  | ||||||
|  |  | ||||||
| 					switch (option) { |  | ||||||
| 						case "Color Themes": |  | ||||||
| 							setContent(themeContent, gbc_themeContent); |  | ||||||
| 							getContentPane().repaint(); |  | ||||||
| 							getContentPane().revalidate(); |  | ||||||
| 							break; |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 			options.setFont(new Font("Arial", Font.PLAIN, 14)); |  | ||||||
|  |  | ||||||
| 			Theme theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()); |  | ||||||
|  |  | ||||||
| 			GridBagConstraints gbc_optionsList = new GridBagConstraints(); |  | ||||||
| 			gbc_optionsList.fill	= GridBagConstraints.BOTH; |  | ||||||
| 			gbc_optionsList.gridx	= 0; |  | ||||||
| 			gbc_optionsList.gridy	= 0; |  | ||||||
| 			gbc_optionsList.anchor	= GridBagConstraints.PAGE_START; |  | ||||||
| 			gbc_optionsList.insets	= new Insets(space, space, space, space); |  | ||||||
|  |  | ||||||
| 			optionsListModel.addElement("Color Themes"); |  | ||||||
| 			options.setModel(optionsListModel); |  | ||||||
| 			contentPanel.add(options, gbc_optionsList); |  | ||||||
|  |  | ||||||
| 			// Theme content |  | ||||||
| 			gbc_themeContent		= new GridBagConstraints(); |  | ||||||
| 			gbc_themeContent.fill	= GridBagConstraints.BOTH; |  | ||||||
| 			gbc_themeContent.gridx	= 1; |  | ||||||
| 			gbc_themeContent.gridy	= 0; |  | ||||||
| 			gbc_themeContent.anchor	= GridBagConstraints.PAGE_START; |  | ||||||
| 			gbc_themeContent.insets	= new Insets(space, space, space, space); |  | ||||||
|  |  | ||||||
| 			GridBagLayout gbl_themeLayout = new GridBagLayout(); |  | ||||||
|  |  | ||||||
| 			gbl_themeLayout.columnWidths	= new int[] { 1, 1 }; |  | ||||||
| 			gbl_themeLayout.rowHeights		= new int[] { 1, 1 }; |  | ||||||
| 			gbl_themeLayout.columnWeights	= new double[] { 1.0, 1.0 }; |  | ||||||
| 			gbl_themeLayout.rowWeights		= new double[] { 0.01, 1.0 }; |  | ||||||
|  |  | ||||||
| 			themeContent.setLayout(gbl_themeLayout); |  | ||||||
|  |  | ||||||
| 			themes.setSelectedItem(Settings.getInstance().getCurrentTheme()); |  | ||||||
|  |  | ||||||
| 			themes.addItemListener(new ItemListener() { |  | ||||||
|  |  | ||||||
| 				@Override |  | ||||||
| 				public void itemStateChanged(ItemEvent e) { |  | ||||||
| 					String selectedValue = (String) themes.getSelectedItem(); |  | ||||||
| 					logger.log(Level.FINEST, selectedValue); |  | ||||||
| 					selectedTheme = Settings.getInstance().getThemes().get(selectedValue); |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 			GridBagConstraints gbc_themes = new GridBagConstraints(); |  | ||||||
| 			gbc_themes.fill		= GridBagConstraints.HORIZONTAL; |  | ||||||
| 			gbc_themes.gridx	= 0; |  | ||||||
| 			gbc_themes.gridy	= 0; |  | ||||||
| 			gbc_themes.anchor	= GridBagConstraints.NORTHWEST; |  | ||||||
| 			gbc_themes.insets	= new Insets(space, space, space, space); |  | ||||||
|  |  | ||||||
| 			themeContent.add(themes, gbc_themes); |  | ||||||
|  |  | ||||||
| 			colorsPanel.setLayout(new BoxLayout(colorsPanel, BoxLayout.Y_AXIS)); |  | ||||||
| 			colorsPanel.setAlignmentX(Component.LEFT_ALIGNMENT); |  | ||||||
|  |  | ||||||
| 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getBackgroundColor(), "Background", 0); |  | ||||||
| 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getCellColor(), "Cells", 1); |  | ||||||
| 			buildCustomizeElement(new JPanel(), |  | ||||||
| 					new JButton(), |  | ||||||
| 					new JTextPane(), |  | ||||||
| 					theme, |  | ||||||
| 					theme.getInteractableForegroundColor(), |  | ||||||
| 					"Interactable Foreground", |  | ||||||
| 					2); |  | ||||||
| 			buildCustomizeElement(new JPanel(), |  | ||||||
| 					new JButton(), |  | ||||||
| 					new JTextPane(), |  | ||||||
| 					theme, |  | ||||||
| 					theme.getInteractableBackgroundColor(), |  | ||||||
| 					"Interactable Background", |  | ||||||
| 					3); |  | ||||||
| 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getMessageColorChat(), "Messages Chat", 4); |  | ||||||
| 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getDateColorChat(), "Date Chat", 5); |  | ||||||
| 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getSelectionColor(), "Selection", 6); |  | ||||||
| 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getTypingMessageColor(), "Typing Message", 7); |  | ||||||
| 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getUserNameColor(), "User Names", 8); |  | ||||||
|  |  | ||||||
| 			GridBagConstraints gbc_colorsPanel = new GridBagConstraints(); |  | ||||||
| 			gbc_colorsPanel.fill		= GridBagConstraints.HORIZONTAL; |  | ||||||
| 			gbc_colorsPanel.gridx		= 0; |  | ||||||
| 			gbc_colorsPanel.gridy		= 1; |  | ||||||
| 			gbc_colorsPanel.gridwidth	= 2; |  | ||||||
| 			gbc_colorsPanel.anchor		= GridBagConstraints.NORTHWEST; |  | ||||||
| 			gbc_colorsPanel.insets		= new Insets(space, 0, 0, 0); |  | ||||||
|  |  | ||||||
| 			themeContent.add(colorsPanel, gbc_colorsPanel); |  | ||||||
|  |  | ||||||
| 			createNewThemeButton.setBackground(theme.getInteractableBackgroundColor()); |  | ||||||
| 			createNewThemeButton.setForeground(theme.getInteractableForegroundColor()); |  | ||||||
| 			colorsPanel.setBackground(theme.getCellColor()); |  | ||||||
|  |  | ||||||
| 			createNewThemeButton.addActionListener((evt) -> { |  | ||||||
| 				try { |  | ||||||
| 					String s = JOptionPane.showInputDialog("Enter a name for the new theme"); |  | ||||||
| 					logger.log(Level.FINEST, s); |  | ||||||
| 					Settings.getInstance() |  | ||||||
| 						.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())); |  | ||||||
|  |  | ||||||
| 					createNewThemeButton.setEnabled(false); |  | ||||||
| 					themes.addItem(themeArray[themeArray.length - 1]); |  | ||||||
|  |  | ||||||
| 					contentPanel.revalidate(); |  | ||||||
| 					contentPanel.repaint(); |  | ||||||
|  |  | ||||||
| 				} catch (Exception e) { |  | ||||||
| 					logger.info("New theme couldn't be created! " + e); |  | ||||||
| 					e.printStackTrace(); |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 			GridBagConstraints gbc_createNewTheme = new GridBagConstraints(); |  | ||||||
| 			gbc_createNewTheme.gridx	= 0; |  | ||||||
| 			gbc_createNewTheme.gridy	= 10; |  | ||||||
|  |  | ||||||
| 			colorsPanel.add(createNewThemeButton, gbc_createNewTheme); |  | ||||||
|  |  | ||||||
| 			// ButtonPane------------------------------------------------------- |  | ||||||
| 			GridBagLayout gbl_buttonPane = new GridBagLayout(); |  | ||||||
| 			gbl_buttonPane.columnWidths		= new int[] { 100, 250, 100, 0 }; |  | ||||||
| 			gbl_buttonPane.rowHeights		= new int[] { 25, 0 }; |  | ||||||
| 			gbl_buttonPane.columnWeights	= new double[] { 0.0, 0.0, 0.0, Double.MIN_VALUE }; |  | ||||||
| 			gbl_buttonPane.rowWeights		= new double[] { 0.0, Double.MIN_VALUE }; |  | ||||||
|  |  | ||||||
| 			getContentPane().add(buttonPane, BorderLayout.SOUTH); |  | ||||||
| 			buttonPane.setLayout(gbl_buttonPane); |  | ||||||
| 			{ |  | ||||||
| 				cancelButton.setActionCommand("Cancel"); |  | ||||||
| 				cancelButton.setBorderPainted(false); |  | ||||||
| 				GridBagConstraints gbc_cancelButton = new GridBagConstraints(); |  | ||||||
| 				gbc_cancelButton.anchor	= GridBagConstraints.NORTHWEST; |  | ||||||
| 				gbc_cancelButton.insets	= new Insets(space, space, space, space); |  | ||||||
| 				gbc_cancelButton.gridx	= 0; |  | ||||||
| 				gbc_cancelButton.gridy	= 0; |  | ||||||
| 				buttonPane.add(cancelButton, gbc_cancelButton); |  | ||||||
|  |  | ||||||
| 				cancelButton.addActionListener((evt) -> { dispose(); }); |  | ||||||
| 			} |  | ||||||
| 			{ |  | ||||||
| 				okButton.setActionCommand("OK"); |  | ||||||
| 				okButton.setBorderPainted(false); |  | ||||||
| 				GridBagConstraints gbc_okButton = new GridBagConstraints(); |  | ||||||
| 				gbc_okButton.anchor	= GridBagConstraints.NORTHEAST; |  | ||||||
| 				gbc_okButton.fill	= GridBagConstraints.EAST; |  | ||||||
| 				gbc_okButton.insets	= new Insets(space, space, space, space); |  | ||||||
| 				gbc_okButton.gridx	= 2; |  | ||||||
| 				gbc_okButton.gridy	= 0; |  | ||||||
| 				buttonPane.add(okButton, gbc_okButton); |  | ||||||
| 				getRootPane().setDefaultButton(okButton); |  | ||||||
| 				okButton.addActionListener((evt) -> { |  | ||||||
| 					try { |  | ||||||
| 						Settings.getInstance().setEnterToSend(Settings.getInstance().isEnterToSend());// still temporary |  | ||||||
|  |  | ||||||
| 						Settings.getInstance().setCurrentTheme(selectedTheme.getThemeName()); |  | ||||||
| 						logger.log(Level.FINER, selectedTheme.getThemeName()); |  | ||||||
|  |  | ||||||
| 						final Theme currentTheme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()); |  | ||||||
| 						changeSettingsScreenColors(currentTheme); |  | ||||||
| 						updateColorVariables(currentTheme); |  | ||||||
| 						EventBus.getInstance().dispatch(new ThemeChangeEvent(currentTheme)); |  | ||||||
| 						Settings.getInstance().save(); |  | ||||||
|  |  | ||||||
| 						revalidate(); |  | ||||||
| 						repaint(); |  | ||||||
| 					} catch (Exception e) { |  | ||||||
| 						logger.warning("Something went wrong when changing the setting"); |  | ||||||
| 						JOptionPane.showMessageDialog(this, "Something went wrong when changing the setting"); |  | ||||||
| 						dispose(); |  | ||||||
| 					} |  | ||||||
| 				}); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		changeSettingsScreenColors(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); |  | ||||||
|          |  | ||||||
|         setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); |  | ||||||
| 		setModal(true); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	private void changeSettingsScreenColors(Theme theme) { |  | ||||||
| 		// whole JDialog |  | ||||||
| 		setBackground(theme.getBackgroundColor()); |  | ||||||
| 		// contentPanel |  | ||||||
| 		contentPanel.setBackground(theme.getBackgroundColor()); |  | ||||||
| 		// buttonPane |  | ||||||
| 		buttonPane.setBackground(theme.getCellColor()); |  | ||||||
| 		// cancelButton |  | ||||||
| 		cancelButton.setBackground(theme.getInteractableBackgroundColor()); |  | ||||||
| 		cancelButton.setForeground(theme.getInteractableForegroundColor()); |  | ||||||
| 		// okButton |  | ||||||
| 		okButton.setBackground(theme.getInteractableBackgroundColor()); |  | ||||||
| 		okButton.setForeground(theme.getInteractableForegroundColor()); |  | ||||||
| 		// options |  | ||||||
| 		options.setSelectionForeground(theme.getUserNameColor()); |  | ||||||
| 		options.setSelectionBackground(theme.getSelectionColor()); |  | ||||||
| 		options.setForeground(theme.getUserNameColor()); |  | ||||||
| 		options.setBackground(theme.getCellColor()); |  | ||||||
| 		// themeContent |  | ||||||
| 		themeContent.setForeground(theme.getUserNameColor()); |  | ||||||
| 		themeContent.setBackground(theme.getCellColor()); |  | ||||||
| 		// themes |  | ||||||
| 		themes.setBackground(theme.getBackgroundColor()); |  | ||||||
| 		themes.setForeground(getInvertedColor(theme.getBackgroundColor())); |  | ||||||
|  |  | ||||||
| 		createNewThemeButton.setBackground(theme.getInteractableBackgroundColor()); |  | ||||||
| 		createNewThemeButton.setForeground(theme.getInteractableForegroundColor()); |  | ||||||
| 		colorsPanel.setBackground(theme.getCellColor()); |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	private void updateColorVariables(Theme theme) { |  | ||||||
| 		temporaryTheme = new Theme("temporaryTheme", theme); |  | ||||||
|  |  | ||||||
| 		colorsPanel.removeAll(); |  | ||||||
|  |  | ||||||
| 		buildCustomizeElement(new JPanel(), |  | ||||||
|  |  | ||||||
| 				new JButton(), |  | ||||||
| 				new JTextPane(), |  | ||||||
| 				theme, |  | ||||||
| 				theme.getBackgroundColor(), |  | ||||||
| 				"Background", |  | ||||||
| 				0); |  | ||||||
| 		buildCustomizeElement(new JPanel(), |  | ||||||
|  |  | ||||||
| 				new JButton(), |  | ||||||
| 				new JTextPane(), |  | ||||||
| 				theme, |  | ||||||
| 				theme.getCellColor(), |  | ||||||
| 				"Cells", |  | ||||||
| 				1); |  | ||||||
| 		buildCustomizeElement(new JPanel(), |  | ||||||
|  |  | ||||||
| 				new JButton(), |  | ||||||
| 				new JTextPane(), |  | ||||||
| 				theme, |  | ||||||
| 				theme.getInteractableForegroundColor(), |  | ||||||
| 				"Interactable Foreground", |  | ||||||
| 				2); |  | ||||||
| 		buildCustomizeElement(new JPanel(), |  | ||||||
|  |  | ||||||
| 				new JButton(), |  | ||||||
| 				new JTextPane(), |  | ||||||
| 				theme, |  | ||||||
| 				theme.getInteractableBackgroundColor(), |  | ||||||
| 				"Interactable Background", |  | ||||||
| 				3); |  | ||||||
| 		buildCustomizeElement(new JPanel(), |  | ||||||
|  |  | ||||||
| 				new JButton(), |  | ||||||
| 				new JTextPane(), |  | ||||||
| 				theme, |  | ||||||
| 				theme.getMessageColorChat(), |  | ||||||
| 				"Messages Chat", |  | ||||||
| 				4); |  | ||||||
| 		buildCustomizeElement(new JPanel(), |  | ||||||
|  |  | ||||||
| 				new JButton(), |  | ||||||
| 				new JTextPane(), |  | ||||||
| 				theme, |  | ||||||
| 				theme.getDateColorChat(), |  | ||||||
| 				"Date Chat", |  | ||||||
| 				5); |  | ||||||
| 		buildCustomizeElement(new JPanel(), |  | ||||||
|  |  | ||||||
| 				new JButton(), |  | ||||||
| 				new JTextPane(), |  | ||||||
| 				theme, |  | ||||||
| 				theme.getSelectionColor(), |  | ||||||
| 				"Selection", |  | ||||||
| 				6); |  | ||||||
| 		buildCustomizeElement(new JPanel(), |  | ||||||
|  |  | ||||||
| 				new JButton(), |  | ||||||
| 				new JTextPane(), |  | ||||||
| 				theme, |  | ||||||
| 				theme.getTypingMessageColor(), |  | ||||||
| 				"Typing Message", |  | ||||||
| 				7); |  | ||||||
| 		buildCustomizeElement(new JPanel(), |  | ||||||
|  |  | ||||||
| 				new JButton(), |  | ||||||
| 				new JTextPane(), |  | ||||||
| 				theme, |  | ||||||
| 				theme.getUserNameColor(), |  | ||||||
| 				"User Names", |  | ||||||
| 				8); |  | ||||||
|  |  | ||||||
| 		GridBagConstraints gbc_createNewTheme = new GridBagConstraints(); |  | ||||||
| 		gbc_createNewTheme.gridx	= 0; |  | ||||||
| 		gbc_createNewTheme.gridy	= 10; |  | ||||||
|  |  | ||||||
| 		colorsPanel.add(createNewThemeButton, gbc_createNewTheme); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	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) { |  | ||||||
| 		textPane.setFont(new Font("Arial", Font.PLAIN, 14)); |  | ||||||
| 		textPane.setBackground(theme.getBackgroundColor()); |  | ||||||
| 		textPane.setForeground(getInvertedColor(theme.getBackgroundColor())); |  | ||||||
| 		textPane.setText(name); |  | ||||||
| 		textPane.setEditable(false); |  | ||||||
|  |  | ||||||
| 		button.setBackground(color); |  | ||||||
| 		button.setPreferredSize(new Dimension(25, 25)); |  | ||||||
|  |  | ||||||
| 		button.addActionListener((evt) -> { |  | ||||||
| 			try { |  | ||||||
| 				Color newColor = JColorChooser.showDialog(null, "Choose a color", color); |  | ||||||
| 				if (newColor.getRGB() != color.getRGB()) { |  | ||||||
| 					logger.log(Level.FINEST, "New Color: " + String.valueOf(color.getRGB())); |  | ||||||
| 					// TODO: When Theme changed in same settings screen, color variable doesnt |  | ||||||
| 					// update. |  | ||||||
| 					temporaryTheme.setColor(yIndex, newColor); |  | ||||||
| 					createNewThemeButton.setEnabled(true); |  | ||||||
| 				} |  | ||||||
| 				button.setBackground(newColor); |  | ||||||
|  |  | ||||||
| 			} catch (Exception e) { |  | ||||||
| 				logger.info("An error occured while opening Color Chooser: " + e); |  | ||||||
| 				e.printStackTrace(); |  | ||||||
| 			} |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		panel.add(textPane); |  | ||||||
| 		panel.add(button); |  | ||||||
| 		panel.setBackground(theme.getCellColor()); |  | ||||||
| 		panel.setAlignmentX(Component.LEFT_ALIGNMENT); |  | ||||||
|  |  | ||||||
| 		colorsPanel.add(panel); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	private Color getInvertedColor(Color color) { return new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue()); } |  | ||||||
| } |  | ||||||
| @@ -2,6 +2,8 @@ package envoy.client.ui; | |||||||
|  |  | ||||||
| import java.awt.Color; | import java.awt.Color; | ||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Project: <strong>envoy-client</strong><br> |  * Project: <strong>envoy-client</strong><br> | ||||||
| @@ -15,16 +17,8 @@ public class Theme implements Serializable { | |||||||
|  |  | ||||||
| 	private static final long serialVersionUID = 141727847527060352L; | 	private static final long serialVersionUID = 141727847527060352L; | ||||||
|  |  | ||||||
| 	private String	themeName; | 	private String				themeName; | ||||||
| 	private Color	backgroundColor; | 	private Map<String, Color>	colors	= new HashMap<>(); | ||||||
| 	private Color	cellColor; |  | ||||||
| 	private Color	interactableBackgroundColor; |  | ||||||
| 	private Color	userNameColor; |  | ||||||
| 	private Color	interactableForegroundColor; |  | ||||||
| 	private Color	messageColorChat; |  | ||||||
| 	private Color	dateColorChat; |  | ||||||
| 	private Color	selectionColor; |  | ||||||
| 	private Color	typingMessageColor; |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Initializes a {@link Theme} with all colors relevant to the application GUI. | 	 * Initializes a {@link Theme} with all colors relevant to the application GUI. | ||||||
| @@ -47,15 +41,15 @@ public class Theme implements Serializable { | |||||||
|  |  | ||||||
| 		this.themeName = themeName; | 		this.themeName = themeName; | ||||||
|  |  | ||||||
| 		this.backgroundColor				= backgroundColor; | 		colors.put("backgroundColor", backgroundColor); | ||||||
| 		this.cellColor						= cellColor; | 		colors.put("cellColor", cellColor); | ||||||
| 		this.interactableForegroundColor	= interactableForegroundColor; | 		colors.put("interactableForegroundColor", interactableForegroundColor); | ||||||
| 		this.interactableBackgroundColor	= interactableBackgroundColor; | 		colors.put("interactableBackgroundColor", interactableBackgroundColor); | ||||||
| 		this.messageColorChat				= messageColorChat; | 		colors.put("messageColorChat", messageColorChat); | ||||||
| 		this.dateColorChat					= dateColorChat; | 		colors.put("dateColorChat", dateColorChat); | ||||||
| 		this.selectionColor					= selectionColor; | 		colors.put("selectionColor", selectionColor); | ||||||
| 		this.typingMessageColor				= typingMessageColor; | 		colors.put("typingMessageColor", typingMessageColor); | ||||||
| 		this.userNameColor					= userNameColor; | 		colors.put("userNameColor", userNameColor); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -66,11 +60,16 @@ public class Theme implements Serializable { | |||||||
| 	 * @param other the {@link Theme} to copy | 	 * @param other the {@link Theme} to copy | ||||||
| 	 */ | 	 */ | ||||||
| 	public Theme(String name, Theme other) { | 	public Theme(String name, Theme other) { | ||||||
| 		this(name, other.backgroundColor, other.cellColor, other.interactableForegroundColor, | 		themeName = name; | ||||||
| 				other.interactableBackgroundColor, other.messageColorChat, other.dateColorChat, other.selectionColor, | 		colors.putAll(other.colors); | ||||||
| 				other.typingMessageColor, other.userNameColor); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @return a {@code Map<String, Color>} of all colors defined for this theme | ||||||
|  | 	 *         with their names as keys | ||||||
|  | 	 */ | ||||||
|  | 	public Map<String, Color> getColors() { return colors; } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return name of the theme | 	 * @return name of the theme | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @since Envoy v0.2-alpha | ||||||
| @@ -81,104 +80,62 @@ public class Theme implements Serializable { | |||||||
| 	 * @return interactableForegroundColor | 	 * @return interactableForegroundColor | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @since Envoy v0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public Color getInteractableForegroundColor() { return interactableForegroundColor; } | 	public Color getInteractableForegroundColor() { return colors.get("interactableForegroundColor"); } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return messageColorChat | 	 * @return messageColorChat | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @since Envoy v0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public Color getMessageColorChat() { return messageColorChat; } | 	public Color getMessageColorChat() { return colors.get("messageColorChat"); } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return dateColorChat | 	 * @return dateColorChat | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @since Envoy v0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public Color getDateColorChat() { return dateColorChat; } | 	public Color getDateColorChat() { return colors.get("dateColorChat"); } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return selectionColor | 	 * @return selectionColor | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @since Envoy v0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public Color getSelectionColor() { return selectionColor; } | 	public Color getSelectionColor() { return colors.get("selectionColor"); } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return typingMessageColor | 	 * @return typingMessageColor | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @since Envoy v0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public Color getTypingMessageColor() { return typingMessageColor; } | 	public Color getTypingMessageColor() { return colors.get("typingMessageColor"); } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return backgroundColor | 	 * @return backgroundColor | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @since Envoy v0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public Color getBackgroundColor() { return backgroundColor; } | 	public Color getBackgroundColor() { return colors.get("backgroundColor"); } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return cellColor | 	 * @return cellColor | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @since Envoy v0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public Color getCellColor() { return cellColor; } | 	public Color getCellColor() { return colors.get("cellColor"); } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return interactableBackgroundColor | 	 * @return interactableBackgroundColor | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @since Envoy v0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public Color getInteractableBackgroundColor() { return interactableBackgroundColor; } | 	public Color getInteractableBackgroundColor() { return colors.get("interactableBackgroundColor"); } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return userNameColor | 	 * @return userNameColor | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @since Envoy v0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public Color getUserNameColor() { return userNameColor; } | 	public Color getUserNameColor() { return colors.get("userNameColor"); } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Sets the a specific {@link Color} in this theme to a new {@link Color} | 	 * Sets the a specific {@link Color} in this theme to a new {@link Color} | ||||||
| 	 * | 	 * | ||||||
| 	 * @param index    - index of the color </br> | 	 * @param colorName the name of the {@link Color} to set | ||||||
| 	 *                 0 = backgroundColor </br> | 	 * @param newColor  the new {@link Color} to be set | ||||||
| 	 *                 1 = cellColor </br> |  | ||||||
| 	 *                 2 = interactableForegroundColor </br> |  | ||||||
| 	 *                 3 = interactableBackgroundColor </br> |  | ||||||
| 	 *                 4 = messageColorChat </br> |  | ||||||
| 	 *                 5 = dateColorChat </br> |  | ||||||
| 	 *                 6 = selectionColor </br> |  | ||||||
| 	 *                 7 = typingMessageColor </br> |  | ||||||
| 	 *                 8 = userNameColor </br> |  | ||||||
| 	 *                 </br> |  | ||||||
| 	 * |  | ||||||
| 	 * @param newColor - new {@link Color} to be set |  | ||||||
| 	 * @since Envoy 0.2-alpha | 	 * @since Envoy 0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public void setColor(int index, Color newColor) { | 	public void setColor(String colorName, Color newColor) { colors.put(colorName, newColor); } | ||||||
| 		switch (index) { |  | ||||||
| 			case 0: |  | ||||||
| 				backgroundColor = newColor; |  | ||||||
| 				break; |  | ||||||
| 			case 1: |  | ||||||
| 				cellColor = newColor; |  | ||||||
| 				break; |  | ||||||
| 			case 2: |  | ||||||
| 				interactableForegroundColor = newColor; |  | ||||||
| 				break; |  | ||||||
| 			case 3: |  | ||||||
| 				interactableBackgroundColor = newColor; |  | ||||||
| 				break; |  | ||||||
| 			case 4: |  | ||||||
| 				messageColorChat = newColor; |  | ||||||
| 				break; |  | ||||||
| 			case 5: |  | ||||||
| 				dateColorChat = newColor; |  | ||||||
| 				break; |  | ||||||
| 			case 6: |  | ||||||
| 				selectionColor = newColor; |  | ||||||
| 				break; |  | ||||||
| 			case 7: |  | ||||||
| 				typingMessageColor = newColor; |  | ||||||
| 				break; |  | ||||||
| 			case 8: |  | ||||||
| 				userNameColor = newColor; |  | ||||||
| 				break; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								src/main/java/envoy/client/ui/settings/SettingsPanel.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/main/java/envoy/client/ui/settings/SettingsPanel.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | package envoy.client.ui.settings; | ||||||
|  |  | ||||||
|  | import java.awt.event.ActionListener; | ||||||
|  |  | ||||||
|  | import javax.swing.JPanel; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Project: <strong>envoy-client</strong><br> | ||||||
|  |  * File: <strong>SettingsPanel.java</strong><br> | ||||||
|  |  * Created: <strong>20 Dec 2019</strong><br> | ||||||
|  |  * | ||||||
|  |  * @author Kai S. K. Engelbart | ||||||
|  |  */ | ||||||
|  | public abstract class SettingsPanel extends JPanel { | ||||||
|  |  | ||||||
|  | 	private static final long serialVersionUID = -3069212622468626050L; | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @return an {@link ActionListener} that should be invoked when the OK button | ||||||
|  | 	 *         is pressed in the {@link SettingsScreen} | ||||||
|  | 	 */ | ||||||
|  | 	public abstract ActionListener getOkButtonAction(); | ||||||
|  | } | ||||||
							
								
								
									
										187
									
								
								src/main/java/envoy/client/ui/settings/SettingsScreen.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								src/main/java/envoy/client/ui/settings/SettingsScreen.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,187 @@ | |||||||
|  | package envoy.client.ui.settings; | ||||||
|  |  | ||||||
|  | import java.awt.BorderLayout; | ||||||
|  | import java.awt.Font; | ||||||
|  | import java.awt.GridBagConstraints; | ||||||
|  | import java.awt.GridBagLayout; | ||||||
|  | import java.awt.Insets; | ||||||
|  | import java.lang.reflect.InvocationTargetException; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.logging.Level; | ||||||
|  | import java.util.logging.Logger; | ||||||
|  |  | ||||||
|  | import javax.swing.DefaultListModel; | ||||||
|  | import javax.swing.JButton; | ||||||
|  | import javax.swing.JDialog; | ||||||
|  | import javax.swing.JList; | ||||||
|  | import javax.swing.JPanel; | ||||||
|  | import javax.swing.ListSelectionModel; | ||||||
|  |  | ||||||
|  | import envoy.client.Settings; | ||||||
|  | import envoy.client.event.EventBus; | ||||||
|  | import envoy.client.event.ThemeChangeEvent; | ||||||
|  | import envoy.client.ui.Theme; | ||||||
|  | import envoy.client.util.EnvoyLog; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * This class provides the GUI to change the user specific settings.<br> | ||||||
|  |  * <br> | ||||||
|  |  * Project: <strong>envoy-client</strong><br> | ||||||
|  |  * File: <strong>SettingsScreen.java</strong><br> | ||||||
|  |  * Created: <strong>31 Oct 2019</strong><br> | ||||||
|  |  * | ||||||
|  |  * @author Leon Hofmeister | ||||||
|  |  * @author Maximilian Käfer | ||||||
|  |  * @author Kai S. K. Engelbart | ||||||
|  |  */ | ||||||
|  | public class SettingsScreen extends JDialog { | ||||||
|  |  | ||||||
|  | 	private static final long serialVersionUID = -4476913491263077107L; | ||||||
|  |  | ||||||
|  | 	private final JPanel contentPanel = new JPanel(); | ||||||
|  |  | ||||||
|  | 	// Settings panel list | ||||||
|  | 	private final DefaultListModel<String>	optionsListModel	= new DefaultListModel<>(); | ||||||
|  | 	private final JList<String>				options				= new JList<>(optionsListModel); | ||||||
|  |  | ||||||
|  | 	// OK and cancel buttons | ||||||
|  | 	private final JPanel	buttonPane		= new JPanel(); | ||||||
|  | 	private final JButton	okButton		= new JButton("Save"); | ||||||
|  | 	private final JButton	cancelButton	= new JButton("Cancel"); | ||||||
|  |  | ||||||
|  | 	private final int space = 5; | ||||||
|  |  | ||||||
|  | 	private SettingsPanel settingsPanel; | ||||||
|  |  | ||||||
|  | 	private static final Logger logger = EnvoyLog.getLogger(SettingsScreen.class.getSimpleName()); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Initializes the settings screen. | ||||||
|  | 	 * | ||||||
|  | 	 * @since Envoy v0.1-alpha | ||||||
|  | 	 */ | ||||||
|  | 	public SettingsScreen() { | ||||||
|  | 		logger.info("Currently selected theme: " + Settings.getInstance().getCurrentTheme()); | ||||||
|  |  | ||||||
|  | 		Map<String, Class<? extends SettingsPanel>> panels = new HashMap<>(); | ||||||
|  | 		panels.put("Color Themes", ThemeCustomizationPanel.class); | ||||||
|  |  | ||||||
|  | 		setBounds(10, 10, 450, 650); | ||||||
|  | 		getContentPane().setLayout(new BorderLayout()); | ||||||
|  | 		{ | ||||||
|  | 			// Content pane | ||||||
|  | 			GridBagLayout gbl_contentPanel = new GridBagLayout(); | ||||||
|  |  | ||||||
|  | 			gbl_contentPanel.columnWidths	= new int[] { 1, 1 }; | ||||||
|  | 			gbl_contentPanel.rowHeights		= new int[] { 1 }; | ||||||
|  | 			gbl_contentPanel.columnWeights	= new double[] { 0.05, 1.0 }; | ||||||
|  | 			gbl_contentPanel.rowWeights		= new double[] { 1.0 }; | ||||||
|  |  | ||||||
|  | 			getContentPane().add(contentPanel, BorderLayout.CENTER); | ||||||
|  | 			contentPanel.setLayout(gbl_contentPanel); | ||||||
|  |  | ||||||
|  | 			options.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | ||||||
|  | 			options.addListSelectionListener((listSelectionEvent) -> { | ||||||
|  | 				if (!listSelectionEvent.getValueIsAdjusting()) { | ||||||
|  | 					// Get selected settings panel | ||||||
|  | 					final String option = options.getSelectedValue(); | ||||||
|  | 					logger.log(Level.FINEST, "Selected settings panel: " + option); | ||||||
|  |  | ||||||
|  | 					// Remove previous settings panel | ||||||
|  | 					if (settingsPanel != null) | ||||||
|  | 						contentPanel.remove(settingsPanel); | ||||||
|  |  | ||||||
|  | 					try { | ||||||
|  | 						settingsPanel = panels.get(option).getDeclaredConstructor().newInstance(); | ||||||
|  |  | ||||||
|  | 						// Add selected settings panel | ||||||
|  | 						contentPanel.add(settingsPanel); | ||||||
|  | 						revalidate(); | ||||||
|  | 						repaint(); | ||||||
|  | 					} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | ||||||
|  | 							| NoSuchMethodException | SecurityException e) { | ||||||
|  | 						e.printStackTrace(); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 			options.setFont(new Font("Arial", Font.PLAIN, 14)); | ||||||
|  |  | ||||||
|  | 			GridBagConstraints gbc_optionsList = new GridBagConstraints(); | ||||||
|  | 			gbc_optionsList.fill	= GridBagConstraints.BOTH; | ||||||
|  | 			gbc_optionsList.gridx	= 0; | ||||||
|  | 			gbc_optionsList.gridy	= 0; | ||||||
|  | 			gbc_optionsList.anchor	= GridBagConstraints.PAGE_START; | ||||||
|  | 			gbc_optionsList.insets	= new Insets(space, space, space, space); | ||||||
|  |  | ||||||
|  | 			panels.keySet().forEach(name -> optionsListModel.addElement(name)); | ||||||
|  | 			contentPanel.add(options, gbc_optionsList); | ||||||
|  |  | ||||||
|  | 			// ButtonPane | ||||||
|  | 			GridBagLayout gbl_buttonPane = new GridBagLayout(); | ||||||
|  | 			gbl_buttonPane.columnWidths		= new int[] { 100, 250, 100, 0 }; | ||||||
|  | 			gbl_buttonPane.rowHeights		= new int[] { 25, 0 }; | ||||||
|  | 			gbl_buttonPane.columnWeights	= new double[] { 0.0, 0.0, 0.0, Double.MIN_VALUE }; | ||||||
|  | 			gbl_buttonPane.rowWeights		= new double[] { 0.0, Double.MIN_VALUE }; | ||||||
|  |  | ||||||
|  | 			getContentPane().add(buttonPane, BorderLayout.SOUTH); | ||||||
|  | 			buttonPane.setLayout(gbl_buttonPane); | ||||||
|  | 			{ | ||||||
|  | 				cancelButton.setActionCommand("Cancel"); | ||||||
|  | 				cancelButton.setBorderPainted(false); | ||||||
|  | 				GridBagConstraints gbc_cancelButton = new GridBagConstraints(); | ||||||
|  | 				gbc_cancelButton.anchor	= GridBagConstraints.NORTHWEST; | ||||||
|  | 				gbc_cancelButton.insets	= new Insets(space, space, space, space); | ||||||
|  | 				gbc_cancelButton.gridx	= 0; | ||||||
|  | 				gbc_cancelButton.gridy	= 0; | ||||||
|  | 				buttonPane.add(cancelButton, gbc_cancelButton); | ||||||
|  |  | ||||||
|  | 				cancelButton.addActionListener((evt) -> { dispose(); }); | ||||||
|  | 			} | ||||||
|  | 			{ | ||||||
|  | 				okButton.setActionCommand("OK"); | ||||||
|  | 				okButton.setBorderPainted(false); | ||||||
|  | 				GridBagConstraints gbc_okButton = new GridBagConstraints(); | ||||||
|  | 				gbc_okButton.anchor	= GridBagConstraints.NORTHEAST; | ||||||
|  | 				gbc_okButton.fill	= GridBagConstraints.EAST; | ||||||
|  | 				gbc_okButton.insets	= new Insets(space, space, space, space); | ||||||
|  | 				gbc_okButton.gridx	= 2; | ||||||
|  | 				gbc_okButton.gridy	= 0; | ||||||
|  | 				buttonPane.add(okButton, gbc_okButton); | ||||||
|  | 				getRootPane().setDefaultButton(okButton); | ||||||
|  |  | ||||||
|  | 				// Invoke settings panel action on button press | ||||||
|  | 				okButton.addActionListener((evt) -> { if (settingsPanel != null) settingsPanel.getOkButtonAction().actionPerformed(evt); }); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Apply current theme | ||||||
|  | 		applyTheme(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); | ||||||
|  |  | ||||||
|  | 		// Respond to theme changes | ||||||
|  | 		EventBus.getInstance().register(ThemeChangeEvent.class, (evt) -> applyTheme(((ThemeChangeEvent) evt).get())); | ||||||
|  |  | ||||||
|  | 		setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); | ||||||
|  | 		setModal(true); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private void applyTheme(Theme theme) { | ||||||
|  | 		// whole JDialog | ||||||
|  | 		setBackground(theme.getBackgroundColor()); | ||||||
|  | 		// contentPanel | ||||||
|  | 		contentPanel.setBackground(theme.getBackgroundColor()); | ||||||
|  | 		// buttonPane | ||||||
|  | 		buttonPane.setBackground(theme.getCellColor()); | ||||||
|  | 		// cancelButton | ||||||
|  | 		cancelButton.setBackground(theme.getInteractableBackgroundColor()); | ||||||
|  | 		cancelButton.setForeground(theme.getInteractableForegroundColor()); | ||||||
|  | 		// okButton | ||||||
|  | 		okButton.setBackground(theme.getInteractableBackgroundColor()); | ||||||
|  | 		okButton.setForeground(theme.getInteractableForegroundColor()); | ||||||
|  | 		// options | ||||||
|  | 		options.setSelectionForeground(theme.getUserNameColor()); | ||||||
|  | 		options.setSelectionBackground(theme.getSelectionColor()); | ||||||
|  | 		options.setForeground(theme.getUserNameColor()); | ||||||
|  | 		options.setBackground(theme.getCellColor()); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -0,0 +1,252 @@ | |||||||
|  | package envoy.client.ui.settings; | ||||||
|  |  | ||||||
|  | import java.awt.Color; | ||||||
|  | import java.awt.Component; | ||||||
|  | import java.awt.Dimension; | ||||||
|  | import java.awt.Font; | ||||||
|  | import java.awt.GridBagConstraints; | ||||||
|  | import java.awt.GridBagLayout; | ||||||
|  | import java.awt.Insets; | ||||||
|  | import java.awt.event.ActionListener; | ||||||
|  | import java.awt.event.ItemEvent; | ||||||
|  | import java.awt.event.ItemListener; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.logging.Level; | ||||||
|  | import java.util.logging.Logger; | ||||||
|  |  | ||||||
|  | import javax.swing.BoxLayout; | ||||||
|  | import javax.swing.JButton; | ||||||
|  | import javax.swing.JColorChooser; | ||||||
|  | import javax.swing.JComboBox; | ||||||
|  | import javax.swing.JOptionPane; | ||||||
|  | import javax.swing.JPanel; | ||||||
|  | import javax.swing.JTextPane; | ||||||
|  |  | ||||||
|  | import envoy.client.Settings; | ||||||
|  | import envoy.client.event.EventBus; | ||||||
|  | import envoy.client.event.ThemeChangeEvent; | ||||||
|  | import envoy.client.ui.Theme; | ||||||
|  | import envoy.client.util.EnvoyLog; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Project: <strong>envoy-client</strong><br> | ||||||
|  |  * File: <strong>ThemeCustomizationPanel.java</strong><br> | ||||||
|  |  * Created: <strong>20 Dec 2019</strong><br> | ||||||
|  |  * | ||||||
|  |  * @author Kai S. K. Engelbart | ||||||
|  |  */ | ||||||
|  | public class ThemeCustomizationPanel extends SettingsPanel { | ||||||
|  |  | ||||||
|  | 	private static final long serialVersionUID = -8697897390666456624L; | ||||||
|  |  | ||||||
|  | 	private JPanel	colorsPanel				= new JPanel(); | ||||||
|  | 	private JButton	createNewThemeButton	= new JButton("Create New Theme"); | ||||||
|  |  | ||||||
|  | 	private String[]			themeArray	= Settings.getInstance().getThemes().keySet().toArray(new String[0]); | ||||||
|  | 	private JComboBox<String>	themes		= new JComboBox<>(themeArray); | ||||||
|  | 	private Theme				temporaryTheme, selectedTheme; | ||||||
|  |  | ||||||
|  | 	private final int space = 5; | ||||||
|  |  | ||||||
|  | 	private static final Logger logger = EnvoyLog.getLogger(ThemeCustomizationPanel.class.getSimpleName()); | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Initializes a {@link ThemeCustomizationPanel} that enables the user to change | ||||||
|  | 	 * the current {@link Theme} and create new themes as part of the | ||||||
|  | 	 * {@link SettingsScreen}. | ||||||
|  | 	 */ | ||||||
|  | 	public ThemeCustomizationPanel() { | ||||||
|  | 		temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); | ||||||
|  |  | ||||||
|  | 		// Theme content | ||||||
|  | 		GridBagConstraints gbc_themeContent = new GridBagConstraints(); | ||||||
|  | 		gbc_themeContent.fill	= GridBagConstraints.BOTH; | ||||||
|  | 		gbc_themeContent.gridx	= 1; | ||||||
|  | 		gbc_themeContent.gridy	= 0; | ||||||
|  | 		gbc_themeContent.anchor	= GridBagConstraints.PAGE_START; | ||||||
|  | 		gbc_themeContent.insets	= new Insets(space, space, space, space); | ||||||
|  |  | ||||||
|  | 		GridBagLayout gbl_themeLayout = new GridBagLayout(); | ||||||
|  |  | ||||||
|  | 		gbl_themeLayout.columnWidths	= new int[] { 1, 1 }; | ||||||
|  | 		gbl_themeLayout.rowHeights		= new int[] { 1, 1 }; | ||||||
|  | 		gbl_themeLayout.columnWeights	= new double[] { 1.0, 1.0 }; | ||||||
|  | 		gbl_themeLayout.rowWeights		= new double[] { 0.01, 1.0 }; | ||||||
|  |  | ||||||
|  | 		setLayout(gbl_themeLayout); | ||||||
|  |  | ||||||
|  | 		themes.setSelectedItem(Settings.getInstance().getCurrentTheme()); | ||||||
|  |  | ||||||
|  | 		themes.addItemListener(new ItemListener() { | ||||||
|  |  | ||||||
|  | 			@Override | ||||||
|  | 			public void itemStateChanged(ItemEvent e) { | ||||||
|  | 				String selectedValue = (String) themes.getSelectedItem(); | ||||||
|  | 				logger.log(Level.FINEST, selectedValue); | ||||||
|  | 				selectedTheme = Settings.getInstance().getThemes().get(selectedValue); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  |  | ||||||
|  | 		GridBagConstraints gbc_themes = new GridBagConstraints(); | ||||||
|  | 		gbc_themes.fill		= GridBagConstraints.HORIZONTAL; | ||||||
|  | 		gbc_themes.gridx	= 0; | ||||||
|  | 		gbc_themes.gridy	= 0; | ||||||
|  | 		gbc_themes.anchor	= GridBagConstraints.NORTHWEST; | ||||||
|  | 		gbc_themes.insets	= new Insets(space, space, space, space); | ||||||
|  |  | ||||||
|  | 		add(themes, gbc_themes); | ||||||
|  |  | ||||||
|  | 		colorsPanel.setLayout(new BoxLayout(colorsPanel, BoxLayout.Y_AXIS)); | ||||||
|  | 		colorsPanel.setAlignmentX(Component.LEFT_ALIGNMENT); | ||||||
|  |  | ||||||
|  | 		Theme theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()); | ||||||
|  | 		buildCustomizeElements(theme); | ||||||
|  |  | ||||||
|  | 		GridBagConstraints gbc_colorsPanel = new GridBagConstraints(); | ||||||
|  | 		gbc_colorsPanel.fill		= GridBagConstraints.HORIZONTAL; | ||||||
|  | 		gbc_colorsPanel.gridx		= 0; | ||||||
|  | 		gbc_colorsPanel.gridy		= 1; | ||||||
|  | 		gbc_colorsPanel.gridwidth	= 2; | ||||||
|  | 		gbc_colorsPanel.anchor		= GridBagConstraints.NORTHWEST; | ||||||
|  | 		gbc_colorsPanel.insets		= new Insets(space, 0, 0, 0); | ||||||
|  |  | ||||||
|  | 		add(colorsPanel, gbc_colorsPanel); | ||||||
|  |  | ||||||
|  | 		createNewThemeButton.setEnabled(false); | ||||||
|  | 		createNewThemeButton.setBackground(theme.getInteractableBackgroundColor()); | ||||||
|  | 		createNewThemeButton.setForeground(theme.getInteractableForegroundColor()); | ||||||
|  | 		colorsPanel.setBackground(theme.getCellColor()); | ||||||
|  |  | ||||||
|  | 		createNewThemeButton.addActionListener((evt) -> { | ||||||
|  | 			try { | ||||||
|  | 				String s = JOptionPane.showInputDialog("Enter a name for the new theme"); | ||||||
|  | 				logger.log(Level.FINEST, s); | ||||||
|  | 				Settings.getInstance() | ||||||
|  | 					.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())); | ||||||
|  |  | ||||||
|  | 				createNewThemeButton.setEnabled(false); | ||||||
|  | 				themes.addItem(themeArray[themeArray.length - 1]); | ||||||
|  |  | ||||||
|  | 			} catch (Exception e) { | ||||||
|  | 				logger.info("New theme couldn't be created! " + e); | ||||||
|  | 				e.printStackTrace(); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  |  | ||||||
|  | 		GridBagConstraints gbc_createNewTheme = new GridBagConstraints(); | ||||||
|  | 		gbc_createNewTheme.gridx	= 0; | ||||||
|  | 		gbc_createNewTheme.gridy	= 10; | ||||||
|  |  | ||||||
|  | 		colorsPanel.add(createNewThemeButton, gbc_createNewTheme); | ||||||
|  |  | ||||||
|  | 		// Apply current theme | ||||||
|  | 		applyTheme(theme); | ||||||
|  |  | ||||||
|  | 		// Respond to theme changes | ||||||
|  | 		EventBus.getInstance().register(ThemeChangeEvent.class, (evt) -> applyTheme(((ThemeChangeEvent) evt).get())); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@Override | ||||||
|  | 	public ActionListener getOkButtonAction() { | ||||||
|  | 		return (evt) -> { | ||||||
|  | 			Settings.getInstance().setCurrentTheme(selectedTheme.getThemeName()); | ||||||
|  | 			logger.log(Level.FINER, "Setting theme: " + selectedTheme.getThemeName()); | ||||||
|  |  | ||||||
|  | 			final Theme currentTheme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()); | ||||||
|  | 			updateColorVariables(currentTheme); | ||||||
|  | 			EventBus.getInstance().dispatch(new ThemeChangeEvent(currentTheme)); | ||||||
|  |  | ||||||
|  | 			revalidate(); | ||||||
|  | 			repaint(); | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private void applyTheme(Theme theme) { | ||||||
|  | 		// themeContent | ||||||
|  | 		setForeground(theme.getUserNameColor()); | ||||||
|  | 		setBackground(theme.getCellColor()); | ||||||
|  |  | ||||||
|  | 		// themes | ||||||
|  | 		themes.setBackground(theme.getBackgroundColor()); | ||||||
|  | 		themes.setForeground(getInvertedColor(theme.getBackgroundColor())); | ||||||
|  |  | ||||||
|  | 		createNewThemeButton.setBackground(theme.getInteractableBackgroundColor()); | ||||||
|  | 		createNewThemeButton.setForeground(theme.getInteractableForegroundColor()); | ||||||
|  | 		colorsPanel.setBackground(theme.getCellColor()); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private void updateColorVariables(Theme theme) { | ||||||
|  | 		temporaryTheme = new Theme("temporaryTheme", theme); | ||||||
|  |  | ||||||
|  | 		colorsPanel.removeAll(); | ||||||
|  |  | ||||||
|  | 		buildCustomizeElements(theme); | ||||||
|  |  | ||||||
|  | 		GridBagConstraints gbc_createNewTheme = new GridBagConstraints(); | ||||||
|  | 		gbc_createNewTheme.gridx	= 0; | ||||||
|  | 		gbc_createNewTheme.gridy	= 10; | ||||||
|  |  | ||||||
|  | 		colorsPanel.add(createNewThemeButton, gbc_createNewTheme); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private void buildCustomizeElements(Theme theme) { | ||||||
|  | 		buildCustomizeElement(theme, theme.getBackgroundColor(), "Background", "backgroundColor"); | ||||||
|  | 		buildCustomizeElement(theme, theme.getCellColor(), "Cells", "cellColor"); | ||||||
|  | 		buildCustomizeElement(theme, theme.getInteractableForegroundColor(), "Interactable Foreground", "interactableForegroundColor"); | ||||||
|  | 		buildCustomizeElement(theme, theme.getInteractableBackgroundColor(), "Interactable Background", "interactableBackgroundColor"); | ||||||
|  | 		buildCustomizeElement(theme, theme.getMessageColorChat(), "Messages Chat", "messageColorChat"); | ||||||
|  | 		buildCustomizeElement(theme, theme.getDateColorChat(), "Date Chat", "dateColorCat"); | ||||||
|  | 		buildCustomizeElement(theme, theme.getSelectionColor(), "Selection", "selectionColor"); | ||||||
|  | 		buildCustomizeElement(theme, theme.getTypingMessageColor(), "Typing Message", "typingMessageColor"); | ||||||
|  | 		buildCustomizeElement(theme, theme.getUserNameColor(), "User Names", "userNameColor"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private void buildCustomizeElement(Theme theme, Color color, String name, String colorName) { | ||||||
|  | 		JPanel		panel		= new JPanel(); | ||||||
|  | 		JButton		button		= new JButton(); | ||||||
|  | 		JTextPane	textPane	= new JTextPane(); | ||||||
|  |  | ||||||
|  | 		textPane.setFont(new Font("Arial", Font.PLAIN, 14)); | ||||||
|  | 		textPane.setBackground(theme.getBackgroundColor()); | ||||||
|  | 		textPane.setForeground(getInvertedColor(theme.getBackgroundColor())); | ||||||
|  | 		textPane.setText(name); | ||||||
|  | 		textPane.setEditable(false); | ||||||
|  |  | ||||||
|  | 		button.setBackground(color); | ||||||
|  | 		button.setPreferredSize(new Dimension(25, 25)); | ||||||
|  |  | ||||||
|  | 		button.addActionListener((evt) -> { | ||||||
|  | 			try { | ||||||
|  | 				Color newColor = JColorChooser.showDialog(null, "Choose a color", color); | ||||||
|  | 				if (newColor.getRGB() != color.getRGB()) { | ||||||
|  | 					logger.log(Level.FINEST, "New Color: " + String.valueOf(color.getRGB())); | ||||||
|  | 					// TODO: When Theme changed in same settings screen, color variable doesn't | ||||||
|  | 					// update | ||||||
|  | 					temporaryTheme.setColor(colorName, newColor); | ||||||
|  | 					createNewThemeButton.setEnabled(true); | ||||||
|  | 				} | ||||||
|  | 				button.setBackground(newColor); | ||||||
|  |  | ||||||
|  | 			} catch (Exception e) { | ||||||
|  | 				logger.info("An error occured while opening Color Chooser: " + e); | ||||||
|  | 				e.printStackTrace(); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  |  | ||||||
|  | 		panel.add(textPane); | ||||||
|  | 		panel.add(button); | ||||||
|  | 		panel.setBackground(theme.getCellColor()); | ||||||
|  | 		panel.setAlignmentX(Component.LEFT_ALIGNMENT); | ||||||
|  |  | ||||||
|  | 		colorsPanel.add(panel); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private Color getInvertedColor(Color color) { return new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue()); } | ||||||
|  | } | ||||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 8.0 KiB | 
		Reference in New Issue
	
	Block a user