From c894d8d44a8642f7681da507adf87e579a157c91 Mon Sep 17 00:00:00 2001 From: dankl Date: Sun, 12 Jan 2020 00:01:15 +0100 Subject: [PATCH] Added --- .../src/main/resources/Messages.properties | 10 ++ .../src/main/resources/Messages_de.properties | 10 ++ .../AccountTransactionsControlView.kt | 83 +++++++++++ .../controls/AccountTransactionsTable.kt | 121 ++++++++++++++++ .../controls/AccountTransactionsView.kt | 129 ++++++++++++++++++ 5 files changed, 353 insertions(+) create mode 100644 BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsControlView.kt create mode 100644 BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsTable.kt create mode 100644 BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt diff --git a/BankingJavaFxApp/src/main/resources/Messages.properties b/BankingJavaFxApp/src/main/resources/Messages.properties index 42a8e4e9..8d2dc35d 100755 --- a/BankingJavaFxApp/src/main/resources/Messages.properties +++ b/BankingJavaFxApp/src/main/resources/Messages.properties @@ -19,6 +19,16 @@ accounts.view.all.accounts=All accounts accounts.view.context.menu.info=Info +account.transactions.control.view.search.label=Find: +account.transactions.control.view.balance.label=Balance: + +account.transactions.table.column.header.value.date=Value date +account.transactions.table.column.header.usage=Usage +account.transactions.table.column.header.amount=Amount +account.transactions.table.context.menu.transfer.money.to=Transfer money to %s +account.transactions.table.context.menu.show.transaction.details=Show details + + add.account.dialog.title=Add account add.account.dialog.bank.code.label=Bank code add.account.dialog.customer.id.and.password.hint=Enter the same values here as in your online banking portal diff --git a/BankingJavaFxApp/src/main/resources/Messages_de.properties b/BankingJavaFxApp/src/main/resources/Messages_de.properties index f3b0dabc..8b9b21c0 100755 --- a/BankingJavaFxApp/src/main/resources/Messages_de.properties +++ b/BankingJavaFxApp/src/main/resources/Messages_de.properties @@ -19,6 +19,16 @@ accounts.view.all.accounts=Alle Konten accounts.view.context.menu.info=Info +account.transactions.control.view.search.label=Suchen: +account.transactions.control.view.balance.label=Saldo: + +account.transactions.table.column.header.value.date=Buchungstag +account.transactions.table.column.header.usage=Verwendungszweck +account.transactions.table.column.header.amount=Betrag +account.transactions.table.context.menu.transfer.money.to=Neue Überweisung an %s +account.transactions.table.context.menu.show.transaction.details=Details anzeigen + + add.account.dialog.title=Konto hinzufügen add.account.dialog.bank.code.label=Bankleitzahl add.account.dialog.customer.id.and.password.hint=Geben Sie hier die selben Werte ein wie auf Ihrer Online Banking Webseite diff --git a/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsControlView.kt b/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsControlView.kt new file mode 100644 index 00000000..5b8f4782 --- /dev/null +++ b/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsControlView.kt @@ -0,0 +1,83 @@ +package net.dankito.banking.ui.javafx.controls + +import javafx.beans.property.SimpleStringProperty +import javafx.geometry.Insets +import javafx.geometry.Pos +import net.dankito.banking.ui.presenter.MainWindowPresenter +import net.dankito.utils.javafx.ui.controls.UpdateButton +import net.dankito.utils.javafx.ui.controls.addButton +import net.dankito.utils.javafx.ui.controls.searchtextfield +import net.dankito.utils.javafx.ui.controls.updateButton +import net.dankito.utils.javafx.ui.extensions.fixedHeight +import tornadofx.* + + +open class AccountTransactionsControlView( + protected val presenter: MainWindowPresenter, + protected val transactionsFilter: SimpleStringProperty, + protected val balance: SimpleStringProperty +) : View() { + + + override val root = borderpane { + fixedHeight = 36.0 + + left = label(messages["account.transactions.control.view.search.label"]) { + borderpaneConstraints { + alignment = Pos.CENTER_LEFT + margin = Insets(4.0, 12.0, 4.0, 4.0) + } + } + + center { + searchtextfield(transactionsFilter) { + + } + } + + right = hbox { + alignment = Pos.CENTER_LEFT + + label(messages["account.transactions.control.view.balance.label"]) { + hboxConstraints { + alignment = Pos.CENTER_LEFT + marginLeft = 48.0 + marginRight = 6.0 + } + } + + label(balance) { + minWidth = 50.0 + alignment = Pos.CENTER_RIGHT + } + + updateButton { + action { updateAccountTransactions(this) } + + hboxConstraints { + marginLeft = 12.0 + } + } + + addButton { + useMaxHeight = true + + // TODO +// action { presenter.showTransferMoneyDialog() } + + hboxConstraints { + marginLeft = 12.0 + } + } + } + } + + private fun updateAccountTransactions(updateButton: UpdateButton) { + presenter.updateAccountsTransactionsAsync { transactions -> + runLater { + updateButton.resetIsUpdating() + } + } + } + +} \ No newline at end of file diff --git a/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsTable.kt b/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsTable.kt new file mode 100644 index 00000000..e79221ef --- /dev/null +++ b/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsTable.kt @@ -0,0 +1,121 @@ +package net.dankito.banking.ui.javafx.controls + +import javafx.beans.binding.ObjectBinding +import javafx.collections.FXCollections +import javafx.collections.ObservableList +import javafx.geometry.Insets +import javafx.geometry.Pos +import javafx.scene.control.ContentDisplay +import javafx.scene.control.ContextMenu +import javafx.scene.control.TableColumn +import javafx.scene.control.TableView +import javafx.scene.layout.Priority +import javafx.scene.paint.Color +import javafx.util.Callback +import net.dankito.banking.ui.model.AccountTransaction +import net.dankito.banking.ui.presenter.MainWindowPresenter +import net.dankito.utils.javafx.ui.extensions.ensureOnlyUsesSpaceIfVisible +import tornadofx.* +import tornadofx.FX.Companion.messages +import java.text.DateFormat + + +open class AccountTransactionsTable @JvmOverloads constructor( + protected val presenter: MainWindowPresenter, + transactions: ObservableList = FXCollections.emptyObservableList() +) : TableView(transactions) { + + + companion object { + val ValueDateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM) + + private val LabelMargin = Insets(4.0, 0.0, 4.0, 4.0) + } + + + init { + initUi() + } + + + protected open fun initUi() { + column(messages["account.transactions.table.column.header.value.date"], AccountTransaction::bookingDate) { + prefWidth = 115.0 + + cellFormat { + text = ValueDateFormat.format(it) + alignment = Pos.CENTER_LEFT + paddingLeft = 4.0 + } + } + + columns.add(TableColumn(messages["account.transactions.table.column.header.usage"]).apply { + + this.cellFormat { + contentDisplay = ContentDisplay.GRAPHIC_ONLY + + graphic = vbox { + prefHeight = 94.0 + alignment = Pos.CENTER_LEFT + + label(it.bookingText ?: "") { + vboxConstraints { + margin = LabelMargin + } + } + + label(it.otherPartyName ?: "") { + isVisible = it.showOtherPartyName + ensureOnlyUsesSpaceIfVisible() + + vboxConstraints { + margin = LabelMargin + } + } + + label(it.usage ?: "") { + vboxConstraints { + margin = LabelMargin + } + } + } + } + + cellValueFactory = Callback { object : ObjectBinding() { + override fun computeValue(): AccountTransaction { + return it.value + } + + } } + + weightedWidth(4.0) + }) + + columns.add(TableColumn(messages["account.transactions.table.column.header.amount"]).apply { + prefWidth = 85.0 + + this.cellFormat { + text = it + alignment = Pos.CENTER_RIGHT + paddingRight = 4.0 + + style { + textFill = if (rowItem.amount.toLong() < 0) Color.RED else Color.GREEN + } + } + + cellValueFactory = Callback { object : ObjectBinding() { + override fun computeValue(): String { + return it.value.amount.toString() + " " + it.value.currency + } + + } } + }) + + + columnResizePolicy = SmartResize.POLICY + + vgrow = Priority.ALWAYS + } + +} \ No newline at end of file diff --git a/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt b/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt new file mode 100644 index 00000000..6130ec69 --- /dev/null +++ b/BankingJavaFxControls/src/main/kotlin/net/dankito/banking/ui/javafx/controls/AccountTransactionsView.kt @@ -0,0 +1,129 @@ +package net.dankito.banking.ui.javafx.controls + +import javafx.beans.property.SimpleBooleanProperty +import javafx.beans.property.SimpleStringProperty +import javafx.collections.FXCollections +import javafx.scene.control.ContextMenu +import javafx.scene.input.ContextMenuEvent +import javafx.scene.input.MouseButton +import javafx.scene.input.MouseEvent +import net.dankito.banking.ui.model.AccountTransaction +import net.dankito.banking.ui.model.responses.GetTransactionsResponse +import net.dankito.banking.ui.presenter.MainWindowPresenter +import tornadofx.* + + +open class AccountTransactionsView(private val presenter: MainWindowPresenter) : View() { + + protected val isAccountSelected = SimpleBooleanProperty(false) + + protected val transactionsFilter = SimpleStringProperty("") + + protected val balance = SimpleStringProperty("") + + protected val transactionsToDisplay = FXCollections.observableArrayList(presenter.allTransactions) + + + protected var currentMenu: ContextMenu? = null + + + init { + presenter.addAccountAddedListener { handleAccountAdded() } + + presenter.addRetrievedAccountTransactionsResponseListener { _, response -> + handleGetTransactionsResponseOffUiThread(response) + } + + transactionsFilter.addListener { _, _, newValue -> + transactionsToDisplay.setAll(presenter.searchAccountTransactions(newValue)) + } + } + + + override val root = vbox { + add(AccountTransactionsControlView(presenter, transactionsFilter, balance).apply { + enableWhen(isAccountSelected) + }) + + add(AccountTransactionsTable(presenter, transactionsToDisplay).apply { + setOnMouseClicked { tableClicked(it, this.selectionModel.selectedItem) } + + setOnContextMenuRequested { event -> showContextMenu(event, this) } + }) + } + + + protected open fun tableClicked(event: MouseEvent, selectedItem: AccountTransaction?) { + if (event.button == MouseButton.PRIMARY || event.button == MouseButton.MIDDLE) { + currentMenu?.hide() + } + + if(event.clickCount == 2 && event.button == MouseButton.PRIMARY) { + if(selectedItem != null) { + showTransactionDetailsDialog(selectedItem) + } + } + } + + protected open fun showContextMenu(event: ContextMenuEvent, table: AccountTransactionsTable) { + currentMenu?.hide() + + val selectedItem = table.selectionModel.selectedItem + + if (selectedItem != null) { + currentMenu = createContextMenuForItems(selectedItem) + currentMenu?.show(table, event.screenX, event.screenY) + } + } + + protected open fun createContextMenuForItems(selectedItem: AccountTransaction): ContextMenu { + val contextMenu = ContextMenu() + + contextMenu.apply { + if (selectedItem.otherPartyName != null) { + item(String.format(FX.messages["account.transactions.table.context.menu.transfer.money.to"], selectedItem.otherPartyName)) { + action { showTransferMoneyDialog(selectedItem) } + } + + separator() + } + + item(FX.messages["account.transactions.table.context.menu.show.transaction.details"]) { + action { + showTransactionDetailsDialog(selectedItem) + } + } + } + + return contextMenu + } + + protected open fun showTransactionDetailsDialog(transaction: AccountTransaction) { + // TODO: +// presenter.showTransactionDetailsWindow(transaction.item) + } + + protected open fun showTransferMoneyDialog(transaction: AccountTransaction) { + // TODO: +// presenter.showTransferMoneyDialog(transaction.bankAccount, TransferMoneyData.fromAccountTransaction(transaction)) + } + + + protected open fun handleAccountAdded() { + isAccountSelected.value = presenter.accounts.isNotEmpty() // TODO: not correct, check if an account has been selected + } + + protected open fun handleGetTransactionsResponseOffUiThread(response: GetTransactionsResponse) { + runLater { handleGetTransactionsResponseOnUiThread(response) } + } + + protected open fun handleGetTransactionsResponseOnUiThread(response: GetTransactionsResponse) { + if (response.isSuccessful) { + transactionsToDisplay.setAll(presenter.allTransactions) // TODO: get that one for currently displayed account and apply current filter on it + + // TODO: if transactions are filtered calculate and show balance of displayed transactions? + balance.value = presenter.balanceOfAllAccounts.toString() // TODO: get that one for currently displayed account and add currency + } + } + +}