/* Copyright 2014 BarD Software s.r.o This file is part of GanttProject, an opensource project management tool. GanttProject is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GanttProject is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GanttProject. If not, see <http://www.gnu.org/licenses/>. */ package net.sourceforge.ganttproject.gui; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.List; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.JColorChooser; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.border.Border; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.jdesktop.swingx.JXLabel; import org.jdesktop.swingx.painter.Painter; import biz.ganttproject.core.option.ListOption; import com.google.common.collect.Lists; /** * Custom component which adds a configurable list of recently used colors to Swing standard color chooser. * * Component per se is not a singleton. However, a list of recent colors is a singleton. The reason is that this * component is used both in options and in properties, and is instantiated through OptionsPageBuilder instance. Passing * the same list of recent colors to all these places isn't easy and seems to be unnecessary, because we want this list * to be the same at least inside one project. * * @author dbarashev (Dmitry Barashev) */ public class GPColorChooser { private static List<Color> ourRecentColors = Lists.newArrayList(); private JColorChooser myChooserImpl; private List<Color> myRecentColors; private Color mySelectedColor; public GPColorChooser() { this(ourRecentColors); } public GPColorChooser(List<Color> recentColors) { myChooserImpl = new JColorChooser(); myChooserImpl.getSelectionModel().addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent arg0) { mySelectedColor = myChooserImpl.getColor(); } }); myRecentColors = recentColors; } public JComponent buildComponent() { JPanel result = new JPanel(new BorderLayout()); result.add(myChooserImpl, BorderLayout.CENTER); JPanel southPanel = new JPanel(new BorderLayout()); southPanel.add(new JLabel("Recent colors"), BorderLayout.WEST); Box colorLabels = Box.createHorizontalBox(); for (final Color c : myRecentColors) { final JXLabel label = new JXLabel(); label.setBackgroundPainter(new Painter<JXLabel>() { @Override public void paint(Graphics2D g, JXLabel object, int width, int height) { g.setColor(c); g.fillRect(4, 4, width-8, height-8); } }); label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); label.setFocusable(true); label.setPreferredSize(new Dimension(20, 20)); label.setMaximumSize(new Dimension(20, 20)); final Border outsideFocusBorder = BorderFactory.createLineBorder(c.darker(), 2); final Border outsideNoFocusBorder = BorderFactory.createEmptyBorder(2,2,2,2); label.setBorder(outsideNoFocusBorder); label.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { label.setBorder(outsideFocusBorder); myChooserImpl.setColor(c); mySelectedColor = c; } @Override public void focusLost(FocusEvent e) { label.setBorder(outsideNoFocusBorder); } }); label.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { label.requestFocus(); } }); colorLabels.add(label); colorLabels.add(Box.createHorizontalStrut(5)); } colorLabels.setBorder(BorderFactory.createEmptyBorder(0, 7, 0, 0)); southPanel.add(colorLabels, BorderLayout.CENTER); southPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 5)); result.add(southPanel, BorderLayout.SOUTH); return result; } public Color getColor() { return mySelectedColor; } public void setColor(Color color) { myChooserImpl.setColor(color); } public static void setRecentColors(List<Color> colors) { ourRecentColors = colors; } public static List<Color> getRecentColors() { return ourRecentColors; } public static ListOption<Color> getRecentColorsOption() { return new RecentColorsOption(ourRecentColors); } }