Added instantaneous theme change, fixed dialog modality

This commit is contained in:
Kai S. K. Engelbart 2019-12-27 16:56:48 +02:00
parent c732c0cf45
commit f0a96b8e39
7 changed files with 120 additions and 160 deletions

View File

@ -186,4 +186,11 @@ public class Settings {
* @since Envoy v0.2-alpha * @since Envoy v0.2-alpha
*/ */
public void setThemes(Map<String, Theme> themes) { this.themes = themes; } public void setThemes(Map<String, Theme> themes) { this.themes = themes; }
/**
* @param themeName the name of the {@link Theme} to get
* @return the {@link Theme} with the specified name
* @since Envoy v0.3-alpha
*/
public Theme getTheme(String themeName) { return themes.get(themeName); }
} }

View File

@ -79,6 +79,8 @@ public class Color extends java.awt.Color {
private static final long serialVersionUID = -9166233199998257344L; private static final long serialVersionUID = -9166233199998257344L;
public Color(java.awt.Color other) { this(other.getRGB()); }
public Color(int rgb) { super(rgb); } public Color(int rgb) { super(rgb); }
public Color(int rgba, boolean hasalpha) { super(rgba, hasalpha); } public Color(int rgba, boolean hasalpha) { super(rgba, hasalpha); }

View File

@ -37,9 +37,12 @@ public class GeneralSettingsPanel extends SettingsPanel {
* This is the constructor for the General class. Here the user can set general * This is the constructor for the General class. Here the user can set general
* settings for the client. * settings for the client.
* *
* @param parent the {@link SettingsScreen} as a part of which this
* {@link SettingsPanel} is displayed
* @since Envoy 0.3-alpha * @since Envoy 0.3-alpha
*/ */
public GeneralSettingsPanel() { public GeneralSettingsPanel(SettingsScreen parent) {
super(parent);
theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()); theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme());
setBackground(theme.getCellColor()); setBackground(theme.getCellColor());

View File

@ -1,15 +1,16 @@
package envoy.client.ui.settings; package envoy.client.ui.settings;
import java.awt.*; import java.awt.*;
import java.util.logging.Logger; import java.util.function.Consumer;
import javax.swing.*; import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import envoy.client.Settings; import envoy.client.Settings;
import envoy.client.ui.PrimaryButton; import envoy.client.ui.PrimaryButton;
import envoy.client.ui.PrimaryTextArea; import envoy.client.ui.PrimaryTextArea;
import envoy.client.ui.Theme; import envoy.client.ui.Theme;
import envoy.client.util.EnvoyLog;
/** /**
* Displays window where you can choose a name for the new {@link Theme}. * Displays window where you can choose a name for the new {@link Theme}.
@ -33,57 +34,47 @@ public class NewThemeScreen extends JDialog {
private PrimaryButton otherName = new PrimaryButton("Other Name"); private PrimaryButton otherName = new PrimaryButton("Other Name");
private PrimaryButton overwrite = new PrimaryButton("Overwrite"); private PrimaryButton overwrite = new PrimaryButton("Overwrite");
private static final Logger logger = EnvoyLog.getLogger(NewThemeScreen.class.getSimpleName()); private final Consumer<String> newThemeAction, modifyThemeAction;
private static final long serialVersionUID = 2369985550946300976L;
private static final long serialVersionUID = 2369985550946300976L;
/** /**
* Creates a window, where you can choose a name for a new {@link Theme}. <br> * Creates a window, where you can choose a name for a new {@link Theme}. <br>
* There are two versions of this Window. The first one is responsible for * There are two versions of this Window. The first one is responsible for
* choosing the name, the second one appears, the the name already exists. * choosing the name, the second one appears, the the name already exists.
* *
* @param parentClass The class, where this constructor is invoked. * @param parent the dialog is launched with its location relative to this {@link SettingsScreen}
* @param newThemeAction is executed when a new theme name is entered
* @param modifyThemeAction is executed when an existing theme name is entered and confirmed
* @since Envoy v0.3-alpha * @since Envoy v0.3-alpha
*/ */
public NewThemeScreen(ThemeCustomizationPanel parentClass) { public NewThemeScreen(SettingsScreen parent, Consumer<String> newThemeAction, Consumer<String> modifyThemeAction) {
this.newThemeAction = newThemeAction;
this.modifyThemeAction = modifyThemeAction;
setLocationRelativeTo(parent);
setTitle("New Theme"); setTitle("New Theme");
setDimensions(true, parentClass);
setVisible(true);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setModal(true); setModal(true);
// TODO: check modalitly
// setModalityType(DEFAULT_MODALITY_TYPE); setDimensions(true);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
Theme theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()); Theme theme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme());
getContentPane().setLayout(new BorderLayout()); getContentPane().setLayout(new BorderLayout());
{ standardPanel.setBackground(theme.getBackgroundColor());
standardPanel.setBackground(theme.getBackgroundColor()); secondaryPanel.setBackground(theme.getBackgroundColor());
secondaryPanel.setBackground(theme.getBackgroundColor()); loadStandardContent(theme);
loadStandardContent(theme, parentClass);
}
} }
private void setDimensions(boolean isStandard, ThemeCustomizationPanel parentClass) { private void setDimensions(boolean isStandard) {
if (isStandard == true) { Dimension size = isStandard ? new Dimension(300, 170) : new Dimension(300, 225);
setPreferredSize(new Dimension(300, 170)); setPreferredSize(size);
setMinimumSize(new Dimension(300, 170)); setMinimumSize(size);
setMaximumSize(new Dimension(300, 170)); setMaximumSize(size);
setBounds(parentClass.getLocation().x + (parentClass.getSize().width),
parentClass.getLocation().y + (parentClass.getSize().height / 2),
300,
170);
} else {
setPreferredSize(new Dimension(300, 225));
setMinimumSize(new Dimension(300, 225));
setMaximumSize(new Dimension(300, 225));
setBounds(parentClass.getLocation().x + (parentClass.getSize().width),
parentClass.getLocation().y + (parentClass.getSize().height / 2),
300,
225);
}
} }
private void loadStandardContent(Theme theme, ThemeCustomizationPanel parentClass) { private void loadStandardContent(Theme theme) {
getContentPane().removeAll(); getContentPane().removeAll();
// ContentPane // ContentPane
@ -139,23 +130,18 @@ public class NewThemeScreen extends JDialog {
standardPanel.add(confirmButton, gbc_confirmButton); standardPanel.add(confirmButton, gbc_confirmButton);
confirmButton.addActionListener((evt) -> { confirmButton.addActionListener((evt) -> {
if (!nameEnterTextArea.getText().isEmpty()) try { if (!nameEnterTextArea.getText().isEmpty()) if (Settings.getInstance().getThemes().containsKey(nameEnterTextArea.getText())) {
if (Settings.getInstance().getThemes().containsKey(nameEnterTextArea.getText())) { // load other panel
// load other panel setDimensions(false);
setDimensions(false, parentClass); loadSecondaryPage(theme);
loadSecondaryPage(theme, parentClass); } else {
} else { newThemeAction.accept(nameEnterTextArea.getText());
parentClass.newTheme(nameEnterTextArea.getText()); dispose();
dispose();
}
} catch (Exception e) {
logger.info("" + "Name could not be set! " + e);
e.printStackTrace();
} }
}); });
} }
private void loadSecondaryPage(Theme theme, ThemeCustomizationPanel parentClass) { private void loadSecondaryPage(Theme theme) {
// ContentPane // ContentPane
getContentPane().removeAll(); getContentPane().removeAll();
@ -233,28 +219,8 @@ public class NewThemeScreen extends JDialog {
secondaryPanel.add(overwrite, gbc_overwrite); secondaryPanel.add(overwrite, gbc_overwrite);
otherName.addActionListener((evt) -> { otherName.addActionListener((evt) -> { setDimensions(true); loadStandardContent(theme); });
try {
setDimensions(true, parentClass);
loadStandardContent(theme, parentClass);
} catch (Exception e) { overwrite.addActionListener((evt) -> { modifyThemeAction.accept(nameEnterTextArea.getText()); dispose(); });
logger.info("Window could not be updated! " + e);
e.printStackTrace();
}
});
overwrite.addActionListener((evt) -> {
try {
dispose();
parentClass.overwriteTheme(nameEnterTextArea.getText());
} catch (Exception e) {
logger.info("Error while overwriting the theme! " + e);
e.printStackTrace();
}
});
} }
} }

View File

@ -18,8 +18,18 @@ import javax.swing.JPanel;
*/ */
public abstract class SettingsPanel extends JPanel { public abstract class SettingsPanel extends JPanel {
protected final SettingsScreen parent;
private static final long serialVersionUID = -3069212622468626050L; private static final long serialVersionUID = -3069212622468626050L;
/**
* Initializes a {@link SettingsPanel}.
*
* @param parent the {@link SettingsScreen} as a part of which this
* {@link SettingsPanel} is displayed
*/
public SettingsPanel(SettingsScreen parent) { this.parent = parent; }
/** /**
* @return an {@link ActionListener} that should be invoked when the OK button * @return an {@link ActionListener} that should be invoked when the OK button
* is pressed in the {@link SettingsScreen} * is pressed in the {@link SettingsScreen}

View File

@ -93,7 +93,7 @@ public class SettingsScreen extends JDialog {
if (settingsPanel != null) contentPanel.remove(settingsPanel); if (settingsPanel != null) contentPanel.remove(settingsPanel);
try { try {
settingsPanel = panels.get(option).getDeclaredConstructor().newInstance(); settingsPanel = panels.get(option).getDeclaredConstructor(getClass()).newInstance(this);
// Add selected settings panel // Add selected settings panel
contentPanel.add(settingsPanel, gbc_panel); contentPanel.add(settingsPanel, gbc_panel);
@ -162,8 +162,7 @@ public class SettingsScreen extends JDialog {
EventBus.getInstance().register(ThemeChangeEvent.class, (evt) -> applyTheme(((ThemeChangeEvent) evt).get())); EventBus.getInstance().register(ThemeChangeEvent.class, (evt) -> applyTheme(((ThemeChangeEvent) evt).get()));
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
//setModal(true); setModal(true);
//TODO: check modalitly
} }
private void applyTheme(Theme theme) { private void applyTheme(Theme theme) {

View File

@ -4,7 +4,6 @@ import java.awt.*;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.ItemEvent; import java.awt.event.ItemEvent;
import java.awt.event.ItemListener; import java.awt.event.ItemListener;
import java.util.Arrays;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -33,10 +32,11 @@ public class ThemeCustomizationPanel extends SettingsPanel {
private JPanel colorsPanel = new JPanel(); private JPanel colorsPanel = new JPanel();
private String[] themeArray = Settings.getInstance().getThemes().keySet().toArray(new String[0]); private DefaultComboBoxModel<String> themesModel = new DefaultComboBoxModel<>(
private JComboBox<String> themes = new JComboBox<>(themeArray); Settings.getInstance().getThemes().keySet().toArray(new String[0]));
private Theme temporaryTheme, selectedTheme; private JComboBox<String> themes = new JComboBox<>(themesModel);
private boolean themeChanged = false; private Theme temporaryTheme;
private boolean themeChanged;
private final Insets insets = new Insets(5, 5, 5, 5); private final Insets insets = new Insets(5, 5, 5, 5);
@ -48,9 +48,12 @@ public class ThemeCustomizationPanel extends SettingsPanel {
* the current {@link Theme} and create new themes as part of the * the current {@link Theme} and create new themes as part of the
* {@link SettingsScreen}. * {@link SettingsScreen}.
* *
* @param parent the {@link SettingsScreen} as a part of which this
* {@link SettingsPanel} is displayed
* @since Envoy v0.2-alpha * @since Envoy v0.2-alpha
*/ */
public ThemeCustomizationPanel() { public ThemeCustomizationPanel(SettingsScreen parent) {
super(parent);
temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()));
GridBagLayout gbl_themeLayout = new GridBagLayout(); GridBagLayout gbl_themeLayout = new GridBagLayout();
@ -64,16 +67,6 @@ public class ThemeCustomizationPanel extends SettingsPanel {
themes.setSelectedItem(Settings.getInstance().getCurrentTheme()); 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(); GridBagConstraints gbc_themes = new GridBagConstraints();
gbc_themes.fill = GridBagConstraints.HORIZONTAL; gbc_themes.fill = GridBagConstraints.HORIZONTAL;
gbc_themes.gridwidth = 2; gbc_themes.gridwidth = 2;
@ -106,26 +99,53 @@ public class ThemeCustomizationPanel extends SettingsPanel {
add(colorsPanel, gbc_colorsPanel); add(colorsPanel, gbc_colorsPanel);
colorsPanel.setBackground(theme.getCellColor()); colorsPanel.setBackground(theme.getCellColor());
// Apply theme upon selection
themes.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
String selectedValue = (String) themes.getSelectedItem();
logger.log(Level.FINEST, "Selected theme: " + selectedValue);
final Theme currentTheme = Settings.getInstance().getTheme(selectedValue);
Settings.getInstance().setCurrentTheme(selectedValue);
EventBus.getInstance().dispatch(new ThemeChangeEvent(currentTheme));
}
});
// Apply current theme // Apply current theme
applyTheme(theme); applyTheme(theme);
// Respond to theme changes // Respond to theme changes
EventBus.getInstance().register(ThemeChangeEvent.class, (evt) -> applyTheme(((ThemeChangeEvent) evt).get())); EventBus.getInstance()
.register(ThemeChangeEvent.class,
(evt) -> {
final Theme currentTheme = ((ThemeChangeEvent) evt).get();
temporaryTheme = new Theme("temporaryTheme", currentTheme);
applyTheme(currentTheme);
});
} }
@Override @Override
public ActionListener getOkButtonAction() { public ActionListener getOkButtonAction() {
return (evt) -> { return (evt) -> {
if (themeChanged) { if (themeChanged) {
try { new NewThemeScreen(parent, (name) -> {
new NewThemeScreen(this).setVisible(true); // Create new theme
} catch (Exception e) { logger.log(Level.FINEST, name);
logger.info("New theme couldn't be created! " + e); Settings.getInstance().addNewThemeToMap(new Theme(name, temporaryTheme));
e.printStackTrace();
} // Add new theme name to combo box
themesModel.addElement(name);
// Select new theme name
themes.setSelectedIndex(themesModel.getSize() - 1);
}, (name) -> {
// Modify theme
Settings.getInstance().getThemes().replace(name, new Theme(name, temporaryTheme));
themes.setSelectedItem(name);
}).setVisible(true);
themeChanged = false; themeChanged = false;
} else {
updateCurrentTheme();
} }
}; };
} }
@ -139,13 +159,16 @@ public class ThemeCustomizationPanel extends SettingsPanel {
themes.setBackground(theme.getInteractableBackgroundColor()); themes.setBackground(theme.getInteractableBackgroundColor());
themes.setForeground(theme.getInteractableForegroundColor()); themes.setForeground(theme.getInteractableForegroundColor());
colorsPanel.setBackground(theme.getCellColor()); colorsPanel.setBackground(theme.getCellColor());
// Color panel
updateColorVariables(theme);
revalidate();
repaint();
} }
private void updateColorVariables(Theme theme) { private void updateColorVariables(Theme theme) {
temporaryTheme = new Theme("temporaryTheme", theme);
colorsPanel.removeAll(); colorsPanel.removeAll();
buildCustomizeElements(theme); buildCustomizeElements(theme);
} }
@ -155,7 +178,7 @@ public class ThemeCustomizationPanel extends SettingsPanel {
buildCustomizeElement(theme, theme.getInteractableForegroundColor(), "Interactable Foreground", "interactableForegroundColor", 3); buildCustomizeElement(theme, theme.getInteractableForegroundColor(), "Interactable Foreground", "interactableForegroundColor", 3);
buildCustomizeElement(theme, theme.getInteractableBackgroundColor(), "Interactable Background", "interactableBackgroundColor", 4); buildCustomizeElement(theme, theme.getInteractableBackgroundColor(), "Interactable Background", "interactableBackgroundColor", 4);
buildCustomizeElement(theme, theme.getMessageColorChat(), "Messages Chat", "messageColorChat", 5); buildCustomizeElement(theme, theme.getMessageColorChat(), "Messages Chat", "messageColorChat", 5);
buildCustomizeElement(theme, theme.getDateColorChat(), "Date Chat", "dateColorCat", 6); buildCustomizeElement(theme, theme.getDateColorChat(), "Date Chat", "dateColorChat", 6);
buildCustomizeElement(theme, theme.getSelectionColor(), "Selection", "selectionColor", 7); buildCustomizeElement(theme, theme.getSelectionColor(), "Selection", "selectionColor", 7);
buildCustomizeElement(theme, theme.getTypingMessageColor(), "Typing Message", "typingMessageColor", 8); buildCustomizeElement(theme, theme.getTypingMessageColor(), "Typing Message", "typingMessageColor", 8);
buildCustomizeElement(theme, theme.getUserNameColor(), "User Names", "userNameColor", 9); buildCustomizeElement(theme, theme.getUserNameColor(), "User Names", "userNameColor", 9);
@ -175,21 +198,15 @@ public class ThemeCustomizationPanel extends SettingsPanel {
button.setPreferredSize(new Dimension(25, 25)); button.setPreferredSize(new Dimension(25, 25));
button.addActionListener((evt) -> { button.addActionListener((evt) -> {
try { java.awt.Color c = JColorChooser.showDialog(null, "Choose a color", color);
java.awt.Color c = JColorChooser.showDialog(null, "Choose a color", color); if (c != null) {
Color newColor = new Color(c.getRGB()); Color newColor = new Color(c);
if (newColor.getRGB() != color.getRGB()) { if (!color.equals(newColor)) {
logger.log(Level.FINEST, "New Color: " + String.valueOf(color.getRGB())); logger.log(Level.FINEST, "New Color: " + newColor);
// TODO: When Theme changed in same settings screen, color variable doesn't
// update
temporaryTheme.setColor(colorName, newColor); temporaryTheme.setColor(colorName, newColor);
themeChanged = true; themeChanged = true;
} }
button.setBackground(newColor); button.setBackground(newColor);
} catch (Exception e) {
logger.info("An error occured while opening Color Chooser: " + e);
e.printStackTrace();
} }
}); });
@ -211,48 +228,4 @@ public class ThemeCustomizationPanel extends SettingsPanel {
colorsPanel.add(button, gbc_button); colorsPanel.add(button, gbc_button);
} }
private void updateCurrentTheme() {
Settings.getInstance().setCurrentTheme(selectedTheme.getThemeName());
logger.log(Level.FINER, "Setting theme: " + selectedTheme.getThemeName());
final Theme currentTheme = Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme());
applyTheme(currentTheme);
updateColorVariables(currentTheme);
EventBus.getInstance().dispatch(new ThemeChangeEvent(currentTheme));
temporaryTheme = new Theme("temporaryTheme", currentTheme);
revalidate();
repaint();
}
/**
* Adds a new {@link Theme} to the theme map.
*
* @param name The name of the new {@link Theme}.
* @since Envoy v0.3-alpha
*/
public void newTheme(String name) {
logger.log(Level.FINEST, name);
Settings.getInstance().addNewThemeToMap(new Theme(name, temporaryTheme));
themeArray = Arrays.copyOf(themeArray, themeArray.length + 1);
themeArray[themeArray.length - 1] = Settings.getInstance().getThemes().get(name).getThemeName();
themes.addItem(themeArray[themeArray.length - 1]);
themes.setSelectedIndex(themeArray.length - 1);
updateCurrentTheme();
}
/**
* Overwrites a specific {@link Theme} located in the theme map and sets the selected {@link Theme} to this new {@link Theme}.
*
* @param key The name of the {@link Theme} to be overwritten.
* @since Envoy v0.3-alpha
*/
public void overwriteTheme(String key) {
Settings.getInstance().getThemes().replace(key, new Theme(key, temporaryTheme));
selectedTheme = Settings.getInstance().getThemes().get(key);
updateCurrentTheme();
}
} }