This commit is contained in:
dankl 2020-01-12 00:01:15 +01:00 committed by dankito
parent 10916d4fba
commit c894d8d44a
5 changed files with 353 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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()
}
}
}
}

View File

@ -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<AccountTransaction> = FXCollections.emptyObservableList<AccountTransaction>()
) : TableView<AccountTransaction>(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<AccountTransaction, AccountTransaction>(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<AccountTransaction>() {
override fun computeValue(): AccountTransaction {
return it.value
}
} }
weightedWidth(4.0)
})
columns.add(TableColumn<AccountTransaction, String>(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<String>() {
override fun computeValue(): String {
return it.value.amount.toString() + " " + it.value.currency
}
} }
})
columnResizePolicy = SmartResize.POLICY
vgrow = Priority.ALWAYS
}
}

View File

@ -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<AccountTransaction>(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
}
}
}