diff --git a/src/main/java/envoy/client/ui/ChatWindow.java b/src/main/java/envoy/client/ui/ChatWindow.java index ea8ab1e..8b1c60c 100644 --- a/src/main/java/envoy/client/ui/ChatWindow.java +++ b/src/main/java/envoy/client/ui/ChatWindow.java @@ -29,6 +29,7 @@ import envoy.client.LocalDB; import envoy.client.Settings; import envoy.client.event.EventBus; import envoy.client.event.ThemeChangeEvent; +import envoy.client.ui.settings.SettingsScreen; import envoy.client.util.EnvoyLog; import envoy.schema.Message; import envoy.schema.User; @@ -157,7 +158,6 @@ public class ChatWindow extends JFrame { settingsButton.addActionListener((evt) -> { try { new SettingsScreen().setVisible(true); - changeChatWindowColors(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); } catch (Exception e) { logger.log(Level.WARNING, "An error occured while opening the settings screen", e); e.printStackTrace(); diff --git a/src/main/java/envoy/client/ui/SettingsScreen.java b/src/main/java/envoy/client/ui/SettingsScreen.java deleted file mode 100644 index 75ce884..0000000 --- a/src/main/java/envoy/client/ui/SettingsScreen.java +++ /dev/null @@ -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: envoy-client
- * File: SettingsScreen.java
- * Created: 31 Oct 2019
- * - * @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 optionsListModel = new DefaultListModel<>(); - private final JList options = new JList<>(); - private JPanel buttonPane = new JPanel(); - - private JPanel themeContent = new JPanel(); - private String[] themeArray = Settings.getInstance().getThemes().keySet().toArray(new String[0]); - private JComboBox themes = new JComboBox<>(themeArray); - - private 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 selectedOption = (JList) 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()); } -} diff --git a/src/main/java/envoy/client/ui/Theme.java b/src/main/java/envoy/client/ui/Theme.java index 78eccc6..c498655 100644 --- a/src/main/java/envoy/client/ui/Theme.java +++ b/src/main/java/envoy/client/ui/Theme.java @@ -2,6 +2,8 @@ package envoy.client.ui; import java.awt.Color; import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; /** * Project: envoy-client
@@ -15,16 +17,8 @@ public class Theme implements Serializable { private static final long serialVersionUID = 141727847527060352L; - private String themeName; - private Color backgroundColor; - private Color cellColor; - private Color interactableBackgroundColor; - private Color userNameColor; - private Color interactableForegroundColor; - private Color messageColorChat; - private Color dateColorChat; - private Color selectionColor; - private Color typingMessageColor; + private String themeName; + private Map colors = new HashMap<>(); /** * 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.backgroundColor = backgroundColor; - this.cellColor = cellColor; - this.interactableForegroundColor = interactableForegroundColor; - this.interactableBackgroundColor = interactableBackgroundColor; - this.messageColorChat = messageColorChat; - this.dateColorChat = dateColorChat; - this.selectionColor = selectionColor; - this.typingMessageColor = typingMessageColor; - this.userNameColor = userNameColor; + colors.put("backgroundColor", backgroundColor); + colors.put("cellColor", cellColor); + colors.put("interactableForegroundColor", interactableForegroundColor); + colors.put("interactableBackgroundColor", interactableBackgroundColor); + colors.put("messageColorChat", messageColorChat); + colors.put("dateColorChat", dateColorChat); + colors.put("selectionColor", selectionColor); + colors.put("typingMessageColor", typingMessageColor); + colors.put("userNameColor", userNameColor); } /** @@ -66,11 +60,16 @@ public class Theme implements Serializable { * @param other the {@link Theme} to copy */ public Theme(String name, Theme other) { - this(name, other.backgroundColor, other.cellColor, other.interactableForegroundColor, - other.interactableBackgroundColor, other.messageColorChat, other.dateColorChat, other.selectionColor, - other.typingMessageColor, other.userNameColor); + themeName = name; + colors.putAll(other.colors); } + /** + * @return a {@code Map} of all colors defined for this theme + * with their names as keys + */ + public Map getColors() { return colors; } + /** * @return name of the theme * @since Envoy v0.2-alpha @@ -81,104 +80,62 @@ public class Theme implements Serializable { * @return interactableForegroundColor * @since Envoy v0.2-alpha */ - public Color getInteractableForegroundColor() { return interactableForegroundColor; } + public Color getInteractableForegroundColor() { return colors.get("interactableForegroundColor"); } /** * @return messageColorChat * @since Envoy v0.2-alpha */ - public Color getMessageColorChat() { return messageColorChat; } + public Color getMessageColorChat() { return colors.get("messageColorChat"); } /** * @return dateColorChat * @since Envoy v0.2-alpha */ - public Color getDateColorChat() { return dateColorChat; } + public Color getDateColorChat() { return colors.get("dateColorChat"); } /** * @return selectionColor * @since Envoy v0.2-alpha */ - public Color getSelectionColor() { return selectionColor; } + public Color getSelectionColor() { return colors.get("selectionColor"); } /** * @return typingMessageColor * @since Envoy v0.2-alpha */ - public Color getTypingMessageColor() { return typingMessageColor; } + public Color getTypingMessageColor() { return colors.get("typingMessageColor"); } /** * @return backgroundColor * @since Envoy v0.2-alpha */ - public Color getBackgroundColor() { return backgroundColor; } + public Color getBackgroundColor() { return colors.get("backgroundColor"); } /** * @return cellColor * @since Envoy v0.2-alpha */ - public Color getCellColor() { return cellColor; } + public Color getCellColor() { return colors.get("cellColor"); } /** * @return interactableBackgroundColor * @since Envoy v0.2-alpha */ - public Color getInteractableBackgroundColor() { return interactableBackgroundColor; } + public Color getInteractableBackgroundColor() { return colors.get("interactableBackgroundColor"); } /** * @return userNameColor * @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} * - * @param index - index of the color
- * 0 = backgroundColor
- * 1 = cellColor
- * 2 = interactableForegroundColor
- * 3 = interactableBackgroundColor
- * 4 = messageColorChat
- * 5 = dateColorChat
- * 6 = selectionColor
- * 7 = typingMessageColor
- * 8 = userNameColor
- *
- * - * @param newColor - new {@link Color} to be set + * @param colorName the name of the {@link Color} to set + * @param newColor the new {@link Color} to be set * @since Envoy 0.2-alpha */ - public void setColor(int index, Color 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; - } - } - + public void setColor(String colorName, Color newColor) { colors.put(colorName, newColor); } } diff --git a/src/main/java/envoy/client/ui/settings/SettingsPanel.java b/src/main/java/envoy/client/ui/settings/SettingsPanel.java new file mode 100644 index 0000000..56e1957 --- /dev/null +++ b/src/main/java/envoy/client/ui/settings/SettingsPanel.java @@ -0,0 +1,23 @@ +package envoy.client.ui.settings; + +import java.awt.event.ActionListener; + +import javax.swing.JPanel; + +/** + * Project: envoy-client
+ * File: SettingsPanel.java
+ * Created: 20 Dec 2019
+ * + * @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(); +} diff --git a/src/main/java/envoy/client/ui/settings/SettingsScreen.java b/src/main/java/envoy/client/ui/settings/SettingsScreen.java new file mode 100644 index 0000000..d34eee4 --- /dev/null +++ b/src/main/java/envoy/client/ui/settings/SettingsScreen.java @@ -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.
+ *
+ * Project: envoy-client
+ * File: SettingsScreen.java
+ * Created: 31 Oct 2019
+ * + * @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 optionsListModel = new DefaultListModel<>(); + private final JList 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> 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()); + } +} diff --git a/src/main/java/envoy/client/ui/settings/ThemeCustomizationPanel.java b/src/main/java/envoy/client/ui/settings/ThemeCustomizationPanel.java new file mode 100644 index 0000000..61e484b --- /dev/null +++ b/src/main/java/envoy/client/ui/settings/ThemeCustomizationPanel.java @@ -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: envoy-client
+ * File: ThemeCustomizationPanel.java
+ * Created: 20 Dec 2019
+ * + * @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 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()); } +} diff --git a/src/main/resources/envoy_logo_old.png b/src/main/resources/envoy_logo_old.png deleted file mode 100644 index 35ef7d9..0000000 Binary files a/src/main/resources/envoy_logo_old.png and /dev/null differ