Display pronunciation in details view

This commit is contained in:
Marvin Elsen 2024-10-03 12:41:12 +02:00
parent d9b7b82c60
commit 12eb98d5b1
Signed by: marvinelsen
GPG Key ID: 820672408CC318C2
7 changed files with 105 additions and 36 deletions

View File

@ -14,7 +14,11 @@ import javafx.collections.FXCollections
import javafx.collections.ObservableList import javafx.collections.ObservableList
import javafx.event.EventHandler import javafx.event.EventHandler
class Model(private val searchService: SearchService, private val findWordsService: FindWordsService, private val findCharacterService: FindCharacterService) { class Model(
private val searchService: SearchService,
private val findWordsService: FindWordsService,
private val findCharacterService: FindCharacterService,
) {
private val internalSelectedEntry: ObjectProperty<DictionaryEntryFx> = SimpleObjectProperty() private val internalSelectedEntry: ObjectProperty<DictionaryEntryFx> = SimpleObjectProperty()
private val internalSearchResults: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList() private val internalSearchResults: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
private val internalWordsContaining: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList() private val internalWordsContaining: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()

View File

@ -14,11 +14,7 @@ class Config {
private const val LOCALE_KEY = "locale" private const val LOCALE_KEY = "locale"
private const val THEME_KEY = "theme" private const val THEME_KEY = "theme"
private const val SCRIPT_KEY = "script" private const val SCRIPT_KEY = "script"
private const val DETAIL_HEADWORD_FONT_SIZE_KEY = "detailHeadwordFontSize"
private const val DETAIL_PRONUNCIATION_FONT_SIZE_KEY = "detailPronunciationFontSize"
private const val DEFAULT_DETAIL_HEADWORD_FONT_SIZE = 40
private const val DEFAULT_DETAIL_PRONUNCIATION_FONT_SIZE = 16
private val DEFAULT_THEME = Theme.SYSTEM private val DEFAULT_THEME = Theme.SYSTEM
private val DEFAULT_SCRIPT = Script.SIMPLIFIED private val DEFAULT_SCRIPT = Script.SIMPLIFIED
private val DEFAULT_LOCALE = Locale.ENGLISH private val DEFAULT_LOCALE = Locale.ENGLISH
@ -26,21 +22,19 @@ class Config {
private val preferences = Preferences.userNodeForPackage(this::class.java) private val preferences = Preferences.userNodeForPackage(this::class.java)
val searchResults = SearchResultsConfig(preferences) val searchResults = SearchResultsConfig(preferences)
val details = DetailsConfig(preferences)
val locale: ObjectProperty<Locale> = SimpleObjectProperty(DEFAULT_LOCALE) val locale: ObjectProperty<Locale> = SimpleObjectProperty(DEFAULT_LOCALE)
val theme: ObjectProperty<Theme> = SimpleObjectProperty(DEFAULT_THEME) val theme: ObjectProperty<Theme> = SimpleObjectProperty(DEFAULT_THEME)
val script: ObjectProperty<Script> = SimpleObjectProperty(DEFAULT_SCRIPT) val script: ObjectProperty<Script> = SimpleObjectProperty(DEFAULT_SCRIPT)
val detailHeadwordFontSize: IntegerProperty = SimpleIntegerProperty(DEFAULT_DETAIL_HEADWORD_FONT_SIZE)
val detailPronunciationFontSize: IntegerProperty = SimpleIntegerProperty(DEFAULT_DETAIL_PRONUNCIATION_FONT_SIZE)
fun save() { fun save() {
preferences.put(LOCALE_KEY, locale.value.toLanguageTag()) preferences.put(LOCALE_KEY, locale.value.toLanguageTag())
preferences.put(THEME_KEY, theme.value.name) preferences.put(THEME_KEY, theme.value.name)
preferences.put(SCRIPT_KEY, script.value.name) preferences.put(SCRIPT_KEY, script.value.name)
preferences.putInt(DETAIL_HEADWORD_FONT_SIZE_KEY, detailHeadwordFontSize.value)
preferences.putInt(DETAIL_PRONUNCIATION_FONT_SIZE_KEY, detailPronunciationFontSize.value)
searchResults.save() searchResults.save()
details.save()
preferences.flush() preferences.flush()
} }
@ -48,16 +42,6 @@ class Config {
fun load() { fun load() {
preferences.sync() preferences.sync()
detailHeadwordFontSize.value = preferences.getInt(
DETAIL_HEADWORD_FONT_SIZE_KEY,
DEFAULT_DETAIL_HEADWORD_FONT_SIZE
)
detailPronunciationFontSize.value = preferences.getInt(
DETAIL_PRONUNCIATION_FONT_SIZE_KEY,
DEFAULT_DETAIL_PRONUNCIATION_FONT_SIZE
)
theme.value = Theme.valueOf( theme.value = Theme.valueOf(
preferences.get( preferences.get(
THEME_KEY, THEME_KEY,
@ -75,10 +59,7 @@ class Config {
locale.value = Locale.forLanguageTag(preferences.get(LOCALE_KEY, DEFAULT_LOCALE.toLanguageTag())) locale.value = Locale.forLanguageTag(preferences.get(LOCALE_KEY, DEFAULT_LOCALE.toLanguageTag()))
searchResults.load() searchResults.load()
} details.load()
fun reset() {
detailHeadwordFontSize.value = DEFAULT_DETAIL_HEADWORD_FONT_SIZE
} }
} }
@ -144,3 +125,42 @@ class SearchResultsConfig(private val preferences: Preferences) {
) )
} }
} }
class DetailsConfig(private val preferences: Preferences) {
companion object {
private const val PRONUNCIATION_KEY = "detailsPronunciation"
private const val HEADWORD_FONT_SIZE_KEY = "detailsHeadwordFontSize"
private const val PRONUNCIATION_FONT_SIZE_KEY = "detailsPronunciationFontSize"
private val DEFAULT_PRONUNCIATION = Pronunciation.PINYIN_WITH_TONE_MARKS
private const val DEFAULT_HEADWORD_FONT_SIZE = 40
private const val DEFAULT_PRONUNCIATION_FONT_SIZE = 16
}
val pronunciation: ObjectProperty<Pronunciation> = SimpleObjectProperty(DEFAULT_PRONUNCIATION)
val headwordFontSize: IntegerProperty = SimpleIntegerProperty(DEFAULT_HEADWORD_FONT_SIZE)
val pronunciationFontSize: IntegerProperty = SimpleIntegerProperty(DEFAULT_PRONUNCIATION_FONT_SIZE)
fun save() {
preferences.put(PRONUNCIATION_KEY, pronunciation.value.name)
preferences.putInt(HEADWORD_FONT_SIZE_KEY, headwordFontSize.value)
preferences.putInt(PRONUNCIATION_FONT_SIZE_KEY, pronunciationFontSize.value)
}
fun load() {
headwordFontSize.value = preferences.getInt(
HEADWORD_FONT_SIZE_KEY,
DEFAULT_HEADWORD_FONT_SIZE
)
pronunciationFontSize.value = preferences.getInt(
PRONUNCIATION_FONT_SIZE_KEY,
DEFAULT_PRONUNCIATION_FONT_SIZE
)
pronunciation.value = Pronunciation.valueOf(
preferences.get(
PRONUNCIATION_KEY,
DEFAULT_PRONUNCIATION.name
)
)
}
}

View File

@ -2,6 +2,7 @@ package com.marvinelsen.willow.ui.controllers
import com.marvinelsen.willow.Model import com.marvinelsen.willow.Model
import com.marvinelsen.willow.config.Config import com.marvinelsen.willow.config.Config
import com.marvinelsen.willow.config.Pronunciation
import com.marvinelsen.willow.config.Script import com.marvinelsen.willow.config.Script
import com.marvinelsen.willow.ui.DictionaryEntryFx import com.marvinelsen.willow.ui.DictionaryEntryFx
import com.marvinelsen.willow.ui.cells.DictionaryEntryCellFactory import com.marvinelsen.willow.ui.cells.DictionaryEntryCellFactory
@ -10,6 +11,7 @@ import javafx.fxml.FXML
import javafx.scene.control.Label import javafx.scene.control.Label
import javafx.scene.control.ListView import javafx.scene.control.ListView
import javafx.scene.control.TabPane import javafx.scene.control.TabPane
import javafx.scene.input.ContextMenuEvent
import javafx.scene.web.WebView import javafx.scene.web.WebView
import kotlinx.html.body import kotlinx.html.body
import kotlinx.html.h1 import kotlinx.html.h1
@ -20,6 +22,9 @@ import kotlinx.html.stream.createHTML
import java.util.ResourceBundle import java.util.ResourceBundle
class DetailsController(private val model: Model, private val config: Config) { class DetailsController(private val model: Model, private val config: Config) {
@FXML
private lateinit var labelPronunciation: Label
@FXML @FXML
private lateinit var resources: ResourceBundle private lateinit var resources: ResourceBundle
@ -47,6 +52,7 @@ class DetailsController(private val model: Model, private val config: Config) {
@Suppress("UnusedPrivateMember") @Suppress("UnusedPrivateMember")
private fun initialize() { private fun initialize() {
initializeLabelHeadword() initializeLabelHeadword()
initializeLabelPronunciation()
initializeTabPaneDetails() initializeTabPaneDetails()
initializeListViewWords() initializeListViewWords()
initializeListViewCharacters() initializeListViewCharacters()
@ -126,7 +132,32 @@ class DetailsController(private val model: Model, private val config: Config) {
model.selectedEntry model.selectedEntry
) )
) )
styleProperty().bind(Bindings.concat("-fx-font-size: ", config.detailHeadwordFontSize.asString(), "px;")) styleProperty().bind(Bindings.concat("-fx-font-size: ", config.details.headwordFontSize.asString(), "px;"))
}
}
private fun initializeLabelPronunciation() {
labelPronunciation.apply {
textProperty().bind(
Bindings.createStringBinding(
{
when (config.details.pronunciation.value!!) {
Pronunciation.PINYIN_WITH_TONE_MARKS -> model.selectedEntry.value?.pinyinWithToneMarksProperty?.value
Pronunciation.PINYIN_WITH_TONE_NUMBERS -> model.selectedEntry.value?.pinyinWithToneNumbersProperty?.value
Pronunciation.ZHUYIN -> model.selectedEntry.value?.zhuyinProperty?.value
}
},
config.details.pronunciation,
model.selectedEntry
)
)
styleProperty().bind(
Bindings.concat(
"-fx-font-size: ",
config.details.pronunciationFontSize.asString(),
"px;"
)
)
} }
} }
@ -144,4 +175,7 @@ class DetailsController(private val model: Model, private val config: Config) {
} }
} }
} }
fun showSelectedEntryContextMenu(contextMenuEvent: ContextMenuEvent) {
}
} }

View File

@ -42,6 +42,9 @@ class PreferencesDialog(owner: Window?, config: Config) : Dialog<PreferencesDial
@FXML @FXML
private lateinit var comboBoxPronunciationSearchResults: ComboBox<Pronunciation> private lateinit var comboBoxPronunciationSearchResults: ComboBox<Pronunciation>
@FXML
private lateinit var comboBoxPronunciationDetails: ComboBox<Pronunciation>
@FXML @FXML
private lateinit var checkBoxShowPronunciationSearchResults: CheckBox private lateinit var checkBoxShowPronunciationSearchResults: CheckBox
@ -63,8 +66,8 @@ class PreferencesDialog(owner: Window?, config: Config) : Dialog<PreferencesDial
@FXML @FXML
private lateinit var spinnerDefinitionFontSizeSearchResults: Spinner<Int> private lateinit var spinnerDefinitionFontSizeSearchResults: Spinner<Int>
private val entryHeadwordFontSizeObjectProperty = config.detailHeadwordFontSize.asObject() private val entryHeadwordFontSizeObjectProperty = config.details.headwordFontSize.asObject()
private val entryPronunciationFontSizeObjectProperty = config.detailPronunciationFontSize.asObject() private val entryPronunciationFontSizeObjectProperty = config.details.pronunciationFontSize.asObject()
private val searchResultHeadwordFontSizeObjectProperty = config.searchResults.headwordFontSize.asObject() private val searchResultHeadwordFontSizeObjectProperty = config.searchResults.headwordFontSize.asObject()
private val searchResultPronunciationFontSizeObjectProperty = config.searchResults.pronunciationFontSize.asObject() private val searchResultPronunciationFontSizeObjectProperty = config.searchResults.pronunciationFontSize.asObject()
@ -100,6 +103,7 @@ class PreferencesDialog(owner: Window?, config: Config) : Dialog<PreferencesDial
comboBoxScript.valueProperty().bindBidirectional(config.script) comboBoxScript.valueProperty().bindBidirectional(config.script)
comboBoxLocale.valueProperty().bindBidirectional(config.locale) comboBoxLocale.valueProperty().bindBidirectional(config.locale)
comboBoxPronunciationSearchResults.valueProperty().bindBidirectional(config.searchResults.pronunciation) comboBoxPronunciationSearchResults.valueProperty().bindBidirectional(config.searchResults.pronunciation)
comboBoxPronunciationDetails.valueProperty().bindBidirectional(config.details.pronunciation)
checkBoxShowDefinitionSearchResults checkBoxShowDefinitionSearchResults
.selectedProperty() .selectedProperty()

View File

@ -1,4 +1,7 @@
.headword { .headword {
-fx-font-family: TW-Kai; -fx-font-family: TW-Kai;
-fx-font-size: 40; }
.pronunciation {
-fx-font-family: "Noto Sans TC";
} }

View File

@ -1,7 +1,3 @@
.root { .root {
-fx-font-family: "Inter Variable"; -fx-font-family: "Inter Variable";
} }
.details-pronunciation {
-fx-font: 16 "Noto Sans TC";
}

View File

@ -1,18 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import com.marvinelsen.willow.ui.cells.DictionaryEntryCellFactory?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.web.WebView?> <?import javafx.scene.web.WebView?>
<?import javafx.geometry.Insets?>
<VBox xmlns="http://javafx.com/javafx/23" xmlns:fx="http://javafx.com/fxml/1" <VBox xmlns="http://javafx.com/javafx/23" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.marvinelsen.willow.ui.controllers.DetailsController" fx:controller="com.marvinelsen.willow.ui.controllers.DetailsController"
stylesheets="/css/details.css"> stylesheets="/css/details.css">
<FlowPane fx:id="flowPaneSelectedEntry" hgap="8.0" onContextMenuRequested="#showSelectedEntryContextMenu"
prefHeight="38.0" prefWidth="412.0" rowValignment="BASELINE" vgap="8.0" VBox.vgrow="NEVER">
<padding>
<Insets bottom="6.0" left="6.0" right="6.0" top="6.0"/>
</padding>
<Label fx:id="labelHeadword" styleClass="headword" text="Label"> <Label fx:id="labelHeadword" styleClass="headword" text="Label">
<padding> <padding>
<Insets left="8" right="8" top="8" bottom="8"/> <Insets left="8" right="8" top="8" bottom="8"/>
</padding> </padding>
</Label> </Label>
<Label fx:id="labelPronunciation" styleClass="pronunciation">
</Label>
</FlowPane>
<TabPane fx:id="tabPaneDetails" tabClosingPolicy="UNAVAILABLE" disable="true" VBox.vgrow="ALWAYS"> <TabPane fx:id="tabPaneDetails" tabClosingPolicy="UNAVAILABLE" disable="true" VBox.vgrow="ALWAYS">
<Tab closable="false" text="%tab.definition"> <Tab closable="false" text="%tab.definition">
<WebView fx:id="webViewDefinition" minHeight="-1.0" minWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0"/> <WebView fx:id="webViewDefinition" minHeight="-1.0" minWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0"/>