/*
GeoGebra - Dynamic Mathematics for Everyone
http://www.geogebra.org
This file is part of GeoGebra.
This program 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.
*/
package org.geogebra.desktop.gui.color;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.plaf.basic.BasicButtonUI;
/**
* Button with popup component for choosing colors. A mouse click on the left
* side of the button sets the selected color. A mouse click on the right side
* triggers a popup with a swatch panel to choose a color. When the popup is
* done the newly selected color is set. An actionPerformed() method can
* retrieve the color by calling getSelectedColor().
*
* @author G. Sturr 2010-7-10
*
*/
public class ColorChooserButton extends JButton {
private static final long serialVersionUID = 1L;
/**
* Generic mode. Preview icon shows a square filled with the current color.
*/
public static int MODE_GENERIC = 1;
/**
* Spreadsheet mode. Preview icon shows a table with four cells, the upper
* row will have the current color as background.
*/
final public static int MODE_SPREADSHEET = 2;
/**
* Current setting for the mode.
*/
private int mode;
private ColorChooserPopup myPopup;
private Color selectedColor;
/** Button constructor */
public ColorChooserButton(int mode) {
super();
this.mode = mode;
myPopup = new ColorChooserPopup(this);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
Point locButton = getLocation();
// trigger popup if the mouse is over the right side of the
// button
if (e.getX() >= 20 && e.getX() <= 38) {
myPopup.show(getParent(), locButton.x,
locButton.y + getHeight());
}
}
});
selectedColor = Color.WHITE;
setIcon(createIcon(selectedColor));
}
public void swatchClicked(Color color) {
selectedColor = color;
handlePopupEvent();
myPopup.setVisible(false);
}
public Color getSelectedColor() {
return selectedColor;
}
public void handlePopupEvent() {
setIcon(createIcon(selectedColor));
repaint();
this.fireActionPerformed(new ActionEvent(this,
ActionEvent.ACTION_PERFORMED, getActionCommand()));
}
/**
* Draw an icon for the button. On the left side there's either a square
* filled with the color for MODE_GENERIC or a grid for MODE_SPREADSHEET.
* Right side is a downward triangle for the drop down popup.
*/
private ImageIcon createIcon(Color selectedColor) {
// Create image
BufferedImage image = new BufferedImage(32, 18,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
// left hand side:
// (a click here just sends back the selected color):
if (mode == MODE_SPREADSHEET) {
// a grid filled with our selected color
int s = 7;
int d = 1;
g2.setColor(selectedColor);
g2.fillRect(d, d, s, s);
g2.setColor(Color.BLACK);
g2.drawRect(d, d, s, s);
g2.setColor(selectedColor);
g2.fillRect(d + s, d, s, s);
g2.setColor(Color.BLACK);
g2.drawRect(d + s, d, s, s);
g2.setColor(this.getBackground());
g2.fillRect(d, d + s, s, s);
g2.setColor(Color.BLACK);
g2.drawRect(d, d + s, s, s);
g2.setColor(this.getBackground());
g2.fillRect(d + s, d + s, s, s);
g2.setColor(Color.BLACK);
g2.drawRect(d + s, d + s, s, s);
} else {
g2.setColor(selectedColor);
g2.fillRect(1, 1, 16, 16);
g2.setColor(Color.BLACK);
g2.drawRect(1, 1, 16, 16);
}
// right hand side: a downward triangle
// a click here triggers the popup
g2.setColor(Color.BLACK);
int x = 23;
int y = 7;
g2.drawLine(x, y, x + 6, y);
g2.drawLine(x + 1, y + 1, x + 5, y + 1);
g2.drawLine(x + 2, y + 2, x + 4, y + 2);
g2.drawLine(x + 3, y + 3, x + 3, y + 3);
return new ImageIcon(image);
}
/*************************************************************
* Swatch Panel Popup
************************************************************/
public static class ColorChooserPopup extends JPopupMenu {
private static final long serialVersionUID = 1L;
private SwatchPanel swatchPanel;
public ColorChooserPopup(ColorChooserButton button) {
super();
setLayout(new BorderLayout());
swatchPanel = new SwatchPanel(button);
add(swatchPanel, BorderLayout.CENTER);
/*
* The following code adds a color picker to this popup menu, it
* still has to be decided if this should be used though.
*
* Some class attributes are missing, so they have to be added in
* case the code comments are removed.
*/
}
/**
* Draw a swatch panel and handle mouse events in the panel.
*/
static class SwatchPanel extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private Color[] colors;
private ColorChooserButton chooserButton;
public SwatchPanel(ColorChooserButton button) {
chooserButton = button;
initColors();
setLayout(new FlowLayout(FlowLayout.LEFT));
setPreferredSize(new Dimension(150, 120));
// color buttons
SwatchButton sb;
for (int i = 0; i < colors.length; ++i) {
sb = new SwatchButton(colors[i]);
sb.addActionListener(this);
add(sb);
}
}
@Override
public void actionPerformed(ActionEvent e) {
chooserButton.swatchClicked(
((SwatchButton) e.getSource()).getColor());
}
/**
* List with colors.
*/
private void initColors() {
colors = new Color[] { new Color(255, 255, 255), // White
new Color(255, 153, 204), // Rose
new Color(255, 204, 153), // Tan
new Color(255, 255, 153), // Light Yellow
new Color(204, 255, 255), // Light Turquoise
new Color(204, 255, 204), // Light Green
new Color(192, 192, 192), // Silver
new Color(255, 0, 255), // Magenta (fuchsia)
new Color(255, 102, 0), // Orange
new Color(255, 255, 0), // Yellow
new Color(153, 204, 255), // Pale Blue
new Color(0, 255, 0), // Green (lime)
new Color(128, 128, 128), // Gray / Grey
new Color(204, 153, 255), // Lavender
new Color(255, 0, 0), // Red
new Color(255, 215, 0), // Gold
new Color(0, 0, 255), // Blue
new Color(153, 204, 0), // Yellow Green
new Color(0, 0, 0), // Black
new Color(153, 51, 102), // Plum
new Color(153, 51, 0), // Brown
new Color(255, 153, 0), // Light Orange
new Color(0, 128, 128), // Teal
new Color(51, 153, 102), // Sea Green
new Color(64, 64, 64), // Dark Gray
new Color(0, 128, 0), // Dark Green
new Color(0, 255, 255), // Cyan (aqua)
new Color(51, 204, 204), // Aqua
new Color(51, 102, 255), // Light Blue
new Color(0, 204, 255), // Sky Blue
new Color(51, 51, 153), // Indigo
// new Color(128,128,0), //Olive
// new Color(51,51,0), //Dark Olive
// new Color(128,0,0), //Maroon
// new Color(102,102,153), //Blue Gray
// new Color(0,0,128), //Navy
// new Color(0,51,0), //Dark Green
// new Color(0,51,102), //Dark Teal
new Color(128, 0, 128) // Purple
};
}
/**
* A simple button for the color swatch, just stores the color and
* tells the button to use SwatchButtonUI.
*
* @author Florian Sonner
*/
static class SwatchButton extends JButton {
private static final long serialVersionUID = 1L;
private Color color;
public SwatchButton(Color color) {
this.color = color;
setCursor(new Cursor(Cursor.HAND_CURSOR));
setUI(new SwatchButtonUI());
}
public Color getColor() {
return color;
}
}
/**
* The UI for the color swatch button. Draws a 16x16 square filled
* with the color of this button and a bevel border.
*
* @author Florian Sonner
*/
static class SwatchButtonUI extends BasicButtonUI {
@Override
public Dimension getPreferredSize(JComponent c) {
return new Dimension(16, 16);
}
@Override
public void paint(Graphics g, JComponent c) {
SwatchButton b = (SwatchButton) c;
// highlight border
if (b.getModel().isPressed()) {
g.setColor(Color.darkGray);
} else {
g.setColor(Color.gray);
}
g.drawLine(0, 0, 0, 15);
g.drawLine(0, 0, 15, 0);
// filling
g.setColor(b.getColor());
g.fillRect(1, 1, 14, 14);
// shadow border
g.setColor(Color.darkGray);
g.drawLine(0, 15, 15, 15);
g.drawLine(15, 0, 15, 15);
}
}
}
}
}