/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* 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 3 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.snap.rcp.colormanip;
import com.bc.ceres.swing.TableLayout;
import org.esa.snap.core.datamodel.ColorPaletteDef;
import org.esa.snap.core.datamodel.ImageInfo;
import org.esa.snap.core.datamodel.ProductNodeEvent;
import org.esa.snap.core.datamodel.RasterDataNode;
import org.esa.snap.core.datamodel.Stx;
import org.esa.snap.core.util.math.Range;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.text.NumberFormatter;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
class Continuous1BandBasicForm implements ColorManipulationChildForm {
private final ColorManipulationForm parentForm;
private final JPanel contentPanel;
private final AbstractButton logDisplayButton;
private final MoreOptionsForm moreOptionsForm;
private final ColorPaletteChooser colorPaletteChooser;
private final JFormattedTextField minField;
private final JFormattedTextField maxField;
private final DiscreteCheckBox discreteCheckBox;
private enum RangeKey {FromPaletteSource, FromData, FromMinMaxFields, FromCurrentPalette}
private boolean shouldFireChooserEvent;
private boolean hidden = false;
Continuous1BandBasicForm(final ColorManipulationForm parentForm) {
ColorPaletteManager.getDefault().loadAvailableColorPalettes(parentForm.getIODir().toFile());
this.parentForm = parentForm;
final TableLayout layout = new TableLayout();
layout.setTableWeightX(1.0);
layout.setTableWeightY(1.0);
layout.setTablePadding(2, 2);
layout.setTableFill(TableLayout.Fill.HORIZONTAL);
layout.setTableAnchor(TableLayout.Anchor.NORTH);
layout.setCellPadding(0, 0, new Insets(8, 2, 2, 2));
layout.setCellPadding(2, 0, new Insets(13, 2, 5, 2));
final JPanel editorPanel = new JPanel(layout);
editorPanel.add(new JLabel("Colour ramp:"));
colorPaletteChooser = new ColorPaletteChooser();
editorPanel.add(colorPaletteChooser);
editorPanel.add(new JLabel("Display range"));
minField = getNumberTextField(0.00001);
maxField = getNumberTextField(1);
final JPanel minPanel = new JPanel(new BorderLayout(5, 2));
minPanel.add(new JLabel("Min:"), BorderLayout.WEST);
minPanel.add(minField, BorderLayout.SOUTH);
final JPanel maxPanel = new JPanel(new BorderLayout(5, 2));
maxPanel.add(new JLabel("Max:"), BorderLayout.EAST);
maxPanel.add(maxField, BorderLayout.SOUTH);
final JPanel minMaxPanel = new JPanel(new BorderLayout(5, 5));
minMaxPanel.add(minPanel, BorderLayout.WEST);
minMaxPanel.add(maxPanel, BorderLayout.EAST);
editorPanel.add(minMaxPanel);
final JButton fromFile = new JButton("Range from File");
final JButton fromData = new JButton("Range from Data");
final JPanel buttonPanel = new JPanel(new BorderLayout(5, 10));
buttonPanel.add(fromFile, BorderLayout.WEST);
buttonPanel.add(fromData, BorderLayout.EAST);
editorPanel.add(new JLabel(" "));
editorPanel.add(buttonPanel);
shouldFireChooserEvent = true;
colorPaletteChooser.addActionListener(createListener(RangeKey.FromCurrentPalette));
minField.addActionListener(createListener(RangeKey.FromMinMaxFields));
maxField.addActionListener(createListener(RangeKey.FromMinMaxFields));
fromFile.addActionListener(createListener(RangeKey.FromPaletteSource));
fromData.addActionListener(createListener(RangeKey.FromData));
contentPanel = new JPanel(new BorderLayout());
contentPanel.add(editorPanel, BorderLayout.NORTH);
moreOptionsForm = new MoreOptionsForm(this, parentForm.getFormModel().canUseHistogramMatching());
discreteCheckBox = new DiscreteCheckBox(parentForm);
moreOptionsForm.addRow(discreteCheckBox);
parentForm.getFormModel().modifyMoreOptionsForm(moreOptionsForm);
logDisplayButton = LogDisplay.createButton();
logDisplayButton.addActionListener(e -> {
final boolean shouldLog10Display = logDisplayButton.isSelected();
final ImageInfo imageInfo = parentForm.getFormModel().getModifiedImageInfo();
if (shouldLog10Display) {
final ColorPaletteDef cpd = imageInfo.getColorPaletteDef();
if (LogDisplay.checkApplicability(cpd)) {
colorPaletteChooser.setLog10Display(true);
imageInfo.setLogScaled(true);
parentForm.applyChanges();
} else {
LogDisplay.showNotApplicableInfo(parentForm.getContentPanel());
logDisplayButton.setSelected(false);
}
} else {
colorPaletteChooser.setLog10Display(false);
imageInfo.setLogScaled(false);
parentForm.applyChanges();
}
});
}
@Override
public Component getContentPanel() {
return contentPanel;
}
@Override
public ColorManipulationForm getParentForm() {
return parentForm;
}
@Override
public void handleFormShown(FormModel formModel) {
hidden = false;
updateFormModel(formModel);
}
@Override
public void handleFormHidden(FormModel formModel) {
hidden = true;
}
@Override
public void updateFormModel(FormModel formModel) {
if (!hidden) {
ColorPaletteManager.getDefault().loadAvailableColorPalettes(parentForm.getIODir().toFile());
colorPaletteChooser.reloadPalettes();
}
final ImageInfo imageInfo = formModel.getOriginalImageInfo();
final ColorPaletteDef cpd = imageInfo.getColorPaletteDef();
final boolean logScaled = imageInfo.isLogScaled();
final boolean discrete = cpd.isDiscrete();
colorPaletteChooser.setLog10Display(logScaled);
colorPaletteChooser.setDiscreteDisplay(discrete);
shouldFireChooserEvent = false;
colorPaletteChooser.setSelectedColorPaletteDefinition(cpd);
shouldFireChooserEvent = true;
discreteCheckBox.setDiscreteColorsMode(discrete);
logDisplayButton.setSelected(logScaled);
parentForm.revalidateToolViewPaneControl();
minField.setValue(cpd.getMinDisplaySample());
maxField.setValue(cpd.getMaxDisplaySample());
}
@Override
public void resetFormModel(FormModel formModel) {
updateFormModel(formModel);
parentForm.revalidateToolViewPaneControl();
}
@Override
public void handleRasterPropertyChange(ProductNodeEvent event, RasterDataNode raster) {
if (event.getPropertyName().equals(RasterDataNode.PROPERTY_NAME_STX)) {
updateFormModel(parentForm.getFormModel());
}
}
@Override
public RasterDataNode[] getRasters() {
return parentForm.getFormModel().getRasters();
}
@Override
public MoreOptionsForm getMoreOptionsForm() {
return moreOptionsForm;
}
@Override
public AbstractButton[] getToolButtons() {
return new AbstractButton[]{
logDisplayButton,
};
}
private ActionListener createListener(final RangeKey key) {
return e -> applyChanges(key);
}
private JFormattedTextField getNumberTextField(double value) {
final NumberFormatter formatter = new NumberFormatter(new DecimalFormat("0.0############"));
formatter.setValueClass(Double.class); // to ensure that double values are returned
final JFormattedTextField numberField = new JFormattedTextField(formatter);
numberField.setValue(value);
final Dimension preferredSize = numberField.getPreferredSize();
preferredSize.width = 70;
numberField.setPreferredSize(preferredSize);
return numberField;
}
private void applyChanges(RangeKey key) {
if (shouldFireChooserEvent) {
final ColorPaletteDef selectedCPD = colorPaletteChooser.getSelectedColorPaletteDefinition();
final ImageInfo currentInfo = parentForm.getFormModel().getModifiedImageInfo();
final ColorPaletteDef currentCPD = currentInfo.getColorPaletteDef();
final ColorPaletteDef deepCopy = selectedCPD.createDeepCopy();
deepCopy.setDiscrete(currentCPD.isDiscrete());
final double min;
final double max;
final ColorPaletteDef cpd;
switch (key) {
case FromPaletteSource:
final Range rangeFromFile = colorPaletteChooser.getRangeFromFile();
min = rangeFromFile.getMin();
max = rangeFromFile.getMax();
cpd = currentCPD;
break;
case FromData:
final Stx stx = parentForm.getStx(parentForm.getFormModel().getRaster());
min = stx.getMinimum();
max = stx.getMaximum();
cpd = currentCPD;
break;
case FromMinMaxFields:
min = (double) minField.getValue();
max = (double) maxField.getValue();
cpd = currentCPD;
break;
default:
min = currentCPD.getMinDisplaySample();
max = currentCPD.getMaxDisplaySample();
cpd = deepCopy;
}
final boolean autoDistribute = true;
currentInfo.setColorPaletteDef(cpd, min, max, autoDistribute);
parentForm.applyChanges();
}
}
}