/** * erlyberly, erlang trace debugger * Copyright (C) 2016 Andy Till * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package erlyberly; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Map; import java.util.Timer; import java.util.TimerTask; import com.moandjiezana.toml.Toml; import com.moandjiezana.toml.TomlWriter; import javafx.beans.property.BooleanProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; /** * Load dot {@link Properties} files, bind them to JavaFX properties and auto-store * them when the JavaFX properties change. * <p> * Call {@link PrefBind#setup()} before hand then {@link PrefBind#bind(String, StringProperty)} away. * <p> * <b>All methods must be called on the JavaFX thread.</b> */ public class PrefBind { private static final long WRITE_TO_DISK_DELAY = 500L; private static final boolean IS_DAEMON = true; private static Timer timer = new Timer(IS_DAEMON); static { timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { synchronized (AWAIT_STORE_LOCK) { if(!awaitingStore) return; awaitingStore = false; } store(); }}, WRITE_TO_DISK_DELAY, WRITE_TO_DISK_DELAY); } private static Map<String, Object> props; private static File erlyberlyConfig; private static final Object AWAIT_STORE_LOCK = new Object(); private static boolean awaitingStore; private PrefBind() {} public static void bind(final String propName, StringProperty stringProp) { if(props == null) { return; } String storedValue = (String) props.get(propName); if(storedValue != null) { stringProp.set(storedValue); } stringProp.addListener((ObservableValue<? extends String> o, String oldValue, String newValue) -> { set(propName, newValue); }); } public static void bindBoolean(final String propName, BooleanProperty boolProp){ if(props == null) { return; } Boolean storedValue = (Boolean) props.get(propName); if(storedValue != null) { boolProp.set(storedValue); } boolProp.addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> { set(propName, newValue); }); } static void store() { try { //props.store(new FileOutputStream(erlyberlyConfig), " erlyberly at https://github.com/andytill/erlyberly"); new TomlWriter().write(props, new FileOutputStream(erlyberlyConfig)); } catch (IOException e) { e.printStackTrace(); } } public static void setup() throws IOException { String home = System.getProperty("user.home"); File homeDir = new File(home); File dotConfigDir = new File(homeDir, ".config"); if(dotConfigDir.exists()) { homeDir = dotConfigDir; } erlyberlyConfig = new File(homeDir, ".erlyberly2"); erlyberlyConfig.createNewFile(); Toml toml; toml = new Toml(); toml.read(new FileInputStream(erlyberlyConfig)); props = toml.getKeyValues(); } public static Object get(Object key) { return props.get(key); } public static Object getOrDefault(String key, Object theDefault) { return props.getOrDefault(key, theDefault); } public static double getOrDefaultDouble(String key, Double theDefault) { return Double.parseDouble(PrefBind.getOrDefault(key, theDefault).toString()); } public static boolean getOrDefaultBoolean(String key, boolean theDefault) { return Boolean.parseBoolean(PrefBind.getOrDefault(key, theDefault).toString()); } public static void set(String propName, Object newValue) { props.put(propName, newValue); synchronized (AWAIT_STORE_LOCK) { awaitingStore = true; } } }