From 9ac6f5174389346e21b7a5ada81dc290d7c40cba Mon Sep 17 00:00:00 2001 From: Marvin Elsen Date: Thu, 26 Sep 2024 23:10:07 +0200 Subject: [PATCH] Implement preference dialog --- .../kotlin/com/marvinelsen/willow/Config.kt | 29 +++++ .../marvinelsen/willow/WillowApplication.kt | 6 +- .../marvinelsen/willow/ui/Configuration.kt | 14 +- .../ui/controllers/DetailsController.kt | 10 ++ .../willow/ui/controllers/MenuController.kt | 18 ++- .../PronunciationStringConverter.kt | 14 ++ .../willow/ui/dialogs/SettingsDialog.kt | 74 +++++++++++ .../ui/formatters/FontSizeTextFormatter.kt | 13 ++ src/main/resources/fxml/menu.fxml | 3 +- src/main/resources/fxml/settings-dialog.fxml | 123 ++++++++++++++++++ 10 files changed, 299 insertions(+), 5 deletions(-) create mode 100644 src/main/kotlin/com/marvinelsen/willow/Config.kt create mode 100644 src/main/kotlin/com/marvinelsen/willow/ui/converters/PronunciationStringConverter.kt create mode 100644 src/main/kotlin/com/marvinelsen/willow/ui/dialogs/SettingsDialog.kt create mode 100644 src/main/kotlin/com/marvinelsen/willow/ui/formatters/FontSizeTextFormatter.kt create mode 100644 src/main/resources/fxml/settings-dialog.fxml diff --git a/src/main/kotlin/com/marvinelsen/willow/Config.kt b/src/main/kotlin/com/marvinelsen/willow/Config.kt new file mode 100644 index 0000000..44d8b0f --- /dev/null +++ b/src/main/kotlin/com/marvinelsen/willow/Config.kt @@ -0,0 +1,29 @@ +package com.marvinelsen.willow + +import javafx.beans.property.IntegerProperty +import javafx.beans.property.SimpleIntegerProperty +import java.util.prefs.Preferences + +class Config { + companion object { + private const val DETAIL_HEADWORD_FONT_SIZE_KEY = "detailHeadwordFontSize" + + private const val DEFAULT_DETAIL_HEADWORD_FONT_SIZE = 16 + } + + private val preferences = Preferences.userNodeForPackage(this::class.java) + + val detailHeadwordFontSize: IntegerProperty = SimpleIntegerProperty(DEFAULT_DETAIL_HEADWORD_FONT_SIZE) + + fun save() { + preferences.putInt(DETAIL_HEADWORD_FONT_SIZE_KEY, detailHeadwordFontSize.value) + } + + fun load() { + detailHeadwordFontSize.value = preferences.getInt(DETAIL_HEADWORD_FONT_SIZE_KEY, DEFAULT_DETAIL_HEADWORD_FONT_SIZE) + } + + fun reset() { + detailHeadwordFontSize.value = DEFAULT_DETAIL_HEADWORD_FONT_SIZE + } +} diff --git a/src/main/kotlin/com/marvinelsen/willow/WillowApplication.kt b/src/main/kotlin/com/marvinelsen/willow/WillowApplication.kt index ae54fd2..9969032 100644 --- a/src/main/kotlin/com/marvinelsen/willow/WillowApplication.kt +++ b/src/main/kotlin/com/marvinelsen/willow/WillowApplication.kt @@ -45,14 +45,16 @@ class WillowApplication : Application() { val searchService = SearchService(dictionary) val findWordsService = FindWordsService(dictionary) val model = Model(searchService, findWordsService) + val config = Config() + config.load() val fxmlLoader = FXMLLoader() fxmlLoader.resources = resourceBundle fxmlLoader.controllerFactory = Callback { type -> when (type) { MainController::class.java -> MainController(model) - MenuController::class.java -> MenuController(model) - DetailsController::class.java -> DetailsController(model) + MenuController::class.java -> MenuController(model, config) + DetailsController::class.java -> DetailsController(model, config) SearchController::class.java -> SearchController(model) ListController::class.java -> ListController(model) else -> error("Trying to instantiate unknown controller type $type") diff --git a/src/main/kotlin/com/marvinelsen/willow/ui/Configuration.kt b/src/main/kotlin/com/marvinelsen/willow/ui/Configuration.kt index 314c10d..1df1e98 100644 --- a/src/main/kotlin/com/marvinelsen/willow/ui/Configuration.kt +++ b/src/main/kotlin/com/marvinelsen/willow/ui/Configuration.kt @@ -1,3 +1,15 @@ package com.marvinelsen.willow.ui -class Configuration +data class Configuration( + val preferredScript: Script = Script.SIMPLIFIED, +) + +enum class Script { + SIMPLIFIED, TRADITIONAL +} + +enum class Pronunciation { + PINYIN_WITH_TONE_MARKS, + PINYIN_WITH_TONE_NUMBERS, + ZHUYIN +} diff --git a/src/main/kotlin/com/marvinelsen/willow/ui/controllers/DetailsController.kt b/src/main/kotlin/com/marvinelsen/willow/ui/controllers/DetailsController.kt index 1e40f15..fa92238 100644 --- a/src/main/kotlin/com/marvinelsen/willow/ui/controllers/DetailsController.kt +++ b/src/main/kotlin/com/marvinelsen/willow/ui/controllers/DetailsController.kt @@ -1,5 +1,6 @@ package com.marvinelsen.willow.ui.controllers +import com.marvinelsen.willow.Config import com.marvinelsen.willow.Model import com.marvinelsen.willow.ui.DictionaryEntryFx import javafx.beans.binding.Bindings @@ -43,6 +44,15 @@ class DetailsController(private val model: Model) { Bindings.createStringBinding({ model.selectedEntry.value?.traditionalProperty?.value }, model.selectedEntry) labelHeadword.textProperty().bind(headwordObjectBinding) + labelHeadword + .styleProperty() + .bind( + Bindings.concat( + "-fx-font-size: ", + config.detailHeadwordFontSize.asString(), + "px;" + ) + ) tabPaneDetails.disableProperty().bind(Bindings.isNull(model.selectedEntry)) diff --git a/src/main/kotlin/com/marvinelsen/willow/ui/controllers/MenuController.kt b/src/main/kotlin/com/marvinelsen/willow/ui/controllers/MenuController.kt index 3a74300..5acf46f 100644 --- a/src/main/kotlin/com/marvinelsen/willow/ui/controllers/MenuController.kt +++ b/src/main/kotlin/com/marvinelsen/willow/ui/controllers/MenuController.kt @@ -1,13 +1,19 @@ package com.marvinelsen.willow.ui.controllers +import com.marvinelsen.willow.Config import com.marvinelsen.willow.Model +import com.marvinelsen.willow.ui.dialogs.SettingsDialog import javafx.application.Platform import javafx.beans.binding.Bindings import javafx.fxml.FXML +import javafx.scene.control.MenuBar import javafx.scene.control.MenuItem @Suppress("UnusedPrivateMember") -class MenuController(private val model: Model) { +class MenuController(private val model: Model, private val config: Config) { + @FXML + private lateinit var menuBar: MenuBar + @FXML private lateinit var menuItemCopyHeadword: MenuItem @@ -20,6 +26,16 @@ class MenuController(private val model: Model) { menuItemCopyHeadword.disableProperty().bind(Bindings.isNull(model.selectedEntry)) } + @FXML + private fun onMenuItemPreferencesAction() { + SettingsDialog(menuBar.scene.window, config).showAndWait().ifPresent { result -> + when (result) { + SettingsDialog.Result.CHANGES -> config.save() + SettingsDialog.Result.NO_CHANGES -> config.load() + } + } + } + @FXML private fun onMenuItemQuitAction() { Platform.exit() diff --git a/src/main/kotlin/com/marvinelsen/willow/ui/converters/PronunciationStringConverter.kt b/src/main/kotlin/com/marvinelsen/willow/ui/converters/PronunciationStringConverter.kt new file mode 100644 index 0000000..21d645d --- /dev/null +++ b/src/main/kotlin/com/marvinelsen/willow/ui/converters/PronunciationStringConverter.kt @@ -0,0 +1,14 @@ +package com.marvinelsen.willow.ui.converters + +import com.marvinelsen.willow.ui.Pronunciation +import javafx.util.StringConverter + +class PronunciationStringConverter : StringConverter() { + override fun toString(pronunciation: Pronunciation) = when (pronunciation) { + Pronunciation.PINYIN_WITH_TONE_MARKS -> "Pinyin with tone marks" + Pronunciation.PINYIN_WITH_TONE_NUMBERS -> "Pinyin with tone numbers" + Pronunciation.ZHUYIN -> "Zhuyin" + } + + override fun fromString(string: String) = null +} diff --git a/src/main/kotlin/com/marvinelsen/willow/ui/dialogs/SettingsDialog.kt b/src/main/kotlin/com/marvinelsen/willow/ui/dialogs/SettingsDialog.kt new file mode 100644 index 0000000..6ce066a --- /dev/null +++ b/src/main/kotlin/com/marvinelsen/willow/ui/dialogs/SettingsDialog.kt @@ -0,0 +1,74 @@ +package com.marvinelsen.willow.ui.dialogs + +import com.marvinelsen.willow.Config +import com.marvinelsen.willow.WillowApplication +import com.marvinelsen.willow.ui.Pronunciation +import com.marvinelsen.willow.ui.formatters.FontSizeTextFormatter +import javafx.fxml.FXMLLoader +import javafx.scene.control.ButtonType +import javafx.scene.control.CheckBox +import javafx.scene.control.ComboBox +import javafx.scene.control.Dialog +import javafx.scene.control.DialogPane +import javafx.scene.control.Spinner +import javafx.stage.Modality +import javafx.stage.Stage +import javafx.stage.Window +import javafx.util.Callback + +@Suppress("MemberVisibilityCanBePrivate") +class SettingsDialog(owner: Window?, config: Config) : Dialog() { + companion object { + private const val DIALOG_MIN_HEIGHT = 400.0 + private const val DIALOG_MIN_WIDTH = 400.0 + } + + enum class Result { + CHANGES, NO_CHANGES + } + + lateinit var comboBoxEntryPronunciation: ComboBox + lateinit var comboBoxListPronunciation: ComboBox + + lateinit var checkBoxListShowPronunciation: CheckBox + lateinit var checkBoxListShowDefinition: CheckBox + + lateinit var spinnerEntryHeadwordFontSize: Spinner + lateinit var spinnerEntryPronunciationFontSize: Spinner + lateinit var spinnerListHeadwordFontSize: Spinner + lateinit var spinnerListPronunciationFontSize: Spinner + lateinit var spinnerListDefinitionFontSize: Spinner + + private val entryHeadwordFontSizeObjectProperty = config.detailHeadwordFontSize.asObject() + + init { + val loader = FXMLLoader(WillowApplication::class.java.getResource("/fxml/settings-dialog.fxml")) + loader.setController(this) + val root: DialogPane = loader.load() + + dialogPane = root + title = "Settings" + isResizable = true + + initOwner(owner) + initModality(Modality.APPLICATION_MODAL) + + (dialogPane.scene.window as Stage).apply { + minWidth = DIALOG_MIN_WIDTH + minHeight = DIALOG_MIN_HEIGHT + } + + with(spinnerEntryHeadwordFontSize) { + editor.textFormatter = FontSizeTextFormatter() + valueFactory.valueProperty().bindBidirectional(entryHeadwordFontSizeObjectProperty) + } + + resultConverter = Callback(::convertToResult) + } + + private fun convertToResult(buttonType: ButtonType) = + when (buttonType) { + ButtonType.APPLY -> Result.CHANGES + else -> Result.NO_CHANGES + } +} diff --git a/src/main/kotlin/com/marvinelsen/willow/ui/formatters/FontSizeTextFormatter.kt b/src/main/kotlin/com/marvinelsen/willow/ui/formatters/FontSizeTextFormatter.kt new file mode 100644 index 0000000..9bb3cd2 --- /dev/null +++ b/src/main/kotlin/com/marvinelsen/willow/ui/formatters/FontSizeTextFormatter.kt @@ -0,0 +1,13 @@ +package com.marvinelsen.willow.ui.formatters + +import javafx.scene.control.TextFormatter +import javafx.util.converter.IntegerStringConverter +import java.util.function.UnaryOperator + +private val digitRegex = """\d*""".toRegex() + +class FontSizeTextFormatter : TextFormatter( + IntegerStringConverter(), + 1, + UnaryOperator { if (digitRegex.matches(it.text)) it else null } +) diff --git a/src/main/resources/fxml/menu.fxml b/src/main/resources/fxml/menu.fxml index 08644ce..916ce50 100644 --- a/src/main/resources/fxml/menu.fxml +++ b/src/main/resources/fxml/menu.fxml @@ -4,10 +4,11 @@ - + diff --git a/src/main/resources/fxml/settings-dialog.fxml b/src/main/resources/fxml/settings-dialog.fxml new file mode 100644 index 0000000..c9831ae --- /dev/null +++ b/src/main/resources/fxml/settings-dialog.fxml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file