Compare commits

..

No commits in common. "6ebdf4051c4869f8340ce476c871ea2bd4523888" and "46af4db9f19e3f5cc84de6f81a8c62a0c52b6aaf" have entirely different histories.

13 changed files with 169 additions and 234 deletions

View File

@ -2,10 +2,10 @@ package com.marvinelsen.willow
import com.marvinelsen.willow.domain.SearchMode
import com.marvinelsen.willow.ui.DictionaryEntryFx
import com.marvinelsen.willow.ui.services.FindCharacterService
import com.marvinelsen.willow.ui.services.FindWordsService
import com.marvinelsen.willow.ui.services.SearchService
import com.marvinelsen.willow.ui.util.ClipboardHelper
import com.marvinelsen.willow.ui.util.FindCharacterService
import com.marvinelsen.willow.ui.util.FindWordsService
import com.marvinelsen.willow.ui.util.SearchService
import javafx.beans.property.ObjectProperty
import javafx.beans.property.ReadOnlyBooleanProperty
import javafx.beans.property.ReadOnlyObjectProperty

View File

@ -7,9 +7,9 @@ import com.marvinelsen.willow.ui.controllers.MainController
import com.marvinelsen.willow.ui.controllers.MenuController
import com.marvinelsen.willow.ui.controllers.SearchController
import com.marvinelsen.willow.ui.controllers.SearchResultsController
import com.marvinelsen.willow.ui.services.FindCharacterService
import com.marvinelsen.willow.ui.services.FindWordsService
import com.marvinelsen.willow.ui.services.SearchService
import com.marvinelsen.willow.ui.util.FindCharacterService
import com.marvinelsen.willow.ui.util.FindWordsService
import com.marvinelsen.willow.ui.util.SearchService
import javafx.application.Application
import javafx.fxml.FXMLLoader
import javafx.scene.Scene
@ -66,7 +66,6 @@ class WillowApplication : Application() {
val root = fxmlLoader.load(javaClass.getResourceAsStream("/fxml/main.fxml")) as BorderPane
val primaryScene = Scene(root, WINDOW_WIDTH, WINDOW_HEIGHT)
// primaryScene.stylesheets.add(javaClass.getResource("/css/dark.css")?.toExternalForm()!!)
primaryStage.apply {
title = WINDOW_TITLE

View File

@ -8,13 +8,9 @@ import javafx.beans.binding.Bindings
import javafx.fxml.FXML
import javafx.scene.control.MenuBar
import javafx.scene.control.MenuItem
import java.util.ResourceBundle
@Suppress("UnusedPrivateMember")
class MenuController(private val model: Model, private val config: Config) {
@FXML
private lateinit var resources: ResourceBundle
@FXML
private lateinit var menuBar: MenuBar
@ -32,10 +28,10 @@ class MenuController(private val model: Model, private val config: Config) {
@FXML
private fun onMenuItemPreferencesAction() {
PreferencesDialog(menuBar.scene.window, config, resources).showAndWait().ifPresent { result ->
PreferencesDialog(menuBar.scene.window, config).showAndWait().ifPresent { result ->
when (result) {
PreferencesDialog.Result.SAVE_CHANGES -> config.save()
PreferencesDialog.Result.DO_NOT_SAVE_CHANGES -> config.load()
PreferencesDialog.Result.CHANGES -> config.save()
PreferencesDialog.Result.NO_CHANGES -> config.load()
}
}
}

View File

@ -1,108 +0,0 @@
package com.marvinelsen.willow.ui.controllers.dialogs
import com.marvinelsen.willow.config.Config
import com.marvinelsen.willow.config.Pronunciation
import com.marvinelsen.willow.config.Script
import com.marvinelsen.willow.config.Theme
import com.marvinelsen.willow.ui.formatters.FontSizeTextFormatter
import javafx.fxml.FXML
import javafx.scene.control.CheckBox
import javafx.scene.control.ComboBox
import javafx.scene.control.Spinner
import java.util.Locale
@Suppress("UnusedPrivateMember")
class PreferencesDialogController(private val config: Config) {
@FXML
private lateinit var comboBoxLocale: ComboBox<Locale>
@FXML
private lateinit var comboBoxTheme: ComboBox<Theme>
@FXML
private lateinit var comboBoxScript: ComboBox<Script>
@FXML
private lateinit var comboBoxPronunciationSearchResults: ComboBox<Pronunciation>
@FXML
private lateinit var comboBoxPronunciationDetails: ComboBox<Pronunciation>
@FXML
private lateinit var checkBoxShowPronunciationSearchResults: CheckBox
@FXML
private lateinit var checkBoxShowDefinitionSearchResults: CheckBox
@FXML
private lateinit var spinnerHeadwordFontSizeDetails: Spinner<Int>
@FXML
private lateinit var spinnerPronunciationFontSizeDetails: Spinner<Int>
@FXML
private lateinit var spinnerHeadwordFontSizeSearchResults: Spinner<Int>
@FXML
private lateinit var spinnerPronunciationFontSizeSearchResults: Spinner<Int>
@FXML
private lateinit var spinnerDefinitionFontSizeSearchResults: Spinner<Int>
private val entryHeadwordFontSizeObjectProperty = config.details.headwordFontSize.asObject()
private val entryPronunciationFontSizeObjectProperty = config.details.pronunciationFontSize.asObject()
private val searchResultHeadwordFontSizeObjectProperty = config.searchResults.headwordFontSize.asObject()
private val searchResultPronunciationFontSizeObjectProperty = config.searchResults.pronunciationFontSize.asObject()
private val searchResultDefinitionFontSizeObjectProperty = config.searchResults.definitionFontSize.asObject()
@FXML
private fun initialize() {
comboBoxLocale.items.addAll(
setOf(
Locale.ENGLISH,
Locale.GERMAN,
Locale.CHINA,
Locale.TAIWAN
)
)
comboBoxTheme.valueProperty().bindBidirectional(config.theme)
comboBoxScript.valueProperty().bindBidirectional(config.script)
comboBoxLocale.valueProperty().bindBidirectional(config.locale)
comboBoxPronunciationSearchResults.valueProperty().bindBidirectional(config.searchResults.pronunciation)
comboBoxPronunciationDetails.valueProperty().bindBidirectional(config.details.pronunciation)
checkBoxShowDefinitionSearchResults
.selectedProperty()
.bindBidirectional(config.searchResults.shouldShowDefinition)
checkBoxShowPronunciationSearchResults
.selectedProperty()
.bindBidirectional(config.searchResults.shouldShowPronunciation)
with(spinnerHeadwordFontSizeDetails) {
editor.textFormatter = FontSizeTextFormatter()
valueFactory.valueProperty().bindBidirectional(entryHeadwordFontSizeObjectProperty)
}
with(spinnerPronunciationFontSizeDetails) {
editor.textFormatter = FontSizeTextFormatter()
valueFactory.valueProperty().bindBidirectional(entryPronunciationFontSizeObjectProperty)
}
with(spinnerHeadwordFontSizeSearchResults) {
editor.textFormatter = FontSizeTextFormatter()
valueFactory.valueProperty().bindBidirectional(searchResultHeadwordFontSizeObjectProperty)
}
with(spinnerPronunciationFontSizeSearchResults) {
editor.textFormatter = FontSizeTextFormatter()
valueFactory.valueProperty().bindBidirectional(searchResultPronunciationFontSizeObjectProperty)
}
with(spinnerDefinitionFontSizeSearchResults) {
editor.textFormatter = FontSizeTextFormatter()
valueFactory.valueProperty().bindBidirectional(searchResultDefinitionFontSizeObjectProperty)
}
}
}

View File

@ -1,42 +1,82 @@
package com.marvinelsen.willow.ui.dialogs
import com.marvinelsen.willow.WillowApplication
import com.marvinelsen.willow.config.Config
import com.marvinelsen.willow.ui.controllers.dialogs.PreferencesDialogController
import com.marvinelsen.willow.config.Pronunciation
import com.marvinelsen.willow.config.Script
import com.marvinelsen.willow.config.Theme
import com.marvinelsen.willow.ui.formatters.FontSizeTextFormatter
import javafx.fxml.FXML
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
import java.util.ResourceBundle
import java.util.Locale
class PreferencesDialog(
owner: Window?,
config: Config,
resources: ResourceBundle,
) : Dialog<PreferencesDialog.Result>() {
class PreferencesDialog(owner: Window?, config: Config) : Dialog<PreferencesDialog.Result>() {
companion object {
private const val MIN_HEIGHT = 400.0
private const val MIN_WIDTH = 400.0
private const val DIALOG_MIN_HEIGHT = 400.0
private const val DIALOG_MIN_WIDTH = 400.0
}
enum class Result {
SAVE_CHANGES, DO_NOT_SAVE_CHANGES
CHANGES, NO_CHANGES
}
@FXML
private lateinit var comboBoxLocale: ComboBox<Locale>
@FXML
private lateinit var comboBoxTheme: ComboBox<Theme>
@FXML
private lateinit var comboBoxScript: ComboBox<Script>
@FXML
private lateinit var comboBoxPronunciationSearchResults: ComboBox<Pronunciation>
@FXML
private lateinit var comboBoxPronunciationDetails: ComboBox<Pronunciation>
@FXML
private lateinit var checkBoxShowPronunciationSearchResults: CheckBox
@FXML
private lateinit var checkBoxShowDefinitionSearchResults: CheckBox
@FXML
private lateinit var spinnerHeadwordFontSizeDetails: Spinner<Int>
@FXML
private lateinit var spinnerPronunciationFontSizeDetails: Spinner<Int>
@FXML
private lateinit var spinnerHeadwordFontSizeSearchResults: Spinner<Int>
@FXML
private lateinit var spinnerPronunciationFontSizeSearchResults: Spinner<Int>
@FXML
private lateinit var spinnerDefinitionFontSizeSearchResults: Spinner<Int>
private val entryHeadwordFontSizeObjectProperty = config.details.headwordFontSize.asObject()
private val entryPronunciationFontSizeObjectProperty = config.details.pronunciationFontSize.asObject()
private val searchResultHeadwordFontSizeObjectProperty = config.searchResults.headwordFontSize.asObject()
private val searchResultPronunciationFontSizeObjectProperty = config.searchResults.pronunciationFontSize.asObject()
private val searchResultDefinitionFontSizeObjectProperty = config.searchResults.definitionFontSize.asObject()
init {
val fxmlLoader = FXMLLoader()
fxmlLoader.resources = resources
fxmlLoader.controllerFactory = Callback { type ->
when (type) {
PreferencesDialogController::class.java -> PreferencesDialogController(config)
else -> error("Trying to instantiate unknown controller type $type")
}
}
val root = fxmlLoader.load(javaClass.getResourceAsStream("/fxml/dialogs/preferences.fxml")) as DialogPane
val loader = FXMLLoader(WillowApplication::class.java.getResource("/fxml/dialogs/preferences.fxml"))
loader.setController(this)
val root: DialogPane = loader.load()
dialogPane = root
title = "Settings"
@ -46,8 +86,55 @@ class PreferencesDialog(
initModality(Modality.APPLICATION_MODAL)
(dialogPane.scene.window as Stage).apply {
minWidth = MIN_WIDTH
minHeight = MIN_HEIGHT
minWidth = DIALOG_MIN_WIDTH
minHeight = DIALOG_MIN_HEIGHT
}
comboBoxLocale.items.addAll(
setOf(
Locale.ENGLISH,
Locale.GERMAN,
Locale.CHINA,
Locale.TAIWAN
)
)
comboBoxTheme.valueProperty().bindBidirectional(config.theme)
comboBoxScript.valueProperty().bindBidirectional(config.script)
comboBoxLocale.valueProperty().bindBidirectional(config.locale)
comboBoxPronunciationSearchResults.valueProperty().bindBidirectional(config.searchResults.pronunciation)
comboBoxPronunciationDetails.valueProperty().bindBidirectional(config.details.pronunciation)
checkBoxShowDefinitionSearchResults
.selectedProperty()
.bindBidirectional(config.searchResults.shouldShowDefinition)
checkBoxShowPronunciationSearchResults
.selectedProperty()
.bindBidirectional(config.searchResults.shouldShowPronunciation)
with(spinnerHeadwordFontSizeDetails) {
editor.textFormatter = FontSizeTextFormatter()
valueFactory.valueProperty().bindBidirectional(entryHeadwordFontSizeObjectProperty)
}
with(spinnerPronunciationFontSizeDetails) {
editor.textFormatter = FontSizeTextFormatter()
valueFactory.valueProperty().bindBidirectional(entryPronunciationFontSizeObjectProperty)
}
with(spinnerHeadwordFontSizeSearchResults) {
editor.textFormatter = FontSizeTextFormatter()
valueFactory.valueProperty().bindBidirectional(searchResultHeadwordFontSizeObjectProperty)
}
with(spinnerPronunciationFontSizeSearchResults) {
editor.textFormatter = FontSizeTextFormatter()
valueFactory.valueProperty().bindBidirectional(searchResultPronunciationFontSizeObjectProperty)
}
with(spinnerDefinitionFontSizeSearchResults) {
editor.textFormatter = FontSizeTextFormatter()
valueFactory.valueProperty().bindBidirectional(searchResultDefinitionFontSizeObjectProperty)
}
resultConverter = Callback(::convertToResult)
@ -55,7 +142,7 @@ class PreferencesDialog(
private fun convertToResult(buttonType: ButtonType) =
when (buttonType) {
ButtonType.APPLY -> Result.SAVE_CHANGES
else -> Result.DO_NOT_SAVE_CHANGES
ButtonType.APPLY -> Result.CHANGES
else -> Result.NO_CHANGES
}
}

View File

@ -1,20 +0,0 @@
package com.marvinelsen.willow.ui.services
import com.marvinelsen.willow.domain.Dictionary
import com.marvinelsen.willow.ui.DictionaryEntryFx
import com.marvinelsen.willow.ui.toDomain
import com.marvinelsen.willow.ui.toFx
import com.marvinelsen.willow.ui.util.task
import javafx.collections.FXCollections
import javafx.collections.ObservableList
import javafx.concurrent.Service
class FindCharacterService(private val dictionary: Dictionary) : Service<ObservableList<DictionaryEntryFx>>() {
lateinit var entry: DictionaryEntryFx
override fun createTask() = task {
if (!this::entry.isInitialized) error("Entry is not initialized")
FXCollections.observableList(dictionary.findCharacters(entry.toDomain()).map { it.toFx() })
}
}

View File

@ -1,20 +0,0 @@
package com.marvinelsen.willow.ui.services
import com.marvinelsen.willow.domain.Dictionary
import com.marvinelsen.willow.ui.DictionaryEntryFx
import com.marvinelsen.willow.ui.toDomain
import com.marvinelsen.willow.ui.toFx
import com.marvinelsen.willow.ui.util.task
import javafx.collections.FXCollections
import javafx.collections.ObservableList
import javafx.concurrent.Service
class FindWordsService(private val dictionary: Dictionary) : Service<ObservableList<DictionaryEntryFx>>() {
lateinit var entry: DictionaryEntryFx
override fun createTask() = task {
if (!this::entry.isInitialized) error("Entry is not initialized")
FXCollections.observableList(dictionary.findWordsContaining(entry.toDomain()).map { it.toFx() })
}
}

View File

@ -1,22 +0,0 @@
package com.marvinelsen.willow.ui.services
import com.marvinelsen.willow.domain.Dictionary
import com.marvinelsen.willow.domain.SearchMode
import com.marvinelsen.willow.ui.DictionaryEntryFx
import com.marvinelsen.willow.ui.toFx
import com.marvinelsen.willow.ui.util.task
import javafx.collections.FXCollections
import javafx.collections.ObservableList
import javafx.concurrent.Service
class SearchService(private val dictionary: Dictionary) : Service<ObservableList<DictionaryEntryFx>>() {
lateinit var searchQuery: String
lateinit var searchMode: SearchMode
override fun createTask() = task {
if (!this::searchQuery.isInitialized) error("Search query is not initialized")
if (!this::searchMode.isInitialized) error("Search mode is not initialized")
FXCollections.observableList(dictionary.search(searchQuery, searchMode).map { it.toFx() })
}
}

View File

@ -0,0 +1,42 @@
package com.marvinelsen.willow.ui.util
import com.marvinelsen.willow.domain.Dictionary
import com.marvinelsen.willow.domain.SearchMode
import com.marvinelsen.willow.ui.DictionaryEntryFx
import com.marvinelsen.willow.ui.toDomain
import com.marvinelsen.willow.ui.toFx
import javafx.collections.FXCollections
import javafx.collections.ObservableList
import javafx.concurrent.Service
class SearchService(private val dictionary: Dictionary) : Service<ObservableList<DictionaryEntryFx>>() {
lateinit var searchQuery: String
lateinit var searchMode: SearchMode
override fun createTask() = task {
if (!this::searchQuery.isInitialized) error("Search query is not initialized")
if (!this::searchMode.isInitialized) error("Search mode is not initialized")
FXCollections.observableList(dictionary.search(searchQuery, searchMode).map { it.toFx() })
}
}
class FindWordsService(private val dictionary: Dictionary) : Service<ObservableList<DictionaryEntryFx>>() {
lateinit var entry: DictionaryEntryFx
override fun createTask() = task {
if (!this::entry.isInitialized) error("Entry is not initialized")
FXCollections.observableList(dictionary.findWordsContaining(entry.toDomain()).map { it.toFx() })
}
}
class FindCharacterService(private val dictionary: Dictionary) : Service<ObservableList<DictionaryEntryFx>>() {
lateinit var entry: DictionaryEntryFx
override fun createTask() = task {
if (!this::entry.isInitialized) error("Entry is not initialized")
FXCollections.observableList(dictionary.findCharacters(entry.toDomain()).map { it.toFx() })
}
}

View File

@ -4,21 +4,13 @@ https://openjfx.io/javadoc/23/javafx.graphics/javafx/scene/doc-files/cssref.html
*/
.root {
willow-background: #282828;
willow-foreground: #dfdfdf;
-fx-base: willow-background;
-fx-accent: #5c7654;
-fx-focus-color: #3e8f25;
willow-background: #2D2D30;
willow-foreground: #ffffff;
-fx-background-color: willow-background;
-fx-text-fill: willow-foreground;
background-color: willow-background;
}
/*.split-pane {
-fx-background-color: willow-background;
}*/
.label {
-fx-text-fill: willow-foreground;
}
@ -26,13 +18,3 @@ https://openjfx.io/javadoc/23/javafx.graphics/javafx/scene/doc-files/cssref.html
.radio-button {
-fx-text-fill: willow-foreground;
}
.list-cell:even {
-fx-text-fill: willow-foreground;
-fx-background: #1e1e1e;
}
.list-cell:odd {
-fx-text-fill: willow-foreground;
-fx-background: #292929;
}

View File

@ -7,7 +7,7 @@
<VBox xmlns="http://javafx.com/javafx/23" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.marvinelsen.willow.ui.controllers.DetailsController"
stylesheets="/css/details.css">
<FlowPane fx:id="flowPaneHeader" styleClass="flow-pane-header" hgap="8.0" onContextMenuRequested="#headerOnContextMenuRequested"
<FlowPane fx:id="flowPaneHeader" hgap="8.0" onContextMenuRequested="#headerOnContextMenuRequested"
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"/>

View File

@ -7,8 +7,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<DialogPane styleClass="preferences-dialog" xmlns="http://javafx.com/javafx/23" xmlns:fx="http://javafx.com/fxml/1"
stylesheets="/css/preferences.css"
fx:controller="com.marvinelsen.willow.ui.controllers.dialogs.PreferencesDialogController">
stylesheets="/css/preferences.css">
<fx:define>
<FXCollections fx:factory="observableArrayList" fx:id="phoneticAlphabets">
<Pronunciation fx:value="PINYIN_WITH_TONE_MARKS"/>
@ -170,6 +169,6 @@
</Tab>
</TabPane>
</content>
<ButtonType fx:constant="APPLY"/>
<ButtonType fx:id="buttonTypeApply" fx:constant="APPLY"/>
<ButtonType fx:constant="CANCEL"/>
</DialogPane>

View File

@ -15,7 +15,7 @@
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0"/>
</BorderPane.margin>
<fx:include source="/fxml/search.fxml"/>
<SplitPane styleClass="split-pane" dividerPositions="0.33" VBox.vgrow="ALWAYS">
<SplitPane dividerPositions="0.33" VBox.vgrow="ALWAYS">
<fx:include source="/fxml/search-results.fxml"/>
<fx:include source="/fxml/details.fxml"/>
</SplitPane>