Compare commits
No commits in common. "cdcfd92f606b577ec51decdc772a1d23c92d9721" and "1ee597f93455b486f6017e6c74925e8d0398dcf3" have entirely different histories.
cdcfd92f60
...
1ee597f934
@ -29,7 +29,6 @@ class WillowApplication : Application() {
|
||||
private const val FONT_SIZE = 12.0
|
||||
|
||||
private const val JDBC_CONNECTION_STRING = "jdbc:sqlite:dictionary.db"
|
||||
val resourceBundle: ResourceBundle = ResourceBundle.getBundle("i18n/willow", Locale.US)
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
@ -46,7 +45,7 @@ class WillowApplication : Application() {
|
||||
val model = Model(searchService, findWordsService)
|
||||
|
||||
val fxmlLoader = FXMLLoader()
|
||||
fxmlLoader.resources = resourceBundle
|
||||
fxmlLoader.resources = ResourceBundle.getBundle("i18n/willow", Locale.US)
|
||||
fxmlLoader.controllerFactory = Callback { type ->
|
||||
when (type) {
|
||||
MainController::class.java -> MainController(model)
|
||||
@ -72,8 +71,7 @@ class WillowApplication : Application() {
|
||||
private fun loadFonts() {
|
||||
Font.loadFont(javaClass.getResourceAsStream("/fonts/inter.ttf"), FONT_SIZE)
|
||||
Font.loadFont(javaClass.getResourceAsStream("/fonts/tw-kai.ttf"), FONT_SIZE)
|
||||
Font.loadFont(javaClass.getResourceAsStream("/fonts/noto-sans-tc-regular.ttf"), FONT_SIZE)
|
||||
Font.loadFont(javaClass.getResourceAsStream("/fonts/noto-sans-tc-bold.ttf"), FONT_SIZE)
|
||||
Font.loadFont(javaClass.getResourceAsStream("/fonts/noto-sans-tc.ttf"), FONT_SIZE)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,6 @@ fun main() {
|
||||
pinyin_with_tone_marks TEXT NOT NULL,
|
||||
pinyin_with_tone_numbers TEXT NOT NULL,
|
||||
zhuyin TEXT NOT NULL,
|
||||
searchable_pinyin TEXT NOT NULL,
|
||||
searchable_pinyin_with_tone_numbers TEXT NOT NULL,
|
||||
definitions JSON NOT NULL,
|
||||
character_count INTEGER NOT NULL,
|
||||
CONSTRAINT character_count_gte CHECK(character_count > 0)
|
||||
@ -38,10 +36,6 @@ fun main() {
|
||||
statement.executeUpdate("CREATE INDEX IF NOT EXISTS idx_cedict_traditional ON cedict (traditional)")
|
||||
statement.executeUpdate("CREATE INDEX IF NOT EXISTS idx_cedict_simplified ON cedict (simplified)")
|
||||
statement.executeUpdate("CREATE INDEX IF NOT EXISTS idx_cedict_character_count ON cedict (character_count)")
|
||||
statement.executeUpdate("CREATE INDEX IF NOT EXISTS idx_cedict_searchable_pinyin ON cedict (searchable_pinyin)")
|
||||
statement.executeUpdate(
|
||||
"CREATE INDEX IF NOT EXISTS idx_cedict_searchable_pinyin_with_tone_numbers ON cedict (searchable_pinyin_with_tone_numbers)"
|
||||
)
|
||||
|
||||
val cedictParser = CedictParser.instance
|
||||
val cedictEntries =
|
||||
@ -51,7 +45,7 @@ fun main() {
|
||||
|
||||
val insertStatement =
|
||||
connection.prepareStatement(
|
||||
"INSERT OR IGNORE INTO cedict(traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, searchable_pinyin, searchable_pinyin_with_tone_numbers, definitions, character_count) VALUES(?,?,?,?,?,?,?,?,?)"
|
||||
"INSERT OR IGNORE INTO cedict(traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, definitions, character_count) VALUES(?,?,?,?,?,?,?)"
|
||||
)
|
||||
for (entry in cedictEntries) {
|
||||
try {
|
||||
@ -77,31 +71,12 @@ fun main() {
|
||||
)
|
||||
insertStatement.setString(
|
||||
6,
|
||||
entry.pinyinSyllables.joinToString(
|
||||
separator = ""
|
||||
) {
|
||||
it
|
||||
.format(TransliterationSystem.PINYIN_WITH_TONE_NUMBERS)
|
||||
.lowercase()
|
||||
.replace("""\d""".toRegex(), "")
|
||||
}
|
||||
)
|
||||
insertStatement.setString(
|
||||
7,
|
||||
entry.pinyinSyllables.joinToString(
|
||||
separator = ""
|
||||
) {
|
||||
it.format(TransliterationSystem.PINYIN_WITH_TONE_NUMBERS).lowercase()
|
||||
}
|
||||
)
|
||||
insertStatement.setString(
|
||||
8,
|
||||
Json.encodeToString(
|
||||
ListSerializer(ListSerializer(String.serializer())),
|
||||
entry.definitions.map { it.glosses }
|
||||
)
|
||||
)
|
||||
insertStatement.setInt(9, entry.traditional.length)
|
||||
insertStatement.setInt(7, entry.traditional.length)
|
||||
} catch (_: Exception) {
|
||||
// no-op
|
||||
}
|
||||
|
@ -20,15 +20,9 @@ fun main() {
|
||||
val (shangWords, time3) = measureTimedValue {
|
||||
sqliteDictionary.findWordsContaining(shang)
|
||||
}
|
||||
val (characters, time4) = measureTimedValue {
|
||||
val searchi = sqliteDictionary.search("師範大學", SearchMode.TRADITIONAL).first()
|
||||
sqliteDictionary.findCharacters(searchi)
|
||||
}
|
||||
println(searchResults)
|
||||
println(shangWords)
|
||||
println(characters)
|
||||
println(time)
|
||||
println(time2)
|
||||
println(time3)
|
||||
println(time4)
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import java.sql.PreparedStatement
|
||||
import java.sql.ResultSet
|
||||
|
||||
class SqliteDictionary(private val connection: Connection) : Dictionary {
|
||||
private val whitespaceRegex = """\s+""".toRegex()
|
||||
|
||||
private val searchSimplifiedPreparedStatement: PreparedStatement by lazy {
|
||||
connection.prepareStatement(
|
||||
@ -30,18 +29,6 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
|
||||
)
|
||||
}
|
||||
|
||||
private val searchPinyinPreparedStatement: PreparedStatement by lazy {
|
||||
connection.prepareStatement(
|
||||
"""
|
||||
SELECT traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, definitions
|
||||
FROM cedict
|
||||
WHERE searchable_pinyin GLOB ?
|
||||
OR searchable_pinyin_with_tone_numbers GLOB ?
|
||||
ORDER BY character_count ASC
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
private val findWordsContaining: PreparedStatement by lazy {
|
||||
connection.prepareStatement(
|
||||
"""
|
||||
@ -53,14 +40,8 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
|
||||
)
|
||||
}
|
||||
|
||||
private val findCharacters = """
|
||||
SELECT traditional, simplified, pinyin_with_tone_marks, pinyin_with_tone_numbers, zhuyin, definitions
|
||||
FROM cedict
|
||||
WHERE traditional IN (?)
|
||||
""".trimIndent()
|
||||
|
||||
override fun search(query: String, searchMode: SearchMode) = when (searchMode) {
|
||||
SearchMode.PINYIN -> searchPinyin(query)
|
||||
SearchMode.PINYIN -> TODO()
|
||||
SearchMode.SIMPLIFIED -> searchSimplified(query)
|
||||
SearchMode.TRADITIONAL -> searchTraditional(query)
|
||||
SearchMode.ENGLISH -> TODO()
|
||||
@ -79,16 +60,7 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
|
||||
}
|
||||
|
||||
override fun findCharacters(entry: DictionaryEntry): List<DictionaryEntry> {
|
||||
val characterList = entry.traditional
|
||||
.split("")
|
||||
.filter { it.isNotBlank() }
|
||||
.joinToString(",") { "'$it'" }
|
||||
|
||||
val query = findCharacters.replace("?", characterList)
|
||||
|
||||
val resultSet: ResultSet = connection.createStatement().executeQuery(query)
|
||||
|
||||
return resultSet.toListOfDictionaryEntries()
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
private fun searchSimplified(query: String): List<DictionaryEntry> {
|
||||
@ -99,17 +71,6 @@ class SqliteDictionary(private val connection: Connection) : Dictionary {
|
||||
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*")
|
||||
|
||||
|
@ -44,13 +44,15 @@ internal class EntryCell : ListCell<DictionaryEntryFx?>() {
|
||||
|
||||
init {
|
||||
text = null
|
||||
if (item != null) {
|
||||
contextMenu = createContextMenuForEntry(item!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateItem(entry: DictionaryEntryFx?, empty: Boolean) {
|
||||
super.updateItem(entry, empty)
|
||||
if (empty || entry == null) {
|
||||
graphic = null
|
||||
contextMenu = null
|
||||
} else {
|
||||
labelHeadword.text = entry.traditionalProperty.value
|
||||
labelPronunciation.text = entry.pinyinWithToneMarksProperty.value
|
||||
@ -58,7 +60,6 @@ internal class EntryCell : ListCell<DictionaryEntryFx?>() {
|
||||
val definition = entry.definitions.joinToString(separator = " / ") { it.joinToString(separator = "; ") }
|
||||
labelDefinition.text = definition
|
||||
|
||||
contextMenu = createContextMenuForEntry(entry)
|
||||
graphic = root
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,6 @@ import javafx.scene.control.Label
|
||||
import javafx.scene.control.ListView
|
||||
import javafx.scene.control.TabPane
|
||||
import javafx.scene.web.WebView
|
||||
import kotlinx.html.body
|
||||
import kotlinx.html.h1
|
||||
import kotlinx.html.html
|
||||
import kotlinx.html.li
|
||||
import kotlinx.html.ol
|
||||
import kotlinx.html.stream.createHTML
|
||||
|
||||
class DetailsController(private val model: Model) {
|
||||
@FXML
|
||||
@ -70,19 +64,19 @@ class DetailsController(private val model: Model) {
|
||||
return@addListener
|
||||
}
|
||||
webViewDefinition.engine.loadContent(
|
||||
createHTML().html {
|
||||
body {
|
||||
h1 {
|
||||
+"CC-CEDICT"
|
||||
}
|
||||
ol {
|
||||
for (definition in newValue.definitions) {
|
||||
li {
|
||||
+definition.joinToString(separator = "; ")
|
||||
}
|
||||
}
|
||||
}
|
||||
buildString {
|
||||
append("<html>")
|
||||
append("<body>")
|
||||
append("<h1>CC-CEDICT</h1>")
|
||||
append("<ol>")
|
||||
for (definition in newValue.definitions) {
|
||||
append("<li>")
|
||||
append(definition.joinToString(separator = "; "))
|
||||
append("</li>")
|
||||
}
|
||||
append("</ol>")
|
||||
append("</body>")
|
||||
append("</html>")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -24,14 +24,5 @@ class SearchController(private val model: Model) {
|
||||
val searchMode = searchModeToggleGroup.selectedToggle.userData as SearchMode
|
||||
model.search(newValue, searchMode)
|
||||
}
|
||||
|
||||
searchModeToggleGroup.selectedToggleProperty().addListener { _, _, newValue ->
|
||||
if (textFieldSearch.text.isNullOrBlank()) {
|
||||
return@addListener
|
||||
}
|
||||
|
||||
val searchMode = newValue.userData as SearchMode
|
||||
model.search(textFieldSearch.text, searchMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,18 @@
|
||||
package com.marvinelsen.willow.ui.util
|
||||
|
||||
import com.marvinelsen.willow.WillowApplication
|
||||
import com.marvinelsen.willow.ui.DictionaryEntryFx
|
||||
import javafx.event.EventHandler
|
||||
import javafx.scene.control.ContextMenu
|
||||
import javafx.scene.control.MenuItem
|
||||
|
||||
fun createContextMenuForEntry(entry: DictionaryEntryFx) = ContextMenu().apply {
|
||||
val menuItemCopyHeadword =
|
||||
MenuItem(WillowApplication.resourceBundle.getString("menubar.edit.copy.headword")).apply {
|
||||
onAction = EventHandler { ClipboardHelper.copyHeadword(entry) }
|
||||
}
|
||||
val menuItemCopyHeadword = MenuItem("Copy Headword").apply {
|
||||
onAction = EventHandler { ClipboardHelper.copyHeadword(entry) }
|
||||
}
|
||||
|
||||
val menuItemCopyPronunciation =
|
||||
MenuItem(WillowApplication.resourceBundle.getString("menubar.edit.copy.pronunciation")).apply {
|
||||
onAction = EventHandler { ClipboardHelper.copyPronunciation(entry) }
|
||||
}
|
||||
val menuItemCopyPronunciation = MenuItem("Copy Pronunciation").apply {
|
||||
onAction = EventHandler { ClipboardHelper.copyPronunciation(entry) }
|
||||
}
|
||||
|
||||
items.addAll(menuItemCopyHeadword, menuItemCopyPronunciation)
|
||||
}
|
||||
|
@ -15,11 +15,6 @@ h1 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
ol {
|
||||
padding-left: 0;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
ol li:only-child {
|
||||
list-style: none;
|
||||
}
|
||||
|
@ -8,11 +8,11 @@
|
||||
|
||||
.list-view {
|
||||
-fx-selection-bar: #B8EEFF;
|
||||
-fx-font-family: "Noto Sans CJK TC";
|
||||
/*-fx-selection-bar-non-focused: green;*/
|
||||
}
|
||||
|
||||
.list-view-entry {
|
||||
-fx-font-family: "Noto Sans TC";
|
||||
-fx-font-size: 20;
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
@ -34,7 +34,7 @@
|
||||
}
|
||||
|
||||
.pronunciation {
|
||||
-fx-font: 16 "Noto Sans TC";
|
||||
-fx-font: 16 "Noto Sans CJK TC";
|
||||
}
|
||||
|
||||
.settings-dialog .content {
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import com.marvinelsen.willow.ui.cells.DictionaryEntryCellFactory?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.web.WebView?>
|
||||
@ -22,11 +21,7 @@
|
||||
<ListView fx:id="listviewSentences"/>
|
||||
</Tab>
|
||||
<Tab id="tabWords" closable="false" disable="false" text="%tab.words">
|
||||
<ListView fx:id="listViewWords">
|
||||
<cellFactory>
|
||||
<DictionaryEntryCellFactory/>
|
||||
</cellFactory>
|
||||
</ListView>
|
||||
<ListView fx:id="listViewWords"/>
|
||||
</Tab>
|
||||
<Tab closable="false" disable="false" text="%tab.characters">
|
||||
<ListView fx:id="listViewCharacters"/>
|
||||
|
@ -31,8 +31,7 @@
|
||||
</userData>
|
||||
</RadioButton>
|
||||
<RadioButton mnemonicParsing="false" text="%search.mode.english"
|
||||
toggleGroup="$searchModeToggleGroup"
|
||||
disable="true">
|
||||
toggleGroup="$searchModeToggleGroup">
|
||||
<userData>
|
||||
<SearchMode fx:value="ENGLISH"/>
|
||||
</userData>
|
||||
|
Loading…
x
Reference in New Issue
Block a user