org.photovault.swingui.color.ColorSettingsDlg.java Source code

Java tutorial

Introduction

Here is the source code for org.photovault.swingui.color.ColorSettingsDlg.java

Source

/*
  Copyright (c) 2006-2007 Harri Kaimio
      
  This file is part of Photovault.
    
  Photovault 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.
    
  Photovault 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.
    
  You should have received a copy of the GNU General Public License
  along with Photovault; if not, write to the Free Software Foundation,
  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/

package org.photovault.swingui.color;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.image.ColorModel;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import javax.media.jai.Histogram;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.ListModel;
import javax.swing.SwingConstants;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.photovault.common.PhotovaultException;
import org.photovault.dcraw.ColorProfileDesc;
import org.photovault.dcraw.RawConversionSettings;
import org.photovault.dcraw.RawImage;
import org.photovault.dcraw.RawImageChangeEvent;
import org.photovault.dcraw.RawImageChangeListener;
import org.photovault.dcraw.RawSettingsFactory;
import org.photovault.image.ChannelMapOperation;
import org.photovault.image.ColorCurve;
import org.photovault.image.ImageRenderingListener;
import org.photovault.image.PhotovaultImage;
import org.photovault.imginfo.FuzzyDate;
import org.photovault.imginfo.PhotoInfo;
import org.photovault.imginfo.PhotoInfoFields;
import org.photovault.swingui.JAIPhotoViewer;
import org.photovault.swingui.selection.PhotoSelectionController;
import org.photovault.swingui.PhotoViewChangeEvent;
import org.photovault.swingui.PhotoViewChangeListener;
import org.photovault.swingui.PreviewImageView;
import org.photovault.swingui.RawPhotoView;

/**
 * Dialog box for altering color settings of a photo. Currently only
 * raw images are supporter but in future support for normal image files
 * should be added.
 * @author Harri Kaimio
 */
public class ColorSettingsDlg extends javax.swing.JDialog implements RawImageChangeListener, RawPhotoView,
        PhotoViewChangeListener, PreviewImageView, ImageRenderingListener {

    private static Log log = LogFactory.getLog(ColorSettingsDlg.class.getName());

    /**
     * Creates new form ColorSettingsDlg
     * @param parent Parent frame of this dialog
     * @param modal Whether the dialog is displayed as modal
     * @param photos Array of the photos that will be edited
     */
    public ColorSettingsDlg(java.awt.Frame parent, ColorSettingsDlgController ctrl, boolean modal,
            PhotoInfo[] photos) {
        super(parent, modal);
        this.ctrl = ctrl;
        initComponents();
        checkIsRawPhoto();
        final ColorSettingsDlg staticThis = this;
        this.colorCurvePanel1.addListener(new ColorCurveChangeListener() {
            public void colorCurveChanging(ColorCurvePanel p, ColorCurve c) {
            }

            public void colorCurveChangeCompleted(ColorCurvePanel p, ColorCurve c) {
                staticThis.colorCurveChanged(c);
            }
        });
    }

    /**
     Controller for the photos that will be edited
     */
    PhotoSelectionController ctrl = null;
    RawConversionSettings rawSettings = null;

    /**
     Color curves, in order value, red, green, blue, saturation
     */
    ColorCurve[] colorCurves = new ColorCurve[5];

    /**
     Curves that will be drawn as references for each channel
     */
    List refCurves[] = new ArrayList[5];

    /**
     Names of the color channels
     */
    static String[] colorCurveNames = { "value", "red", "green", "blue", "saturation" };

    /**
     Colors for the curves
     */
    static Color[] curveColors = { Color.BLACK, Color.RED, new Color(0.0f, 0.7f, 0.0f), Color.BLUE,
            new Color(0.2f, 0.2f, 0.0f) };

    /**
     Colors for the reference curves
     */
    static Color[] refCurveColors = { Color.GRAY, Color.PINK, new Color(0.5f, 1.0f, 0.5f),
            new Color(0.5f, 0.5f, 1.0f), new Color(0.5f, 0.5f, 0.2f) };

    /**
     What histogram is shown with each channel
     */
    static String[] channelHistType = { PhotovaultImage.HISTOGRAM_RGB_CHANNELS,
            PhotovaultImage.HISTOGRAM_RGB_CHANNELS, PhotovaultImage.HISTOGRAM_RGB_CHANNELS,
            PhotovaultImage.HISTOGRAM_RGB_CHANNELS, PhotovaultImage.HISTOGRAM_IHS_CHANNELS, };
    /**
     The band of the histogram defined in @see channelHistTypes that is
     associated with each channel. -1 means that all histogram bands should be
     shown.
     */
    static int[] channelHistBand = { -1, 0, 1, 2, 2 };

    /**
      Color curve currently displayed
     */
    int currentColorCurve = 0;

    protected void applyChanges() {
        ctrl.save();
        photoChanged = true;
    }

    /**
     Discard changes made in the dialog & reload model values
     */
    protected void discardChanges() {
        // TODO: Hibernate refactoring
        ctrl.discard();
    }

    public void setTagListModel(ListModel listModel) {
    }

    static class ModelValueAnnotation extends JPanel {
        public ModelValueAnnotation(Color color) {
            super();
            this.color = color;
            Polygon p = new Polygon();
            p.addPoint(5, 0);
            p.addPoint(9, 5);
            p.addPoint(5, 10);
            p.addPoint(1, 5);
            shape = p;
        }

        Color color;
        Polygon shape;

        public Dimension getPreferredSize() {
            return new Dimension(10, 10);
        }

        public void paint(Graphics g) {
            Graphics g2 = g.create();
            g2.setColor(color);
            g2.fillPolygon(shape);
        }
    }

    /**
     Size of the slider labels (Size of the lowest & highest labels will affect 
     the length of slider track, therefore they must be of same size in all 
     sliders.
     */
    Dimension sliderLabelDimension = null;

    /**
     Get a standard sized label for the sliders.
     @param txt Text to show in label.
     @return Label.
     */
    private JComponent getSliderLabel(String txt) {
        if (sliderLabelDimension == null) {
            JLabel maxLabel = new JLabel(String.valueOf(12000));
            sliderLabelDimension = maxLabel.getPreferredSize();
        }
        JLabel l = new JLabel(txt, SwingConstants.CENTER);
        l.setPreferredSize(sliderLabelDimension);
        return l;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        fieldSliderCombo1 = new org.photovault.swingui.color.FieldSliderCombo();
        fieldSliderCombo2 = new org.photovault.swingui.color.FieldSliderCombo();
        dlgControlPane = new javax.swing.JPanel();
        applyBtn = new javax.swing.JButton();
        discardBtn = new javax.swing.JButton();
        closeBtn = new javax.swing.JButton();
        okBtn = new javax.swing.JButton();
        colorSettingTabs = new javax.swing.JTabbedPane();
        rawControlsPane = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        evCorrSlider = new org.photovault.swingui.color.FieldSliderCombo();
        {
            Hashtable sliderLabels = new Hashtable();
            sliderLabels.put(new Double(-2.0), getSliderLabel("-2"));
            sliderLabels.put(new Double(-1.0), new JLabel("-1"));
            sliderLabels.put(new Double(0), new JLabel("0"));
            sliderLabels.put(new Double(1.0), new JLabel("1"));
            sliderLabels.put(new Double(1.99), getSliderLabel("2"));
            evCorrSlider.setLabelTable(sliderLabels);
            evCorrSlider.putClientProperty("JSlider.isFilled", Boolean.FALSE);
        }
        jLabel3 = new javax.swing.JLabel();
        hlightCompSlider = new org.photovault.swingui.color.FieldSliderCombo();
        {
            Hashtable compressSliderLabels = new Hashtable();
            compressSliderLabels.put(new Double(-1.0), getSliderLabel(Double.toString(-1.0)));
            compressSliderLabels.put(new Double(0.0), getSliderLabel(Double.toString(0.0)));
            compressSliderLabels.put(new Double(1.0), getSliderLabel(Double.toString(1.0)));
            compressSliderLabels.put(new Double(2.0), getSliderLabel(Double.toString(2.0)));
            hlightCompSlider.setLabelTable(compressSliderLabels);
            hlightCompSlider.putClientProperty("JSlider.isFilled", Boolean.FALSE);
        }
        jLabel5 = new javax.swing.JLabel();
        blackLevelSlider = new org.photovault.swingui.color.FieldSliderCombo();
        {
            Hashtable sliderLabels = new Hashtable();
            sliderLabels.put(new Double(-500.0), getSliderLabel(Integer.toString(-500)));
            sliderLabels.put(new Double(0.0), getSliderLabel(Integer.toString(0)));
            sliderLabels.put(new Double(500.0), getSliderLabel(Integer.toString(500)));
            sliderLabels.put(new Double(1000.0), getSliderLabel(Integer.toString(1000)));
            blackLevelSlider.setLabelTable(sliderLabels);
            blackLevelSlider.putClientProperty("JSlider.isFilled", Boolean.FALSE);
        }
        jLabel2 = new javax.swing.JLabel();
        ctempSlider = new org.photovault.swingui.color.FieldSliderCombo();
        {
            Hashtable sliderLabels = new Hashtable();
            sliderLabels.put(new Double(2000.0), getSliderLabel(Integer.toString(2000)));
            sliderLabels.put(new Double(5000.0), getSliderLabel(Integer.toString(5000)));
            sliderLabels.put(new Double(8000.0), getSliderLabel(Integer.toString(8000)));
            sliderLabels.put(new Double(11000.0), getSliderLabel(Integer.toString(11000)));
            sliderLabels.put(new Double(14000.0), getSliderLabel(Integer.toString(14000)));
            ctempSlider.setLabelTable(sliderLabels);
            ctempSlider.putClientProperty("JSlider.isFilled", Boolean.FALSE);
        }
        jLabel4 = new javax.swing.JLabel();
        greenGainSlider = new org.photovault.swingui.color.FieldSliderCombo();
        Hashtable greenGainLabels = new Hashtable();
        greenGainLabels.put(new Double(-1.0), getSliderLabel("-1"));
        greenGainLabels.put(new Double(0.0), getSliderLabel("0"));
        greenGainLabels.put(new Double(1.0), getSliderLabel("+1"));
        greenGainSlider.setLabelTable(greenGainLabels);
        greenGainSlider.putClientProperty("JSlider.isFilled", Boolean.FALSE);
        rawHistogramPane = rawHistogramPane = new HistogramPane();
        jLabel6 = new javax.swing.JLabel();
        hlightRecoverySlider = new org.photovault.swingui.color.FieldSliderCombo();
        jLabel7 = new javax.swing.JLabel();
        waveletDenoiseSlider = new org.photovault.swingui.color.FieldSliderCombo();
        whiteLevelSlider = new org.photovault.swingui.color.FieldSliderCombo();
        jLabel8 = new javax.swing.JLabel();
        colorSettingControls = new javax.swing.JPanel();
        colorCurveSelectionCombo = new javax.swing.JComboBox();
        colorCurvePanel1 = new org.photovault.swingui.color.ColorCurvePanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Colors");

        applyBtn.setAction(ctrl.getActionAdapter("save"));
        applyBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                applyBtnActionPerformed(evt);
            }
        });

        discardBtn.setAction(ctrl.getActionAdapter("discard"));
        discardBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                discardBtnActionPerformed(evt);
            }
        });

        closeBtn.setText("Close");
        closeBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeBtnActionPerformed(evt);
            }
        });

        okBtn.setText("OK");
        okBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                okBtnActionPerformed(evt);
            }
        });

        org.jdesktop.layout.GroupLayout dlgControlPaneLayout = new org.jdesktop.layout.GroupLayout(dlgControlPane);
        dlgControlPane.setLayout(dlgControlPaneLayout);
        dlgControlPaneLayout.setHorizontalGroup(
                dlgControlPaneLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add(
                        org.jdesktop.layout.GroupLayout.TRAILING,
                        dlgControlPaneLayout.createSequentialGroup().addContainerGap(24, Short.MAX_VALUE).add(okBtn)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED).add(applyBtn)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED).add(discardBtn)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED).add(closeBtn)));
        dlgControlPaneLayout.setVerticalGroup(dlgControlPaneLayout
                .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(org.jdesktop.layout.GroupLayout.TRAILING, dlgControlPaneLayout.createSequentialGroup()
                        .add(dlgControlPaneLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                .add(closeBtn).add(discardBtn).add(applyBtn).add(okBtn))
                        .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));

        jLabel1.setText("EV correction");

        evCorrSlider.setFractionDigits(2);
        evCorrSlider.setMajorTickSpacing(1.0);
        evCorrSlider.setMaximum(2.0);
        evCorrSlider.setMinimum(-2.0);
        evCorrSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                evCorrSliderStateChanged(evt);
            }
        });

        jLabel3.setText("Compress highlights");

        hlightCompSlider.setMajorTickSpacing(1.0);
        hlightCompSlider.setMaximum(2.0);
        hlightCompSlider.setMinimum(-1.0);
        hlightCompSlider.setValue(0.0);
        hlightCompSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                hlightCompSliderStateChanged(evt);
            }
        });

        jLabel5.setText("Black level");

        blackLevelSlider.setFractionDigits(0);
        blackLevelSlider.setMajorTickSpacing(500.0);
        blackLevelSlider.setMaximum(1000.0);
        blackLevelSlider.setMinimum(-500.0);
        blackLevelSlider.setValue(0.0);
        blackLevelSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                blackLevelSliderStateChanged(evt);
            }
        });

        jLabel2.setText("Color Temperature");

        ctempSlider.setFractionDigits(0);
        ctempSlider.setMajorTickSpacing(3000.0);
        ctempSlider.setMaximum(14000.0);
        ctempSlider.setMinimum(2000.0);
        ctempSlider.setValue(5500.0);
        ctempSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                ctempSliderStateChanged(evt);
            }
        });

        jLabel4.setText("Green");

        greenGainSlider.setFractionDigits(2);
        greenGainSlider.setMajorTickSpacing(1.0);
        greenGainSlider.setMinimum(-1.0);
        greenGainSlider.setValue(0.0);
        greenGainSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                greenGainSliderStateChanged(evt);
            }
        });

        rawHistogramPane.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        org.jdesktop.layout.GroupLayout rawHistogramPaneLayout = new org.jdesktop.layout.GroupLayout(
                rawHistogramPane);
        rawHistogramPane.setLayout(rawHistogramPaneLayout);
        rawHistogramPaneLayout.setHorizontalGroup(rawHistogramPaneLayout
                .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add(0, 423, Short.MAX_VALUE));
        rawHistogramPaneLayout.setVerticalGroup(rawHistogramPaneLayout
                .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add(0, 0, Short.MAX_VALUE));

        jLabel6.setText("Recover highlights");

        hlightRecoverySlider.setFractionDigits(0);
        hlightRecoverySlider.setMaximum(7.0);
        hlightRecoverySlider.setName("hlightRecoverySlider"); // NOI18N
        hlightRecoverySlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                hlightRecoverySliderStateChanged(evt);
            }
        });

        jLabel7.setText("Noise reduction");

        waveletDenoiseSlider.setFractionDigits(0);
        waveletDenoiseSlider.setMajorTickSpacing(400.0);
        waveletDenoiseSlider.setMaximum(1200.0);
        waveletDenoiseSlider.setValue(0.0);
        waveletDenoiseSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                waveletDenoiseSliderStateChanged(evt);
            }
        });

        whiteLevelSlider.setMaximum(65536.0);
        whiteLevelSlider.setMinimum(1000.0);
        whiteLevelSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                whiteLevelSliderStateChanged(evt);
            }
        });

        jLabel8.setText("White level");

        org.jdesktop.layout.GroupLayout rawControlsPaneLayout = new org.jdesktop.layout.GroupLayout(
                rawControlsPane);
        rawControlsPane.setLayout(rawControlsPaneLayout);
        rawControlsPaneLayout.setHorizontalGroup(rawControlsPaneLayout
                .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(rawControlsPaneLayout.createSequentialGroup().addContainerGap().add(rawControlsPaneLayout
                        .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                        .add(rawControlsPaneLayout.createSequentialGroup()
                                .add(hlightCompSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 288,
                                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .addContainerGap())
                        .add(rawControlsPaneLayout.createSequentialGroup()
                                .add(rawControlsPaneLayout
                                        .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                        .add(rawHistogramPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .add(jLabel1).add(jLabel3).add(jLabel7).add(jLabel6).add(jLabel4)
                                        .add(jLabel2)
                                        .add(rawControlsPaneLayout.createSequentialGroup().add(rawControlsPaneLayout
                                                .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                                                .add(whiteLevelSlider, 0, 0, Short.MAX_VALUE)
                                                .add(waveletDenoiseSlider, 0, 0, Short.MAX_VALUE)
                                                .add(hlightRecoverySlider, 0, 0, Short.MAX_VALUE)
                                                .add(greenGainSlider, 0, 0, Short.MAX_VALUE)
                                                .add(ctempSlider, 0, 0, Short.MAX_VALUE)
                                                .add(blackLevelSlider, 0, 0, Short.MAX_VALUE).add(evCorrSlider,
                                                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 297,
                                                        Short.MAX_VALUE))
                                                .add(63, 63, 63).add(jLabel5)))
                                .add(372, 372, 372))
                        .add(rawControlsPaneLayout.createSequentialGroup().add(jLabel8).addContainerGap(237,
                                Short.MAX_VALUE)))));
        rawControlsPaneLayout.setVerticalGroup(rawControlsPaneLayout
                .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(rawControlsPaneLayout.createSequentialGroup().add(jLabel1)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(evCorrSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED).add(jLabel3)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(hlightCompSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED).add(jLabel8)
                        .add(rawControlsPaneLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                .add(rawControlsPaneLayout.createSequentialGroup().add(62, 62, 62).add(jLabel5))
                                .add(rawControlsPaneLayout.createSequentialGroup()
                                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                        .add(whiteLevelSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 64,
                                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                        .add(18, 18, 18)
                        .add(blackLevelSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 64,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED).add(jLabel2)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(ctempSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 65,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED).add(jLabel4)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(greenGainSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 64,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED).add(jLabel6)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(hlightRecoverySlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 64,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED).add(jLabel7)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(waveletDenoiseSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(rawHistogramPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addContainerGap()));

        colorSettingTabs.addTab("Raw conversion", rawControlsPane);

        colorCurveSelectionCombo.setModel(new javax.swing.DefaultComboBoxModel(
                new String[] { "Value", "Red", "Green", "Blue", "Saturation" }));
        colorCurveSelectionCombo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                colorCurveSelectionComboActionPerformed(evt);
            }
        });

        colorCurvePanel1
                .setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED,
                        java.awt.Color.white, java.awt.Color.lightGray, null, null));

        org.jdesktop.layout.GroupLayout colorCurvePanel1Layout = new org.jdesktop.layout.GroupLayout(
                colorCurvePanel1);
        colorCurvePanel1.setLayout(colorCurvePanel1Layout);
        colorCurvePanel1Layout.setHorizontalGroup(colorCurvePanel1Layout
                .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add(0, 289, Short.MAX_VALUE));
        colorCurvePanel1Layout.setVerticalGroup(colorCurvePanel1Layout
                .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add(0, 300, Short.MAX_VALUE));

        org.jdesktop.layout.GroupLayout colorSettingControlsLayout = new org.jdesktop.layout.GroupLayout(
                colorSettingControls);
        colorSettingControls.setLayout(colorSettingControlsLayout);
        colorSettingControlsLayout.setHorizontalGroup(colorSettingControlsLayout
                .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(colorSettingControlsLayout.createSequentialGroup()
                        .add(colorSettingControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                .add(colorSettingControlsLayout.createSequentialGroup().add(155, 155, 155).add(
                                        colorCurveSelectionCombo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                                .add(org.jdesktop.layout.GroupLayout.TRAILING,
                                        colorSettingControlsLayout.createSequentialGroup().addContainerGap().add(
                                                colorCurvePanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                        .addContainerGap()));
        colorSettingControlsLayout.setVerticalGroup(
                colorSettingControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                        .add(colorSettingControlsLayout.createSequentialGroup().add(25, 25, 25)
                                .add(colorCurveSelectionCombo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(colorCurvePanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .addContainerGap(308, Short.MAX_VALUE)));

        colorSettingTabs.addTab("Colors", colorSettingControls);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(layout.createSequentialGroup().addContainerGap(198, Short.MAX_VALUE)
                        .add(dlgControlPane, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap())
                .add(layout.createSequentialGroup().addContainerGap()
                        .add(colorSettingTabs, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 329,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
        layout.setVerticalGroup(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup().addContainerGap()
                        .add(colorSettingTabs, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 713, Short.MAX_VALUE)
                        .add(18, 18, 18).add(dlgControlPane, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)));

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
     Called when use selects a different color curve for editing
     */
    private void colorCurveSelectionComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_colorCurveSelectionComboActionPerformed
        int i = colorCurveSelectionCombo.getSelectedIndex();
        showCurve(i);
    }//GEN-LAST:event_colorCurveSelectionComboActionPerformed

    private void greenGainSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_greenGainSliderStateChanged
        double greenEv = greenGainSlider.getValue();
        double newGain = Math.pow(2, greenEv);
        if (Math.abs(newGain - this.greenGain) > 0.005) {
            greenGain = newGain;
            ctrl.viewChanged(this, PhotoInfoFields.RAW_GREEN, newGain);
            if (rawSettings != null) {
                RawSettingsFactory f = new RawSettingsFactory(rawSettings);
                f.setGreenGain(newGain);
                try {
                    rawSettings = f.create();
                } catch (PhotovaultException ex) {
                    log.error("Error setting color temp: " + ex.getMessage());
                }
                firePreviewChangeEvent(new RawSettingsPreviewEvent(this, ctrl.getPhotos(), rawSettings));
                reloadHistogram();
            }
        }

    }//GEN-LAST:event_greenGainSliderStateChanged

    /**
     * Color temperature slider value was changed
     * @param evt Event describing the change
     */
    private void ctempSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_ctempSliderStateChanged
        double newCTemp = ctempSlider.getValue();
        if (Math.abs(newCTemp - this.colorTemp) > 10) {
            colorTemp = newCTemp;
            ctrl.viewChanged(this, PhotoInfoFields.RAW_CTEMP, newCTemp);
            if (rawSettings != null) {
                RawSettingsFactory f = new RawSettingsFactory(rawSettings);
                f.setColorTemp(newCTemp);
                try {
                    rawSettings = f.create();
                } catch (PhotovaultException ex) {
                    log.error("Error setting color temp: " + ex.getMessage());
                }
                firePreviewChangeEvent(new RawSettingsPreviewEvent(this, ctrl.getPhotos(), rawSettings));
                reloadHistogram();
            }
        }
    }//GEN-LAST:event_ctempSliderStateChanged

    private void blackLevelSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_blackLevelSliderStateChanged
        int newBlack = (int) blackLevelSlider.getValue();
        if (Math.abs(newBlack - black) > 0.05) {

            black = newBlack;
            ctrl.viewChanged(this, PhotoInfoFields.RAW_BLACK_LEVEL, black);
            if (rawSettings != null) {
                RawSettingsFactory f = new RawSettingsFactory(rawSettings);
                f.setBlack(newBlack);
                try {
                    rawSettings = f.create();
                } catch (PhotovaultException ex) {
                    log.error("Error setting black: " + ex.getMessage());
                }
                firePreviewChangeEvent(new RawSettingsPreviewEvent(this, ctrl.getPhotos(), rawSettings));
                reloadHistogram();
            }
        }

    }//GEN-LAST:event_blackLevelSliderStateChanged

    private void evCorrSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_evCorrSliderStateChanged
        double newEv = evCorrSlider.getValue();
        if (Math.abs(newEv - evCorr) > 0.05) {
            evCorr = newEv;
            ctrl.viewChanged(this, PhotoInfoFields.RAW_EV_CORR, evCorr);
            if (rawSettings != null) {
                RawSettingsFactory f = new RawSettingsFactory(rawSettings);
                f.setEvCorr(newEv);
                try {
                    rawSettings = f.create();
                } catch (PhotovaultException ex) {
                    log.error("Error setting EV correction: " + ex.getMessage());
                }
                firePreviewChangeEvent(new RawSettingsPreviewEvent(this, ctrl.getPhotos(), rawSettings));
                reloadHistogram();
            }
        }
    }//GEN-LAST:event_evCorrSliderStateChanged

    private void hlightCompSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_hlightCompSliderStateChanged
        double newHlightComp = hlightCompSlider.getValue();
        if ((Math.abs(newHlightComp - this.hlightComp) > 0.001)) {
            this.hlightComp = newHlightComp;
            ctrl.viewChanged(this, PhotoInfoFields.RAW_HLIGHT_COMP, hlightComp);
            if (rawSettings != null) {
                RawSettingsFactory f = new RawSettingsFactory(rawSettings);
                f.setHlightComp(newHlightComp);
                try {
                    rawSettings = f.create();
                } catch (PhotovaultException ex) {
                    log.error("Error setting green gain: " + ex.getMessage());
                }
                firePreviewChangeEvent(new RawSettingsPreviewEvent(this, ctrl.getPhotos(), rawSettings));
                reloadHistogram();
            }
        }

    }//GEN-LAST:event_hlightCompSliderStateChanged

    /**
     * Close button was pressed. Close the window
     * @param evt The ButtonEvent
     */
    private void closeBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeBtnActionPerformed
        discardChanges();
        setVisible(false);
    }//GEN-LAST:event_closeBtnActionPerformed

    /**
     * Discard button was pressed. Instruct controller to discard changes made
     * @param evt The ButtonEvent
     */
    private void discardBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_discardBtnActionPerformed
        discardChanges();
    }//GEN-LAST:event_discardBtnActionPerformed

    /**
     * Apply button was pressed. Save all changes made.
     * @param evt The ButtonEvent
     */
    private void applyBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_applyBtnActionPerformed
        applyChanges();
    }//GEN-LAST:event_applyBtnActionPerformed

    /**
     * OK button was pressed. Save changes & close window
     * @param evt Event
     */
    private void okBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okBtnActionPerformed
        applyChanges();
        setVisible(false);
    }//GEN-LAST:event_okBtnActionPerformed

    private void hlightRecoverySliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_hlightRecoverySliderStateChanged
        int newRecovery = (int) hlightRecoverySlider.getValue();
        if (newRecovery != hlightRecovery) {

            hlightRecovery = newRecovery;
            ctrl.viewChanged(this, PhotoInfoFields.RAW_HLIGHT_RECOVERY, hlightRecovery);
            if (rawSettings != null) {
                RawSettingsFactory f = new RawSettingsFactory(rawSettings);
                f.setHlightRecovery(hlightRecovery);
                try {
                    rawSettings = f.create();
                } catch (PhotovaultException ex) {
                    log.error("Error setting black: " + ex.getMessage());
                }
                firePreviewChangeEvent(new RawSettingsPreviewEvent(this, ctrl.getPhotos(), rawSettings));
                reloadHistogram();
            }
        }
    }//GEN-LAST:event_hlightRecoverySliderStateChanged

    private void waveletDenoiseSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_waveletDenoiseSliderStateChanged
        float newDenoise = (float) waveletDenoiseSlider.getValue();
        if (newDenoise != denoise) {

            denoise = newDenoise;
            ctrl.viewChanged(this, PhotoInfoFields.RAW_WAVELET_DENOISE_THRESHOLD, denoise);
            if (rawSettings != null) {
                RawSettingsFactory f = new RawSettingsFactory(rawSettings);
                f.setWaveletThreshold(denoise);
                try {
                    rawSettings = f.create();
                } catch (PhotovaultException ex) {
                    log.error("Error setting black: " + ex.getMessage());
                }
                firePreviewChangeEvent(new RawSettingsPreviewEvent(this, ctrl.getPhotos(), rawSettings));
                reloadHistogram();
            }
        }
    }//GEN-LAST:event_waveletDenoiseSliderStateChanged

    private void whiteLevelSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_whiteLevelSliderStateChanged
        int newWhite = (int) whiteLevelSlider.getValue();
        if (Math.abs(newWhite - white) > 1) {

            white = newWhite;
            ctrl.viewChanged(this, PhotoInfoFields.RAW_WHITE_LEVEL, white);
            if (rawSettings != null) {
                RawSettingsFactory f = new RawSettingsFactory(rawSettings);
                f.setWhite(newWhite);
                try {
                    rawSettings = f.create();
                } catch (PhotovaultException ex) {
                    log.error("Error setting black: " + ex.getMessage());
                }
                firePreviewChangeEvent(new RawSettingsPreviewEvent(this, ctrl.getPhotos(), rawSettings));
                reloadHistogram();
            }
        }
    }//GEN-LAST:event_whiteLevelSliderStateChanged

    /**
     Called by colorCurvePane when use has edited the curve
     @param c the curve after editing.
     */
    private void colorCurveChanged(ColorCurve c) {
        colorCurves[currentColorCurve] = c;
        switch (currentColorCurve) {
        case 0:
            ctrl.viewChanged(this, PhotoInfoFields.COLOR_CURVE_VALUE, c);
            break;
        case 1:
            ctrl.viewChanged(this, PhotoInfoFields.COLOR_CURVE_RED, c);
            break;
        case 2:
            ctrl.viewChanged(this, PhotoInfoFields.COLOR_CURVE_GREEN, c);
            break;
        case 3:
            ctrl.viewChanged(this, PhotoInfoFields.COLOR_CURVE_BLUE, c);
            break;
        case 4:
            ctrl.viewChanged(this, PhotoInfoFields.COLOR_CURVE_SATURATION, c);
            break;
        default:
            // Should never happend
            break;
        }
    }

    RawImage rawPreviewImage = null;
    RawImage previewCtrlImage = null;
    PhotoInfo previewCtrlPhoto = null;

    /**
     * Set the preview image into which the changes done in dialog are
     * immediately applied.
     * @param ri Test image
     */
    public void setPreview(RawImage ri) {
        rawPreviewImage = ri;
        if (ri != null) {
            ((HistogramPane) rawHistogramPane).setHistogram(ri.getHistogramBins());
            ((HistogramPane) rawHistogramPane).setTransferGraph(ri.getGammaLut());
        }
    }

    /**
     Send event to all preview windows that the raw settings have been changed.
     @param e Event that describes the change
     */
    void firePreviewChangeEvent(RawSettingsPreviewEvent e) {
        if (previewCtrl != null) {
            previewCtrl.previewRawSettingsChanged(e);
        }
    }

    /**
     Inform preview control that saturation has changed
     @param newSat New saturation value
     */
    void notifyPreviewSaturationChange(double newSat) {
        if (previewCtrl != null) {
            previewCtrl.setSaturation(newSat);
        }
    }

    /**
     Reload the histogram data from RawImage displayed in preview control if
     the image matches to current model. If this is not the case, disable 
     histogram.
     */
    void reloadHistogram() {
        if (previewCtrl == null) {
            return;
        }
        PhotoInfo[] model = ctrl.getPhotos();
        PhotoInfo photo = previewCtrl.getPhoto();
        if (photo != null && model != null && model.length == 1 && model[0] == photo) {
            byte[] lut = previewCtrl.getRawConversionLut();
            ((HistogramPane) rawHistogramPane).setTransferGraph(lut);
            ((HistogramPane) rawHistogramPane).setHistogram(previewCtrl.getRawImageHistogram());
        } else {
            /* Preview control is not displaying image that matches to the current
               model, so we do not have histogram data available.
             */
            ((HistogramPane) rawHistogramPane).setTransferGraph(null);
            ((HistogramPane) rawHistogramPane).setHistogram(null);

        }
    }

    JAIPhotoViewer previewCtrl = null;

    /**
     Checks if the model supports raw conversion settings and disables
     or enables controls based on this. Raw settings are only allowed if all 
     photos controlled bu ctrl are raw photos.
     */
    void checkIsRawPhoto() {
        PhotoInfo[] photos = ctrl.getPhotos();
        boolean isRaw = true;
        if (photos != null) {
            /*
             If any of the photos is not a raw image we cannot use raw controls
             */
            for (int n = 0; n < photos.length; n++) {
                if (photos[n].getRawSettings() == null) {
                    isRaw = false;
                    break;
                }
            }
        } else {
            isRaw = false;
        }
        setRawControlsEnabled(isRaw);
    }

    /**
     Enable or disble all controls that affect raw conversion settings
     @param enable <code>true</code> if the controls should be enabled
     */
    void setRawControlsEnabled(boolean enable) {
        colorSettingTabs.setEnabledAt(0, enable);
        this.rawControlsPane.setEnabled(enable);
        evCorrSlider.setEnabled(enable);
        hlightCompSlider.setEnabled(enable);
        hlightRecoverySlider.setEnabled(enable);
        ctempSlider.setEnabled(enable);
        greenGainSlider.setEnabled(enable);
        blackLevelSlider.setEnabled(enable);
        whiteLevelSlider.setEnabled(enable);
        waveletDenoiseSlider.setEnabled(enable);
        if (!enable && colorSettingTabs.getSelectedIndex() == 0) {
            colorSettingTabs.setSelectedIndex(1);
        }
    }

    /**
     Show a different color curve in colorCurvePane
     */
    private void showCurve(int chan) {
        currentColorCurve = chan;
        if (colorCurves[chan] == null) {
            // The curve is not present in current profile
            ColorCurve c = colorCurves[chan] = new ColorCurve();
            c.addPoint(0.0, 0.0);
            c.addPoint(1.0, 1.0);
        }
        colorCurvePanel1.setCurve(colorCurves[chan], curveColors[chan]);
        colorCurvePanel1.clearReferenceCurves();
        if (refCurves[chan] != null) {
            for (Object c : refCurves[chan]) {
                if (c == null) {
                    c = new ColorCurve();
                }
                colorCurvePanel1.addReferenceCurve((ColorCurve) c, refCurveColors[chan]);
            }
        }

        // Draw also the curves for other channels
        for (int n = 0; n < colorCurves.length; n++) {
            if (n != chan) {
                ColorCurve c = colorCurves[n];
                if (c == null) {
                    c = new ColorCurve();
                }
                colorCurvePanel1.addReferenceCurve(c, refCurveColors[n]);
            }
        }
        colorCurveSelectionCombo.setSelectedIndex(chan);
        int[] histData = histograms.get(colorCurveNames[chan]);
        colorCurvePanel1.setHistogram(histData, Color.BLACK);
    }

    /**
     Enable or disable color curves for individual red, green, blue and saturation 
     channels.
     @param isEnabled If <code>true</code>, give user possibility to select 
     curves for all channels. If <code>false</code>, force display of value curve only
         
     */
    private void setColorChannelCurvesEnabled(boolean isEnabled) {
        ComboBoxModel newModel = colorCurveSelectionCombo.getModel();
        int newSelection = colorCurveSelectionCombo.getSelectedIndex();
        if (isEnabled) {
            newModel = new DefaultComboBoxModel(new String[] { "Value", "Red", "Green", "Blue", "Saturation" });
        } else {
            newModel = new DefaultComboBoxModel(new String[] { "Value" });
            newSelection = 0;
        }
        colorCurveSelectionCombo.setModel(newModel);
        colorCurveSelectionCombo.setSelectedIndex(newSelection);
    }

    /**
     Array of color profiles that match to the items in colorProfileCombo
     combo box.
     */
    ColorProfileDesc profiles[] = null;

    boolean photoChanged = false;

    /**
       Shows the dialog.
       @return True if the dialog modified the photo data, false otherwise.
    */

    public boolean showDialog() {
        photoChanged = false;
        setVisible(true);
        return photoChanged;
    }

    /**
     * callback that is called is the preview image changes.
     * @param ev The change event
     */
    public void rawImageSettingsChanged(RawImageChangeEvent ev) {

    }

    /*
     PhotoInfoView implementation
     */

    public void setPhotographer(String newValue) {
    }

    public String getPhotographer() {
        return null;
    }

    public void setPhotographerMultivalued(boolean mv) {
    }

    public void setFuzzyDate(FuzzyDate newValue) {
    }

    public FuzzyDate getFuzzyDate() {
        return null;
    }

    public void setFuzzyDateMultivalued(boolean mv) {
    }

    public void setQuality(Number quality) {
    }

    public Number getQuality() {
        return null;
    }

    public void setQualityMultivalued(boolean mv) {
    }

    public void setShootingPlace(String newValue) {
    }

    public String getShootingPlace() {
        return null;
    }

    public void setShootingPlaceMultivalued(boolean mv) {
    }

    public void setFocalLength(Number newValue) {
    }

    public Number getFocalLength() {
        return null;
    }

    public void setFocalLengthMultivalued(boolean mv) {
    }

    public void setFStop(Number newValue) {
    }

    public Number getFStop() {
        return null;
    }

    public void setFStopMultivalued(boolean mv) {
    }

    public void setCamera(String newValue) {
    }

    public String getCamera() {
        return null;
    }

    public void setCameraMultivalued(boolean mv) {
    }

    public void setFilm(String newValue) {
    }

    public String getFilm() {
        return null;
    }

    public void setFilmMultivalued(boolean mv) {
    }

    public void setLens(String newValue) {
    }

    public String getLens() {
        return null;
    }

    public void setLensMultivalued(boolean mv) {
    }

    public void setDescription(String newValue) {
    }

    public String getDescription() {
        return null;
    }

    public void setDescriptionMultivalued(boolean mv) {
    }

    public void setTechNotes(String newValue) {
    }

    public String getTechNotes() {
        return null;
    }

    public void setTechNotesMultivalued(boolean mv) {
    }

    public void setShutterSpeed(Number newValue) {
    }

    public Number getShutterSpeed() {
        return null;
    }

    public void setShutterSpeedMultivalued(boolean mv) {
    }

    public void setFilmSpeed(Number newValue) {
    }

    public Number getFilmSpeed() {
        return null;
    }

    public void setFilmSpeedMultivalued(boolean mv) {
    }

    public void setFolderTreeModel(TreeModel model) {
    }

    public void setRawSettings(RawConversionSettings rawSettings) {
        this.rawSettings = rawSettings;
        if (rawSettings != null) {
            double evCorr = rawSettings.getEvCorr();
            evCorrSlider.setValue(evCorr);
            double comp = rawSettings.getHighlightCompression();
            hlightCompSlider.setValue(comp);
            double recovery = rawSettings.getHlightRecovery();
            hlightRecoverySlider.setValue(recovery);
            blackLevelSlider.setValue(rawSettings.getBlack());
            whiteLevelSlider.setValue(rawSettings.getWhite());
            double colorTemp = rawSettings.getColorTemp();
            ctempSlider.setValue((int) colorTemp);
            double g = rawSettings.getGreenGain();
            double logGreen = Math.log(g) / Math.log(2);
            greenGainSlider.setValue(logGreen);
            waveletDenoiseSlider.setValue(rawSettings.getWaveletThreshold());
            firePreviewChangeEvent(new RawSettingsPreviewEvent(this, ctrl.getPhotos(), rawSettings));
        }
    }

    public void setRawSettingsMultivalued(boolean mv) {
    }

    public RawConversionSettings getRawSettings() {
        return rawSettings;
    }

    public void setColorChannelMapping(ChannelMapOperation cm) {
    }

    public void setColorChannelMappingMultivalued(boolean mv) {

    }

    public ChannelMapOperation getColorChannelMapping() {
        return null;
    }

    public void expandFolderTreePath(TreePath path) {
    }

    int black = 0;
    int white = 65535;

    public void setRawBlack(int black) {
        this.black = black;
        blackLevelSlider.setValue((double) black);
    }

    public void setRawBlack(int black, List refValues) {
        this.black = black;
        blackLevelSlider.setValue((double) black);
        if (refValues != null && refValues.size() > 1) {
            double[] annotations = new double[refValues.size()];
            for (int n = 0; n < refValues.size(); n++) {
                annotations[n] = ((Number) refValues.get(n)).doubleValue();
            }
            blackLevelSlider.setAnnotations(annotations);
            blackLevelSlider.setMultivalued(true);
        } else {
            // restore the normal label table without any extra annotations
            blackLevelSlider.setAnnotations(null);
            blackLevelSlider.setMultivalued(false);
        }
    }

    public void setRawBlackMultivalued(boolean multivalued, Object[] values) {
        if (values != null && values.length > 1) {
            double[] annotations = new double[values.length];
            for (int n = 0; n < values.length; n++) {
                annotations[n] = ((Number) values[n]).doubleValue();
            }
            blackLevelSlider.setAnnotations(annotations);
        } else {
            // restore the normal label table without any extra annotations
            blackLevelSlider.setAnnotations(null);
        }
        blackLevelSlider.setMultivalued(multivalued);
    }

    public int getRawBlack() {
        return (int) blackLevelSlider.getValue();
    }

    public void setRawWhite(int white) {
        this.white = white;
        whiteLevelSlider.setValue((double) white);
    }

    public void setRawWhite(int white, List refValues) {
        this.white = white;
        whiteLevelSlider.setValue((double) white);
        if (refValues != null && refValues.size() > 1) {
            double[] annotations = new double[refValues.size()];
            for (int n = 0; n < refValues.size(); n++) {
                annotations[n] = ((Number) refValues.get(n)).doubleValue();
            }
            whiteLevelSlider.setAnnotations(annotations);
            whiteLevelSlider.setMultivalued(true);
        } else {
            // restore the normal label table without any extra annotations
            whiteLevelSlider.setAnnotations(null);
            whiteLevelSlider.setMultivalued(false);
        }
    }

    public void setRawWhiteMultivalued(boolean multivalued, Object[] values) {
        if (values != null && values.length > 1) {
            double[] annotations = new double[values.length];
            for (int n = 0; n < values.length; n++) {
                annotations[n] = ((Number) values[n]).doubleValue();
            }
            whiteLevelSlider.setAnnotations(annotations);
        } else {
            // restore the normal label table without any extra annotations
            whiteLevelSlider.setAnnotations(null);
        }
        whiteLevelSlider.setMultivalued(multivalued);
    }

    public int getRawWhite() {
        return (int) whiteLevelSlider.getValue();
    }

    float denoise = 0;

    public void setRawWaveletDenoiseThreshold(float denoise, List refValues) {
        this.denoise = denoise;
        waveletDenoiseSlider.setValue((double) denoise);
        if (refValues != null && refValues.size() > 1) {
            double[] annotations = new double[refValues.size()];
            for (int n = 0; n < refValues.size(); n++) {
                annotations[n] = ((Number) refValues.get(n)).doubleValue();
            }
            waveletDenoiseSlider.setAnnotations(annotations);
            waveletDenoiseSlider.setMultivalued(true);
        } else {
            // restore the normal label table without any extra annotations
            waveletDenoiseSlider.setAnnotations(null);
            waveletDenoiseSlider.setMultivalued(false);
        }

    }

    public float getRawWaveletDenoiseThreshold() {
        return (int) waveletDenoiseSlider.getValue();
    }

    double evCorr = 0.0;

    public void setRawEvCorr(double evCorr) {
        this.evCorr = evCorr;
        evCorrSlider.setValue(evCorr);
    }

    public void setRawEvCorr(double evCorr, List refValues) {
        this.evCorr = evCorr;
        evCorrSlider.setValue(evCorr);
        if (refValues != null && refValues.size() > 1) {
            annotateSlider(evCorrSlider, refValues);
            evCorrSlider.setMultivalued(true);
        } else {
            evCorrSlider.setAnnotations(null);
            evCorrSlider.setMultivalued(false);
        }
    }

    public void setRawEvCorrMultivalued(boolean multivalued, Object[] values) {
        if (values != null && values.length > 1) {
            annotateSlider(evCorrSlider, values);
        } else {
            // restore the normal label table without any extra annotations
            evCorrSlider.setAnnotations(null);
        }
        evCorrSlider.setMultivalued(multivalued);
    }

    public double getRawEvCorr() {
        return evCorrSlider.getValue();
    }

    double hlightComp = 0.0;
    Hashtable hlightSliderLabels = null;

    public void setRawHlightComp(double comp) {
        this.hlightComp = comp;
        hlightCompSlider.setValue(comp);
    }

    public void setRawHlightComp(double comp, List refValues) {
        this.hlightComp = comp;
        hlightCompSlider.setValue(comp);
        if (refValues != null && refValues.size() > 1) {
            annotateSlider(hlightCompSlider, refValues);
            hlightCompSlider.setMultivalued(true);
        } else {
            hlightCompSlider.setAnnotations(null);
            hlightCompSlider.setMultivalued(false);
        }
    }

    int hlightRecovery;

    public int getHlightRecovery() {
        return (int) hlightRecoverySlider.getValue();
    }

    public void setRawHlightRecovery(int recovery, List refValues) {
        this.hlightRecovery = recovery;
        hlightRecoverySlider.setValue(recovery);
        if (refValues != null && refValues.size() != 1) {
            annotateSlider(hlightRecoverySlider, refValues);
            hlightRecoverySlider.setMultivalued(true);
        } else {
            hlightRecoverySlider.setAnnotations(null);
            hlightRecoverySlider.setMultivalued(false);
        }
    }

    public void setRawHlightCompMultivalued(boolean multivalued, Object[] values) {
        if (values != null && values.length > 1) {
            annotateSlider(hlightCompSlider, values);
        } else {
            // restore the normal label table without any extra annotations
            hlightCompSlider.setAnnotations(null);
        }
        hlightCompSlider.setMultivalued(multivalued);
    }

    public double getRawHlightComp() {
        double comp = hlightCompSlider.getValue();
        return comp;
    }

    double colorTemp = 0.0;

    public void setRawColorTemp(double ct) {
        colorTemp = ct;
        ctempSlider.setValue(ct);
    }

    public void setRawColorTemp(double ct, List refValues) {
        colorTemp = ct;
        ctempSlider.setValue(ct);
        if (refValues != null && refValues.size() > 1) {
            annotateSlider(ctempSlider, refValues);
            ctempSlider.setMultivalued(true);
        } else {
            ctempSlider.setAnnotations(null);
            ctempSlider.setMultivalued(false);
        }
    }

    public void setRawColorTempMultivalued(boolean multivalued, Object[] values) {
        if (values != null && values.length > 1) {
            annotateSlider(ctempSlider, values);
        } else {
            // restore the normal label table without any extra annotations
            ctempSlider.setAnnotations(null);
        }
        ctempSlider.setMultivalued(multivalued);
    }

    public double getRawColorTemp() {
        return (double) ctempSlider.getValue();
    }

    double greenGain = 1.0;

    public void setRawGreenGain(double g) {
        greenGain = g;
        double logGreen = Math.log(g) / Math.log(2);
        greenGainSlider.setValue(logGreen);
    }

    public void setRawGreenGain(double g, List refValues) {
        greenGain = g;
        double logGreen = Math.log(g) / Math.log(2);
        greenGainSlider.setValue(logGreen);
        if (refValues != null && refValues.size() > 1) {
            double[] annotations = new double[refValues.size()];
            for (int n = 0; n < refValues.size(); n++) {
                annotations[n] = Math.log(((Number) refValues.get(n)).doubleValue()) / Math.log(2);
            }
            greenGainSlider.setAnnotations(annotations);
            greenGainSlider.setMultivalued(true);
        } else {
            greenGainSlider.setAnnotations(null);
            greenGainSlider.setMultivalued(false);
        }
    }

    public void setRawGreenGainMultivalued(boolean multivalued, Object[] values) {
        if (values != null && values.length > 1) {
            double[] annotations = new double[values.length];
            for (int n = 0; n < values.length; n++) {
                annotations[n] = Math.log(((Number) values[n]).doubleValue()) / Math.log(2);
            }
            greenGainSlider.setAnnotations(annotations);
        } else {
            // restore the normal label table without any extra annotations
            greenGainSlider.setAnnotations(null);
        }
        greenGainSlider.setMultivalued(multivalued);
    }

    public double getRawGreenGain() {
        double greenEv = greenGainSlider.getValue();
        double green = Math.pow(2, greenEv);
        return green;
    }

    ColorProfileDesc profile = null;

    public void setRawProfile(ColorProfileDesc p) {
        profile = p;
        // setupColorProfile();
    }

    public void setRawProfile(ColorProfileDesc p, List refValues) {
        profile = p;
        // setupColorProfile();
    }

    public void setRawProfileMultivalued(boolean multivalued, Object[] values) {
    }

    public ColorProfileDesc getRawProfile() {
        return profile;
    }

    public void setColorChannelCurve(String name, ColorCurve curve) {
        for (int n = 0; n < colorCurveNames.length; n++) {
            if (colorCurveNames[n].equals(name)) {
                colorCurves[n] = curve;
                refCurves[n] = null;
                showCurve(currentColorCurve);
                break;
            }
        }
    }

    /**
     Set new value for a color channel curve
     @param name Name of the curve to set
     @param curve The new curve
     @param refCurves Reference curves to show in the background     
     */
    public void setColorChannelCurve(String name, ColorCurve curve, List refCurves) {
        for (int n = 0; n < colorCurveNames.length; n++) {
            if (colorCurveNames[n].equals(name)) {
                colorCurves[n] = curve;
                this.refCurves[n] = refCurves;
                showCurve(currentColorCurve);
                break;
            }
        }
    }

    /**
     @deprecated
     */
    public void setColorChannelMultivalued(String name, boolean isMultivalued, ColorCurve[] values) {
        for (int n = 0; n < colorCurveNames.length; n++) {
            if (colorCurveNames[n].equals(name)) {
                if (isMultivalued) {
                    ArrayList<ColorCurve> curves = new ArrayList<ColorCurve>(values.length);
                    for (ColorCurve c : values) {
                        curves.add(c);
                    }
                    refCurves[n] = curves;
                    if (currentColorCurve == n) {
                        showCurve(n);
                    }

                }
                break;
            }
        }

    }

    /**
     Get current value of a color channel curve
     @param name Name of the curve
     @return Current curve for the channel or <code>null</code> if not specified.
     */
    public ColorCurve getColorChannelCurve(String name) {
        ColorCurve ret = null;
        for (int n = 0; n < colorCurveNames.length; n++) {
            if (colorCurveNames[n].equals(name)) {
                ret = colorCurves[n];
                break;
            }
        }
        return ret;
    }

    /**
     Get reference curves displayed for channel
     @param name Name of the channel
     @return Reference curves displayed for a channel or <code>null</code> if 
     no reference curves are displayed-
     */
    public List getRefCurves(String channel) {
        List ret = null;
        for (int n = 0; n < colorCurveNames.length; n++) {
            if (colorCurveNames[n].equals(channel)) {
                ret = refCurves[n];
                break;
            }
        }
        return ret;
    }

    /**
     @deprecated
     */
    private void annotateSlider(FieldSliderCombo slider, Object[] values) {
        double[] annotations = new double[values.length];
        for (int n = 0; n < values.length; n++) {
            annotations[n] = ((Number) values[n]).doubleValue();
        }
        slider.setAnnotations(annotations);
    }

    /**
     Annotate a slider with given values
     @param slider The slider to annotate
     @param values Annotation values. Note! Cannot be null!!
     */
    private void annotateSlider(FieldSliderCombo slider, List values) {
        double[] annotations = new double[values.size()];
        for (int n = 0; n < values.size(); n++) {
            annotations[n] = ((Number) values.get(n)).doubleValue();
        }
        slider.setAnnotations(annotations);
    }

    /**
     This callback is called by JAIPhotoViewer when the image displayed in the 
     control is changed.
     */
    public void photoViewChanged(PhotoViewChangeEvent e) {
        reloadHistogram();
    }

    PhotovaultImage previewImage = null;

    /**
     Called when preview image in some view associated with this controller changes.
     */
    public void modelPreviewImageChanged(PhotovaultImage preview) {
        if (previewImage != null) {
            previewImage.removeRenderingListener(this);
        }
        previewImage = preview;
        setupColorCurvesForImage();
    }

    public PhotovaultImage getPreviewImage() {
        return previewImage;
    }

    /**
     A new rendering of current image is created. Update color curves based on it.     
     */
    public void newRenderingCreated(PhotovaultImage img) {
        img.removeRenderingListener(this);
        if (img == previewImage) {
            setupColorCurvesForImage();
        }
    }

    private void setupColorCurvesForImage() {
        if (previewImage != null) {
            ColorModel cm = previewImage.getCorrectedImageColorModel();
            if (cm != null) {
                setColorChannelCurvesEnabled(cm.getNumColorComponents() >= 3);
            } else {
                /*
                 The image has not yet been rendered. Register a listener so that 
                 we can complete setup after rendering the image
                 */
                previewImage.addRenderingListener(this);
            }
        }
        // Update color curves with histogram data from this image.
        showCurve(currentColorCurve);
    }

    public void setField(PhotoInfoFields field, Object newValue) {
        // TODO: implement
    }

    public void setFieldMultivalued(PhotoInfoFields field, boolean isMultivalued) {
        // TODO: implement
    }

    public Object getField(PhotoInfoFields field) {
        // TODO: Implement
        return null;
    }

    public void setField(PhotoInfoFields field, Object newValue, List refValues) {
        switch (field) {
        case COLOR_CURVE_VALUE:
            this.setColorChannelCurve("value", (ColorCurve) newValue, refValues);
            break;
        case COLOR_CURVE_SATURATION:
            this.setColorChannelCurve("saturation", (ColorCurve) newValue, refValues);
            break;
        case COLOR_CURVE_RED:
            this.setColorChannelCurve("red", (ColorCurve) newValue, refValues);
            break;
        case COLOR_CURVE_GREEN:
            this.setColorChannelCurve("green", (ColorCurve) newValue, refValues);
            break;
        case COLOR_CURVE_BLUE:
            this.setColorChannelCurve("blue", (ColorCurve) newValue, refValues);
            break;
        case RAW_BLACK_LEVEL:
            setRawBlack(newValue != null ? ((Number) newValue).intValue() : 0, refValues);
            break;
        case RAW_WHITE_LEVEL:
            setRawWhite(newValue != null ? ((Number) newValue).intValue() : 0, refValues);
            break;
        case RAW_CTEMP:
            setRawColorTemp(newValue != null ? ((Number) newValue).doubleValue() : 0, refValues);
            break;
        case RAW_EV_CORR:
            setRawEvCorr(newValue != null ? ((Number) newValue).doubleValue() : 0, refValues);
            break;
        case RAW_GREEN:
            setRawGreenGain(newValue != null ? ((Number) newValue).doubleValue() : 0, refValues);
            break;
        case RAW_HLIGHT_COMP:
            setRawHlightComp(newValue != null ? ((Number) newValue).doubleValue() : 0, refValues);
            break;
        case RAW_HLIGHT_RECOVERY:
            setRawHlightRecovery(newValue != null ? ((Number) newValue).intValue() : 0, refValues);
            break;
        case RAW_WAVELET_DENOISE_THRESHOLD:
            setRawWaveletDenoiseThreshold(newValue != null ? ((Number) newValue).floatValue() : 0, refValues);
            break;
        case RAW_COLOR_PROFILE:
            setRawProfile((ColorProfileDesc) newValue, refValues);
            break;
        default:
            // No action for other fields
            break;
        }
    }

    /**
     * Histograms for each color channel
     */
    Map<String, int[]> histograms = new HashMap<String, int[]>();

    /**
     * Set histogram displayed for a certain channel
     * @param channel Name of the color channel
     * @param histData Array of values for each histogram bin
     */
    public void setHistogram(String channel, int[] histData) {
        if (histData == null) {
            histograms.remove(channel);
        } else {
            histograms.put(channel, histData);
        }

        if (colorCurveNames[currentColorCurve].equals(channel)) {
            showCurve(currentColorCurve);
        }
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton applyBtn;
    private org.photovault.swingui.color.FieldSliderCombo blackLevelSlider;
    private javax.swing.JButton closeBtn;
    private org.photovault.swingui.color.ColorCurvePanel colorCurvePanel1;
    private javax.swing.JComboBox colorCurveSelectionCombo;
    private javax.swing.JPanel colorSettingControls;
    private javax.swing.JTabbedPane colorSettingTabs;
    private org.photovault.swingui.color.FieldSliderCombo ctempSlider;
    private javax.swing.JButton discardBtn;
    private javax.swing.JPanel dlgControlPane;
    private org.photovault.swingui.color.FieldSliderCombo evCorrSlider;
    private org.photovault.swingui.color.FieldSliderCombo fieldSliderCombo1;
    private org.photovault.swingui.color.FieldSliderCombo fieldSliderCombo2;
    private org.photovault.swingui.color.FieldSliderCombo greenGainSlider;
    private org.photovault.swingui.color.FieldSliderCombo hlightCompSlider;
    private org.photovault.swingui.color.FieldSliderCombo hlightRecoverySlider;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JButton okBtn;
    private javax.swing.JPanel rawControlsPane;
    private javax.swing.JPanel rawHistogramPane;
    private org.photovault.swingui.color.FieldSliderCombo waveletDenoiseSlider;
    private org.photovault.swingui.color.FieldSliderCombo whiteLevelSlider;
    // End of variables declaration//GEN-END:variables

}