/* * PrefsController.java - Copyright(c) 2013 Joe Pasqua * Provided under the MIT License. See the LICENSE file for details. * Created: Oct 31, 2013 */ package org.noroomattheinn.visibletesla; import java.util.Date; import javafx.beans.binding.Bindings; import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; import javafx.beans.property.IntegerProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.ComboBox; import javafx.scene.control.Dialogs; import javafx.scene.control.Label; import javafx.scene.control.PasswordField; import javafx.scene.control.Slider; import javafx.scene.control.TextArea; import javafx.scene.control.TextField; import javafx.scene.layout.AnchorPane; import javafx.util.converter.NumberStringConverter; import org.noroomattheinn.fxextensions.TimeSelector; import org.noroomattheinn.utils.MailGun; import org.noroomattheinn.utils.Utils; public class PrefsController extends BaseController { /*------------------------------------------------------------------------------ * * General Application Preferences * *----------------------------------------------------------------------------*/ // // UI Elements // @FXML private CheckBox wakeOnTabChange; @FXML private Slider idleThresholdSlider; @FXML private Label idleThresholdLabel; @FXML private CheckBox offerExperimental; @FXML private CheckBox enableProxy; @FXML private TextField proxyHost; @FXML private TextField proxyPort; @FXML private ComboBox<String> graphsTimePeriod; @FXML private TextField customGoogleAPIKey; @FXML private CheckBox useCustomGoogleAPIKey; @FXML private TextField customMailGunKey; @FXML private CheckBox useCustomMailGunKey; @FXML private TextField customNumerousKey; @FXML private TextField emailForNotifications; @FXML private Slider fontScaleSlider; @FXML private Label fontScale; @FXML private CheckBox enableRest; @FXML private TextField restPort; @FXML private PasswordField authCode; @FXML private TextField customURLSrc; @FXML private ComboBox<String> overviewRange; @FXML private ComboBox<String> chargeTimeType; @FXML private ComboBox<String> logLevel; @FXML private CheckBox anonRest; @FXML private CheckBox anonCharge; @FXML private CheckBox anonFailure; @FXML private CheckBox includeLoc; @FXML private Slider ditherAmt; // Overrides @FXML private ComboBox<String> overrideWheelsCombo; @FXML private CheckBox overrideWheelsActive; @FXML private ComboBox<String> overrideColorCombo; @FXML private CheckBox overrideColorActive; @FXML private ComboBox<String> overrideUnitsCombo; @FXML private CheckBox overrideUnitsActive; @FXML private ComboBox<String> overrideModelCombo; @FXML private CheckBox overrideModelActive; @FXML private ComboBox<String> overrideRoofCombo; @FXML private CheckBox overrideRoofActive; // // Action Handlers // @FXML void setAuthCode(ActionEvent event) { String code = authCode.getText(); String externalForm = app.setPW(code); prefs.authCode.set(externalForm); } @FXML void displayUUID(ActionEvent event) { AnchorPane pane = new AnchorPane(); String body = "This value is only known to you and allows you to identify " + "your information amongst anonymized data at VisibleTesla.com\n" + "ID: " + vtVehicle.getVehicle().getUUID(); TextArea t = new TextArea(body); pane.getChildren().add(t); Dialogs.showCustomDialog( app.stage, pane, "Your Anonymous UUID", "General Preferences", Dialogs.DialogOptions.OK, null); } @FXML void showAppFiles(ActionEvent event) { Utils.openFileViewer(app.appFileFolder().getAbsolutePath()); } @FXML void wakeOnTCHandler(ActionEvent event) { } @FXML void generalHandleAFF(ActionEvent event) { Dialogs.showInformationDialog(app.stage, "This change will take effect the next time the application is started.\n", "Please Note...", "General Preferences"); } @FXML void testDelivery(ActionEvent event) { String msg = "Testing delivery from VisibleTesla on "; String addr = prefs.notificationAddress.get(); if (addr == null || addr.length() == 0) { Dialogs.showWarningDialog(app.stage, "You must supply an email address before testing delivery", "Test Problem"); } String date = String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS", new Date()); if (!MailGun.get().send(addr, msg + date)) { Dialogs.showWarningDialog(app.stage, "Error delivering your test message.\n" + "Please check your email address.\n" + "If you have changed any advanced settings,\n" + "please double check them or revert to defaults", "Test Problem"); } else { Dialogs.showInformationDialog(app.stage, "The test message has been sent to the specified\n" + "address. If you do not receive it within 15 minutes,\n" + "please check your email address and try again. After\n" + "two attempts with a correct email address, please post\n" + "a message in the forums.", "Message Sent"); } } // // Intialize the UI // private void initGeneralPrefsUI() { // Basic bindToCheckBox(wakeOnTabChange, prefs.wakeOnTabChange); bindToIntegerProperty(idleThresholdSlider, idleThresholdLabel, prefs.idleThresholdInMinutes); bindToComboBox(graphsTimePeriod, prefs.loadPeriod); bindToTextField(emailForNotifications, prefs.notificationAddress); bindToComboBox(overviewRange, prefs.overviewRange); bindToComboBox(chargeTimeType, prefs.chargeTimeType); bindToCheckBox(anonRest, prefs.dataOptions.submitAnonRest); bindToCheckBox(anonCharge, prefs.dataOptions.submitAnonCharge); bindToCheckBox(anonFailure, prefs.submitAnonFailure); bindToCheckBox(includeLoc, prefs.dataOptions.includeLocData); bindToDoubleProperty(ditherAmt, null, prefs.dataOptions.ditherLocAmt); // Advanced bindToCheckBox(enableProxy, prefs.enableProxy); bindToTextField(proxyHost, prefs.proxyHost); bindToTextField(proxyPort, prefs.proxyPort); bindToCheckBox(offerExperimental, prefs.offerExperimental); bindToCheckBox(useCustomGoogleAPIKey, prefs.useCustomGoogleAPIKey); bindToTextField(customGoogleAPIKey, prefs.googleAPIKey); bindToCheckBox(useCustomMailGunKey, prefs.useCustomMailGunKey); bindToTextField(customMailGunKey, prefs.mailGunKey); bindToTextField(customNumerousKey, prefs.numerousKey); bindToIntegerProperty(fontScaleSlider, fontScale, prefs.fontScale); bindToCheckBox(enableRest, prefs.enableRest); bindToTextField(restPort, prefs.restPort); bindToTextField(customURLSrc, prefs.customURLSource); bindToComboBox(logLevel, prefs.logLevel); // Overrides bindToComboBox(overrideWheelsCombo, prefs.overrides.wheels); bindToCheckBox(overrideWheelsActive, prefs.overrides.doWheels); bindToComboBox(overrideColorCombo, prefs.overrides.color); bindToCheckBox(overrideColorActive, prefs.overrides.doColor); bindToComboBox(overrideUnitsCombo, prefs.overrides.units); bindToCheckBox(overrideUnitsActive, prefs.overrides.doUnits); bindToComboBox(overrideModelCombo, prefs.overrides.model); bindToCheckBox(overrideModelActive, prefs.overrides.doModel); bindToComboBox(overrideRoofCombo, prefs.overrides.roof); bindToCheckBox(overrideRoofActive, prefs.overrides.doRoof); } /*------------------------------------------------------------------------------ * * Preferences related to the Location Tab * *----------------------------------------------------------------------------*/ // // UI Elements // @FXML private CheckBox collectLocationData; @FXML private Slider locMinTime; @FXML private Label locMinTimeDisplay; @FXML private Slider locMinDist; @FXML private Label locMinDistDisplay; @FXML private CheckBox streamWhenPossible; // // Initialize the UI // private void initLocationPrefsUI() { bindToCheckBox(collectLocationData, prefs.collectLocationData); bindToCheckBox(streamWhenPossible, prefs.dataOptions.streamWhenPossible); bindToIntegerProperty(locMinTime, locMinTimeDisplay, prefs.dataOptions.locMinTime); bindToIntegerProperty(locMinDist, locMinDistDisplay, prefs.dataOptions.locMinDist); } /*------------------------------------------------------------------------------ * * Preferences related to the Graphs Tab * *----------------------------------------------------------------------------*/ // // UI Elements // @FXML private CheckBox ignoreGaps; @FXML private Slider gapTime; @FXML private Label gapTimeDisplay; @FXML private CheckBox limitVS; @FXML private ComboBox<String> vsFromHour; @FXML private ComboBox<String> vsFromMin; @FXML private ComboBox<String> vsFromAMPM; @FXML private ComboBox<String> vsToHour; @FXML private ComboBox<String> vsToMin; @FXML private ComboBox<String> vsToAMPM; // // Initialize the UI // private void initGraphsPrefsUI() { bindToCheckBox(ignoreGaps, prefs.ignoreGraphGaps); bindToIntegerProperty(gapTime, gapTimeDisplay, prefs.graphGapTime); final TimeSelector vsFromTime = new TimeSelector(vsFromHour, vsFromMin, vsFromAMPM); final TimeSelector vsToTime = new TimeSelector(vsToHour, vsToMin, vsToAMPM); vsFromTime.bind(prefs.dataOptions.restLimitFrom); vsToTime.bind(prefs.dataOptions.restLimitTo); bindToCheckBox(limitVS, prefs.dataOptions.restLimitEnabled); limitVS.selectedProperty().addListener(new ChangeListener<Boolean>() { @Override public void changed(ObservableValue ov, Boolean t, Boolean t1) { vsFromTime.enable(t1); vsToTime.enable(t1); } }); vsFromTime.enable(limitVS.selectedProperty().get()); vsToTime.enable(limitVS.selectedProperty().get()); } /*------------------------------------------------------------------------------ * * Preferences related to the Scheduler Tab * *----------------------------------------------------------------------------*/ @FXML private CheckBox safeMinCharge; @FXML private CheckBox safePlugged; private void initSchedulerPrefsUI() { bindToCheckBox(safeMinCharge, prefs.safeIncludesMinCharge); bindToCheckBox(safePlugged, prefs.safeIncludesPluggedIn); } /*------------------------------------------------------------------------------ * * Methods overriden from BaseController * *----------------------------------------------------------------------------*/ @Override protected void fxInitialize() { } @Override protected void initializeState() { initGeneralPrefsUI(); initSchedulerPrefsUI(); initLocationPrefsUI(); initGraphsPrefsUI(); } @Override protected void activateTab() { } @Override protected void refresh() { } /*------------------------------------------------------------------------------ * * PRIVATE - Utility Methods * *----------------------------------------------------------------------------*/ private void bindToComboBox(final ComboBox<String> cb, final StringProperty property) { cb.getSelectionModel().select(property.get()); cb.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() { @Override public void changed(ObservableValue<? extends String> ov, String old, String cur) { if (cur != null) { property.set(cur); } } }); property.addListener(new ChangeListener<String>() { @Override public void changed(ObservableValue<? extends String> ov, String old, String cur) { cb.getSelectionModel().select(cur); } }); } private void bindToCheckBox(final CheckBox cb, final BooleanProperty property) { cb.setSelected(property.get()); property.bindBidirectional(cb.selectedProperty()); } private void bindToTextField(TextField tf, StringProperty property) { tf.setText(property.get()); property.bindBidirectional(tf.textProperty()); } private void bindToTextField(TextField tf, IntegerProperty property) { tf.setText(property.getValue().toString()); Bindings.bindBidirectional(tf.textProperty(), property, new NumberStringConverter("####")); } private void bindToIntegerProperty( final Slider slider, final Label label, final IntegerProperty property) { // Watch for any changes to the property and update the UI appropriately property.addListener(new ChangeListener<Number>() { @Override public void changed( ObservableValue<? extends Number> ov, Number old, Number cur) { slider.setValue(cur.intValue()); label.setText(String.valueOf(cur.intValue())); } }); slider.setValue(property.get()); label.setText(String.valueOf(property.get())); slider.valueProperty().addListener(new ChangeListener<Number>() { @Override public void changed( ObservableValue<? extends Number> ov, Number old, Number cur) { property.set(cur.intValue()); label.setText(String.valueOf(cur.intValue())); } }); } private void bindToDoubleProperty( final Slider slider, final Label label, final DoubleProperty property) { // Watch for any changes to the property and update the UI appropriately property.addListener(new ChangeListener<Number>() { @Override public void changed( ObservableValue<? extends Number> ov, Number old, Number cur) { slider.setValue(cur.doubleValue()); if (label != null) label.setText(String.valueOf(cur.doubleValue())); } }); slider.setValue(property.get()); if (label != null) label.setText(String.valueOf(property.get())); slider.valueProperty().addListener(new ChangeListener<Number>() { @Override public void changed( ObservableValue<? extends Number> ov, Number old, Number cur) { property.set(cur.doubleValue()); if (label != null) label.setText(String.valueOf(cur.doubleValue())); } }); } }