001package jmri.util.swing;
002
003import java.awt.Color;
004import java.awt.Component;
005import java.awt.event.ActionEvent;
006import java.util.ArrayList;
007import javax.swing.JColorChooser;
008import javax.swing.JDialog;
009import javax.swing.colorchooser.AbstractColorChooserPanel;
010
011/**
012 * Display the Java color chooser that includes a custom JMRI panel.
013 * The custom panel is provided by {@link JmriColorChooserPanel}.
014 * <p>
015 * Maintain a list of recently used colors.  This includes colors found
016 * during loading and subsequent changes.
017 * @author Dave Sand Copyright (C) 2018
018 * @since 4.13.1
019 */
020public class JmriColorChooser {
021
022    /**
023     * The colors used by the current JMRI session.
024     * The XML loading process creates the initial list and
025     * subsequent activity will add new colors.
026     */
027    static private ArrayList<Color> recentColors = new ArrayList<>();
028    static private boolean _suppressAdd = false;
029
030    /**
031     * Add a new color to the recent list.
032     * Null values and duplicates are not added.
033     * @param color The color object to be added.
034     */
035    static public void addRecentColor(Color color) {
036        if (color == null || _suppressAdd || !color.toString().contains("java.awt.Color")) {
037            // Ignore null or default system colors
038            return;
039        }
040        if (!recentColors.contains(color)) {
041            recentColors.add(color);
042        }
043    }
044
045    /**
046     * Suppress adding colors while temporarily displaying colors to
047     * wysiwyg applications of JmriColorChooser - e.g. use of RGB
048     * tab while editing colors on CPE panels.
049     * @param set if true, previewed color is not added.
050     */
051    static public void suppressAddRecentColor(boolean set) {
052        _suppressAdd = set;
053    }
054
055    /**
056     * Provide a copy of the recent color list.
057     * This is used by {@link JmriColorChooserPanel} to build
058     * the recent color list.
059     * @return the recent color list.
060     */
061    static public ArrayList<Color> getRecentColors() {
062        return new ArrayList<>(recentColors);
063    }
064
065    /**
066     * The number of tabs in the color chooser, 5 standard plus the custom JMRI tab
067     */
068    static Color color;
069    
070    /**
071     * Display the customized color selection dialog.
072     * The JMRI custom panel is added before the Java supplied panels so that
073     * it will be the default panel.
074     * @param comp The calling component.  It is not used but provided to simplify migration.
075     * @param dialogTitle The title at the top of the dialog.
076     * @param currentColor The color that will be set as the starting value for the dialog.
077     * @return the selected color for a OK response, the orignal color for a Cancel response.
078     */
079    static public Color showDialog(Component comp, String dialogTitle, Color currentColor) {
080        color = currentColor == null ? Color.WHITE : currentColor;
081        String title = dialogTitle == null ? "" : dialogTitle;
082        JColorChooser chooser = extendColorChooser(new JColorChooser(color));
083        JDialog d = JColorChooser.createDialog(null, title, true, chooser,
084            ((ActionEvent e) -> {
085                color = chooser.getColor();
086            }),
087            null);
088        d.setVisible(true);
089        return color;
090    }
091
092    /**
093     * Add or replace the JMRI custom panel at the beginning of the chooser tabs
094     * @param chooser The chooser object to be updated.
095     * @return the updated chooser object
096     */
097     static public JColorChooser extendColorChooser(JColorChooser chooser) {
098
099        int colorTabCount ;
100
101        AbstractColorChooserPanel[] currPanels = chooser.getChooserPanels();
102        colorTabCount = currPanels.length + 1 ;
103        AbstractColorChooserPanel[] newPanels = new AbstractColorChooserPanel[colorTabCount];
104        newPanels[0] = new jmri.util.swing.JmriColorChooserPanel();
105        int idx = 1;
106        for (int i = 0; i < currPanels.length; i++) {
107            if (!currPanels[i].getDisplayName().equals("JMRI")) {  // NOI18N
108                // Copy non JMRI panels
109                newPanels[idx] = currPanels[i];
110                idx++;
111            }
112        }
113        chooser.setChooserPanels(newPanels);
114        _suppressAdd = false;   // reset to default
115        return chooser;
116    }
117}