/* * 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.parameter; import java.util.Collection; import java.util.Optional; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Pos; import javafx.scene.control.ContentDisplay; import javafx.scene.control.RadioButton; import javafx.scene.control.ScrollPane; import javafx.scene.control.Tooltip; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeTableCell; import javafx.scene.control.TreeTableColumn; import javafx.scene.control.TreeTableView; import javafx.scene.layout.BorderPane; import javafx.util.Callback; import org.geotoolkit.utility.parameter.ParametersExt; import org.opengis.parameter.GeneralParameterDescriptor; import org.opengis.parameter.GeneralParameterValue; import org.opengis.parameter.ParameterDescriptor; import org.opengis.parameter.ParameterDescriptorGroup; import org.opengis.parameter.ParameterValue; import org.opengis.parameter.ParameterValueGroup; import org.opengis.util.GenericName; import org.opengis.util.InternationalString; /** * * @author Johann Sorel (Geomatys) */ public class FXParameterEditor extends BorderPane { private final TreeTableView treetable = new TreeTableView(); private ParameterValueGroup parameter; public FXParameterEditor() { //this will cause the column width to fit the view area treetable.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY); treetable.getStylesheets().add("org/geotoolkit/gui/javafx/parameter/parameters.css"); final ScrollPane scroll = new ScrollPane(treetable); scroll.setFitToWidth(true); scroll.setFitToHeight(true); setCenter(scroll); treetable.getColumns().add(new ParamEnableColumn()); treetable.getColumns().add(new ParamNameColumn()); treetable.getColumns().add(new ParamValueColumn()); setPrefSize(300, 300); setMinSize(250, 250); } public TreeTableView getTreetable() { return treetable; } public void setParameter(ParameterValueGroup parameter) { this.parameter = parameter; treetable.setRoot(toTree(null, parameter.getDescriptor(), parameter)); treetable.setShowRoot(false); } public ParameterValueGroup getParameter() { return parameter; } private TreeItem toTree(ParameterValueGroup parent, GeneralParameterDescriptor desc, GeneralParameterValue parameter){ final TreeItem<ParamEntry> root = new TreeItem<>(new ParamEntry(parent,desc,parameter)); if(parameter!=null && desc instanceof ParameterDescriptorGroup){ final ParameterDescriptorGroup descGroup = (ParameterDescriptorGroup) desc; final ParameterValueGroup group = (ParameterValueGroup) parameter; for(GeneralParameterDescriptor childDesc : descGroup.descriptors()){ //TODO , handle multiplicity if(childDesc.getMaximumOccurs()>1) continue; GeneralParameterValue childVal = ParametersExt.getParameter(group, childDesc.getName().getCode()); if(childVal==null && childDesc.getMinimumOccurs()>0){ childVal = ParametersExt.getOrCreateParameter(group, childDesc.getName().getCode()); } final TreeItem item = toTree(group, childDesc, childVal); root.getChildren().add(item); } } return root; } private static class ParamEntry { public ParameterValueGroup parent; public GeneralParameterDescriptor desc; public final SimpleObjectProperty<GeneralParameterValue> value; public ParamEntry(ParameterValueGroup parent, GeneralParameterDescriptor desc, GeneralParameterValue value) { this.parent = parent; this.desc = desc; this.value = new SimpleObjectProperty<>(value); } } public class ParamNameColumn extends TreeTableColumn<ParamEntry,ParamEntry>{ public ParamNameColumn() { super("Property"); setCellValueFactory((CellDataFeatures<ParamEntry, ParamEntry> param) -> new SimpleObjectProperty<>(param.getValue().getValue())); setCellFactory((TreeTableColumn<ParamEntry, ParamEntry> param) -> new ParamNameCell()); setEditable(false); setPrefWidth(200); setMinWidth(120); } } public class ParamValueColumn extends TreeTableColumn<ParamEntry,GeneralParameterValue>{ public ParamValueColumn() { super("Value"); setCellValueFactory(new Callback<CellDataFeatures<ParamEntry, GeneralParameterValue>, ObservableValue<GeneralParameterValue>>() { @Override public ObservableValue<GeneralParameterValue> call(CellDataFeatures<ParamEntry, GeneralParameterValue> param) { return param.getValue().getValue().value; } }); setCellFactory((TreeTableColumn<ParamEntry, GeneralParameterValue> param) -> new ParamValueCell()); setEditable(true); setPrefWidth(200); setMinWidth(120); } } public class ParamEnableColumn extends TreeTableColumn<ParamEntry,GeneralParameterValue>{ public ParamEnableColumn() { super(""); setCellValueFactory(new Callback<CellDataFeatures<ParamEntry, GeneralParameterValue>, ObservableValue<GeneralParameterValue>>() { @Override public ObservableValue<GeneralParameterValue> call(CellDataFeatures<ParamEntry, GeneralParameterValue> param) { return param.getValue().getValue().value; } }); setCellFactory((TreeTableColumn<ParamEntry, GeneralParameterValue> param) -> new ParamEnableCell()); setEditable(true); setPrefWidth(30); setMinWidth(30); setMaxWidth(30); } } private class ParamNameCell extends TreeTableCell<ParamEntry, ParamEntry>{ @Override protected void updateItem(ParamEntry item, boolean empty) { super.updateItem(item, empty); setText(null); setGraphic(null); setTooltip(null); setAlignment(Pos.CENTER_LEFT); if(!empty && item !=null){ final GeneralParameterDescriptor desc = item.desc; //get name from alias String name = null; final Collection<GenericName> aliases = desc.getAlias(); if(!aliases.isEmpty()){ final GenericName alias = aliases.iterator().next(); name = alias.toInternationalString().toString(); } //use code if not defined if(name == null){ name = desc.getName().getCode(); } setText(name); final InternationalString remarks = desc.getRemarks(); if(remarks!=null){ setTooltip(new Tooltip(remarks.toString())); } } } } private class ParamValueCell extends TreeTableCell<ParamEntry, GeneralParameterValue>{ public ParamValueCell() { setAlignment(Pos.CENTER_LEFT); setContentDisplay(ContentDisplay.GRAPHIC_ONLY); } @Override protected void updateItem(GeneralParameterValue item, boolean empty) { super.updateItem(item, empty); final ParamEntry entry = getTreeTableRow().getItem(); setText(null); setGraphic(null); if (!empty && entry != null && entry.value.getValue() != null && entry.desc instanceof ParameterDescriptor) { Optional<FXValueEditor> opt = FXValueEditorSpi.findEditor((ParameterDescriptor) entry.desc); if (opt.isPresent()) { final FXValueEditor valEditor = opt.get(); final ParameterValue pval = (ParameterValue) entry.value.getValue(); if(pval.getValue()!=null) valEditor.valueProperty().setValue(pval.getValue()); valEditor.valueProperty().addListener((ObservableValue observable, Object oldValue, Object newValue) -> { pval.setValue(newValue); }); setGraphic(valEditor.getComponent()); } } } } private class ParamEnableCell extends TreeTableCell<ParamEntry, GeneralParameterValue>{ private final RadioButton cb = new RadioButton(); public ParamEnableCell() { setAlignment(Pos.CENTER); setContentDisplay(ContentDisplay.GRAPHIC_ONLY); cb.setSelected(false); cb.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { final ParamEntry entry = getTreeTableRow().getItem(); if(entry!=null){ if(cb.isSelected()){ if(entry.value.getValue()==null){ final ParameterValue val = ParametersExt.getOrCreateValue(entry.parent,entry.desc.getName().getCode()); entry.value.setValue(val); } }else{ if(entry.value.getValue()!=null){ entry.parent.values().remove(entry.value.getValue()); entry.value.setValue(null); } } } } }); } @Override protected void updateItem(GeneralParameterValue item, boolean empty) { super.updateItem(item, empty); final ParamEntry entry = getTreeTableRow().getItem(); setText(null); setGraphic(null); if(!empty && entry!=null && entry.value != null){ final int minOcc = entry.desc.getMinimumOccurs(); final int maxOcc = entry.desc.getMaximumOccurs(); if(minOcc==0 && maxOcc==1){ setGraphic(cb); cb.setSelected(entry.value.getValue()!=null); } } } } }