/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2015, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotoolkit.gui.javafx.layer;
import java.awt.geom.AffineTransform;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.logging.Level;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.layout.GridPane;
import javafx.util.StringConverter;
import org.apache.sis.internal.referencing.j2d.AffineTransform2D;
import org.geotoolkit.coverage.amended.AmendedCoverageReference;
import org.geotoolkit.coverage.io.CoverageStoreException;
import org.geotoolkit.gui.javafx.crs.FXCRSButton;
import org.geotoolkit.internal.GeotkFX;
import org.geotoolkit.internal.Loggers;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
/**
*
* @author Johann Sorel (Geomatys)
*/
public class FXCoverageDecoratorPane extends GridPane {
private static final StringConverter CVT =new StringConverter<Double>() {
private final DecimalFormat df = new DecimalFormat("#.#########");
@Override
public synchronized String toString(Double value) {
if (value == null) {
return "";
}
return df.format(value);
}
@Override
public synchronized Double fromString(String value) {
try {
if (value == null) {
return null;
}
value = value.trim();
if (value.length() < 1) {
return null;
}
return df.parse(value).doubleValue();
} catch (ParseException ex) {
throw new RuntimeException(ex);
}
}
};
@FXML private GridPane uiTrsPane;
@FXML private CheckBox uiCrs;
@FXML private CheckBox uiGridToCrs;
private final FXCRSButton crsButton = new FXCRSButton();
private final Spinner<Double> uiScaleX = new Spinner<>(new SpinnerValueFactory.DoubleSpinnerValueFactory(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0, 1.0));
private final Spinner<Double> uiScaleY = new Spinner<>(new SpinnerValueFactory.DoubleSpinnerValueFactory(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0, 1.0));
private final Spinner<Double> uiShearX = new Spinner<>(new SpinnerValueFactory.DoubleSpinnerValueFactory(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 0.0, 1.0));
private final Spinner<Double> uiShearY = new Spinner<>(new SpinnerValueFactory.DoubleSpinnerValueFactory(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 0.0, 1.0));
private final Spinner<Double> uiTranslateX = new Spinner<>(new SpinnerValueFactory.DoubleSpinnerValueFactory(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 0.0, 1.0));
private final Spinner<Double> uiTranslateY = new Spinner<>(new SpinnerValueFactory.DoubleSpinnerValueFactory(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 0.0, 1.0));
private final AmendedCoverageReference decoratedRef;
public FXCoverageDecoratorPane(AmendedCoverageReference ref) {
GeotkFX.loadJRXML(this, FXCoverageDecoratorPane.class);
this.decoratedRef = ref;
add(crsButton, 0, 1, 2, 1);
uiTrsPane.add(uiScaleX, 1, 0);
uiTrsPane.add(uiScaleY, 1, 1);
uiTrsPane.add(uiShearX, 3, 0);
uiTrsPane.add(uiShearY, 3, 1);
uiTrsPane.add(uiTranslateX, 5, 0);
uiTrsPane.add(uiTranslateY, 5, 1);
uiScaleX.setEditable(true);
uiScaleY.setEditable(true);
uiScaleX.setEditable(true);
uiShearX.setEditable(true);
uiShearY.setEditable(true);
uiTranslateX.setEditable(true);
uiTranslateY.setEditable(true);
uiScaleX.getValueFactory().setConverter(CVT);
uiScaleY.getValueFactory().setConverter(CVT);
uiShearX.getValueFactory().setConverter(CVT);
uiShearY.getValueFactory().setConverter(CVT);
uiTranslateX.getValueFactory().setConverter(CVT);
uiTranslateY.getValueFactory().setConverter(CVT);
uiTrsPane.disableProperty().bind(uiGridToCrs.selectedProperty().not());
crsButton.disableProperty().bind(uiCrs.selectedProperty().not());
ChangeListener<Boolean> lst = (s, ov, nv) -> {
if (nv) return;
commitEditorText(uiScaleX);
commitEditorText(uiScaleY);
commitEditorText(uiShearX);
commitEditorText(uiShearY);
commitEditorText(uiTranslateX);
commitEditorText(uiTranslateY);
};
uiScaleX.focusedProperty().addListener(lst);
uiScaleY.focusedProperty().addListener(lst);
uiShearX.focusedProperty().addListener(lst);
uiShearY.focusedProperty().addListener(lst);
uiTranslateX.focusedProperty().addListener(lst);
uiTranslateY.focusedProperty().addListener(lst);
updateFields();
}
private void updateFields(){
CoordinateReferenceSystem crs = decoratedRef.getOverrideCRS();
uiCrs.setSelected(crs!=null);
if(crs==null){
try {
crs = decoratedRef.getGridGeometry(decoratedRef.getImageIndex()).getCoordinateReferenceSystem();
} catch (CoverageStoreException ex) {
Loggers.JAVAFX.log(Level.FINE, ex.getMessage(), ex);
}
}
crsButton.crsProperty().set(crs);
MathTransform overrideGridToCrs = decoratedRef.getOverrideGridToCrs();
uiGridToCrs.setSelected(overrideGridToCrs!=null);
if(overrideGridToCrs==null){
try {
overrideGridToCrs = decoratedRef.getGridGeometry(decoratedRef.getImageIndex()).getGridToCRS();
} catch (CoverageStoreException ex) {
Loggers.JAVAFX.log(Level.FINE, ex.getMessage(), ex);
}
}
if(overrideGridToCrs instanceof AffineTransform){
final AffineTransform aff = (AffineTransform) overrideGridToCrs;
uiScaleX.getValueFactory().setValue(aff.getScaleX());
uiScaleY.getValueFactory().setValue(aff.getScaleY());
uiShearX.getValueFactory().setValue(aff.getShearX());
uiShearY.getValueFactory().setValue(aff.getShearY());
uiTranslateX.getValueFactory().setValue(aff.getTranslateX());
uiTranslateY.getValueFactory().setValue(aff.getTranslateY());
}else{
uiScaleX.getValueFactory().setValue(1.0);
uiScaleY.getValueFactory().setValue(1.0);
uiShearX.getValueFactory().setValue(0.0);
uiShearY.getValueFactory().setValue(0.0);
uiTranslateX.getValueFactory().setValue(0.0);
uiTranslateY.getValueFactory().setValue(0.0);
}
}
@FXML
void resetCrs(ActionEvent event) {
decoratedRef.setOverrideCRS(null);
CoordinateReferenceSystem crs = null;
uiCrs.setSelected(false);
try {
crs = decoratedRef.getGridGeometry(decoratedRef.getImageIndex()).getCoordinateReferenceSystem();
} catch (CoverageStoreException ex) {
Loggers.JAVAFX.log(Level.FINE, ex.getMessage(), ex);
}
crsButton.crsProperty().set(crs);
}
@FXML
void resetGridToCrs(ActionEvent event) {
decoratedRef.setOverrideGridToCrs(null);
MathTransform overrideGridToCrs = null;
uiGridToCrs.setSelected(false);
try {
overrideGridToCrs = decoratedRef.getGridGeometry(decoratedRef.getImageIndex()).getGridToCRS();
} catch (CoverageStoreException ex) {
Loggers.JAVAFX.log(Level.FINE, ex.getMessage(), ex);
}
if(overrideGridToCrs instanceof AffineTransform){
final AffineTransform aff = (AffineTransform) overrideGridToCrs;
uiScaleX.getValueFactory().setValue(aff.getScaleX());
uiScaleY.getValueFactory().setValue(aff.getScaleY());
uiShearX.getValueFactory().setValue(aff.getShearX());
uiShearY.getValueFactory().setValue(aff.getShearY());
uiTranslateX.getValueFactory().setValue(aff.getTranslateX());
uiTranslateY.getValueFactory().setValue(aff.getTranslateY());
}else{
uiScaleX.getValueFactory().setValue(1.0);
uiScaleY.getValueFactory().setValue(1.0);
uiShearX.getValueFactory().setValue(0.0);
uiShearY.getValueFactory().setValue(0.0);
uiTranslateX.getValueFactory().setValue(0.0);
uiTranslateY.getValueFactory().setValue(0.0);
}
}
@FXML
void apply(ActionEvent event) {
if(uiCrs.isSelected()){
decoratedRef.setOverrideCRS(crsButton.crsProperty().get());
}else{
decoratedRef.setOverrideCRS(null);
}
if(uiGridToCrs.isSelected()){
final AffineTransform2D gridToCrs = new AffineTransform2D(
uiScaleX.getValue(),
uiShearY.getValue(),
uiShearX.getValue(),
uiScaleY.getValue(),
uiTranslateX.getValue(),
uiTranslateY.getValue());
decoratedRef.setOverrideGridToCrs(gridToCrs);
}else{
decoratedRef.setOverrideGridToCrs(null);
}
}
private <T> void commitEditorText(Spinner<T> spinner) {
if (!spinner.isEditable()) return;
String text = spinner.getEditor().getText();
SpinnerValueFactory<T> valueFactory = spinner.getValueFactory();
if (valueFactory != null) {
StringConverter<T> converter = valueFactory.getConverter();
if (converter != null) {
T value = converter.fromString(text);
valueFactory.setValue(value);
}
}
}
}