/* * 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.io.File; import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.logging.Level; import java.util.prefs.Preferences; import java.util.regex.Pattern; import javafx.beans.binding.Bindings; import javafx.beans.property.Property; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ObservableValue; import javafx.util.StringConverter; import org.apache.sis.util.ObjectConverter; import org.apache.sis.util.ObjectConverters; import org.geotoolkit.gui.javafx.util.FXFileTextField; import org.geotoolkit.internal.Loggers; /** * An editor allowing setting of a parameter of URL, Path or File value. * * @author Johann Sorel (Geomatys) * @author Alexis Manin (Geomatys) */ public class FXURLEditor extends FXValueEditor { private static final Pattern PROTOCOL_START = Pattern.compile("^\\w+://"); private static final Class[] ALLOWED_CLASSES = new Class[]{URL.class, URI.class, Path.class, File.class}; /** * Custom field for path edition. */ private final PropertyPathEditor pathField = new PropertyPathEditor(); /** * Converts value typed in input field to valid path or URI for target * property. */ private ObjectConverter<String, Object> valueConverter; private final SimpleObjectProperty valueProperty = new SimpleObjectProperty(); public FXURLEditor(final Spi originatingSpi) { super(originatingSpi); String previousPath = getPreviousPath(); if (previousPath != null && !previousPath.isEmpty()) { try { final Path rootPath = Paths.get(previousPath); if (Files.isDirectory(rootPath)) { pathField.rootPath.set(previousPath); } else if (Files.isDirectory(rootPath.getParent())) { pathField.rootPath.set(rootPath.getParent().toAbsolutePath().toString()); } } catch (Exception e) { Loggers.JAVAFX.log(Level.WARNING, "Cannot initialize root path for editor : " + previousPath, e); } } currentAttributeType.addListener(this::updateConverter); currentParamDesc.addListener(this::updateConverter); Bindings.bindBidirectional(pathField.textProperty(), valueProperty, new StringConverter() { @Override public String toString(Object object) { if (object == null || valueConverter == null || valueConverter.inverse() == null) return null; return valueConverter.inverse().apply(object); } @Override public Object fromString(String string) { if (string == null || valueConverter == null) return null; return valueConverter.apply(checkAndAdaptPath(string)); } }); } @Override public Property valueProperty() { return valueProperty; } public void updateConverter(ObservableValue observable, Object oldValue, Object newValue) { valueConverter = ObjectConverters.find(String.class, getValueClass()); } protected static String checkAndAdaptPath(final String input) { if (input == null || input.isEmpty()) return input; if (PROTOCOL_START.matcher(input).find()) { return input; } else { Path target = Paths.get(input); if (Files.exists(target)) { return target.toAbsolutePath().toUri().toString(); } else { return "http://" + input; } } } @Override public FXFileTextField getComponent() { return pathField; } public FXURLEditor copy(){ final FXURLEditor cp = new FXURLEditor((Spi)spi); cp.pathField.showOpenProperty().setValue(pathField.showOpenProperty().getValue()); return cp; } public static String getPreviousPath() { final Preferences prefs = Preferences.userNodeForPackage(FXURLEditor.class); return checkAndAdaptPath(prefs.get("path", null)); } public static void setPreviousPath(final String path) { if (path == null) return; final Preferences prefs = Preferences.userNodeForPackage(FXURLEditor.class); prefs.put("path", checkAndAdaptPath(path)); } private static class PropertyPathEditor extends FXFileTextField { @Override protected String chooseInputContent() { final String chosenPath = super.chooseInputContent(); setPreviousPath(chosenPath); return chosenPath; } } public static final class Spi extends FXValueEditorSpi { @Override public boolean canHandle(Class binding) { if (binding == null) return false; for (final Class current : ALLOWED_CLASSES) { if (current.isAssignableFrom(binding)) { return true; } } return false; } @Override public FXValueEditor createEditor() { return new FXURLEditor(this); } } }