/* * 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.contexttree; import java.awt.Color; import javafx.application.Platform; import javafx.embed.swing.SwingFXUtils; import javafx.event.ActionEvent; import javafx.geometry.Pos; import javafx.scene.control.ContentDisplay; import javafx.scene.control.TextField; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeTableCell; import javafx.scene.control.TreeTableColumn; import javafx.scene.control.TreeTableRow; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import javafx.scene.text.TextAlignment; import org.geotoolkit.client.ClientFactory; import org.geotoolkit.data.FeatureStore; import org.geotoolkit.data.session.Session; import org.geotoolkit.font.FontAwesomeIcons; import org.geotoolkit.font.IconBuilder; import org.geotoolkit.gui.javafx.util.FXUtilities; import org.geotoolkit.internal.GeotkFX; import org.geotoolkit.map.CoverageMapLayer; import org.geotoolkit.map.FeatureMapLayer; import org.geotoolkit.map.MapItem; import org.geotoolkit.storage.StorageEvent; import org.geotoolkit.storage.StorageListener; import org.geotoolkit.storage.coverage.CoverageStore; /** * Context tree column with name and type icon. * For FeatureMapLayer a small red asterik may be displayed when there are uncommited changes. * * @author Johann Sorel (Geomatys) */ public class MapItemNameColumn<T> extends TreeTableColumn<T,String>{ private static final Image ICON_RASTER = new Image("/org/geotoolkit/gui/javafx/icon/raster-icon.png"); private static final Image ICON_VECTOR = new Image("/org/geotoolkit/gui/javafx/icon/vector-icon.png"); private static final Image ICON_SERVICE = new Image("/org/geotoolkit/gui/javafx/icon/service-icon.png"); private static final Image ICON_SENSOR = new Image("/org/geotoolkit/gui/javafx/icon/sensor-icon.png"); private static final Image ICON_FOLDER = SwingFXUtils.toFXImage(IconBuilder.createImage(FontAwesomeIcons.ICON_FOLDER_O,16,Color.GRAY),null); public MapItemNameColumn() { super(GeotkFX.getString(MapItemNameColumn.class,"layers")); setCellValueFactory(param -> FXUtilities.beanProperty(((CellDataFeatures)param).getValue().getValue(), "name", String.class)); setCellFactory((TreeTableColumn<T, String> param) -> new Cell()); setEditable(true); setPrefWidth(200); setMinWidth(120); } public static class Cell<T> extends TreeTableCell<T,String> implements StorageListener<StorageEvent, StorageEvent>{ private final TextField textField = new TextField(); private final StorageListener.Weak weakListener = new StorageListener.Weak(this); public Cell(){ textField.setMaxWidth(Double.POSITIVE_INFINITY); textField.setOnAction((ActionEvent evt) -> commitEdit(textField.getText())); } @Override public void startEdit() { super.startEdit(); setText(null); setGraphic(null); setContentDisplay(ContentDisplay.GRAPHIC_ONLY); final BorderPane pane = new BorderPane(); pane.setLeft(createIcon()); pane.setCenter(textField); textField.textProperty().bindBidirectional(itemProperty()); setGraphic(pane); textField.requestFocus(); } @Override public void commitEdit(String newValue) { textField.textProperty().unbind(); super.commitEdit(newValue); updateItem(getItem(), isEmpty()); } @Override public void cancelEdit() { textField.commitValue(); textField.textProperty().unbind(); super.cancelEdit(); updateItem(getItem(), isEmpty()); } @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); setText(null); setGraphic(null); setContentDisplay(ContentDisplay.LEFT); setAlignment(Pos.CENTER_LEFT); setTextAlignment(TextAlignment.LEFT); setWrapText(false); if(empty) return; String str = (item==null)? " " : item; if(str.isEmpty()) str = " "; setText(str); final TreeTableRow row = getTreeTableRow(); if(row==null) return; final TreeItem ti = row.getTreeItem(); if(ti==null) return; weakListener.unregisterAll(); if(ti instanceof StyleMapItem){ final BorderPane pane = new BorderPane(createIcon()); pane.setMaxSize(BorderPane.USE_COMPUTED_SIZE,Double.MAX_VALUE); pane.setPrefSize(BorderPane.USE_COMPUTED_SIZE, BorderPane.USE_COMPUTED_SIZE); setGraphic(pane); }else if(ti instanceof TreeMapItem){ setGraphic(createIcon()); final Object object = ti.getValue(); if(object instanceof FeatureMapLayer){ final FeatureMapLayer fml = (FeatureMapLayer) object; final Session session = fml.getCollection().getSession(); weakListener.registerSource(session); if(session.hasPendingChanges()){ setText(getText()+" *"); } } } } private ImageView createIcon(){ final TreeTableRow row = getTreeTableRow(); if(row==null) return null; final TreeItem ti = row.getTreeItem(); if(ti==null) return null; if(ti instanceof StyleMapItem){ final ImageView view = new ImageView(); view.imageProperty().bind(((StyleMapItem)ti).imageProperty()); return view; }else if(ti instanceof TreeMapItem){ final MapItem mapItem = (MapItem) ((TreeMapItem)ti).getValue(); return new ImageView(getTypeIcon(mapItem)); } return null; } @Override public void structureChanged(StorageEvent event) {} @Override public void contentChanged(StorageEvent event) { //change the edition asteriks if(!isEditing()){ Platform.runLater(()-> updateItem(getItem(), false)); } } } public static Image getTypeIcon(MapItem mapItem){ if(mapItem instanceof FeatureMapLayer){ final FeatureStore store = ((FeatureMapLayer)mapItem).getCollection().getSession().getFeatureStore(); if(store!=null && store.getFactory() instanceof ClientFactory){ return ICON_SERVICE; }else{ return ICON_VECTOR; } }else if(mapItem instanceof CoverageMapLayer){ final CoverageStore store = ((CoverageMapLayer)mapItem).getCoverageReference().getStore(); if(store!=null && store.getFactory() instanceof ClientFactory){ return ICON_SERVICE; }else{ return ICON_RASTER; } }else{ //container return ICON_FOLDER; } } }