package chatty.gui.components.settings; import chatty.gui.HtmlColors; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JColorChooser; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** * A color chooser with a preview that has a primary and secondary color. * * <ul> * <li>The primary color is the one to be chosen and can either be of the type * {@literal FOREGROUND} or of the type {@literal BACKGROUND}.</li> * <li>The secondary color is only used for the preview, as * background/foreground for the primary color (depending on whether the primary * color is set to foreground/background).</li> * </ul> * * @author tduva */ public class ColorChooser extends JDialog { /** * The type of the primary color if it is to be used as foreground color */ public static final int FOREGROUND = 0; /** * The type of the primary color if it is to be used as background color */ public static final int BACKGROUND = 1; /** * The actual type of the primary color */ private int type = FOREGROUND; private final JColorChooser chooser = new JColorChooser(); private final MyPreview preview = new MyPreview(); private final JButton doneButton = new JButton("Use selected color"); private final JButton cancelButton = new JButton("Cancel"); /** * The secondary color that is used for the preview. */ private Color secondaryColor; /** * Whether to actually return the chosen Color, or return the preset, which * is determined which button is used for closing the dialog. */ private boolean returnNewColor; public ColorChooser(JDialog parent) { super(parent); setModal(true); setTitle("Choose color"); setLayout(new GridBagLayout()); setResizable(false); // Configure chooser chooser.addChooserPanel(new NamedColorsPanel()); chooser.setPreviewPanel(preview); // Add listener to update preview when a new color has been selected chooser.getSelectionModel().addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { updatePreview(); } }); // Layout GridBagConstraints gbc = new GridBagConstraints(); gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 1; gbc.weighty = 1; gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2; add(chooser, gbc); gbc.insets = new Insets(5,5,5,5); gbc.gridy = 1; gbc.gridwidth = 1; add(doneButton, gbc); gbc.gridx = 1; gbc.weightx = 0.2; add(cancelButton, gbc); // Button listener to close the dialog ActionListener buttonListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == doneButton) { returnNewColor = true; } setVisible(false); } }; // Add button listener to buttons doneButton.addActionListener(buttonListener); cancelButton.addActionListener(buttonListener); pack(); } /** * Update the preview with the new primary color. Use as foreground or * background depending on the type and use secondary color as the other * one. */ private void updatePreview() { Color newColor = chooser.getColor(); if (type == FOREGROUND) { preview.update(newColor, secondaryColor); } else { preview.update(secondaryColor, newColor); } } /** * Let the user choose a Color and return a String representation of that * Color. * * @param type The type of the color to choose ({@code FOREGROUND} or * {@code BACKGROUND}) * @param presetColor The {@code Color} to preset the color to choose with * @param secondaryColor The secondary color to be used for the preview * @param name The name of the color to choose (a short description) * @param text The text to be used for the preview * @return A String representation of the chosen Color, or of the preset * Color if the dialog was canceled * @see chooseColor(int, Color, Color, String, String) */ public String chooseColorString(int type, Color presetColor, Color secondaryColor, String name, String text) { return HtmlColors.getNamedColorString( chooseColor(type, presetColor, secondaryColor, name, text)); } /** * Let the user choose a Color and return that Color. * * @param type The type of the color to choose ({@code FOREGROUND} or * {@code BACKGROUND}) * @param presetColor The {@code Color} to preset the color to choose with * @param secondaryColor The secondary color to be used for the preview * @param name The name of the color to choose (a short description) * @param text The text to be used for the preview * @return The chosen color, or the preset Color if the dialog was canceled */ public Color chooseColor(int type, Color presetColor, Color secondaryColor, String name, String text) { // Update dialog setLocationRelativeTo(getParent()); returnNewColor = false; setTitle("Change Color: "+name); // Save type and secondary color for further use (primary color is not // used outside this method and the chooser) this.type = type; this.secondaryColor = secondaryColor; // Update preview and chooser preview.setText(text); chooser.setColor(presetColor); setVisible(true); // Wait until the user closes the dialog, which might also change // {@code returnNewColor} if the "Done" button is pressed if (returnNewColor) { return chooser.getColor(); } return presetColor; } /** * Preview to be used for the color chooser. */ static class MyPreview extends JLabel { MyPreview() { super("Preview Text", CENTER); setPreferredSize(new Dimension(400,50)); // Set opaque so the background is rendered setOpaque(true); setFont(new Font("Arial", Font.BOLD, 14)); } /** * Update the foreground and background colors. * * @param foreground * @param background */ public void update(Color foreground, Color background) { super.setForeground(foreground); super.setBackground(background); } /** * Override so the JColorChooser doesn't change the color on it's own, * which might not have the wanted effect. * * @param foregroundColor */ @Override public void setForeground(Color foregroundColor) { } /** * Override so the JColorChooser doesn't change the color on it's own, * which might not have the wanted effect. * * @param foregroundColor */ @Override public void setBackground(Color backgroundColor) { } } }