Added new AccountSelectionBox, still buggy due to weird javafx combobox stuff.

This commit is contained in:
Andrew Lalis 2024-01-11 22:16:24 -05:00
parent 7ceaca7068
commit 3521dee149
4 changed files with 79 additions and 38 deletions

View File

@ -8,7 +8,7 @@ import com.andrewlalis.perfin.model.Account;
import com.andrewlalis.perfin.model.CreditAndDebitAccounts;
import com.andrewlalis.perfin.model.Profile;
import com.andrewlalis.perfin.model.Transaction;
import com.andrewlalis.perfin.view.AccountComboBoxCellFactory;
import com.andrewlalis.perfin.view.component.AccountSelectionBox;
import com.andrewlalis.perfin.view.component.FileSelectionArea;
import com.andrewlalis.perfin.view.component.validation.ValidationApplier;
import com.andrewlalis.perfin.view.component.validation.validators.CurrencyAmountValidator;
@ -42,14 +42,16 @@ public class EditTransactionController implements RouteSelectionListener {
@FXML public TextArea descriptionField;
@FXML public HBox linkedAccountsContainer;
@FXML public ComboBox<Account> linkDebitAccountComboBox;
@FXML public ComboBox<Account> linkCreditAccountComboBox;
@FXML public AccountSelectionBox debitAccountSelector;
@FXML public AccountSelectionBox creditAccountSelector;
@FXML public VBox attachmentsVBox;
private FileSelectionArea attachmentsSelectionArea;
@FXML public Button saveButton;
private Transaction transaction;
@FXML public void initialize() {
// Setup error field validation.
var timestampValid = new ValidationApplier<>(new PredicateValidator<String>()
@ -67,8 +69,8 @@ public class EditTransactionController implements RouteSelectionListener {
).validatedInitially().attach(descriptionField, descriptionField.textProperty());
// Linked accounts will use a property derived from both the debit and credit selections.
Property<CreditAndDebitAccounts> linkedAccountsProperty = new SimpleObjectProperty<>(getSelectedAccounts());
linkDebitAccountComboBox.valueProperty().addListener((observable, oldValue, newValue) -> linkedAccountsProperty.setValue(getSelectedAccounts()));
linkCreditAccountComboBox.valueProperty().addListener((observable, oldValue, newValue) -> linkedAccountsProperty.setValue(getSelectedAccounts()));
debitAccountSelector.valueProperty().addListener((observable, oldValue, newValue) -> linkedAccountsProperty.setValue(getSelectedAccounts()));
creditAccountSelector.valueProperty().addListener((observable, oldValue, newValue) -> linkedAccountsProperty.setValue(getSelectedAccounts()));
var linkedAccountsValid = new ValidationApplier<>(new PredicateValidator<CreditAndDebitAccounts>()
.addPredicate(accounts -> accounts.hasCredit() || accounts.hasDebit(), "At least one account must be linked.")
.addPredicate(
@ -81,13 +83,7 @@ public class EditTransactionController implements RouteSelectionListener {
saveButton.disableProperty().bind(formValid.not());
// Update the lists of accounts available for linking based on the selected currency.
var cellFactory = new AccountComboBoxCellFactory();
linkDebitAccountComboBox.setCellFactory(cellFactory);
linkDebitAccountComboBox.setButtonCell(cellFactory.call(null));
linkCreditAccountComboBox.setCellFactory(cellFactory);
linkCreditAccountComboBox.setButtonCell(cellFactory.call(null));
currencyChoiceBox.valueProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("Set currency to " + newValue);
updateLinkAccountComboBoxes(newValue);
});
@ -126,7 +122,7 @@ public class EditTransactionController implements RouteSelectionListener {
@Override
public void onRouteSelected(Object context) {
Transaction transaction = (Transaction) context;
transaction = (Transaction) context;
boolean creatingNew = transaction == null;
if (creatingNew) {
@ -147,11 +143,8 @@ public class EditTransactionController implements RouteSelectionListener {
Thread.ofVirtual().start(() -> Profile.getCurrent().getDataSource().useTransactionRepository(repo -> {
CreditAndDebitAccounts accounts = repo.findLinkedAccounts(transaction.id);
Platform.runLater(() -> {
System.out.println(linkCreditAccountComboBox.getItems().indexOf(accounts.creditAccount()));
// linkCreditAccountComboBox.getSelectionModel().select(accounts.creditAccount());
// linkCreditAccountComboBox.getButtonCell().updateIndex(linkCreditAccountComboBox.getSelectionModel().getSelectedIndex());
// linkDebitAccountComboBox.getSelectionModel().select(accounts.debitAccount());
// linkDebitAccountComboBox.getButtonCell().updateIndex(linkDebitAccountComboBox.getSelectionModel().getSelectedIndex());
debitAccountSelector.getSelectionModel().select(accounts.debitAccount());
creditAccountSelector.getSelectionModel().select(accounts.creditAccount());
});
}));
}
@ -173,8 +166,8 @@ public class EditTransactionController implements RouteSelectionListener {
private CreditAndDebitAccounts getSelectedAccounts() {
return new CreditAndDebitAccounts(
linkCreditAccountComboBox.getValue(),
linkDebitAccountComboBox.getValue()
creditAccountSelector.getValue(),
debitAccountSelector.getValue()
);
}
@ -202,18 +195,16 @@ public class EditTransactionController implements RouteSelectionListener {
Profile.getCurrent().getDataSource().useAccountRepository(repo -> {
List<Account> availableAccounts = new ArrayList<>();
if (currency != null) availableAccounts.addAll(repo.findAllByCurrency(currency));
availableAccounts.add(null);
Platform.runLater(() -> {
linkDebitAccountComboBox.getItems().clear();
linkDebitAccountComboBox.getItems().addAll(availableAccounts);
linkDebitAccountComboBox.getSelectionModel().selectLast();
linkDebitAccountComboBox.getButtonCell().updateIndex(availableAccounts.size() - 1);
linkCreditAccountComboBox.getItems().clear();
linkCreditAccountComboBox.getItems().addAll(availableAccounts);
linkCreditAccountComboBox.getSelectionModel().selectLast();
linkCreditAccountComboBox.getButtonCell().updateIndex(availableAccounts.size() - 1);
System.out.println("link account boxes updated.");
debitAccountSelector.setAccounts(availableAccounts);
creditAccountSelector.setAccounts(availableAccounts);
if (transaction != null) {
Profile.getCurrent().getDataSource().useTransactionRepository(transactionRepo -> {
var linkedAccounts = transactionRepo.findLinkedAccounts(transaction.id);
debitAccountSelector.getSelectionModel().select(linkedAccounts.debitAccount());
creditAccountSelector.getSelectionModel().select(linkedAccounts.creditAccount());
});
}
});
});
});

View File

@ -24,6 +24,7 @@ public class AccountComboBoxCellFactory implements Callback<ListView<Account>, L
public AccountListCell(String emptyCellText) {
this.emptyCellText = emptyCellText;
label.getStyleClass().add("normal-color-text-fill");
setGraphic(label);
}
@Override

View File

@ -0,0 +1,52 @@
package com.andrewlalis.perfin.view.component;
import com.andrewlalis.perfin.model.Account;
import com.andrewlalis.perfin.view.AccountComboBoxCellFactory;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.ComboBox;
import java.util.List;
/**
* A box that allows the user to select one account from a list of options.
*/
public class AccountSelectionBox extends ComboBox<Account> {
private final BooleanProperty allowNoneProperty = new SimpleBooleanProperty(true);
public AccountSelectionBox() {
valueProperty().bind(getSelectionModel().selectedItemProperty());
var factory = new AccountComboBoxCellFactory();
setCellFactory(factory);
setButtonCell(factory.call(null));
}
public void setAccounts(List<Account> accounts) {
if (getAllowNone() && !accounts.contains(null)) {
accounts.add(null);
}
getItems().clear();
getItems().addAll(accounts);
int idx;
if (getAllowNone()) {
getSelectionModel().select(null);
idx = accounts.indexOf(null);
} else {
getSelectionModel().clearSelection();
idx = 0;
}
getButtonCell().updateIndex(idx);
}
public final BooleanProperty allowNoneProperty() {
return allowNoneProperty;
}
public final boolean getAllowNone() {
return allowNoneProperty.get();
}
public final void setAllowNone(boolean value) {
allowNoneProperty.set(value);
}
}

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import com.andrewlalis.perfin.view.component.AccountSelectionBox?>
<?import com.andrewlalis.perfin.view.component.PropertiesPane?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
@ -41,16 +42,12 @@
<!-- Container for linked accounts -->
<HBox styleClass="std-padding,std-spacing" fx:id="linkedAccountsContainer">
<VBox>
<Label text="Debited Account" labelFor="${linkDebitAccountComboBox}" styleClass="bold-text"/>
<ComboBox fx:id="linkDebitAccountComboBox">
<tooltip><Tooltip text="The account whose assets will increase as a result of this transaction."/></tooltip>
</ComboBox>
<Label text="Debited Account" labelFor="${debitAccountSelector}" styleClass="bold-text"/>
<AccountSelectionBox fx:id="debitAccountSelector" allowNone="true"/>
</VBox>
<VBox>
<Label text="Credited Account" labelFor="${linkCreditAccountComboBox}" styleClass="bold-text"/>
<ComboBox fx:id="linkCreditAccountComboBox">
<tooltip><Tooltip text="The account whose assets will decrease as a result of this transaction."/></tooltip>
</ComboBox>
<Label text="Credited Account" labelFor="${creditAccountSelector}" styleClass="bold-text"/>
<AccountSelectionBox fx:id="creditAccountSelector" allowNone="true"/>
</VBox>
</HBox>
<!-- Container for attachments -->