Implement find characters
This commit is contained in:
parent
cb52240eea
commit
d9b7b82c60
@ -3,6 +3,7 @@ package com.marvinelsen.willow
|
|||||||
import com.marvinelsen.willow.domain.SearchMode
|
import com.marvinelsen.willow.domain.SearchMode
|
||||||
import com.marvinelsen.willow.ui.DictionaryEntryFx
|
import com.marvinelsen.willow.ui.DictionaryEntryFx
|
||||||
import com.marvinelsen.willow.ui.util.ClipboardHelper
|
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.FindWordsService
|
||||||
import com.marvinelsen.willow.ui.util.SearchService
|
import com.marvinelsen.willow.ui.util.SearchService
|
||||||
import javafx.beans.property.ObjectProperty
|
import javafx.beans.property.ObjectProperty
|
||||||
@ -13,10 +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) {
|
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()
|
||||||
|
private val internalCharacters: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
|
||||||
|
|
||||||
val selectedEntry: ReadOnlyObjectProperty<DictionaryEntryFx> = internalSelectedEntry
|
val selectedEntry: ReadOnlyObjectProperty<DictionaryEntryFx> = internalSelectedEntry
|
||||||
|
|
||||||
@ -24,6 +26,8 @@ class Model(private val searchService: SearchService, private val findWordsServi
|
|||||||
FXCollections.unmodifiableObservableList(internalSearchResults)
|
FXCollections.unmodifiableObservableList(internalSearchResults)
|
||||||
val wordsContaining: ObservableList<DictionaryEntryFx> =
|
val wordsContaining: ObservableList<DictionaryEntryFx> =
|
||||||
FXCollections.unmodifiableObservableList(internalWordsContaining)
|
FXCollections.unmodifiableObservableList(internalWordsContaining)
|
||||||
|
val characters: ObservableList<DictionaryEntryFx> =
|
||||||
|
FXCollections.unmodifiableObservableList(internalCharacters)
|
||||||
|
|
||||||
val isSearching: ReadOnlyBooleanProperty = searchService.runningProperty()
|
val isSearching: ReadOnlyBooleanProperty = searchService.runningProperty()
|
||||||
val isFindingWords: ReadOnlyBooleanProperty = findWordsService.runningProperty()
|
val isFindingWords: ReadOnlyBooleanProperty = findWordsService.runningProperty()
|
||||||
@ -35,6 +39,9 @@ class Model(private val searchService: SearchService, private val findWordsServi
|
|||||||
findWordsService.onSucceeded = EventHandler {
|
findWordsService.onSucceeded = EventHandler {
|
||||||
internalWordsContaining.setAll(findWordsService.value)
|
internalWordsContaining.setAll(findWordsService.value)
|
||||||
}
|
}
|
||||||
|
findCharacterService.onSucceeded = EventHandler {
|
||||||
|
internalCharacters.setAll(findCharacterService.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun search(query: String, searchMode: SearchMode) {
|
fun search(query: String, searchMode: SearchMode) {
|
||||||
@ -48,6 +55,11 @@ class Model(private val searchService: SearchService, private val findWordsServi
|
|||||||
findWordsService.restart()
|
findWordsService.restart()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun findCharacters() {
|
||||||
|
findCharacterService.entry = internalSelectedEntry.value
|
||||||
|
findCharacterService.restart()
|
||||||
|
}
|
||||||
|
|
||||||
fun selectEntry(entry: DictionaryEntryFx) {
|
fun selectEntry(entry: DictionaryEntryFx) {
|
||||||
internalSelectedEntry.value = entry
|
internalSelectedEntry.value = entry
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ 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.util.FindCharacterService
|
||||||
import com.marvinelsen.willow.ui.util.FindWordsService
|
import com.marvinelsen.willow.ui.util.FindWordsService
|
||||||
import com.marvinelsen.willow.ui.util.SearchService
|
import com.marvinelsen.willow.ui.util.SearchService
|
||||||
import javafx.application.Application
|
import javafx.application.Application
|
||||||
@ -44,7 +45,8 @@ class WillowApplication : Application() {
|
|||||||
val dictionary = SqliteDictionary(connection)
|
val dictionary = SqliteDictionary(connection)
|
||||||
val searchService = SearchService(dictionary)
|
val searchService = SearchService(dictionary)
|
||||||
val findWordsService = FindWordsService(dictionary)
|
val findWordsService = FindWordsService(dictionary)
|
||||||
val model = Model(searchService, findWordsService)
|
val findCharacterService = FindCharacterService(dictionary)
|
||||||
|
val model = Model(searchService, findWordsService, findCharacterService)
|
||||||
val config = Config()
|
val config = Config()
|
||||||
config.load()
|
config.load()
|
||||||
|
|
||||||
|
@ -78,9 +78,11 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val findCharacters = """
|
private val findCharacters = """
|
||||||
SELECT traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, definitions
|
WITH cte(id, character) AS (VALUES ?)
|
||||||
FROM cedict
|
SELECT traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, definitions
|
||||||
WHERE traditional IN (?)
|
FROM cedict INNER JOIN cte
|
||||||
|
ON cte.character = cedict.traditional OR cte.character = cedict.simplified
|
||||||
|
ORDER BY cte.id
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
override fun search(query: String, searchMode: SearchMode) = when (searchMode) {
|
override fun search(query: String, searchMode: SearchMode) = when (searchMode) {
|
||||||
@ -107,7 +109,8 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
|
|||||||
val characterList = entry.traditional
|
val characterList = entry.traditional
|
||||||
.split("")
|
.split("")
|
||||||
.filter { it.isNotBlank() }
|
.filter { it.isNotBlank() }
|
||||||
.joinToString(",") { "'$it'" }
|
.mapIndexed { index, s -> "($index, '$s')" }
|
||||||
|
.joinToString(",")
|
||||||
|
|
||||||
val query = findCharacters.replace("?", characterList)
|
val query = findCharacters.replace("?", characterList)
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ class DetailsController(private val model: Model, private val config: Config) {
|
|||||||
initializeLabelHeadword()
|
initializeLabelHeadword()
|
||||||
initializeTabPaneDetails()
|
initializeTabPaneDetails()
|
||||||
initializeListViewWords()
|
initializeListViewWords()
|
||||||
|
initializeListViewCharacters()
|
||||||
initializeWebViewDefinition()
|
initializeWebViewDefinition()
|
||||||
|
|
||||||
model.selectedEntry.addListener { _, _, newEntry ->
|
model.selectedEntry.addListener { _, _, newEntry ->
|
||||||
@ -59,6 +60,10 @@ class DetailsController(private val model: Model, private val config: Config) {
|
|||||||
model.findWords()
|
model.findWords()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"tabCharacters" -> {
|
||||||
|
model.findCharacters()
|
||||||
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
webViewDefinition.engine.loadContent(newEntry.createCedictDefinitionHtml())
|
webViewDefinition.engine.loadContent(newEntry.createCedictDefinitionHtml())
|
||||||
@ -78,6 +83,13 @@ class DetailsController(private val model: Model, private val config: Config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initializeListViewCharacters() {
|
||||||
|
listViewCharacters.apply {
|
||||||
|
cellFactory = DictionaryEntryCellFactory(resources, config)
|
||||||
|
items = model.characters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun initializeTabPaneDetails() {
|
private fun initializeTabPaneDetails() {
|
||||||
tabPaneDetails.apply {
|
tabPaneDetails.apply {
|
||||||
disableProperty().bind(Bindings.isNull(model.selectedEntry))
|
disableProperty().bind(Bindings.isNull(model.selectedEntry))
|
||||||
@ -90,6 +102,10 @@ class DetailsController(private val model: Model, private val config: Config) {
|
|||||||
model.findWords()
|
model.findWords()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"tabCharacters" -> {
|
||||||
|
model.findCharacters()
|
||||||
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,3 +30,13 @@ class FindWordsService(private val dictionary: Dictionary) : Service<ObservableL
|
|||||||
FXCollections.observableList(dictionary.findWordsContaining(entry.toDomain()).map { it.toFx() })
|
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() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,17 +14,16 @@
|
|||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
<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" disable="false" text="%tab.definition">
|
<Tab closable="false" text="%tab.definition">
|
||||||
<WebView fx:id="webViewDefinition" minHeight="-1.0" minWidth="-1.0" prefHeight="-1.0"
|
<WebView fx:id="webViewDefinition" minHeight="-1.0" minWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0"/>
|
||||||
prefWidth="-1.0"/>
|
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="tabSentences" closable="false" disable="false" text="%tab.sentences">
|
<Tab id="tabSentences" closable="false" text="%tab.sentences">
|
||||||
<ListView fx:id="listviewSentences"/>
|
<ListView fx:id="listviewSentences"/>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="tabWords" closable="false" disable="false" text="%tab.words">
|
<Tab id="tabWords" closable="false" text="%tab.words">
|
||||||
<ListView fx:id="listViewWords"/>
|
<ListView fx:id="listViewWords"/>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab closable="false" disable="false" text="%tab.characters">
|
<Tab id="tabCharacters" closable="false" text="%tab.characters">
|
||||||
<ListView fx:id="listViewCharacters"/>
|
<ListView fx:id="listViewCharacters"/>
|
||||||
</Tab>
|
</Tab>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
|
Loading…
Reference in New Issue
Block a user