package nodebox.client;
import nodebox.graphics.Color;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.EventListener;
public class ColorWell extends JComponent {
private Color color = new Color();
private transient ClickHandler clickHandler = new ClickHandler();
private transient ColorPicker colorPicker = new ColorPicker();
/**
* Only one <code>ChangeEvent</code> is needed per slider instance since the
* event's only (read-only) state is the source property. The source
* of events generated here is always "this". The event is lazily
* created the first time that an event notification is fired.
*
* @see #fireStateChanged
*/
protected transient ChangeEvent changeEvent = null;
public ColorWell() {
setPreferredSize(new Dimension(40, 30));
addMouseListener(clickHandler);
addMouseMotionListener(clickHandler);
}
@Override
public void paint(Graphics g) {
g.setColor(color.getAwtColor());
Rectangle r = g.getClipBounds();
g.fillRect(r.x, r.y, r.width, r.height);
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
if (color.equals(this.color)) return;
this.color = color;
fireStateChanged();
repaint();
}
/**
* Adds a ChangeListener to the slider.
*
* @param l the ChangeListener to add
* @see #fireStateChanged
* @see #removeChangeListener
*/
public void addChangeListener(ChangeListener l) {
listenerList.add(ChangeListener.class, l);
}
/**
* Removes a ChangeListener from the slider.
*
* @param l the ChangeListener to remove
* @see #fireStateChanged
* @see #addChangeListener
*/
public void removeChangeListener(ChangeListener l) {
listenerList.remove(ChangeListener.class, l);
}
/**
* Returns an array of all the <code>ChangeListener</code>s added
* to this JSlider with addChangeListener().
*
* @return all of the <code>ChangeListener</code>s added or an empty
* array if no listeners have been added
* @since 1.4
*/
public ChangeListener[] getChangeListeners() {
return (ChangeListener[]) listenerList.getListeners(
ChangeListener.class);
}
protected void fireStateChanged() {
if (changeEvent == null) {
changeEvent = new ChangeEvent(this);
}
for (EventListener l : listenerList.getListeners(ChangeListener.class)) {
((ChangeListener) l).stateChanged(changeEvent);
}
}
private class ClickHandler implements MouseListener, MouseMotionListener {
private boolean isDragging;
public void mouseClicked(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
if (isDragging) {
colorPicker.setVisible(false);
}
isDragging = false;
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
isDragging = true;
JComponent c = ColorWell.this;
Point pt = e.getPoint();
JFrame frame = (JFrame) SwingUtilities.getWindowAncestor(c);
pt = SwingUtilities.convertPoint(c, pt, frame.getContentPane());
MouseEvent newEvent = new MouseEvent(colorPicker, e.getID(), e.getWhen(), e.getModifiers(), (int) pt.getX(), (int) pt.getY(), e.getClickCount(), e.isPopupTrigger(), e.getButton());
colorPicker.dispatchEvent(newEvent);
}
public void mouseMoved(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
isDragging = false;
JComponent c = ColorWell.this;
JFrame frame = (JFrame) SwingUtilities.getWindowAncestor(c);
if (frame == null) return;
Point pt = c.getLocation();
pt = SwingUtilities.convertPoint(c, pt, frame.getContentPane());
Rectangle r = c.getBounds();
frame.setGlassPane(colorPicker);
colorPicker.setVisible(true);
colorPicker.setPoint(new Point(pt.x, pt.y + r.height));
frame.validate();
}
}
private java.awt.Color colorFromPoint(int x, int y) {
float h = x / 255.0F;
float s = 1.0F;
float b = 1.0F - (y / 100.0F);
return java.awt.Color.getHSBColor(h, s, b);
}
private class ColorPicker extends JComponent implements MouseListener, MouseMotionListener {
public Point point;
public Point dragPoint;
public Rectangle pickerRect;
private ColorPicker() {
addMouseListener(this);
addMouseMotionListener(this);
}
public void setPoint(Point point) {
this.point = point;
pickerRect = new Rectangle(point.x, point.y, 255, 100);
}
public void setDragPoint(Point dragPoint) {
this.dragPoint = dragPoint;
repaint();
int x = dragPoint.x - point.x;
int y = dragPoint.y - point.y;
setColor(new Color(colorFromPoint(x, y)));
}
@Override
public void paint(Graphics g) {
if (point == null) return;
//Graphics2D g2 = (Graphics2D) g;
Rectangle r = g.getClipBounds();
//g2.setColor(new java.awt.Color(30, 30, 30, 100));
//g2.fillRect(r.x, r.y, r.width, r.height);
g.setColor(new java.awt.Color(200, 200, 200, 220));
g.fillRect(pickerRect.x, pickerRect.y, pickerRect.width, pickerRect.height);
for (int y = 0; y < 100; y++) {
for (int x = 0; x < 255; x++) {
g.setColor(colorFromPoint(x, y));
g.fillRect(pickerRect.x + x, pickerRect.y + y, 1, 1);
}
}
if (dragPoint == null) return;
if (!pickerRect.contains(dragPoint)) return;
}
public void mouseClicked(MouseEvent e) {
if (pickerRect.contains(e.getPoint())) {
setDragPoint(e.getPoint());
}
setVisible(false);
}
public void mouseDragged(MouseEvent e) {
setDragPoint(e.getPoint());
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
setVisible(false);
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
}
}