Implement words beginning and refactor words containing
All checks were successful
Pull Request / build (pull_request) Successful in 3m35s

This commit is contained in:
Marvin Elsen 2024-10-14 22:44:48 +02:00
parent 40222f67ed
commit c427af15b6
Signed by: marvinelsen
GPG Key ID: 820672408CC318C2
13 changed files with 212 additions and 87 deletions

View File

@ -5,7 +5,8 @@ import com.marvinelsen.willow.ui.DictionaryEntryFx
import com.marvinelsen.willow.ui.SentenceFx import com.marvinelsen.willow.ui.SentenceFx
import com.marvinelsen.willow.ui.services.FindCharacterService import com.marvinelsen.willow.ui.services.FindCharacterService
import com.marvinelsen.willow.ui.services.FindSentencesService import com.marvinelsen.willow.ui.services.FindSentencesService
import com.marvinelsen.willow.ui.services.FindWordsService import com.marvinelsen.willow.ui.services.FindWordsBeginningService
import com.marvinelsen.willow.ui.services.FindWordsContainingService
import com.marvinelsen.willow.ui.services.SearchService import com.marvinelsen.willow.ui.services.SearchService
import com.marvinelsen.willow.ui.util.ClipboardHelper import com.marvinelsen.willow.ui.util.ClipboardHelper
import javafx.beans.property.ObjectProperty import javafx.beans.property.ObjectProperty
@ -18,12 +19,14 @@ import javafx.event.EventHandler
class Model( class Model(
private val searchService: SearchService, private val searchService: SearchService,
private val findWordsService: FindWordsService, private val findWordsBeginningService: FindWordsBeginningService,
private val findWordsContainingService: FindWordsContainingService,
private val findCharacterService: FindCharacterService, private val findCharacterService: FindCharacterService,
private val findSentencesService: FindSentencesService, private val findSentencesService: FindSentencesService,
) { ) {
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 internalWordsBeginning: 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() private val internalCharacters: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
private val internalSentences: ObservableList<SentenceFx> = FXCollections.observableArrayList() private val internalSentences: ObservableList<SentenceFx> = FXCollections.observableArrayList()
@ -32,6 +35,8 @@ class Model(
val searchResults: ObservableList<DictionaryEntryFx> = val searchResults: ObservableList<DictionaryEntryFx> =
FXCollections.unmodifiableObservableList(internalSearchResults) FXCollections.unmodifiableObservableList(internalSearchResults)
val wordsBeginning: ObservableList<DictionaryEntryFx> =
FXCollections.unmodifiableObservableList(internalWordsBeginning)
val wordsContaining: ObservableList<DictionaryEntryFx> = val wordsContaining: ObservableList<DictionaryEntryFx> =
FXCollections.unmodifiableObservableList(internalWordsContaining) FXCollections.unmodifiableObservableList(internalWordsContaining)
val characters: ObservableList<DictionaryEntryFx> = val characters: ObservableList<DictionaryEntryFx> =
@ -40,7 +45,8 @@ class Model(
FXCollections.unmodifiableObservableList(internalSentences) FXCollections.unmodifiableObservableList(internalSentences)
val isSearching: ReadOnlyBooleanProperty = searchService.runningProperty() val isSearching: ReadOnlyBooleanProperty = searchService.runningProperty()
val isFindingWords: ReadOnlyBooleanProperty = findWordsService.runningProperty() val isFindingWordsBeginning: ReadOnlyBooleanProperty = findWordsBeginningService.runningProperty()
val isFindingWordsContaining: ReadOnlyBooleanProperty = findWordsContainingService.runningProperty()
val isFindingCharacters: ReadOnlyBooleanProperty = findCharacterService.runningProperty() val isFindingCharacters: ReadOnlyBooleanProperty = findCharacterService.runningProperty()
val isFindingSentences: ReadOnlyBooleanProperty = findSentencesService.runningProperty() val isFindingSentences: ReadOnlyBooleanProperty = findSentencesService.runningProperty()
@ -48,8 +54,11 @@ class Model(
searchService.onSucceeded = EventHandler { searchService.onSucceeded = EventHandler {
internalSearchResults.setAll(searchService.value) internalSearchResults.setAll(searchService.value)
} }
findWordsService.onSucceeded = EventHandler { findWordsBeginningService.onSucceeded = EventHandler {
internalWordsContaining.setAll(findWordsService.value) internalWordsBeginning.setAll(findWordsBeginningService.value)
}
findWordsContainingService.onSucceeded = EventHandler {
internalWordsContaining.setAll(findWordsContainingService.value)
} }
findCharacterService.onSucceeded = EventHandler { findCharacterService.onSucceeded = EventHandler {
internalCharacters.setAll(findCharacterService.value) internalCharacters.setAll(findCharacterService.value)
@ -65,9 +74,14 @@ class Model(
searchService.restart() searchService.restart()
} }
fun findWords() { fun findWordsBeginning() {
findWordsService.entry = internalSelectedEntry.value findWordsBeginningService.entry = internalSelectedEntry.value
findWordsService.restart() findWordsBeginningService.restart()
}
fun findWordsContaining() {
findWordsContainingService.entry = internalSelectedEntry.value
findWordsContainingService.restart()
} }
fun findCharacters() { fun findCharacters() {
@ -81,6 +95,7 @@ class Model(
} }
fun selectEntry(entry: DictionaryEntryFx) { fun selectEntry(entry: DictionaryEntryFx) {
internalWordsBeginning.setAll(emptyList())
internalWordsContaining.setAll(emptyList()) internalWordsContaining.setAll(emptyList())
internalCharacters.setAll(emptyList()) internalCharacters.setAll(emptyList())
internalSentences.setAll(emptyList()) internalSentences.setAll(emptyList())

View File

@ -9,7 +9,8 @@ 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.services.FindCharacterService import com.marvinelsen.willow.ui.services.FindCharacterService
import com.marvinelsen.willow.ui.services.FindSentencesService import com.marvinelsen.willow.ui.services.FindSentencesService
import com.marvinelsen.willow.ui.services.FindWordsService import com.marvinelsen.willow.ui.services.FindWordsBeginningService
import com.marvinelsen.willow.ui.services.FindWordsContainingService
import com.marvinelsen.willow.ui.services.SearchService import com.marvinelsen.willow.ui.services.SearchService
import javafx.application.Application import javafx.application.Application
import javafx.fxml.FXMLLoader import javafx.fxml.FXMLLoader
@ -45,10 +46,17 @@ class WillowApplication : Application() {
} }
val dictionary = SqliteDictionary(connection) val dictionary = SqliteDictionary(connection)
val searchService = SearchService(dictionary) val searchService = SearchService(dictionary)
val findWordsService = FindWordsService(dictionary) val findWordsBeginningService = FindWordsBeginningService(dictionary)
val findWordsContainingService = FindWordsContainingService(dictionary)
val findCharacterService = FindCharacterService(dictionary) val findCharacterService = FindCharacterService(dictionary)
val findSentenceService = FindSentencesService(dictionary) val findSentenceService = FindSentencesService(dictionary)
val model = Model(searchService, findWordsService, findCharacterService, findSentenceService) val model = Model(
searchService,
findWordsBeginningService,
findWordsContainingService,
findCharacterService,
findSentenceService
)
val config = Config() val config = Config()
config.load() config.load()

View File

@ -2,8 +2,11 @@ package com.marvinelsen.willow.domain
interface Dictionary { interface Dictionary {
fun search(query: String, searchMode: SearchMode): List<DictionaryEntry> fun search(query: String, searchMode: SearchMode): List<DictionaryEntry>
fun findWordsBeginning(entry: DictionaryEntry): List<DictionaryEntry>
fun findWordsContaining(entry: DictionaryEntry): List<DictionaryEntry> fun findWordsContaining(entry: DictionaryEntry): List<DictionaryEntry>
fun findSentencesContaining(entry: DictionaryEntry): List<Sentence>
fun findCharacters(entry: DictionaryEntry): List<DictionaryEntry> fun findCharacters(entry: DictionaryEntry): List<DictionaryEntry>
fun searchSegments(phrase: String): List<DictionaryEntry>
fun findSentencesContaining(entry: DictionaryEntry): List<Sentence>
} }

View File

@ -66,6 +66,17 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
ORDER BY cte.id ORDER BY cte.id
""".trimIndent() """.trimIndent()
private val findWordsBeginning: PreparedStatement by lazy {
connection.prepareStatement(
"""
SELECT traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, cedict_definitions, cross_straits_definitions, moe_definitions
FROM entry
WHERE traditional GLOB ?
ORDER BY character_count ASC
""".trimIndent()
)
}
private val findWordsContaining: PreparedStatement by lazy { private val findWordsContaining: PreparedStatement by lazy {
connection.prepareStatement( connection.prepareStatement(
""" """
@ -98,12 +109,53 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
} }
override fun search(query: String, searchMode: SearchMode) = when (searchMode) { override fun search(query: String, searchMode: SearchMode) = when (searchMode) {
SearchMode.PINYIN -> searchPinyin(query)
SearchMode.SIMPLIFIED -> searchSimplified(query) SearchMode.SIMPLIFIED -> searchSimplified(query)
SearchMode.TRADITIONAL -> searchTraditional(query) SearchMode.TRADITIONAL -> searchTraditional(query)
SearchMode.PINYIN -> searchPinyin(query)
SearchMode.SEGMENTS -> searchSegments(query) SearchMode.SEGMENTS -> searchSegments(query)
} }
private fun searchSimplified(query: String): List<DictionaryEntry> {
searchSimplifiedPreparedStatement.setString(1, "$query*")
val resultSet: ResultSet = searchSimplifiedPreparedStatement.executeQuery()
return resultSet.toListOfDictionaryEntries()
}
private fun searchTraditional(query: String): List<DictionaryEntry> {
searchTraditionalPreparedStatement.setString(1, "$query*")
val resultSet: ResultSet = searchTraditionalPreparedStatement.executeQuery()
return resultSet.toListOfDictionaryEntries()
}
private fun searchPinyin(query: String): List<DictionaryEntry> {
val sanitizedQuery = query.lowercase().replace(whitespaceRegex, "")
searchPinyinPreparedStatement.setString(1, "$sanitizedQuery*")
searchPinyinPreparedStatement.setString(2, "$sanitizedQuery*")
val resultSet: ResultSet = searchPinyinPreparedStatement.executeQuery()
return resultSet.toListOfDictionaryEntries()
}
private fun searchSegments(phrase: String): List<DictionaryEntry> {
val segments = segmentBs.segment(phrase, SegmentResultHandlers.word())
val segmentsListString = segments
.mapIndexed { index, s -> "($index, '$s')" }
.joinToString(",")
val query = searchSegments.replace("?", segmentsListString)
val resultSet: ResultSet = connection.createStatement().executeQuery(query)
return resultSet.toListOfDictionaryEntries()
}
override fun findWordsContaining(entry: DictionaryEntry): List<DictionaryEntry> { override fun findWordsContaining(entry: DictionaryEntry): List<DictionaryEntry> {
findWordsContaining.setString(1, "_%${entry.traditional}%") findWordsContaining.setString(1, "_%${entry.traditional}%")
@ -112,12 +164,12 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
return resultSet.toListOfDictionaryEntries() return resultSet.toListOfDictionaryEntries()
} }
override fun findSentencesContaining(entry: DictionaryEntry): List<Sentence> { override fun findWordsBeginning(entry: DictionaryEntry): List<DictionaryEntry> {
findSentences.setString(1, "_%${entry.traditional}%") findWordsBeginning.setString(1, "${entry.traditional}?*")
val resultSet: ResultSet = findSentences.executeQuery() val resultSet: ResultSet = findWordsBeginning.executeQuery()
return resultSet.toListOfSentences() return resultSet.toListOfDictionaryEntries()
} }
override fun findCharacters(entry: DictionaryEntry): List<DictionaryEntry> { override fun findCharacters(entry: DictionaryEntry): List<DictionaryEntry> {
@ -145,45 +197,12 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
return resultSet.toListOfDictionaryEntries() return resultSet.toListOfDictionaryEntries()
} }
override fun searchSegments(phrase: String): List<DictionaryEntry> { override fun findSentencesContaining(entry: DictionaryEntry): List<Sentence> {
val segments = segmentBs.segment(phrase, SegmentResultHandlers.word()) findSentences.setString(1, "_%${entry.traditional}%")
val segmentsListString = segments val resultSet: ResultSet = findSentences.executeQuery()
.mapIndexed { index, s -> "($index, '$s')" }
.joinToString(",")
val query = searchSegments.replace("?", segmentsListString) return resultSet.toListOfSentences()
val resultSet: ResultSet = connection.createStatement().executeQuery(query)
return resultSet.toListOfDictionaryEntries()
}
private fun searchSimplified(query: String): List<DictionaryEntry> {
searchSimplifiedPreparedStatement.setString(1, "$query*")
val resultSet: ResultSet = searchSimplifiedPreparedStatement.executeQuery()
return resultSet.toListOfDictionaryEntries()
}
private fun searchPinyin(query: String): List<DictionaryEntry> {
val sanitizedQuery = query.lowercase().replace(whitespaceRegex, "")
searchPinyinPreparedStatement.setString(1, "$sanitizedQuery*")
searchPinyinPreparedStatement.setString(2, "$sanitizedQuery*")
val resultSet: ResultSet = searchPinyinPreparedStatement.executeQuery()
return resultSet.toListOfDictionaryEntries()
}
private fun searchTraditional(query: String): List<DictionaryEntry> {
searchTraditionalPreparedStatement.setString(1, "$query*")
val resultSet: ResultSet = searchTraditionalPreparedStatement.executeQuery()
return resultSet.toListOfDictionaryEntries()
} }
} }

View File

@ -54,7 +54,10 @@ class DetailsController(private val model: Model, private val config: Config) {
private lateinit var webViewDefinition: WebView private lateinit var webViewDefinition: WebView
@FXML @FXML
private lateinit var listViewWords: ListView<DictionaryEntryFx> private lateinit var listViewWordsContaining: ListView<DictionaryEntryFx>
@FXML
private lateinit var listViewWordsBeginning: ListView<DictionaryEntryFx>
@FXML @FXML
private lateinit var listViewCharacters: ListView<DictionaryEntryFx> private lateinit var listViewCharacters: ListView<DictionaryEntryFx>
@ -63,13 +66,19 @@ class DetailsController(private val model: Model, private val config: Config) {
private lateinit var progressIndicatorCharacters: ProgressIndicator private lateinit var progressIndicatorCharacters: ProgressIndicator
@FXML @FXML
private lateinit var progressIndicatorWords: ProgressIndicator private lateinit var progressIndicatorWordsContaining: ProgressIndicator
@FXML
private lateinit var progressIndicatorWordsBeginning: ProgressIndicator
@FXML @FXML
private lateinit var labelNoCharactersFound: Label private lateinit var labelNoCharactersFound: Label
@FXML @FXML
private lateinit var labelNoWordsFound: Label private lateinit var labelNoWordsContainingFound: Label
@FXML
private lateinit var labelNoWordsBeginningFound: Label
@FXML @FXML
private lateinit var listViewSentences: ListView<SentenceFx> private lateinit var listViewSentences: ListView<SentenceFx>
@ -85,7 +94,8 @@ class DetailsController(private val model: Model, private val config: Config) {
initializeLabelHeadword() initializeLabelHeadword()
initializeLabelPronunciation() initializeLabelPronunciation()
initializeTabPaneDetails() initializeTabPaneDetails()
initializeListViewWords() initializeListViewWordsContaining()
initializeListViewWordsBeginning()
initializeListViewCharacters() initializeListViewCharacters()
initializeListViewSentences() initializeListViewSentences()
initializeWebViewDefinition() initializeWebViewDefinition()
@ -193,17 +203,30 @@ class DetailsController(private val model: Model, private val config: Config) {
.bind(Bindings.and(Bindings.isEmpty(model.sentences), Bindings.not(model.isFindingSentences))) .bind(Bindings.and(Bindings.isEmpty(model.sentences), Bindings.not(model.isFindingSentences)))
} }
private fun initializeListViewWords() { private fun initializeListViewWordsContaining() {
listViewWords.apply { listViewWordsContaining.apply {
cellFactory = DictionaryEntryCellFactory(resources, config) cellFactory = DictionaryEntryCellFactory(resources, config)
items = model.wordsContaining items = model.wordsContaining
disableProperty().bind(Bindings.or(model.isFindingWords, Bindings.isEmpty(model.wordsContaining))) disableProperty().bind(Bindings.or(model.isFindingWordsContaining, Bindings.isEmpty(model.wordsContaining)))
} }
progressIndicatorWords.visibleProperty().bind(model.isFindingWords) progressIndicatorWordsContaining.visibleProperty().bind(model.isFindingWordsContaining)
labelNoWordsFound labelNoWordsContainingFound
.visibleProperty() .visibleProperty()
.bind(Bindings.and(Bindings.isEmpty(model.wordsContaining), Bindings.not(model.isFindingWords))) .bind(Bindings.and(Bindings.isEmpty(model.wordsContaining), Bindings.not(model.isFindingWordsContaining)))
}
private fun initializeListViewWordsBeginning() {
listViewWordsBeginning.apply {
cellFactory = DictionaryEntryCellFactory(resources, config)
items = model.wordsBeginning
disableProperty().bind(Bindings.or(model.isFindingWordsBeginning, Bindings.isEmpty(model.wordsBeginning)))
}
progressIndicatorWordsBeginning.visibleProperty().bind(model.isFindingWordsBeginning)
labelNoWordsBeginningFound
.visibleProperty()
.bind(Bindings.and(Bindings.isEmpty(model.wordsBeginning), Bindings.not(model.isFindingWordsBeginning)))
} }
private fun initializeListViewCharacters() { private fun initializeListViewCharacters() {
@ -246,9 +269,12 @@ class DetailsController(private val model: Model, private val config: Config) {
private fun lazyUpdateTabContent(selectedTabId: String?) { private fun lazyUpdateTabContent(selectedTabId: String?) {
when (selectedTabId) { when (selectedTabId) {
"tabWords" -> { "tabWords" -> {
if (model.wordsContaining.isNotEmpty()) return if (model.wordsContaining.isEmpty()) {
model.findWordsContaining()
model.findWords() }
if (model.wordsBeginning.isEmpty()) {
model.findWordsBeginning()
}
} }
"tabCharacters" -> { "tabCharacters" -> {

View File

@ -0,0 +1,20 @@
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 FindWordsBeginningService(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.findWordsBeginning(entry.toDomain()).map { it.toFx() })
}
}

View File

@ -9,7 +9,7 @@ import javafx.collections.FXCollections
import javafx.collections.ObservableList import javafx.collections.ObservableList
import javafx.concurrent.Service import javafx.concurrent.Service
class FindWordsService(private val dictionary: Dictionary) : Service<ObservableList<DictionaryEntryFx>>() { class FindWordsContainingService(private val dictionary: Dictionary) : Service<ObservableList<DictionaryEntryFx>>() {
lateinit var entry: DictionaryEntryFx lateinit var entry: DictionaryEntryFx
override fun createTask() = task { override fun createTask() = task {

View File

@ -1,14 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.*?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import javafx.scene.web.WebView?> <?import javafx.scene.web.WebView?>
<VBox xmlns="http://javafx.com/javafx/23" xmlns:fx="http://javafx.com/fxml/1" <VBox stylesheets="/css/details.css" xmlns="http://javafx.com/javafx/23" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.marvinelsen.willow.ui.controllers.DetailsController" fx:controller="com.marvinelsen.willow.ui.controllers.DetailsController">
stylesheets="/css/details.css"> <FlowPane fx:id="flowPaneHeader" hgap="8.0" onContextMenuRequested="#headerOnContextMenuRequested" prefHeight="38.0"
<FlowPane fx:id="flowPaneHeader" styleClass="flow-pane-header" hgap="8.0" onContextMenuRequested="#headerOnContextMenuRequested" prefWidth="412.0" rowValignment="BASELINE" styleClass="flow-pane-header" vgap="8.0" VBox.vgrow="NEVER">
prefHeight="38.0" prefWidth="412.0" rowValignment="BASELINE" vgap="8.0" VBox.vgrow="NEVER">
<padding> <padding>
<Insets bottom="6.0" left="6.0" right="6.0" top="6.0"/> <Insets bottom="6.0" left="6.0" right="6.0" top="6.0"/>
</padding> </padding>
@ -16,14 +15,15 @@
<Label fx:id="labelPronunciation" styleClass="pronunciation"> <Label fx:id="labelPronunciation" styleClass="pronunciation">
</Label> </Label>
</FlowPane> </FlowPane>
<TabPane fx:id="tabPaneDetails" tabClosingPolicy="UNAVAILABLE" disable="true" VBox.vgrow="ALWAYS"> <TabPane fx:id="tabPaneDetails" tabClosingPolicy="UNAVAILABLE" VBox.vgrow="ALWAYS">
<Tab closable="false" text="%tab.definition"> <Tab closable="false" text="%tab.definition">
<WebView fx:id="webViewDefinition" minHeight="-1.0" minWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0"/> <WebView fx:id="webViewDefinition" minHeight="-1.0" minWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0"/>
</Tab> </Tab>
<Tab id="tabSentences" closable="false" text="%tab.sentences"> <Tab id="tabSentences" closable="false" text="%tab.sentences">
<StackPane> <StackPane>
<ProgressIndicator fx:id="progressIndicatorSentences" visible="false"/> <ProgressIndicator fx:id="progressIndicatorSentences" visible="false"/>
<Label fx:id="labelNoSentencesFound" text="%list.no_sentences_found" textAlignment="CENTER" visible="false" <Label fx:id="labelNoSentencesFound" text="%list.no_sentences_found" textAlignment="CENTER"
visible="false"
wrapText="true"> wrapText="true">
<padding> <padding>
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0"/> <Insets bottom="8.0" left="8.0" right="8.0" top="8.0"/>
@ -33,16 +33,40 @@
</StackPane> </StackPane>
</Tab> </Tab>
<Tab id="tabWords" closable="false" text="%tab.words"> <Tab id="tabWords" closable="false" text="%tab.words">
<VBox maxHeight="1.7976931348623157E308">
<TitledPane animated="false" maxHeight="-Infinity" text="%list.words_beginning" VBox.vgrow="ALWAYS">
<StackPane> <StackPane>
<ListView fx:id="listViewWords"/> <padding>
<Label fx:id="labelNoWordsFound" text="%list.no_words_found" textAlignment="CENTER" <Insets bottom="0.0" left="0.0" right="0.0" top="0.0"/>
visible="false" wrapText="true"> </padding>
<ProgressIndicator fx:id="progressIndicatorWordsBeginning" visible="false"/>
<Label fx:id="labelNoWordsBeginningFound" text="%list.no_words_found" textAlignment="CENTER"
visible="false"
wrapText="true">
<padding> <padding>
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0"/> <Insets bottom="8.0" left="8.0" right="8.0" top="8.0"/>
</padding> </padding>
</Label> </Label>
<ProgressIndicator fx:id="progressIndicatorWords" visible="false"/> <ListView fx:id="listViewWordsBeginning" prefHeight="4000"/>
</StackPane> </StackPane>
</TitledPane>
<TitledPane animated="false" maxHeight="-Infinity" text="%list.words_containing" VBox.vgrow="ALWAYS">
<StackPane>
<padding>
<Insets bottom="0.0" left="0.0" right="0.0" top="0.0"/>
</padding>
<ProgressIndicator fx:id="progressIndicatorWordsContaining" visible="false"/>
<Label fx:id="labelNoWordsContainingFound" text="%list.no_words_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="listViewWordsContaining" prefHeight="4000"/>
</StackPane>
</TitledPane>
</VBox>
</Tab> </Tab>
<Tab fx:id="tabCharacters" id="tabCharacters" closable="false" text="%tab.characters"> <Tab fx:id="tabCharacters" id="tabCharacters" closable="false" text="%tab.characters">
<StackPane> <StackPane>

View File

@ -21,3 +21,5 @@ search.mode.phrase=Phrase
list.no_characters_found=No characters found list.no_characters_found=No characters found
list.no_words_found=No words found list.no_words_found=No words found
list.no_sentences_found=No sentences found. list.no_sentences_found=No sentences found.
list.words_beginning=Words beginning
list.words_containing=Words containing

View File

@ -21,3 +21,5 @@ search.mode.phrase=Phrase
list.no_characters_found=No characters found list.no_characters_found=No characters found
list.no_words_found=No words found list.no_words_found=No words found
list.no_sentences_found=No sentences found. list.no_sentences_found=No sentences found.
list.words_beginning=Words beginning
list.words_containing=Words containing

View File

@ -21,3 +21,5 @@ search.mode.phrase=Phrase
list.no_characters_found=No characters found list.no_characters_found=No characters found
list.no_words_found=No words found list.no_words_found=No words found
list.no_sentences_found=No sentences found. list.no_sentences_found=No sentences found.
list.words_beginning=Words beginning
list.words_containing=Words containing

View File

@ -21,3 +21,5 @@ search.mode.phrase=Phrase
list.no_characters_found=No characters found list.no_characters_found=No characters found
list.no_words_found=No words found list.no_words_found=No words found
list.no_sentences_found=No sentences found. list.no_sentences_found=No sentences found.
list.words_beginning=Words beginning
list.words_containing=Words containing

View File

@ -21,3 +21,5 @@ search.mode.phrase=Phrase
list.no_characters_found=No characters found list.no_characters_found=No characters found
list.no_words_found=No words found list.no_words_found=No words found
list.no_sentences_found=No sentences found. list.no_sentences_found=No sentences found.
list.words_beginning=Words beginning
list.words_containing=Words containing