Implement find sentence function
This commit is contained in:
parent
50017f45c4
commit
168d1634a2
@ -2,7 +2,9 @@ package com.marvinelsen.willow
|
||||
|
||||
import com.marvinelsen.willow.domain.SearchMode
|
||||
import com.marvinelsen.willow.ui.DictionaryEntryFx
|
||||
import com.marvinelsen.willow.ui.SentenceFx
|
||||
import com.marvinelsen.willow.ui.services.FindCharacterService
|
||||
import com.marvinelsen.willow.ui.services.FindSentencesService
|
||||
import com.marvinelsen.willow.ui.services.FindWordsService
|
||||
import com.marvinelsen.willow.ui.services.SearchService
|
||||
import com.marvinelsen.willow.ui.util.ClipboardHelper
|
||||
@ -18,11 +20,13 @@ class Model(
|
||||
private val searchService: SearchService,
|
||||
private val findWordsService: FindWordsService,
|
||||
private val findCharacterService: FindCharacterService,
|
||||
private val findSentencesService: FindSentencesService,
|
||||
) {
|
||||
private val internalSelectedEntry: ObjectProperty<DictionaryEntryFx> = SimpleObjectProperty()
|
||||
private val internalSearchResults: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
|
||||
private val internalWordsContaining: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
|
||||
private val internalCharacters: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
|
||||
private val internalSentences: ObservableList<SentenceFx> = FXCollections.observableArrayList()
|
||||
|
||||
val selectedEntry: ReadOnlyObjectProperty<DictionaryEntryFx> = internalSelectedEntry
|
||||
|
||||
@ -32,10 +36,13 @@ class Model(
|
||||
FXCollections.unmodifiableObservableList(internalWordsContaining)
|
||||
val characters: ObservableList<DictionaryEntryFx> =
|
||||
FXCollections.unmodifiableObservableList(internalCharacters)
|
||||
val sentences: ObservableList<SentenceFx> =
|
||||
FXCollections.unmodifiableObservableList(internalSentences)
|
||||
|
||||
val isSearching: ReadOnlyBooleanProperty = searchService.runningProperty()
|
||||
val isFindingWords: ReadOnlyBooleanProperty = findWordsService.runningProperty()
|
||||
val isFindingCharacters: ReadOnlyBooleanProperty = findCharacterService.runningProperty()
|
||||
val isFindingSentences: ReadOnlyBooleanProperty = findSentencesService.runningProperty()
|
||||
|
||||
init {
|
||||
searchService.onSucceeded = EventHandler {
|
||||
@ -47,6 +54,9 @@ class Model(
|
||||
findCharacterService.onSucceeded = EventHandler {
|
||||
internalCharacters.setAll(findCharacterService.value)
|
||||
}
|
||||
findSentencesService.onSucceeded = EventHandler {
|
||||
internalSentences.setAll(findSentencesService.value)
|
||||
}
|
||||
}
|
||||
|
||||
fun search(query: String, searchMode: SearchMode) {
|
||||
@ -65,9 +75,15 @@ class Model(
|
||||
findCharacterService.restart()
|
||||
}
|
||||
|
||||
fun findSentences() {
|
||||
findSentencesService.entry = internalSelectedEntry.value
|
||||
findSentencesService.restart()
|
||||
}
|
||||
|
||||
fun selectEntry(entry: DictionaryEntryFx) {
|
||||
internalWordsContaining.setAll(emptyList())
|
||||
internalCharacters.setAll(emptyList())
|
||||
internalSentences.setAll(emptyList())
|
||||
internalSelectedEntry.value = entry
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ 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.FindSentencesService
|
||||
import com.marvinelsen.willow.ui.services.FindWordsService
|
||||
import com.marvinelsen.willow.ui.services.SearchService
|
||||
import javafx.application.Application
|
||||
@ -46,7 +47,8 @@ class WillowApplication : Application() {
|
||||
val searchService = SearchService(dictionary)
|
||||
val findWordsService = FindWordsService(dictionary)
|
||||
val findCharacterService = FindCharacterService(dictionary)
|
||||
val model = Model(searchService, findWordsService, findCharacterService)
|
||||
val findSentenceService = FindSentencesService(dictionary)
|
||||
val model = Model(searchService, findWordsService, findCharacterService, findSentenceService)
|
||||
val config = Config()
|
||||
config.load()
|
||||
|
||||
|
@ -3,7 +3,7 @@ package com.marvinelsen.willow.domain
|
||||
interface Dictionary {
|
||||
fun search(query: String, searchMode: SearchMode): List<DictionaryEntry>
|
||||
fun findWordsContaining(entry: DictionaryEntry): List<DictionaryEntry>
|
||||
fun findSentencesContaining(entry: DictionaryEntry): List<DictionaryEntry>
|
||||
fun findSentencesContaining(entry: DictionaryEntry): List<Sentence>
|
||||
fun findCharacters(entry: DictionaryEntry): List<DictionaryEntry>
|
||||
fun searchSegments(phrase: String): List<DictionaryEntry>
|
||||
}
|
||||
|
@ -86,6 +86,17 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
|
||||
ORDER BY cte.id
|
||||
""".trimIndent()
|
||||
|
||||
private val findSentences: PreparedStatement by lazy {
|
||||
connection.prepareStatement(
|
||||
"""
|
||||
SELECT traditional, simplified
|
||||
FROM sentence
|
||||
WHERE traditional LIKE ?
|
||||
ORDER BY character_count ASC
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
override fun search(query: String, searchMode: SearchMode) = when (searchMode) {
|
||||
SearchMode.PINYIN -> searchPinyin(query)
|
||||
SearchMode.SIMPLIFIED -> searchSimplified(query)
|
||||
@ -101,8 +112,12 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
|
||||
return resultSet.toListOfDictionaryEntries()
|
||||
}
|
||||
|
||||
override fun findSentencesContaining(entry: DictionaryEntry): List<DictionaryEntry> {
|
||||
return emptyList()
|
||||
override fun findSentencesContaining(entry: DictionaryEntry): List<Sentence> {
|
||||
findSentences.setString(1, "_%${entry.traditional}%")
|
||||
|
||||
val resultSet: ResultSet = findSentences.executeQuery()
|
||||
|
||||
return resultSet.toListOfSentences()
|
||||
}
|
||||
|
||||
override fun findCharacters(entry: DictionaryEntry): List<DictionaryEntry> {
|
||||
@ -191,3 +206,16 @@ private fun ResultSet.toListOfDictionaryEntries() = buildList {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun ResultSet.toSentence() = Sentence(
|
||||
traditional = this.getString(1),
|
||||
simplified = this.getString(2),
|
||||
)
|
||||
|
||||
private fun ResultSet.toListOfSentences() = buildList {
|
||||
this@toListOfSentences.use {
|
||||
while (it.next()) {
|
||||
add(it.toSentence())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
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,
|
||||
)
|
@ -0,0 +1,44 @@
|
||||
package com.marvinelsen.willow.ui.cells
|
||||
|
||||
import com.marvinelsen.willow.ui.SentenceFx
|
||||
import javafx.scene.control.Label
|
||||
import javafx.scene.control.ListCell
|
||||
import javafx.scene.control.ListView
|
||||
import javafx.scene.layout.VBox
|
||||
import javafx.util.Callback
|
||||
|
||||
class SentenceCellFactory() : Callback<ListView<SentenceFx?>, ListCell<SentenceFx?>> {
|
||||
|
||||
override fun call(listView: ListView<SentenceFx?>): ListCell<SentenceFx?> {
|
||||
val sentenceCell = SentenceCell()
|
||||
sentenceCell.prefWidthProperty().bind(listView.widthProperty().subtract(CELL_PADDING))
|
||||
return sentenceCell
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val CELL_PADDING = 16
|
||||
}
|
||||
}
|
||||
|
||||
internal class SentenceCell() : ListCell<SentenceFx?>() {
|
||||
private val labelTraditional = Label().apply {
|
||||
styleClass.add("chinese")
|
||||
styleClass.add("list-view-sentence-cell")
|
||||
}
|
||||
private val root = VBox(labelTraditional)
|
||||
|
||||
init {
|
||||
text = null
|
||||
}
|
||||
|
||||
override fun updateItem(sentence: SentenceFx?, empty: Boolean) {
|
||||
super.updateItem(sentence, empty)
|
||||
if (empty || sentence == null) {
|
||||
graphic = null
|
||||
} else {
|
||||
labelTraditional.text = sentence.traditionalProperty.value
|
||||
|
||||
graphic = root
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,9 @@ import com.marvinelsen.willow.config.Config
|
||||
import com.marvinelsen.willow.config.Pronunciation
|
||||
import com.marvinelsen.willow.config.Script
|
||||
import com.marvinelsen.willow.ui.DictionaryEntryFx
|
||||
import com.marvinelsen.willow.ui.SentenceFx
|
||||
import com.marvinelsen.willow.ui.cells.DictionaryEntryCellFactory
|
||||
import com.marvinelsen.willow.ui.cells.SentenceCellFactory
|
||||
import com.marvinelsen.willow.ui.util.createContextMenuForEntry
|
||||
import javafx.beans.binding.Bindings
|
||||
import javafx.fxml.FXML
|
||||
@ -68,6 +70,16 @@ class DetailsController(private val model: Model, private val config: Config) {
|
||||
@FXML
|
||||
private lateinit var labelNoWordsFound: Label
|
||||
|
||||
@FXML
|
||||
private lateinit var listViewSentences: ListView<SentenceFx>
|
||||
|
||||
@FXML
|
||||
private lateinit var progressIndicatorSentences: ProgressIndicator
|
||||
|
||||
@FXML
|
||||
private lateinit var labelNoSentencesFound: Label
|
||||
|
||||
|
||||
@FXML
|
||||
private fun initialize() {
|
||||
initializeLabelHeadword()
|
||||
@ -75,6 +87,7 @@ class DetailsController(private val model: Model, private val config: Config) {
|
||||
initializeTabPaneDetails()
|
||||
initializeListViewWords()
|
||||
initializeListViewCharacters()
|
||||
initializeListViewSentences()
|
||||
initializeWebViewDefinition()
|
||||
}
|
||||
|
||||
@ -167,6 +180,19 @@ class DetailsController(private val model: Model, private val config: Config) {
|
||||
)
|
||||
}
|
||||
|
||||
private fun initializeListViewSentences() {
|
||||
listViewSentences.apply {
|
||||
cellFactory = SentenceCellFactory()
|
||||
items = model.sentences
|
||||
|
||||
disableProperty().bind(Bindings.or(model.isFindingSentences, Bindings.isEmpty(model.sentences)))
|
||||
}
|
||||
progressIndicatorSentences.visibleProperty().bind(model.isFindingSentences)
|
||||
labelNoSentencesFound
|
||||
.visibleProperty()
|
||||
.bind(Bindings.and(Bindings.isEmpty(model.sentences), Bindings.not(model.isFindingSentences)))
|
||||
}
|
||||
|
||||
private fun initializeListViewWords() {
|
||||
listViewWords.apply {
|
||||
cellFactory = DictionaryEntryCellFactory(resources, config)
|
||||
@ -324,6 +350,12 @@ class DetailsController(private val model: Model, private val config: Config) {
|
||||
model.findCharacters()
|
||||
}
|
||||
|
||||
"tabSentences" -> {
|
||||
if (model.sentences.isNotEmpty()) return
|
||||
|
||||
model.findSentences()
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package com.marvinelsen.willow.ui.services
|
||||
|
||||
import com.marvinelsen.willow.domain.Dictionary
|
||||
import com.marvinelsen.willow.ui.DictionaryEntryFx
|
||||
import com.marvinelsen.willow.ui.SentenceFx
|
||||
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 FindSentencesService(private val dictionary: Dictionary) : Service<ObservableList<SentenceFx>>() {
|
||||
lateinit var entry: DictionaryEntryFx
|
||||
|
||||
override fun createTask() = task {
|
||||
if (!this::entry.isInitialized) error("Entry is not initialized")
|
||||
|
||||
FXCollections.observableList(dictionary.findSentencesContaining(entry.toDomain()).map { it.toFx() })
|
||||
}
|
||||
}
|
@ -21,7 +21,16 @@
|
||||
<WebView fx:id="webViewDefinition" minHeight="-1.0" minWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0"/>
|
||||
</Tab>
|
||||
<Tab id="tabSentences" closable="false" text="%tab.sentences">
|
||||
<ListView fx:id="listViewSentences"/>
|
||||
<StackPane>
|
||||
<ProgressIndicator fx:id="progressIndicatorSentences" visible="false"/>
|
||||
<Label fx:id="labelNoSentencesFound" text="%list.no_sentences_found" textAlignment="CENTER" visible="false"
|
||||
wrapText="true">
|
||||
<padding>
|
||||
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0"/>
|
||||
</padding>
|
||||
</Label>
|
||||
<ListView fx:id="listViewSentences"/>
|
||||
</StackPane>
|
||||
</Tab>
|
||||
<Tab id="tabWords" closable="false" text="%tab.words">
|
||||
<StackPane>
|
||||
|
@ -20,3 +20,4 @@ list.no_entries_found=No matching entries found
|
||||
search.mode.phrase=Phrase
|
||||
list.no_characters_found=No characters found
|
||||
list.no_words_found=No words found
|
||||
list.no_sentences_found=No sentences found.
|
||||
|
@ -20,3 +20,4 @@ list.no_entries_found=No matching entries found
|
||||
search.mode.phrase=Phrase
|
||||
list.no_characters_found=No characters found
|
||||
list.no_words_found=No words found
|
||||
list.no_sentences_found=No sentences found.
|
||||
|
@ -20,3 +20,4 @@ list.no_entries_found=No matching entries found
|
||||
search.mode.phrase=Phrase
|
||||
list.no_characters_found=No characters found
|
||||
list.no_words_found=No words found
|
||||
list.no_sentences_found=No sentences found.
|
||||
|
@ -20,3 +20,4 @@ list.no_entries_found=No matching entries found
|
||||
search.mode.phrase=Phrase
|
||||
list.no_characters_found=No characters found
|
||||
list.no_words_found=No words found
|
||||
list.no_sentences_found=No sentences found.
|
||||
|
@ -20,3 +20,4 @@ list.no_entries_found=No matching entries found
|
||||
search.mode.phrase=Phrase
|
||||
list.no_characters_found=No characters found
|
||||
list.no_words_found=No words found
|
||||
list.no_sentences_found=No sentences found.
|
||||
|
Loading…
Reference in New Issue
Block a user