package com.MyCompany.examplebean;

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyEditorSupport;

/*
 * The CustomColorEditor class is the custom editor for the Color property in
 * MyLine. The important methods here are getCustomEditor() and paintValue().
 *
 * getCustomEditor must return a Component that can edit the property.
 * In this case, it returns a Panel that contains a set of colored boxes, one 
 * for each of the colors in the static colors[] array. When one of these boxes
 * is clicked, the value of the property is set to the color in that box. These
 * boxes (which are instances of ColoredRect, an inner class of
 * CustomColorEditor) also paint a heavy black square around their edge if they
 * represent the current property value.
 *
 * paintValue must paint a depiction of the property value in the Rectangle 
 * supplied.
 * In this case, it fills the Rectangle with the current color value.
 */
public class MyLineColorEditor extends PropertyEditorSupport {
	static final Color[] colors = new Color[] { Color.black, Color.red,
												Color.yellow, Color.green,
												Color.blue };
	
	private Panel editorPanel = null;
	
	// we keep a reference to the currently selected color box, to know which
	// one should be highlighted (this is used in the ColoredRect.paint(..)
	// method).
	private ColoredRect currentRect = null;
							
	public boolean supportsCustomEditor() {
		return true;
	}
	public Component getCustomEditor() {
		editorPanel = new Panel( new FlowLayout() );
		
		Color currentValue = (Color)getValue();
		
		for ( int i = 0; i < colors.length; i++ ) {
			ColoredRect crect = new ColoredRect( colors[i] );
			if (colors[i].equals( currentValue )) {
				currentRect = crect;
			}
			
			editorPanel.add( crect );
		}
		
		return editorPanel;
	}
	
	public boolean isPaintable() {
		return true;
	}
	public void paintValue( Graphics g, Rectangle rect ) {
		paintColoredRect( (Color)getValue(), g, rect );
	}
	
	
	void colorChosen( Color color ) {
		setValue( color );
		firePropertyChange();

		editorPanel.repaint();
	}
	
	// This is a utility method, used by both the paintValue() method and the
	// ColoredRects. It fills the rectangle with the color, and draws a black
	// box around the outside.
	static void paintColoredRect( Color color, Graphics g, Rectangle rect  ) {
		g.setColor( color );
		g.fillRect( rect.x, rect.y, rect.width, rect.height );
		
		// draw a black outline
		g.setColor( Color.black );
		g.drawRect( rect.x, rect.y, rect.width, rect.height );
	}
	
	class ColoredRect extends Component {
		private Color color;
		
		public ColoredRect( Color c ) {
			color = c;
			
			this.addMouseListener( new MouseAdapter() {
				public void mouseClicked( MouseEvent e ) {
					click();
				}
			});
		}
		
		private void click() {
			// now this ColoredRect should be highlighted.
			currentRect = this;
			colorChosen( color );
		}
	
		public void paint( Graphics g ) {
			Dimension size = getSize();
			
			// The box is inset from the edge of the Component rectangle to
			// leave room for the heavy line around the selected color.
			Rectangle rect = new Rectangle( 3, 3, size.width-7, size.height-7 );
			
			paintColoredRect( color, g, rect );
			
			if ( currentRect == this ) {
				// the color in this ColoredRect is the property value, so paint
				// a heavy line around the outside.
				g.setColor( Color.black );
				g.drawRect( 0, 0, size.width - 1, size.height - 1 );
				g.drawRect( 1, 1, size.width - 3, size.height - 3 );
			}
		}
		public Dimension getPreferredSize() {
			return new Dimension( 24, 24 );
		}
	}
}

