// Copyright 1996, Marimba Inc. All Rights Reserved.


// @(#)ColorPaletteWidget.java, 1.6, 12/19/96





package marimba.gui;





import java.io.*;


import java.awt.*;


import java.net.*;


import java.util.*;





import marimba.io.*;


import marimba.persist.*;





/**


 * A popup widget for choosing a color from a palette.


 * It also displays a button at the bottom which, when


 * clicked, shows a dialog with a color picker with which


 * the color can be chosen.


 *


 * @author	Klaas Waslander


 * @version 	1.6, 12/19/96


 */


public class ColorPaletteWidget extends PopupWidget {


    /** The number of rows for this color palette. */


    protected final static int  ROWS = 5;





    /** The number of columns for this color palette. */


    protected final static int  COLS = 4;





    /** The size of a color field. */


    protected final static int  SIZE = 15;





    /** The gap between the color fields. */


    protected final static int  GAP  = 3;





    /**


     * The initial value of the color palette.


     */


    public Color  value;





    /**


     * The index of the currently selected color.


     */


    public int  selected = -1;





    /**


     * The color button that uses this color palette.


     */


    public ColorButtonWidget  target;





    /**


     * Indicates whether the color is a custom color


     * or one of the default colors in the palette.


     */


    public boolean  customColor;





    /**


     * A hashtable with the default colors.


     */


    public static Hashtable colHash = new Hashtable();





    /**


     * The default colors in an array.


     */


    public static Color colors[] = new Color[ROWS*COLS];





    /** The "other..." button in the palette. */


    protected CommandButtonWidget  button = new CommandButtonWidget();





    /** The dialog that pops up when the "other..." button is clicked. */


    protected WidgetDialog  pickerDialog;





    /**


     * Create the color table.


     */


    static {


	int  colorNr = 0;


	addColor(255, 255, 255, colorNr++);


	addColor(0, 0, 0, colorNr++);


	addColor(192, 192, 192, colorNr++);


	addColor(128, 128, 128, colorNr++);





	addColor(255, 0, 0, colorNr++);


	addColor(128, 0, 0, colorNr++);


	addColor(255, 255, 0, colorNr++);


	addColor(128, 128, 0, colorNr++);





	addColor(0, 255, 0, colorNr++);


	addColor(0, 128, 0, colorNr++);


	addColor(0, 255, 255, colorNr++);


	addColor(0, 128, 128, colorNr++);





	addColor(0, 0, 255, colorNr++);


	addColor(0, 0, 128, colorNr++);


	addColor(255, 0, 255, colorNr++);


	addColor(128, 0, 128, colorNr++);





	addColor(192, 220, 192, colorNr++);


	addColor(166, 202, 240, colorNr++);


	addColor(255, 251, 240, colorNr++);





	// this color cannot be added because of the <none> color


	// addColor(160, 160, 164, colorNr++);


    }





    /**


     * Add a color to the color table.


     */


    static void addColor(int c1, int c2, int c3, int colorNr) {


	Color  col = new Color(c1, c2, c3);


	colHash.put(col, new Integer(colorNr));


	colors[colorNr] = col;


    }





    /**


     * Lookup a color in the color table, returns


     * the index of the given color.


     */


    protected static int lookup(Color col) {


	if (col == null) {


	    return colors.length-1;


	}


	Integer i = (Integer)colHash.get(col);


	return (i == null) ? -1 : i.intValue();


    }





    /**


     * Constructor, which takes the colorbutton this widget


     * belongs to and pops up the palette immediatly.


     */


    public ColorPaletteWidget(ColorButtonWidget target) {


	lineMode = SOLID;


	this.target = target;


	value = target.getColorValue();


	setFont(new Font("Dialog", Font.PLAIN, 10));


	selected = lookup(value);


	if (selected == -1) {


	    customColor = true;


	}





	int  colorHeight = ROWS * (SIZE+GAP) + GAP + 2;


	int  colorWidth = COLS * (SIZE+GAP) + GAP + 4;


	FontMetrics fm = getFontMetrics(font);





	add(button);


	button.setText("Other...");


	button.reshape(GAP+2, colorHeight + 5, (COLS-1)*(SIZE+GAP)-GAP, fm.getHeight()+2);





	popup(target, 0, target.height, colorWidth,


		fm.getHeight() + 9 + ROWS * (SIZE+GAP) + GAP + 4);


	fit();


    }





    /**


     * Paint the colors.


     */


    public void paint(Graphics g) {


	int  y = GAP + 2;


	for (int r = 0, n = 0 ; r < ROWS ; r++, y += SIZE + GAP) {


	    for (int c = 0, x = GAP + 2 ; c < COLS ; c++, x += SIZE + GAP) {


		paintColorField(g, colors[n], x, y, n == selected);


		n++;


	    }


	}


	if (customColor) {


	    paintColorField(g, value, (COLS-1)*(SIZE+GAP)+GAP+2, button.y, selected < 0);


	}





	int  colorHeight = ROWS * (SIZE+GAP) + GAP + 3;


	int  lineWidth = COLS * (SIZE+GAP) - GAP;


	g.setColor(background.darker());


	g.drawLine(GAP+2, colorHeight, GAP+2+lineWidth, colorHeight);


	g.setColor(background.brighter());


	g.drawLine(GAP+2+lineWidth, colorHeight, GAP+2+lineWidth, colorHeight);


	g.drawLine(GAP+2, colorHeight+1, GAP+2+lineWidth, colorHeight+1);


    }





    /**


     * Paint a 3D style colorfield at the given position


     * selected or unselected.


     */


    protected void paintColorField(Graphics g, Color col, int x, int y, boolean selected) {


	g.setColor(background.darker());


	g.drawLine(x, y, x+SIZE-1, y);


	g.drawLine(x, y, x, y+SIZE-1);





	g.setColor(Color.black);


	g.drawLine(x+1, y+1, x+SIZE-2, y+1);


	g.drawLine(x+1, y+1, x+1, y+SIZE-2);





	g.setColor(background.brighter());


	g.drawLine(x, y+SIZE, x+SIZE, y+SIZE);


	g.drawLine(x+SIZE, y, x+SIZE, y+SIZE);





	g.setColor(background);


	g.drawLine(x+1, y+SIZE-1, x+SIZE-1, y+SIZE-1);


	g.drawLine(x+SIZE-1, y+1, x+SIZE-1, y+SIZE-1);





	if (col != null) {


	    g.setColor(col);


	    g.fillRect(x+2, y+2, SIZE-3, SIZE-3);


	} else {


	    g.setColor(foreground);


	    for (int i = 1 ; i < SIZE-2 ; i += 3) {


		g.drawLine(x+1+i, y+1, x+SIZE-2, y+(SIZE-2)-i);


		g.drawLine(x+1, y+(SIZE-2)-i, x+1+i, y+SIZE-2);


	    }


	}





	if (selected) {


	    g.setColor(Color.black);


	    g.drawRect(x+1, y+1, SIZE-2, SIZE-2);


	    g.setColor(background.brighter());


	    g.drawRect(x, y, SIZE, SIZE);


	    g.setColor(Color.black);


	    g.drawRect(x-1, y-1, SIZE+2, SIZE+2);


	}


    }





    /**


     * Find the target based on the given event,


     * returns -1 if no target is found.


     */


    protected int findTarget(Event evt) {


	if ((evt.x >= 0) && (evt.x < width) && (evt.y >= 0) && (evt.y < height)) {


	    int selcol = Math.max(0, Math.min(COLS-1, (evt.x-GAP)/(SIZE+GAP)));


	    int selrow = Math.max(0, Math.min(ROWS-1, (evt.y-GAP)/(SIZE+GAP)));


	    return selcol + selrow*COLS;


	} else {


	    return -1;


	}


    }





    /**


     * Creates the colorpicker presentation that


     * is being shown in the colorpicker dialog.


     */


    protected Presentation createPicker() {


	Presentation  result = new Presentation();


	ColorPickerWidget  picker = new ColorPickerWidget();


	CommandButtonWidget  ok = new CommandButtonWidget("Ok", FILLED);


	CommandButtonWidget  cancel = new CommandButtonWidget("Cancel", FILLED);





	result.resize(230, 130);


	result.setTitle("Color");


	result.setFont(new Font("Dialog", Font.PLAIN, 10));


	result.setBackground(background);


	result.setHilite(hilite);


	result.setForeground(foreground);


	result.setFillMode(SOLID);


	result.setResizable(false);





	result.add(picker);


	result.add(ok);


	result.add(cancel);





	picker.reshape(12, 7, 202, 83);


	picker.setName("colorpicker");


	picker.setFilled(true);


	picker.setValue(value);





	ok.reshape(59, 96, 75, 22);


	ok.setName("ok");


	ok.setDefault(true);





	cancel.reshape(143, 96, 75, 22);


	cancel.setName("cancel");





	return  result;


    }





    /**


     * Handle Events.


     */


    public boolean handleEvent(Event evt) {


	switch (evt.id) {


	    case Event.MOUSE_MOVE: {


		if (evt.target == this) {


		    int  sel = findTarget(evt);


		    if (sel >= 0) {


			selected = sel;


			repaint();


		    }


		}


		break;


	    }





	    case Event.MOUSE_DOWN:


	    case Event.MOUSE_DRAG:


		if (evt.target == this) {


		    int  sel = findTarget(evt);


		    if (sel != selected) {


			selected = sel;


			if (selected < 0) {


			    selected = lookup(value);


			}


			repaint();


		    }


		}


		return true;





	    case Event.MOUSE_UP:


		if (evt.target == this) {


		    if (selected >= 0) {


			target.setValue(colors[selected]);


			target.action();


		    }


		    target.clearPopups();


		}


		return true;





	    case Event.ACTION_EVENT:


		if (evt.target == button) {


		    // pop down and fire up the great color picker by Carl!


		    pickerDialog = new WidgetDialog(this, createPicker());


		    target.clearPopups();


		    pickerDialog.show();


		    return true;


		}





		// colorpicker action events


		if (evt.target != null && evt.target instanceof Widget) {


		    Widget  w = (Widget)evt.target;


		    if (w.name != null && w.name.equals("ok")) {


			Object  col = pickerDialog.util.getWidget("colorpicker").getValue();


			target.setValue(col);


			target.action();


			pickerDialog.close();


		    }


		    if (w.name != null && w.name.equals("cancel")) {


			pickerDialog.close();


		    }


		}


		break;


	}


	return super.handleEvent(evt);


    }


}


