/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2014, 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.style.graduation;
import java.util.List;
import java.util.function.Function;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import org.geotoolkit.display2d.ext.graduation.GraduationSymbolizer;
import org.geotoolkit.display2d.ext.graduation.GraduationSymbolizer.Graduation;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.image.ImageView;
import javafx.util.Callback;
import org.geotoolkit.gui.javafx.style.FXStyleElementController;
import org.geotoolkit.gui.javafx.util.ButtonTableCell;
import org.geotoolkit.gui.javafx.util.FXUtilities;
import org.geotoolkit.internal.GeotkFX;
/**
*
* @author Johann Sorel (Geomatys)
*/
public class FXGraduationSymbolizer extends FXStyleElementController<GraduationSymbolizer> {
@FXML
private TableView<Graduation> uiTable;
@FXML
private SplitPane uiSplit;
private FXGraduation uiGraduation;
private boolean updatingSubEditor = false;
@FXML
void addGraduation(ActionEvent event) {
final Graduation graduation = new Graduation();
uiTable.getItems().add(graduation);
}
@Override
public Class<GraduationSymbolizer> getEditedClass() {
return GraduationSymbolizer.class;
}
@Override
public GraduationSymbolizer newValue() {
return new GraduationSymbolizer();
}
@Override
public void initialize() {
super.initialize();
uiGraduation = new FXGraduation();
uiGraduation.visibleProperty().bind(uiTable.getSelectionModel().selectedItemProperty().isNotNull());
uiGraduation.managedProperty().bind(uiGraduation.visibleProperty());
final ScrollPane scrollPane = new ScrollPane(uiGraduation);
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);
uiSplit.getItems().add(scrollPane);
uiTable.setEditable(true);
uiTable.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
uiTable.getSelectionModel().getSelectedItems().addListener(new ListChangeListener<Graduation>() {
@Override
public void onChanged(ListChangeListener.Change<? extends Graduation> c) {
if(updatingSubEditor) return;
final Graduation graduation = uiTable.getSelectionModel().getSelectedItem();
if(graduation!=null){
uiGraduation.valueProperty().set(graduation);
}
}
});
FXUtilities.hideTableHeader(uiTable);
uiGraduation.valueProperty().addListener(new ChangeListener<Graduation>() {
@Override
public void changed(ObservableValue<? extends Graduation> observable, Graduation oldValue, Graduation newValue) {
if(updating) return;
final List<TablePosition> cells = uiTable.getSelectionModel().getSelectedCells();
final int index = cells.isEmpty() ? -1 : cells.get(0).getRow();
if(index>=0 && newValue!=null){
updatingSubEditor = true;
uiTable.getItems().set(index, newValue);
uiTable.getSelectionModel().clearAndSelect(index);
updatingSubEditor = false;
}
}
});
final TableColumn<Graduation,String> nameCol = new TableColumn<>();
nameCol.setEditable(false);
nameCol.setMinWidth(100);
nameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Graduation, String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<Graduation, String> param) {
final Graduation graduation = param.getValue();
return new SimpleObjectProperty<>(String.valueOf(graduation.getStep()));
}
});
final TableColumn<Graduation,Graduation> deleteCol = new TableColumn<>();
deleteCol.setEditable(true);
deleteCol.setPrefWidth(30);
deleteCol.setMinWidth(30);
deleteCol.setMaxWidth(30);
deleteCol.setCellValueFactory((TableColumn.CellDataFeatures<Graduation, Graduation> param) -> new SimpleObjectProperty<>((Graduation)param.getValue()));
deleteCol.setCellFactory((TableColumn<Graduation, Graduation> p) -> new DeleteButton());
uiTable.getColumns().add(nameCol);
uiTable.getColumns().add(deleteCol);
uiTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
uiTable.setTableMenuButtonVisible(false);
}
@Override
protected void updateEditor(GraduationSymbolizer styleElement) {
uiTable.getSelectionModel().clearSelection();
uiTable.setItems(FXCollections.observableArrayList(styleElement.getGraduations()));
uiTable.getItems().addListener(new ListChangeListener<Graduation>() {
@Override
public void onChanged(ListChangeListener.Change<? extends Graduation> c) {
if(updating) return;
final GraduationSymbolizer symbolizer = new GraduationSymbolizer();
symbolizer.getGraduations().addAll(uiTable.getItems());
value.set(symbolizer);
}
});
}
private class DeleteButton extends ButtonTableCell<Graduation, Graduation>{
public DeleteButton() {
super(false, new ImageView(GeotkFX.ICON_DELETE), null,
//JavaFX bug : do not use lambda here : java.lang.VerifyError: Bad type on operand stack->invokedynamic
new Function<Graduation,Graduation>() {
public Graduation apply(Graduation t) {
uiTable.getItems().remove(t);
return t;
}
});
}
}
}