Compare commits
No commits in common. "52acfeb5da5f23271693fea89caeb12752839897" and "8976165b27a917e4c51ef6cdf8cb62090e5a465f" have entirely different histories.
52acfeb5da
...
8976165b27
@ -32,7 +32,6 @@ dependencies {
|
|||||||
implementation(libs.segment)
|
implementation(libs.segment)
|
||||||
|
|
||||||
implementation(libs.ikonli.javafx)
|
implementation(libs.ikonli.javafx)
|
||||||
implementation(libs.ikonli.material2)
|
|
||||||
|
|
||||||
implementation(libs.slf4j.nop)
|
implementation(libs.slf4j.nop)
|
||||||
|
|
||||||
@ -51,7 +50,6 @@ kotlin {
|
|||||||
javafx {
|
javafx {
|
||||||
version = libs.versions.javafx.get()
|
version = libs.versions.javafx.get()
|
||||||
modules("javafx.base", "javafx.graphics", "javafx.controls", "javafx.fxml", "javafx.web")
|
modules("javafx.base", "javafx.graphics", "javafx.controls", "javafx.fxml", "javafx.web")
|
||||||
// setPlatform("mac")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
detekt {
|
detekt {
|
||||||
|
@ -36,7 +36,6 @@ segment = { module = "com.github.houbb:segment", version.ref = "segment" }
|
|||||||
slf4j-nop = { module = "org.slf4j:slf4j-nop", version.ref = "slf4j" }
|
slf4j-nop = { module = "org.slf4j:slf4j-nop", version.ref = "slf4j" }
|
||||||
|
|
||||||
ikonli-javafx = { module = "org.kordamp.ikonli:ikonli-javafx", version.ref = "ikonli-javafx" }
|
ikonli-javafx = { module = "org.kordamp.ikonli:ikonli-javafx", version.ref = "ikonli-javafx" }
|
||||||
ikonli-material2 = { group = "org.kordamp.ikonli", name = "ikonli-material2-pack", version.ref = "ikonli-javafx" }
|
|
||||||
|
|
||||||
# Detekt
|
# Detekt
|
||||||
# See: https://detekt.dev
|
# See: https://detekt.dev
|
||||||
|
@ -2,4 +2,4 @@ package com.marvinelsen.willow
|
|||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
actualMain(args)
|
actualMain(args)
|
||||||
}
|
}
|
@ -2,10 +2,10 @@ package com.marvinelsen.willow
|
|||||||
|
|
||||||
import com.marvinelsen.willow.domain.SearchMode
|
import com.marvinelsen.willow.domain.SearchMode
|
||||||
import com.marvinelsen.willow.domain.SqliteDictionary
|
import com.marvinelsen.willow.domain.SqliteDictionary
|
||||||
import com.marvinelsen.willow.domain.entities.DictionaryEntry
|
import com.marvinelsen.willow.ui.DictionaryEntryFx
|
||||||
import com.marvinelsen.willow.domain.entities.Sentence
|
import com.marvinelsen.willow.ui.SentenceFx
|
||||||
import com.marvinelsen.willow.ui.undo.Command
|
import com.marvinelsen.willow.ui.toDomain
|
||||||
import com.marvinelsen.willow.ui.undo.UndoManager
|
import com.marvinelsen.willow.ui.toFx
|
||||||
import com.marvinelsen.willow.ui.util.ClipboardHelper
|
import com.marvinelsen.willow.ui.util.ClipboardHelper
|
||||||
import javafx.beans.property.BooleanProperty
|
import javafx.beans.property.BooleanProperty
|
||||||
import javafx.beans.property.ObjectProperty
|
import javafx.beans.property.ObjectProperty
|
||||||
@ -18,17 +18,15 @@ import javafx.collections.ObservableList
|
|||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Suppress("TooManyFunctions")
|
|
||||||
class Model(
|
class Model(
|
||||||
private val dictionary: SqliteDictionary,
|
private val dictionary: SqliteDictionary,
|
||||||
private val undoManager: UndoManager,
|
|
||||||
) {
|
) {
|
||||||
private val internalSelectedEntry: ObjectProperty<DictionaryEntry> = SimpleObjectProperty()
|
private val internalSelectedEntry: ObjectProperty<DictionaryEntryFx> = SimpleObjectProperty()
|
||||||
private val internalSearchResults: ObservableList<DictionaryEntry> = FXCollections.observableArrayList()
|
private val internalSearchResults: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
|
||||||
private val internalWordsBeginning: ObservableList<DictionaryEntry> = FXCollections.observableArrayList()
|
private val internalWordsBeginning: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
|
||||||
private val internalWordsContaining: ObservableList<DictionaryEntry> = FXCollections.observableArrayList()
|
private val internalWordsContaining: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
|
||||||
private val internalCharacters: ObservableList<DictionaryEntry> = FXCollections.observableArrayList()
|
private val internalCharacters: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
|
||||||
private val internalSentences: ObservableList<Sentence> = FXCollections.observableArrayList()
|
private val internalSentences: ObservableList<SentenceFx> = FXCollections.observableArrayList()
|
||||||
|
|
||||||
private val internalIsSearching: BooleanProperty = SimpleBooleanProperty(false)
|
private val internalIsSearching: BooleanProperty = SimpleBooleanProperty(false)
|
||||||
private val internalIsFindingWordsBeginning: BooleanProperty = SimpleBooleanProperty(false)
|
private val internalIsFindingWordsBeginning: BooleanProperty = SimpleBooleanProperty(false)
|
||||||
@ -41,20 +39,17 @@ class Model(
|
|||||||
private val internalFinishedFindingCharacters: BooleanProperty = SimpleBooleanProperty(false)
|
private val internalFinishedFindingCharacters: BooleanProperty = SimpleBooleanProperty(false)
|
||||||
private val internalFinishedFindingSentences: BooleanProperty = SimpleBooleanProperty(false)
|
private val internalFinishedFindingSentences: BooleanProperty = SimpleBooleanProperty(false)
|
||||||
|
|
||||||
val canUndo: ReadOnlyBooleanProperty = undoManager.canUndoProperty
|
val selectedEntry: ReadOnlyObjectProperty<DictionaryEntryFx> = internalSelectedEntry
|
||||||
val canRedo: ReadOnlyBooleanProperty = undoManager.canRedoProperty
|
|
||||||
|
|
||||||
val selectedEntry: ReadOnlyObjectProperty<DictionaryEntry> = internalSelectedEntry
|
val searchResults: ObservableList<DictionaryEntryFx> =
|
||||||
|
|
||||||
val searchResults: ObservableList<DictionaryEntry> =
|
|
||||||
FXCollections.unmodifiableObservableList(internalSearchResults)
|
FXCollections.unmodifiableObservableList(internalSearchResults)
|
||||||
val wordsBeginning: ObservableList<DictionaryEntry> =
|
val wordsBeginning: ObservableList<DictionaryEntryFx> =
|
||||||
FXCollections.unmodifiableObservableList(internalWordsBeginning)
|
FXCollections.unmodifiableObservableList(internalWordsBeginning)
|
||||||
val wordsContaining: ObservableList<DictionaryEntry> =
|
val wordsContaining: ObservableList<DictionaryEntryFx> =
|
||||||
FXCollections.unmodifiableObservableList(internalWordsContaining)
|
FXCollections.unmodifiableObservableList(internalWordsContaining)
|
||||||
val characters: ObservableList<DictionaryEntry> =
|
val characters: ObservableList<DictionaryEntryFx> =
|
||||||
FXCollections.unmodifiableObservableList(internalCharacters)
|
FXCollections.unmodifiableObservableList(internalCharacters)
|
||||||
val sentences: ObservableList<Sentence> =
|
val sentences: ObservableList<SentenceFx> =
|
||||||
FXCollections.unmodifiableObservableList(internalSentences)
|
FXCollections.unmodifiableObservableList(internalSentences)
|
||||||
|
|
||||||
val isSearching: ReadOnlyBooleanProperty = internalIsSearching
|
val isSearching: ReadOnlyBooleanProperty = internalIsSearching
|
||||||
@ -70,26 +65,10 @@ class Model(
|
|||||||
|
|
||||||
private val coroutineScope = MainScope()
|
private val coroutineScope = MainScope()
|
||||||
|
|
||||||
fun copyHeadwordOfSelectedEntry() {
|
|
||||||
ClipboardHelper.copyString(internalSelectedEntry.value.traditional)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copyPronunciationOfSelectedEntry() {
|
|
||||||
ClipboardHelper.copyString(internalSelectedEntry.value.pinyinWithToneMarks)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun undoSelection() {
|
|
||||||
undoManager.undo()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun redoSelection() {
|
|
||||||
undoManager.redo()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun search(query: String, searchMode: SearchMode) {
|
fun search(query: String, searchMode: SearchMode) {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
internalIsSearching.value = true
|
internalIsSearching.value = true
|
||||||
internalSearchResults.setAll(dictionary.search(query, searchMode))
|
internalSearchResults.setAll(dictionary.search(query, searchMode).map { it.toFx() })
|
||||||
internalIsSearching.value = false
|
internalIsSearching.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,7 +78,8 @@ class Model(
|
|||||||
internalIsFindingWordsBeginning.value = true
|
internalIsFindingWordsBeginning.value = true
|
||||||
internalWordsBeginning.setAll(
|
internalWordsBeginning.setAll(
|
||||||
dictionary
|
dictionary
|
||||||
.findWordsBeginningWith(internalSelectedEntry.value)
|
.findWordsBeginningWith(internalSelectedEntry.value.toDomain())
|
||||||
|
.map { it.toFx() }
|
||||||
)
|
)
|
||||||
internalIsFindingWordsBeginning.value = false
|
internalIsFindingWordsBeginning.value = false
|
||||||
internalFinishedFindingWordsBeginning.value = true
|
internalFinishedFindingWordsBeginning.value = true
|
||||||
@ -111,7 +91,8 @@ class Model(
|
|||||||
internalIsFindingWordsContaining.value = true
|
internalIsFindingWordsContaining.value = true
|
||||||
internalWordsContaining.setAll(
|
internalWordsContaining.setAll(
|
||||||
dictionary
|
dictionary
|
||||||
.findWordsContaining(internalSelectedEntry.value)
|
.findWordsContaining(internalSelectedEntry.value.toDomain())
|
||||||
|
.map { it.toFx() }
|
||||||
)
|
)
|
||||||
internalIsFindingWordsContaining.value = false
|
internalIsFindingWordsContaining.value = false
|
||||||
internalFinishedFindingWordsContaining.value = true
|
internalFinishedFindingWordsContaining.value = true
|
||||||
@ -123,7 +104,8 @@ class Model(
|
|||||||
internalIsFindingCharacters.value = true
|
internalIsFindingCharacters.value = true
|
||||||
internalCharacters.setAll(
|
internalCharacters.setAll(
|
||||||
dictionary
|
dictionary
|
||||||
.findCharactersOf(internalSelectedEntry.value)
|
.findCharactersOf(internalSelectedEntry.value.toDomain())
|
||||||
|
.map { it.toFx() }
|
||||||
)
|
)
|
||||||
internalIsFindingCharacters.value = false
|
internalIsFindingCharacters.value = false
|
||||||
internalFinishedFindingCharacters.value = true
|
internalFinishedFindingCharacters.value = true
|
||||||
@ -135,30 +117,20 @@ class Model(
|
|||||||
internalIsFindingSentences.value = true
|
internalIsFindingSentences.value = true
|
||||||
internalSentences.setAll(
|
internalSentences.setAll(
|
||||||
dictionary
|
dictionary
|
||||||
.findExampleSentencesFor(internalSelectedEntry.value)
|
.findExampleSentencesFor(internalSelectedEntry.value.toDomain())
|
||||||
|
.map { it.toFx() }
|
||||||
)
|
)
|
||||||
internalIsFindingSentences.value = false
|
internalIsFindingSentences.value = false
|
||||||
internalFinishedFindingSentences.value = true
|
internalFinishedFindingSentences.value = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun selectEntry(entry: DictionaryEntry) {
|
fun selectEntry(entry: DictionaryEntryFx) {
|
||||||
undoManager.execute(object : Command {
|
internalWordsBeginning.setAll(emptyList())
|
||||||
private val previouslySelectedEntry = internalSelectedEntry.value
|
internalWordsContaining.setAll(emptyList())
|
||||||
|
internalCharacters.setAll(emptyList())
|
||||||
|
internalSentences.setAll(emptyList())
|
||||||
|
|
||||||
override fun execute() {
|
|
||||||
select(entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun undo() {
|
|
||||||
if (previouslySelectedEntry == null) return
|
|
||||||
|
|
||||||
select(previouslySelectedEntry)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun select(entry: DictionaryEntry) {
|
|
||||||
internalFinishedFindingCharacters.value = false
|
internalFinishedFindingCharacters.value = false
|
||||||
internalFinishedFindingWordsBeginning.value = false
|
internalFinishedFindingWordsBeginning.value = false
|
||||||
internalFinishedFindingWordsContaining.value = false
|
internalFinishedFindingWordsContaining.value = false
|
||||||
@ -166,4 +138,12 @@ class Model(
|
|||||||
|
|
||||||
internalSelectedEntry.value = entry
|
internalSelectedEntry.value = entry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun copyHeadwordOfSelectedEntry() {
|
||||||
|
ClipboardHelper.copyString(internalSelectedEntry.value.traditionalProperty.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copyPronunciationOfSelectedEntry() {
|
||||||
|
ClipboardHelper.copyString(internalSelectedEntry.value.pinyinWithToneMarksProperty.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import com.marvinelsen.willow.ui.controllers.MainController
|
|||||||
import com.marvinelsen.willow.ui.controllers.MenuController
|
import com.marvinelsen.willow.ui.controllers.MenuController
|
||||||
import com.marvinelsen.willow.ui.controllers.SearchController
|
import com.marvinelsen.willow.ui.controllers.SearchController
|
||||||
import com.marvinelsen.willow.ui.controllers.SearchResultsController
|
import com.marvinelsen.willow.ui.controllers.SearchResultsController
|
||||||
import com.marvinelsen.willow.ui.undo.UndoManager
|
|
||||||
import javafx.application.Application
|
import javafx.application.Application
|
||||||
import javafx.application.HostServices
|
import javafx.application.HostServices
|
||||||
import javafx.fxml.FXMLLoader
|
import javafx.fxml.FXMLLoader
|
||||||
@ -42,10 +41,8 @@ class WillowApplication : Application() {
|
|||||||
autoCommit = false
|
autoCommit = false
|
||||||
}
|
}
|
||||||
val dictionary = SqliteDictionary(connection)
|
val dictionary = SqliteDictionary(connection)
|
||||||
val undoManager = UndoManager()
|
|
||||||
val model = Model(
|
val model = Model(
|
||||||
dictionary,
|
dictionary,
|
||||||
undoManager
|
|
||||||
)
|
)
|
||||||
val config = Config()
|
val config = Config()
|
||||||
config.load()
|
config.load()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.marvinelsen.willow.domain.entities.definitions
|
package com.marvinelsen.willow.domain
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
@ -1,8 +1,5 @@
|
|||||||
package com.marvinelsen.willow.domain
|
package com.marvinelsen.willow.domain
|
||||||
|
|
||||||
import com.marvinelsen.willow.domain.entities.DictionaryEntry
|
|
||||||
import com.marvinelsen.willow.domain.entities.Sentence
|
|
||||||
|
|
||||||
interface Dictionary {
|
interface Dictionary {
|
||||||
suspend fun search(query: String, searchMode: SearchMode): List<DictionaryEntry>
|
suspend fun search(query: String, searchMode: SearchMode): List<DictionaryEntry>
|
||||||
|
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
package com.marvinelsen.willow.domain.entities
|
package com.marvinelsen.willow.domain
|
||||||
|
|
||||||
import com.marvinelsen.willow.domain.entities.definitions.CrossStraitsDefinition
|
|
||||||
import com.marvinelsen.willow.domain.entities.definitions.MoedictDefinition
|
|
||||||
|
|
||||||
data class DictionaryEntry(
|
data class DictionaryEntry(
|
||||||
val traditional: String,
|
val traditional: String,
|
@ -1,4 +1,4 @@
|
|||||||
package com.marvinelsen.willow.domain.entities.definitions
|
package com.marvinelsen.willow.domain
|
||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
@ -1,4 +1,4 @@
|
|||||||
package com.marvinelsen.willow.domain.entities
|
package com.marvinelsen.willow.domain
|
||||||
|
|
||||||
data class Sentence(
|
data class Sentence(
|
||||||
val traditional: String,
|
val traditional: String,
|
@ -8,8 +8,6 @@ import com.github.houbb.segment.support.segment.impl.Segments
|
|||||||
import com.github.houbb.segment.support.segment.mode.impl.SegmentModes
|
import com.github.houbb.segment.support.segment.mode.impl.SegmentModes
|
||||||
import com.github.houbb.segment.support.segment.result.impl.SegmentResultHandlers
|
import com.github.houbb.segment.support.segment.result.impl.SegmentResultHandlers
|
||||||
import com.github.houbb.segment.support.tagging.pos.tag.impl.SegmentPosTaggings
|
import com.github.houbb.segment.support.tagging.pos.tag.impl.SegmentPosTaggings
|
||||||
import com.marvinelsen.willow.domain.entities.DictionaryEntry
|
|
||||||
import com.marvinelsen.willow.domain.entities.Sentence
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
package com.marvinelsen.willow.ui
|
||||||
|
|
||||||
|
import com.marvinelsen.willow.domain.CrossStraitsDefinition
|
||||||
|
import com.marvinelsen.willow.domain.DictionaryEntry
|
||||||
|
import com.marvinelsen.willow.domain.MoedictDefinition
|
||||||
|
import javafx.beans.property.SimpleStringProperty
|
||||||
|
import javafx.beans.property.StringProperty
|
||||||
|
import javafx.collections.FXCollections
|
||||||
|
import javafx.collections.ObservableList
|
||||||
|
|
||||||
|
data class DictionaryEntryFx(
|
||||||
|
val traditionalProperty: StringProperty,
|
||||||
|
val simplifiedProperty: StringProperty,
|
||||||
|
val pinyinWithToneMarksProperty: StringProperty,
|
||||||
|
val pinyinWithToneNumbersProperty: StringProperty,
|
||||||
|
val zhuyinProperty: StringProperty,
|
||||||
|
val cedictDefinitions: ObservableList<List<String>>,
|
||||||
|
val crossStraitsDefinitions: ObservableList<CrossStraitsDefinition>,
|
||||||
|
val moedictDefinitions: ObservableList<MoedictDefinition>,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun DictionaryEntry.toFx() = DictionaryEntryFx(
|
||||||
|
traditionalProperty = SimpleStringProperty(this.traditional),
|
||||||
|
simplifiedProperty = SimpleStringProperty(this.simplified),
|
||||||
|
pinyinWithToneMarksProperty = SimpleStringProperty(this.pinyinWithToneMarks),
|
||||||
|
pinyinWithToneNumbersProperty = SimpleStringProperty(this.pinyinWithToneNumbers),
|
||||||
|
zhuyinProperty = SimpleStringProperty(this.zhuyin),
|
||||||
|
cedictDefinitions = FXCollections.observableList(this.cedictDefinitions),
|
||||||
|
crossStraitsDefinitions = FXCollections.observableList(this.crossStraitsDefinitions),
|
||||||
|
moedictDefinitions = FXCollections.observableList(this.moedictDefinitions),
|
||||||
|
)
|
||||||
|
|
||||||
|
fun DictionaryEntryFx.toDomain() = DictionaryEntry(
|
||||||
|
traditional = this.traditionalProperty.value,
|
||||||
|
simplified = this.simplifiedProperty.value,
|
||||||
|
pinyinWithToneMarks = this.pinyinWithToneMarksProperty.value,
|
||||||
|
pinyinWithToneNumbers = this.pinyinWithToneNumbersProperty.value,
|
||||||
|
zhuyin = this.zhuyinProperty.value,
|
||||||
|
cedictDefinitions = this.cedictDefinitions.toList(),
|
||||||
|
crossStraitsDefinitions = this.crossStraitsDefinitions.toList(),
|
||||||
|
moedictDefinitions = this.moedictDefinitions.toList(),
|
||||||
|
)
|
20
src/main/kotlin/com/marvinelsen/willow/ui/SentenceFx.kt
Normal file
20
src/main/kotlin/com/marvinelsen/willow/ui/SentenceFx.kt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package com.marvinelsen.willow.ui
|
||||||
|
|
||||||
|
import com.marvinelsen.willow.domain.Sentence
|
||||||
|
import javafx.beans.property.SimpleStringProperty
|
||||||
|
import javafx.beans.property.StringProperty
|
||||||
|
|
||||||
|
data class SentenceFx(
|
||||||
|
val traditionalProperty: StringProperty,
|
||||||
|
val simplifiedProperty: StringProperty,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun Sentence.toFx() = SentenceFx(
|
||||||
|
traditionalProperty = SimpleStringProperty(this.traditional),
|
||||||
|
simplifiedProperty = SimpleStringProperty(this.simplified),
|
||||||
|
)
|
||||||
|
|
||||||
|
fun SentenceFx.toDomain() = Sentence(
|
||||||
|
traditional = this.traditionalProperty.value,
|
||||||
|
simplified = this.simplifiedProperty.value,
|
||||||
|
)
|
@ -3,7 +3,7 @@ package com.marvinelsen.willow.ui.cells
|
|||||||
import com.marvinelsen.willow.config.Config
|
import com.marvinelsen.willow.config.Config
|
||||||
import com.marvinelsen.willow.config.Pronunciation
|
import com.marvinelsen.willow.config.Pronunciation
|
||||||
import com.marvinelsen.willow.config.Script
|
import com.marvinelsen.willow.config.Script
|
||||||
import com.marvinelsen.willow.domain.entities.DictionaryEntry
|
import com.marvinelsen.willow.ui.DictionaryEntryFx
|
||||||
import com.marvinelsen.willow.ui.util.createContextMenuForEntry
|
import com.marvinelsen.willow.ui.util.createContextMenuForEntry
|
||||||
import javafx.application.HostServices
|
import javafx.application.HostServices
|
||||||
import javafx.beans.binding.Bindings
|
import javafx.beans.binding.Bindings
|
||||||
@ -20,9 +20,9 @@ class DictionaryEntryCellFactory(
|
|||||||
private val resources: ResourceBundle,
|
private val resources: ResourceBundle,
|
||||||
private val config: Config,
|
private val config: Config,
|
||||||
private val hostServices: HostServices,
|
private val hostServices: HostServices,
|
||||||
) : Callback<ListView<DictionaryEntry?>, ListCell<DictionaryEntry?>> {
|
) : Callback<ListView<DictionaryEntryFx?>, ListCell<DictionaryEntryFx?>> {
|
||||||
|
|
||||||
override fun call(listView: ListView<DictionaryEntry?>): ListCell<DictionaryEntry?> {
|
override fun call(listView: ListView<DictionaryEntryFx?>): ListCell<DictionaryEntryFx?> {
|
||||||
val entryCell = EntryCell(resources, config, hostServices)
|
val entryCell = EntryCell(resources, config, hostServices)
|
||||||
entryCell.prefWidthProperty().bind(listView.widthProperty().subtract(CELL_PADDING))
|
entryCell.prefWidthProperty().bind(listView.widthProperty().subtract(CELL_PADDING))
|
||||||
return entryCell
|
return entryCell
|
||||||
@ -37,69 +37,59 @@ private class EntryCell(
|
|||||||
private val resources: ResourceBundle,
|
private val resources: ResourceBundle,
|
||||||
private val config: Config,
|
private val config: Config,
|
||||||
private val hostServices: HostServices,
|
private val hostServices: HostServices,
|
||||||
) : ListCell<DictionaryEntry?>() {
|
) : ListCell<DictionaryEntryFx?>() {
|
||||||
|
|
||||||
private val labelHeadword by lazy {
|
private val labelHeadword = Label().apply {
|
||||||
Label().apply {
|
styleClass.add("headword")
|
||||||
styleClass.add("headword")
|
styleProperty().bind(
|
||||||
styleProperty().bind(
|
Bindings.concat(
|
||||||
Bindings.concat(
|
"-fx-font-size: ",
|
||||||
"-fx-font-size: ",
|
config.searchResults.headwordFontSize.asString(),
|
||||||
config.searchResults.headwordFontSize.asString(),
|
"px;"
|
||||||
"px;"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val labelDefinition by lazy {
|
private val labelDefinition = Label().apply {
|
||||||
Label().apply {
|
styleClass.add("definition")
|
||||||
styleClass.add("definition")
|
styleProperty().bind(
|
||||||
styleProperty().bind(
|
Bindings.concat(
|
||||||
Bindings.concat(
|
"-fx-font-size: ",
|
||||||
"-fx-font-size: ",
|
config.searchResults.definitionFontSize.asString(),
|
||||||
config.searchResults.definitionFontSize.asString(),
|
"px;"
|
||||||
"px;"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
visibleProperty().bind(config.searchResults.shouldShowDefinition)
|
)
|
||||||
managedProperty().bind(config.searchResults.shouldShowDefinition)
|
visibleProperty().bind(config.searchResults.shouldShowDefinition)
|
||||||
}
|
managedProperty().bind(config.searchResults.shouldShowDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val labelPronunciation by lazy {
|
private val labelPronunciation = Label().apply {
|
||||||
Label().apply {
|
styleClass.add("pronunciation")
|
||||||
styleClass.add("pronunciation")
|
styleProperty().bind(
|
||||||
styleProperty().bind(
|
Bindings.concat(
|
||||||
Bindings.concat(
|
"-fx-font-size: ",
|
||||||
"-fx-font-size: ",
|
config.searchResults.pronunciationFontSize.asString(),
|
||||||
config.searchResults.pronunciationFontSize.asString(),
|
"px;"
|
||||||
"px;"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
visibleProperty().bind(config.searchResults.shouldShowPronunciation)
|
)
|
||||||
managedProperty().bind(config.searchResults.shouldShowPronunciation)
|
visibleProperty().bind(config.searchResults.shouldShowPronunciation)
|
||||||
}
|
managedProperty().bind(config.searchResults.shouldShowPronunciation)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val flowPane by lazy {
|
private val flowPane = FlowPane(labelHeadword, labelPronunciation).apply {
|
||||||
FlowPane(labelHeadword, labelPronunciation).apply {
|
hgap = FLOW_PANE_HGAP
|
||||||
hgap = FLOW_PANE_HGAP
|
rowValignment = VPos.BASELINE
|
||||||
rowValignment = VPos.BASELINE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val root by lazy {
|
private val root = VBox(flowPane, labelDefinition).apply {
|
||||||
VBox(flowPane, labelDefinition).apply {
|
styleClass.add("search-result")
|
||||||
styleClass.add("search-result")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
text = null
|
text = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateItem(entry: DictionaryEntry?, empty: Boolean) {
|
override fun updateItem(entry: DictionaryEntryFx?, empty: Boolean) {
|
||||||
super.updateItem(entry, empty)
|
super.updateItem(entry, empty)
|
||||||
if (empty || entry == null) {
|
if (empty || entry == null) {
|
||||||
graphic = null
|
graphic = null
|
||||||
@ -109,8 +99,8 @@ private class EntryCell(
|
|||||||
Bindings.createStringBinding(
|
Bindings.createStringBinding(
|
||||||
{
|
{
|
||||||
when (config.script.value!!) {
|
when (config.script.value!!) {
|
||||||
Script.SIMPLIFIED -> entry.simplified
|
Script.SIMPLIFIED -> entry.simplifiedProperty.value
|
||||||
Script.TRADITIONAL -> entry.traditional
|
Script.TRADITIONAL -> entry.traditionalProperty.value
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
config.script
|
config.script
|
||||||
@ -120,9 +110,9 @@ private class EntryCell(
|
|||||||
Bindings.createStringBinding(
|
Bindings.createStringBinding(
|
||||||
{
|
{
|
||||||
when (config.searchResults.pronunciation.value!!) {
|
when (config.searchResults.pronunciation.value!!) {
|
||||||
Pronunciation.PINYIN_WITH_TONE_MARKS -> entry.pinyinWithToneMarks
|
Pronunciation.PINYIN_WITH_TONE_MARKS -> entry.pinyinWithToneMarksProperty.value
|
||||||
Pronunciation.PINYIN_WITH_TONE_NUMBERS -> entry.pinyinWithToneNumbers
|
Pronunciation.PINYIN_WITH_TONE_NUMBERS -> entry.pinyinWithToneNumbersProperty.value
|
||||||
Pronunciation.ZHUYIN -> entry.zhuyin
|
Pronunciation.ZHUYIN -> entry.zhuyinProperty.value
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
config.searchResults.pronunciation
|
config.searchResults.pronunciation
|
||||||
|
@ -2,7 +2,7 @@ package com.marvinelsen.willow.ui.cells
|
|||||||
|
|
||||||
import com.marvinelsen.willow.config.Config
|
import com.marvinelsen.willow.config.Config
|
||||||
import com.marvinelsen.willow.config.Script
|
import com.marvinelsen.willow.config.Script
|
||||||
import com.marvinelsen.willow.domain.entities.Sentence
|
import com.marvinelsen.willow.ui.SentenceFx
|
||||||
import com.marvinelsen.willow.ui.util.createContextMenuForSentence
|
import com.marvinelsen.willow.ui.util.createContextMenuForSentence
|
||||||
import javafx.application.HostServices
|
import javafx.application.HostServices
|
||||||
import javafx.beans.binding.Bindings
|
import javafx.beans.binding.Bindings
|
||||||
@ -17,9 +17,9 @@ class SentenceCellFactory(
|
|||||||
private val resources: ResourceBundle,
|
private val resources: ResourceBundle,
|
||||||
private val config: Config,
|
private val config: Config,
|
||||||
private val hostServices: HostServices,
|
private val hostServices: HostServices,
|
||||||
) : Callback<ListView<Sentence?>, ListCell<Sentence?>> {
|
) : Callback<ListView<SentenceFx?>, ListCell<SentenceFx?>> {
|
||||||
|
|
||||||
override fun call(listView: ListView<Sentence?>): ListCell<Sentence?> {
|
override fun call(listView: ListView<SentenceFx?>): ListCell<SentenceFx?> {
|
||||||
val sentenceCell = SentenceCell(resources, config, hostServices)
|
val sentenceCell = SentenceCell(resources, config, hostServices)
|
||||||
sentenceCell.prefWidthProperty().bind(listView.widthProperty().subtract(CELL_PADDING))
|
sentenceCell.prefWidthProperty().bind(listView.widthProperty().subtract(CELL_PADDING))
|
||||||
return sentenceCell
|
return sentenceCell
|
||||||
@ -34,35 +34,29 @@ private class SentenceCell(
|
|||||||
private val resources: ResourceBundle,
|
private val resources: ResourceBundle,
|
||||||
private val config: Config,
|
private val config: Config,
|
||||||
private val hostServices: HostServices,
|
private val hostServices: HostServices,
|
||||||
) : ListCell<Sentence?>() {
|
) : ListCell<SentenceFx?>() {
|
||||||
|
|
||||||
private val labelSentence by lazy {
|
private val labelSentence = Label().apply {
|
||||||
Label().apply {
|
styleClass.add("sentence")
|
||||||
styleClass.add("sentence")
|
isWrapText = true
|
||||||
isWrapText = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val root by lazy {
|
|
||||||
VBox(labelSentence)
|
|
||||||
}
|
}
|
||||||
|
private val root = VBox(labelSentence)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
text = null
|
text = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateItem(sentence: Sentence?, empty: Boolean) {
|
override fun updateItem(sentence: SentenceFx?, empty: Boolean) {
|
||||||
super.updateItem(sentence, empty)
|
super.updateItem(sentence, empty)
|
||||||
if (empty || sentence == null) {
|
if (empty || sentence == null) {
|
||||||
graphic = null
|
graphic = null
|
||||||
contextMenu = null
|
|
||||||
} else {
|
} else {
|
||||||
labelSentence.textProperty().bind(
|
labelSentence.textProperty().bind(
|
||||||
Bindings.createStringBinding(
|
Bindings.createStringBinding(
|
||||||
{
|
{
|
||||||
when (config.script.value!!) {
|
when (config.script.value!!) {
|
||||||
Script.SIMPLIFIED -> sentence.simplified
|
Script.SIMPLIFIED -> sentence.simplifiedProperty.value
|
||||||
Script.TRADITIONAL -> sentence.traditional
|
Script.TRADITIONAL -> sentence.traditionalProperty.value
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
config.script
|
config.script
|
||||||
|
@ -4,8 +4,8 @@ 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.Pronunciation
|
||||||
import com.marvinelsen.willow.config.Script
|
import com.marvinelsen.willow.config.Script
|
||||||
import com.marvinelsen.willow.domain.entities.DictionaryEntry
|
import com.marvinelsen.willow.ui.DictionaryEntryFx
|
||||||
import com.marvinelsen.willow.domain.entities.Sentence
|
import com.marvinelsen.willow.ui.SentenceFx
|
||||||
import com.marvinelsen.willow.ui.cells.DictionaryEntryCellFactory
|
import com.marvinelsen.willow.ui.cells.DictionaryEntryCellFactory
|
||||||
import com.marvinelsen.willow.ui.cells.SentenceCellFactory
|
import com.marvinelsen.willow.ui.cells.SentenceCellFactory
|
||||||
import com.marvinelsen.willow.ui.util.createContextMenuForEntry
|
import com.marvinelsen.willow.ui.util.createContextMenuForEntry
|
||||||
@ -60,13 +60,13 @@ class DetailsController(
|
|||||||
private lateinit var webViewDefinition: WebView
|
private lateinit var webViewDefinition: WebView
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private lateinit var listViewWordsContaining: ListView<DictionaryEntry>
|
private lateinit var listViewWordsContaining: ListView<DictionaryEntryFx>
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private lateinit var listViewWordsBeginning: ListView<DictionaryEntry>
|
private lateinit var listViewWordsBeginning: ListView<DictionaryEntryFx>
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private lateinit var listViewCharacters: ListView<DictionaryEntry>
|
private lateinit var listViewCharacters: ListView<DictionaryEntryFx>
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private lateinit var progressIndicatorCharacters: ProgressIndicator
|
private lateinit var progressIndicatorCharacters: ProgressIndicator
|
||||||
@ -87,7 +87,7 @@ class DetailsController(
|
|||||||
private lateinit var labelNoWordsBeginningFound: Label
|
private lateinit var labelNoWordsBeginningFound: Label
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private lateinit var listViewSentences: ListView<Sentence>
|
private lateinit var listViewSentences: ListView<SentenceFx>
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private lateinit var progressIndicatorSentences: ProgressIndicator
|
private lateinit var progressIndicatorSentences: ProgressIndicator
|
||||||
@ -114,8 +114,8 @@ class DetailsController(
|
|||||||
{
|
{
|
||||||
val selectedEntry = model.selectedEntry.value
|
val selectedEntry = model.selectedEntry.value
|
||||||
when (config.script.value!!) {
|
when (config.script.value!!) {
|
||||||
Script.SIMPLIFIED -> selectedEntry?.simplified
|
Script.SIMPLIFIED -> selectedEntry?.simplifiedProperty?.value
|
||||||
Script.TRADITIONAL -> selectedEntry?.traditional
|
Script.TRADITIONAL -> selectedEntry?.traditionalProperty?.value
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
config.script,
|
config.script,
|
||||||
@ -139,9 +139,20 @@ class DetailsController(
|
|||||||
{
|
{
|
||||||
val selectedEntry = model.selectedEntry.value
|
val selectedEntry = model.selectedEntry.value
|
||||||
when (config.details.pronunciation.value!!) {
|
when (config.details.pronunciation.value!!) {
|
||||||
Pronunciation.PINYIN_WITH_TONE_MARKS -> selectedEntry?.pinyinWithToneMarks
|
Pronunciation.PINYIN_WITH_TONE_MARKS ->
|
||||||
Pronunciation.PINYIN_WITH_TONE_NUMBERS -> selectedEntry?.pinyinWithToneNumbers
|
selectedEntry
|
||||||
Pronunciation.ZHUYIN -> selectedEntry?.zhuyin
|
?.pinyinWithToneMarksProperty
|
||||||
|
?.value
|
||||||
|
|
||||||
|
Pronunciation.PINYIN_WITH_TONE_NUMBERS ->
|
||||||
|
selectedEntry
|
||||||
|
?.pinyinWithToneNumbersProperty
|
||||||
|
?.value
|
||||||
|
|
||||||
|
Pronunciation.ZHUYIN ->
|
||||||
|
selectedEntry
|
||||||
|
?.zhuyinProperty
|
||||||
|
?.value
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
config.details.pronunciation,
|
config.details.pronunciation,
|
||||||
@ -172,13 +183,13 @@ class DetailsController(
|
|||||||
model.selectedEntry.addListener { _, _, newEntry ->
|
model.selectedEntry.addListener { _, _, newEntry ->
|
||||||
if (newEntry == null) return@addListener
|
if (newEntry == null) return@addListener
|
||||||
|
|
||||||
tabPaneDetails.selectionModel.select(0)
|
lazyUpdateTabContent(tabPaneDetails.selectionModel.selectedItem.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
tabCharacters.disableProperty().bind(
|
tabCharacters.disableProperty().bind(
|
||||||
Bindings.createBooleanBinding(
|
Bindings.createBooleanBinding(
|
||||||
{
|
{
|
||||||
(model.selectedEntry.value?.traditional?.length ?: 0) < 2
|
(model.selectedEntry.value?.traditionalProperty?.value?.length ?: 0) < 2
|
||||||
},
|
},
|
||||||
model.selectedEntry
|
model.selectedEntry
|
||||||
)
|
)
|
||||||
@ -204,11 +215,6 @@ class DetailsController(
|
|||||||
items = model.wordsContaining
|
items = model.wordsContaining
|
||||||
|
|
||||||
disableProperty().bind(Bindings.or(model.isFindingWordsContaining, Bindings.isEmpty(model.wordsContaining)))
|
disableProperty().bind(Bindings.or(model.isFindingWordsContaining, Bindings.isEmpty(model.wordsContaining)))
|
||||||
|
|
||||||
selectionModel.selectedItemProperty().addListener { _, _, newEntry ->
|
|
||||||
if (newEntry == null) return@addListener
|
|
||||||
model.selectEntry(newEntry)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
progressIndicatorWordsContaining.visibleProperty().bind(model.isFindingWordsContaining)
|
progressIndicatorWordsContaining.visibleProperty().bind(model.isFindingWordsContaining)
|
||||||
labelNoWordsContainingFound
|
labelNoWordsContainingFound
|
||||||
@ -222,11 +228,6 @@ class DetailsController(
|
|||||||
items = model.wordsBeginning
|
items = model.wordsBeginning
|
||||||
|
|
||||||
disableProperty().bind(Bindings.or(model.isFindingWordsBeginning, Bindings.isEmpty(model.wordsBeginning)))
|
disableProperty().bind(Bindings.or(model.isFindingWordsBeginning, Bindings.isEmpty(model.wordsBeginning)))
|
||||||
|
|
||||||
selectionModel.selectedItemProperty().addListener { _, _, newEntry ->
|
|
||||||
if (newEntry == null) return@addListener
|
|
||||||
model.selectEntry(newEntry)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
progressIndicatorWordsBeginning.visibleProperty().bind(model.isFindingWordsBeginning)
|
progressIndicatorWordsBeginning.visibleProperty().bind(model.isFindingWordsBeginning)
|
||||||
labelNoWordsBeginningFound
|
labelNoWordsBeginningFound
|
||||||
@ -240,11 +241,6 @@ class DetailsController(
|
|||||||
items = model.characters
|
items = model.characters
|
||||||
|
|
||||||
disableProperty().bind(Bindings.or(model.isFindingCharacters, Bindings.isEmpty(model.characters)))
|
disableProperty().bind(Bindings.or(model.isFindingCharacters, Bindings.isEmpty(model.characters)))
|
||||||
|
|
||||||
selectionModel.selectedItemProperty().addListener { _, _, newEntry ->
|
|
||||||
if (newEntry == null) return@addListener
|
|
||||||
model.selectEntry(newEntry)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
progressIndicatorCharacters.visibleProperty().bind(model.isFindingCharacters)
|
progressIndicatorCharacters.visibleProperty().bind(model.isFindingCharacters)
|
||||||
labelNoCharactersFound
|
labelNoCharactersFound
|
||||||
@ -303,7 +299,7 @@ class DetailsController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createDefinitionHtml(entry: DictionaryEntry) = createHTML().html {
|
private fun createDefinitionHtml(entry: DictionaryEntryFx) = createHTML().html {
|
||||||
body {
|
body {
|
||||||
if (entry.cedictDefinitions.isNotEmpty()) {
|
if (entry.cedictDefinitions.isNotEmpty()) {
|
||||||
div(classes = "cedict-definition") {
|
div(classes = "cedict-definition") {
|
||||||
@ -335,7 +331,7 @@ class DetailsController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DIV.cedictDefinition(entry: DictionaryEntry) = ol {
|
private fun DIV.cedictDefinition(entry: DictionaryEntryFx) = ol {
|
||||||
for (definition in entry.cedictDefinitions) {
|
for (definition in entry.cedictDefinitions) {
|
||||||
li {
|
li {
|
||||||
+definition.joinToString(separator = "; ")
|
+definition.joinToString(separator = "; ")
|
||||||
@ -343,7 +339,7 @@ private fun DIV.cedictDefinition(entry: DictionaryEntry) = ol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DIV.crossStraitsDefinition(entry: DictionaryEntry) = ol {
|
private fun DIV.crossStraitsDefinition(entry: DictionaryEntryFx) = ol {
|
||||||
entry.crossStraitsDefinitions.forEach { definition ->
|
entry.crossStraitsDefinitions.forEach { definition ->
|
||||||
li {
|
li {
|
||||||
span(classes = "definition") {
|
span(classes = "definition") {
|
||||||
@ -362,7 +358,7 @@ private fun DIV.crossStraitsDefinition(entry: DictionaryEntry) = ol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DIV.moeDefinition(entry: DictionaryEntry) =
|
private fun DIV.moeDefinition(entry: DictionaryEntryFx) =
|
||||||
entry.moedictDefinitions.groupBy { it.type ?: "" }.entries.forEach { (type, definitions) ->
|
entry.moedictDefinitions.groupBy { it.type ?: "" }.entries.forEach { (type, definitions) ->
|
||||||
if (type != "") {
|
if (type != "") {
|
||||||
span(classes = "type") {
|
span(classes = "type") {
|
||||||
|
@ -3,17 +3,10 @@ package com.marvinelsen.willow.ui.controllers
|
|||||||
import com.marvinelsen.willow.Model
|
import com.marvinelsen.willow.Model
|
||||||
import com.marvinelsen.willow.domain.SearchMode
|
import com.marvinelsen.willow.domain.SearchMode
|
||||||
import javafx.fxml.FXML
|
import javafx.fxml.FXML
|
||||||
import javafx.scene.control.Button
|
|
||||||
import javafx.scene.control.TextField
|
import javafx.scene.control.TextField
|
||||||
import javafx.scene.control.ToggleGroup
|
import javafx.scene.control.ToggleGroup
|
||||||
|
|
||||||
class SearchController(private val model: Model) {
|
class SearchController(private val model: Model) {
|
||||||
@FXML
|
|
||||||
private lateinit var buttonUndo: Button
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private lateinit var buttonRedo: Button
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private lateinit var searchModeToggleGroup: ToggleGroup
|
private lateinit var searchModeToggleGroup: ToggleGroup
|
||||||
|
|
||||||
@ -25,9 +18,6 @@ class SearchController(private val model: Model) {
|
|||||||
private fun initialize() {
|
private fun initialize() {
|
||||||
textFieldSearch.textProperty().addListener { _, _, _ -> search() }
|
textFieldSearch.textProperty().addListener { _, _, _ -> search() }
|
||||||
searchModeToggleGroup.selectedToggleProperty().addListener { _, _, _ -> search() }
|
searchModeToggleGroup.selectedToggleProperty().addListener { _, _, _ -> search() }
|
||||||
|
|
||||||
buttonUndo.disableProperty().bind(model.canUndo.not())
|
|
||||||
buttonRedo.disableProperty().bind(model.canRedo.not())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun search() {
|
private fun search() {
|
||||||
@ -40,12 +30,4 @@ class SearchController(private val model: Model) {
|
|||||||
|
|
||||||
model.search(searchQuery, searchMode)
|
model.search(searchQuery, searchMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onButtonRedoAction() {
|
|
||||||
model.redoSelection()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onButtonUndoAction() {
|
|
||||||
model.undoSelection()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +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.domain.entities.DictionaryEntry
|
import com.marvinelsen.willow.ui.DictionaryEntryFx
|
||||||
import com.marvinelsen.willow.ui.cells.DictionaryEntryCellFactory
|
import com.marvinelsen.willow.ui.cells.DictionaryEntryCellFactory
|
||||||
import javafx.application.HostServices
|
import javafx.application.HostServices
|
||||||
import javafx.beans.binding.Bindings
|
import javafx.beans.binding.Bindings
|
||||||
@ -29,7 +29,7 @@ class SearchResultsController(
|
|||||||
private lateinit var labelNoEntriesFound: Label
|
private lateinit var labelNoEntriesFound: Label
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private lateinit var listViewSearchResults: ListView<DictionaryEntry>
|
private lateinit var listViewSearchResults: ListView<DictionaryEntryFx>
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@Suppress("UnusedPrivateMember")
|
@Suppress("UnusedPrivateMember")
|
||||||
@ -45,7 +45,7 @@ class SearchResultsController(
|
|||||||
.visibleProperty()
|
.visibleProperty()
|
||||||
.bind(Bindings.and(Bindings.isEmpty(model.searchResults), Bindings.not(model.isSearching)))
|
.bind(Bindings.and(Bindings.isEmpty(model.searchResults), Bindings.not(model.isSearching)))
|
||||||
|
|
||||||
listViewSearchResults.selectionModel.selectedItemProperty().addListener { _, _, newValue: DictionaryEntry? ->
|
listViewSearchResults.selectionModel.selectedItemProperty().addListener { _, _, newValue: DictionaryEntryFx? ->
|
||||||
if (newValue == null) {
|
if (newValue == null) {
|
||||||
return@addListener
|
return@addListener
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package com.marvinelsen.willow.ui.undo
|
|
||||||
|
|
||||||
interface Command {
|
|
||||||
fun execute()
|
|
||||||
fun undo()
|
|
||||||
fun redo() = execute()
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package com.marvinelsen.willow.ui.undo
|
|
||||||
|
|
||||||
import javafx.beans.property.SimpleBooleanProperty
|
|
||||||
import java.util.Stack
|
|
||||||
|
|
||||||
class UndoManager {
|
|
||||||
private val undoStack = Stack<Command>()
|
|
||||||
private val redoStack = Stack<Command>()
|
|
||||||
|
|
||||||
val canUndoProperty = SimpleBooleanProperty(false)
|
|
||||||
val canRedoProperty = SimpleBooleanProperty(false)
|
|
||||||
|
|
||||||
fun execute(command: Command) {
|
|
||||||
redoStack.clear()
|
|
||||||
|
|
||||||
undoStack.push(command).execute()
|
|
||||||
|
|
||||||
canUndoProperty.value = undoStack.size > 1
|
|
||||||
canRedoProperty.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun undo() {
|
|
||||||
if (undoStack.isEmpty()) return
|
|
||||||
|
|
||||||
redoStack.push(undoStack.pop()).undo()
|
|
||||||
|
|
||||||
canUndoProperty.value = undoStack.size > 1
|
|
||||||
canRedoProperty.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun redo() {
|
|
||||||
if (redoStack.isEmpty()) return
|
|
||||||
|
|
||||||
undoStack.push(redoStack.pop()).redo()
|
|
||||||
|
|
||||||
canUndoProperty.value = true
|
|
||||||
canRedoProperty.value = !redoStack.isEmpty()
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.marvinelsen.willow.ui.util
|
||||||
|
|
||||||
|
import javafx.concurrent.Task
|
||||||
|
|
||||||
|
fun <T> task(block: () -> T) = object : Task<T>() {
|
||||||
|
override fun call() = block()
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package com.marvinelsen.willow.ui.util
|
package com.marvinelsen.willow.ui.util
|
||||||
|
|
||||||
import com.marvinelsen.willow.domain.entities.DictionaryEntry
|
import com.marvinelsen.willow.ui.DictionaryEntryFx
|
||||||
import com.marvinelsen.willow.domain.entities.Sentence
|
import com.marvinelsen.willow.ui.SentenceFx
|
||||||
import javafx.application.HostServices
|
import javafx.application.HostServices
|
||||||
import javafx.event.EventHandler
|
import javafx.event.EventHandler
|
||||||
import javafx.scene.control.ContextMenu
|
import javafx.scene.control.ContextMenu
|
||||||
@ -11,24 +11,24 @@ import java.nio.charset.StandardCharsets
|
|||||||
import java.util.ResourceBundle
|
import java.util.ResourceBundle
|
||||||
|
|
||||||
fun createContextMenuForEntry(
|
fun createContextMenuForEntry(
|
||||||
entry: DictionaryEntry,
|
entry: DictionaryEntryFx,
|
||||||
resourceBundle: ResourceBundle,
|
resourceBundle: ResourceBundle,
|
||||||
hostServices: HostServices,
|
hostServices: HostServices,
|
||||||
) = ContextMenu().apply {
|
) = ContextMenu().apply {
|
||||||
val menuItemCopyHeadword =
|
val menuItemCopyHeadword =
|
||||||
MenuItem(resourceBundle.getString("menubar.edit.copy.headword")).apply {
|
MenuItem(resourceBundle.getString("menubar.edit.copy.headword")).apply {
|
||||||
onAction = EventHandler { ClipboardHelper.copyString(entry.traditional) }
|
onAction = EventHandler { ClipboardHelper.copyString(entry.traditionalProperty.value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val menuItemCopyPronunciation =
|
val menuItemCopyPronunciation =
|
||||||
MenuItem(resourceBundle.getString("menubar.edit.copy.pronunciation")).apply {
|
MenuItem(resourceBundle.getString("menubar.edit.copy.pronunciation")).apply {
|
||||||
onAction = EventHandler { ClipboardHelper.copyString(entry.pinyinWithToneMarks) }
|
onAction = EventHandler { ClipboardHelper.copyString(entry.pinyinWithToneMarksProperty.value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val menuItemSearchOnWeb =
|
val menuItemSearchOnWeb =
|
||||||
MenuItem(resourceBundle.getString("menubar.edit.search-web")).apply {
|
MenuItem(resourceBundle.getString("menubar.edit.search-web")).apply {
|
||||||
onAction = EventHandler {
|
onAction = EventHandler {
|
||||||
val query = URLEncoder.encode(entry.traditional, StandardCharsets.UTF_8)
|
val query = URLEncoder.encode(entry.traditionalProperty.value, StandardCharsets.UTF_8)
|
||||||
hostServices.showDocument("https://duckduckgo.com/?q=$query")
|
hostServices.showDocument("https://duckduckgo.com/?q=$query")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,19 +37,19 @@ fun createContextMenuForEntry(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createContextMenuForSentence(
|
fun createContextMenuForSentence(
|
||||||
sentence: Sentence,
|
sentence: SentenceFx,
|
||||||
resourceBundle: ResourceBundle,
|
resourceBundle: ResourceBundle,
|
||||||
hostServices: HostServices,
|
hostServices: HostServices,
|
||||||
) = ContextMenu().apply {
|
) = ContextMenu().apply {
|
||||||
val menuItemCopySentence =
|
val menuItemCopySentence =
|
||||||
MenuItem(resourceBundle.getString("menubar.edit.copy.sentence")).apply {
|
MenuItem(resourceBundle.getString("menubar.edit.copy.sentence")).apply {
|
||||||
onAction = EventHandler { ClipboardHelper.copyString(sentence.traditional) }
|
onAction = EventHandler { ClipboardHelper.copyString(sentence.traditionalProperty.value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val menuItemSearchOnWeb =
|
val menuItemSearchOnWeb =
|
||||||
MenuItem(resourceBundle.getString("menubar.edit.search-web")).apply {
|
MenuItem(resourceBundle.getString("menubar.edit.search-web")).apply {
|
||||||
onAction = EventHandler {
|
onAction = EventHandler {
|
||||||
val query = URLEncoder.encode(sentence.traditional, StandardCharsets.UTF_8)
|
val query = URLEncoder.encode(sentence.traditionalProperty.value, StandardCharsets.UTF_8)
|
||||||
hostServices.showDocument("https://duckduckgo.com/?q=$query")
|
hostServices.showDocument("https://duckduckgo.com/?q=$query")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,31 +5,9 @@
|
|||||||
<?import javafx.scene.layout.FlowPane?>
|
<?import javafx.scene.layout.FlowPane?>
|
||||||
<?import javafx.scene.layout.HBox?>
|
<?import javafx.scene.layout.HBox?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import org.kordamp.ikonli.javafx.FontIcon?>
|
|
||||||
<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.SearchController" spacing="8">
|
fx:controller="com.marvinelsen.willow.ui.controllers.SearchController" spacing="8">
|
||||||
|
<TextField fx:id="textFieldSearch" promptText="%search.prompt" HBox.hgrow="ALWAYS"/>
|
||||||
<HBox alignment="CENTER_LEFT" prefHeight="0.0" spacing="6.0" VBox.vgrow="NEVER">
|
|
||||||
<Button fx:id="buttonUndo" contentDisplay="GRAPHIC_ONLY" disable="true" graphicTextGap="0.0"
|
|
||||||
mnemonicParsing="false" onAction="#onButtonUndoAction">
|
|
||||||
<graphic>
|
|
||||||
<FontIcon iconLiteral="mdal-arrow_back" iconSize="16"/>
|
|
||||||
</graphic>
|
|
||||||
<tooltip>
|
|
||||||
<Tooltip text="Go back one search (Alt+Left Arrow)"/>
|
|
||||||
</tooltip>
|
|
||||||
</Button>
|
|
||||||
<Button fx:id="buttonRedo" contentDisplay="GRAPHIC_ONLY" disable="true" graphicTextGap="0.0"
|
|
||||||
mnemonicParsing="false" onAction="#onButtonRedoAction">
|
|
||||||
<graphic>
|
|
||||||
<FontIcon iconLiteral="mdal-arrow_forward" iconSize="16"/>
|
|
||||||
</graphic>
|
|
||||||
<tooltip>
|
|
||||||
<Tooltip text="Go forward one search (Alt+Right Arrow)"/>
|
|
||||||
</tooltip>
|
|
||||||
</Button>
|
|
||||||
<TextField fx:id="textFieldSearch" promptText="%search.prompt" HBox.hgrow="ALWAYS"/>
|
|
||||||
</HBox>
|
|
||||||
<FlowPane hgap="8.0" vgap="8.0">
|
<FlowPane hgap="8.0" vgap="8.0">
|
||||||
<Label text="%search.mode"/>
|
<Label text="%search.mode"/>
|
||||||
<RadioButton mnemonicParsing="false" selected="true" text="%search.mode.simplified">
|
<RadioButton mnemonicParsing="false" selected="true" text="%search.mode.simplified">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user