/* Copyright (C) 1999,2000,2003,2004 by Peter Eastman

   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; either version 2 of the License, or (at your option) any later version.

   This program 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. */

package artofillusion.ui;

import artofillusion.*;
import artofillusion.math.*;
import buoy.event.*;
import buoy.widget.*;
import java.awt.*;
import java.util.*;
import java.util.prefs.*;
import javax.swing.*;

/** ColorChooser is a BDialog in which the user can edit an RGBColor object.  It allows the
    color to be specified using the RGB, HSV, or HLS color models. */

public class ColorChooser extends BDialog
{
  private RGBColor oldColor, newColor;
  private ValueSlider slider1, slider2, slider3;
  private BLabel label1, label2, label3;
  private Widget oldColorPatch, newColorPatch;
  private BComboBox modeC;
  
  private static int mode;
  
  static
  {
    try
    {
      mode = Preferences.userNodeForPackage(ColorChooser.class).getInt("defaultColorModel", 1);
    }
    catch (Exception ex)
    {
      mode = 1;
    }
  }
  
  public ColorChooser(BFrame parent, String title, RGBColor c)
  {
    super(parent, title, true);
    BorderContainer content = new BorderContainer();
    setContent(BOutline.createEmptyBorder(content, ModellingApp.standardDialogInsets));
    oldColor = c;
    newColor = c.duplicate();

    // Add the buttons at the bottom.

    RowContainer buttons = new RowContainer();
    buttons.add(Translate.button("ok", this, "doOk"));
    buttons.add(Translate.button("cancel", this, "dispose"));
    content.add(buttons, BorderContainer.SOUTH, new LayoutInfo());

    // Add the main panel.

    FormContainer center = new FormContainer(new double [] {0.0, 1.0, 0.0}, new double [] {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0});
    center.setDefaultLayout(new LayoutInfo(LayoutInfo.WEST, LayoutInfo.HORIZONTAL, null, null));
    content.add(center, BorderContainer.CENTER);
    center.add(label1 = Translate.label("Red"), 0, 0, 2, 1);
    center.add(label2 = Translate.label("Green"), 0, 2, 2, 1);
    center.add(label3 = Translate.label("Blue"), 0, 4, 2, 1);
    LayoutInfo sliderLayout = new LayoutInfo(LayoutInfo.WEST, LayoutInfo.HORIZONTAL, new Insets(0, 0, 0, 5), null);
    center.add(slider1 = new ValueSlider(0.0, 1.0, 100, (double) newColor.getRed()), 0, 1, 2, 1, sliderLayout);
    center.add(slider2 = new ValueSlider(0.0, 1.0, 100, (double) newColor.getGreen()), 0, 3, 2, 1, sliderLayout);
    center.add(slider3 = new ValueSlider(0.0, 1.0, 100, (double) newColor.getBlue()), 0, 5, 2, 1, sliderLayout);
    slider1.addEventLink(ValueChangedEvent.class, this, "valueChanged");
    slider2.addEventLink(ValueChangedEvent.class, this, "valueChanged");
    slider3.addEventLink(ValueChangedEvent.class, this, "valueChanged");
    center.add(new BLabel("Color Model:"), 0, 6);
    center.add(modeC = new BComboBox(new String [] {"RGB", "HSV", "HLS"}), 1, 6, new LayoutInfo(LayoutInfo.WEST, LayoutInfo.NONE, null, null));
    modeC.addEventLink(ValueChangedEvent.class, this, "modeChanged");
    modeC.setSelectedIndex(mode);
    LayoutInfo patchLayout = new LayoutInfo();
    center.add(new BLabel("Original Color"), 2, 0, patchLayout);
    center.add(oldColorPatch = oldColor.getSample(50, 30), 2, 1, patchLayout);
    center.add(new BLabel("New Color"), 2, 2, patchLayout);
    center.add(newColorPatch = newColor.getSample(50, 30), 2, 3, patchLayout);
    addAsListener(this);
    modeChanged();
    pack();
    setResizable(false);
    UIUtilities.centerWindow(this);
    setVisible(true);
  }

  /** Add this as a key listener to every component. */
  
  private void addAsListener(Widget w)
  {
    w.addEventLink(KeyPressedEvent.class, this, "keyPressed");
    if (w instanceof WidgetContainer)
      {
        Iterator iter = ((WidgetContainer) w).getChildren();
        while (iter.hasNext())
          addAsListener((Widget) iter.next());
      }
  }

  private void doOk()
  {
    oldColor.setRGB(newColor.getRed(), newColor.getGreen(), newColor.getBlue());
    dispose();
  }

  private void valueChanged()
  {
    float values[];

    values = new float [] {(float) slider1.getValue(), (float) slider2.getValue(), (float) slider3.getValue()};
    if (mode == 0)
      newColor.setRGB(values[0], values[1], values[2]);
    else if (mode == 1)
      newColor.setHSV(values[0]*360.0f, values[1], values[2]);
    else
      newColor.setHLS(values[0]*360.0f, values[1], values[2]);
    newColorPatch.setBackground(newColor.getColor());
    newColorPatch.repaint();
  }
    
  /** Pressing Return and Escape are equivalent to clicking OK and Cancel. */
    
  private void keyPressed(KeyPressedEvent ev)
  {
    int code = ev.getKeyCode();

    if (code != KeyPressedEvent.VK_ENTER && code != KeyPressedEvent.VK_ESCAPE)
      return;
    if (code == KeyPressedEvent.VK_ENTER && ev.getWidget() instanceof BButton)
      return;
    if (code == KeyPressedEvent.VK_ENTER)
      oldColor.setRGB(newColor.getRed(), newColor.getGreen(), newColor.getBlue());
    dispose();
  }
  
  private void modeChanged()
  {
    float values[];
    mode = modeC.getSelectedIndex();
    if (mode == 0)
      {
	label1.setText(Translate.text("Red"));
	label2.setText(Translate.text("Green"));
	label3.setText(Translate.text("Blue"));
	values = new float [] {newColor.getRed(), newColor.getGreen(), newColor.getBlue()};
      }
    else if (mode == 1)
      {
	label1.setText(Translate.text("Hue"));
	label2.setText(Translate.text("Saturation"));
	label3.setText(Translate.text("Value"));
	values = newColor.getHSV();
	values[0] /= 360.0;
      }
    else
      {
	label1.setText(Translate.text("Hue"));
	label2.setText(Translate.text("Lightness"));
	label3.setText(Translate.text("Saturation"));
	values = newColor.getHLS();
	values[0] /= 360.0;
      }
    slider1.setValue(values[0]);
    slider2.setValue(values[1]);
    slider3.setValue(values[2]);
    Preferences.userNodeForPackage(ColorChooser.class).putInt("defaultColorModel", mode);
  }
}
