From ce90cc5d080d7aefa59f20b098fa4466794833af Mon Sep 17 00:00:00 2001 From: dankito Date: Thu, 4 Jun 2020 13:17:53 +0200 Subject: [PATCH] Implemented autocomplete list for banks in AddAccountDialog --- .../ui/javafx/dialogs/AddAccountDialog.kt | 50 +++++++++- .../addaccount/BankInfoListCellFragment.kt | 87 ++++++++++++++++++ .../dialogs/addaccount/BankInfoViewModel.kt | 19 ++++ .../icons/bank_does_not_support_fints_3_0.png | Bin 0 -> 3788 bytes .../icons/bank_supports_fints_3_0.png | Bin 0 -> 3904 bytes 5 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/addaccount/BankInfoListCellFragment.kt create mode 100644 ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/addaccount/BankInfoViewModel.kt create mode 100755 ui/BankingJavaFxControls/src/main/resources/icons/bank_does_not_support_fints_3_0.png create mode 100755 ui/BankingJavaFxControls/src/main/resources/icons/bank_supports_fints_3_0.png diff --git a/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/AddAccountDialog.kt b/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/AddAccountDialog.kt index 54cd51ab..b0260d2e 100755 --- a/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/AddAccountDialog.kt +++ b/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/AddAccountDialog.kt @@ -1,5 +1,6 @@ package net.dankito.banking.ui.javafx.dialogs +import com.sun.javafx.scene.traversal.Direction import javafx.beans.property.SimpleBooleanProperty import javafx.beans.property.SimpleStringProperty import javafx.geometry.Insets @@ -11,10 +12,14 @@ import javafx.scene.layout.Priority import javafx.scene.paint.Color import javafx.scene.text.Font import javafx.scene.text.FontWeight +import kotlinx.coroutines.* import net.dankito.banking.ui.model.responses.AddAccountResponse import net.dankito.banking.ui.presenter.BankingPresenter import net.dankito.banking.fints.model.BankInfo +import net.dankito.banking.ui.javafx.dialogs.addaccount.BankInfoListCellFragment +import net.dankito.utils.javafx.ui.controls.AutoCompletionSearchTextField import net.dankito.utils.javafx.ui.controls.ProcessingIndicatorButton +import net.dankito.utils.javafx.ui.controls.autocompletionsearchtextfield import net.dankito.utils.javafx.ui.dialogs.Window import net.dankito.utils.javafx.ui.extensions.ensureOnlyUsesSpaceIfVisible import net.dankito.utils.javafx.ui.extensions.fixedHeight @@ -40,8 +45,12 @@ open class AddAccountDialog(protected val presenter: BankingPresenter) : Window( protected val bankCode = SimpleStringProperty("") + protected var txtfldBankCode: AutoCompletionSearchTextField by singleAssign() + protected var selectedBank: BankInfo? = null + protected var lastSearchBanksJob: Job? = null + protected val customerId = SimpleStringProperty("") protected val password = SimpleStringProperty("") @@ -75,9 +84,17 @@ open class AddAccountDialog(protected val presenter: BankingPresenter) : Window( } } - textfield(bankCode) { + txtfldBankCode = autocompletionsearchtextfield(bankCode) { prefHeight = TextFieldHeight + textProperty().addListener { _, _, newValue -> searchBanks(newValue) } +// focusedProperty().addListener { _, _, newValue -> +// if(newValue) searchBanks(text) +// } + + onAutoCompletion = { bankSelected(it) } + listCellFragment = BankInfoListCellFragment::class + vboxConstraints { margin = TextFieldMargins } @@ -182,6 +199,37 @@ open class AddAccountDialog(protected val presenter: BankingPresenter) : Window( } + protected open fun searchBanks(query: String?) { + lastSearchBanksJob?.cancel() + + lastSearchBanksJob = GlobalScope.launch(Dispatchers.IO) { + val filteredBanks = presenter.searchBanksByNameBankCodeOrCity(query?.toString()) + + withContext(Dispatchers.Main) { + txtfldBankCode.setAutoCompleteList(filteredBanks) + } + } + } + + protected open fun bankSelected(bank: BankInfo) { + unfocusBankCodeTextField() + + selectedBank = bank + + bankCode.value = bank.bankCode + + checkIfRequiredDataHasBeenEntered() + + if (bank.supportsFinTs3_0 == false) { +// showBankDoesNotSupportFinTs30ErrorMessage(bank) // TODO + } + } + + protected open fun unfocusBankCodeTextField() { + txtfldBankCode.impl_traverse(Direction.NEXT) + } + + protected open fun checkIsEnteredBankCodeValid(enteredBankCode: String?) { enteredBankCode?.let { val banksSearchResult = presenter.searchBanksByNameBankCodeOrCity(enteredBankCode) diff --git a/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/addaccount/BankInfoListCellFragment.kt b/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/addaccount/BankInfoListCellFragment.kt new file mode 100644 index 00000000..7a75afb4 --- /dev/null +++ b/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/addaccount/BankInfoListCellFragment.kt @@ -0,0 +1,87 @@ +package net.dankito.banking.ui.javafx.dialogs.addaccount + +import javafx.geometry.Pos +import javafx.scene.control.Labeled +import javafx.scene.effect.ColorAdjust +import javafx.scene.image.Image +import javafx.scene.image.ImageView +import javafx.scene.layout.Priority +import javafx.scene.paint.Color +import javafx.scene.text.Font +import net.dankito.banking.fints.model.BankInfo +import tornadofx.* + + +open class BankInfoListCellFragment : ListCellFragment() { + + companion object { + const val ItemHeight = 40.0 + + val Fints30SupportedIcon = Image("icons/bank_supports_fints_3_0.png") + + val Fints30NotSupportedIcon = Image("icons/bank_does_not_support_fints_3_0.png") + } + + + open val bank = BankInfoViewModel().bindTo(this) + + + override val root = hbox { + prefHeight = ItemHeight + + paddingTop = 4.0 + paddingBottom = 4.0 + + imageview { + alignment = Pos.CENTER + fitWidth = ItemHeight + isPreserveRatio = true + + setFints3SupportedOrNotIcon(this) + + bank.supportsFinTs3_0.addListener { _, _, _ -> setFints3SupportedOrNotIcon(this) } + } + + vbox { + hboxConstraints { + hGrow = Priority.ALWAYS + + marginLeft = 4.0 + } + + label(bank.bankName) { + useMaxWidth = true + + font = Font.font(14.0) + } + + hbox { + alignment = Pos.CENTER_LEFT + + label(bank.bankCode) + + label(bank.bankAddress) { + useMaxWidth = true + + hboxConstraints { + marginLeft = 12.0 + } + } + + vboxConstraints { + marginTop = 6.0 + } + } + } + } + + protected open fun setFints3SupportedOrNotIcon(imageView: ImageView) { + if (bank.supportsFinTs3_0.value) { + imageView.image = Fints30SupportedIcon + } + else { + imageView.image = Fints30NotSupportedIcon + } + } + +} \ No newline at end of file diff --git a/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/addaccount/BankInfoViewModel.kt b/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/addaccount/BankInfoViewModel.kt new file mode 100644 index 00000000..0830659f --- /dev/null +++ b/ui/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/dialogs/addaccount/BankInfoViewModel.kt @@ -0,0 +1,19 @@ +package net.dankito.banking.ui.javafx.dialogs.addaccount + +import javafx.beans.property.SimpleBooleanProperty +import javafx.beans.property.SimpleStringProperty +import net.dankito.banking.fints.model.BankInfo +import tornadofx.ItemViewModel + + +open class BankInfoViewModel : ItemViewModel() { + + val supportsFinTs3_0 = bind { SimpleBooleanProperty(item?.supportsFinTs3_0 ?: false) } + + val bankName = bind { SimpleStringProperty(item?.name) } + + val bankCode = bind { SimpleStringProperty(item?.bankCode) } + + val bankAddress = bind { SimpleStringProperty(item?.let { item.postalCode + " " + item.city }) } + +} \ No newline at end of file diff --git a/ui/BankingJavaFxControls/src/main/resources/icons/bank_does_not_support_fints_3_0.png b/ui/BankingJavaFxControls/src/main/resources/icons/bank_does_not_support_fints_3_0.png new file mode 100755 index 0000000000000000000000000000000000000000..402b6e59e28d847e65ca40973e0deb03406b1c64 GIT binary patch literal 3788 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

|5o9mHTLWEL-}kpl;=bGWZ8(DR*l%K%^j6h+ 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