added mainframe class

This commit is contained in:
Sven Vogel 2023-07-23 14:56:41 +02:00
parent 183b25e784
commit 88deb75ed7
6 changed files with 166 additions and 93 deletions

View File

@ -1,11 +1,9 @@
package me.teridax.jcash;
import me.teridax.jcash.banking.management.BankingManagementSystem;
import me.teridax.jcash.gui.IconProvider;
import me.teridax.jcash.gui.Loader;
import me.teridax.jcash.gui.MainFrame;
import me.teridax.jcash.gui.Utils;
import me.teridax.jcash.gui.account.AccountController;
import me.teridax.jcash.gui.login.LoginController;
import me.teridax.jcash.lang.Locales;
import javax.swing.*;
@ -16,82 +14,30 @@ import java.util.logging.Level;
import static me.teridax.jcash.Logging.LOGGER;
import static me.teridax.jcash.Logging.initializeSystemLogger;
import static me.teridax.jcash.lang.Translator.translate;
public final class Main {
private static final String LOGIN_SCREEN_STRING_IDENT = "LoginScreen";
private static final String PROFILE_SCREEN_STRING_IDENT = "ProfileScreen";
private static final String VERSION = "v2.0.0";
/**
* Main instance of this program. Contains the primary window.
*/
private static Main instance;
/**
* Primary window of this program
*/
private final JFrame window;
private final CardLayout layout;
private BankingManagementSystem bms;
private LoginController loginMask;
private AccountController accountController;
private final MainFrame window;
private Main() {
// create main window and set defaults
this.window = new JFrame();
this.window.setTitle(translate("Cashmachine") + getInfoString());
this.window.setLocationByPlatform(true);
this.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.window.setIconImage(IconProvider.getWindowIcon());
this.layout = new CardLayout();
this.window.getContentPane().setLayout(this.layout);
initialize();
}
private String getInfoString() {
return " locale: [" + Locales.getDefaultLocale().toString() + "] " + VERSION;
}
private void initialize() {
// create the login mask
this.loginMask = new LoginController();
// when we have logged in set the account viewer as window content
this.loginMask.addAccountSelectionListener(account -> {
LOGGER.finer("account selected: " + Objects.toString(account, "null"));
accountController.setProfile(account, bms);
layout.show(window.getContentPane(), PROFILE_SCREEN_STRING_IDENT);
});
this.window.getContentPane().add(loginMask.getView(), LOGIN_SCREEN_STRING_IDENT);
// create the account viewer
this.accountController = new AccountController();
this.window.getContentPane().add(accountController.getView(), PROFILE_SCREEN_STRING_IDENT);
this.window = new MainFrame();
}
public void loadDatabase() {
try {
this.bms = Loader.load();
var bms = Loader.load();
this.window.setBms(bms);
} catch (Exception e) {
LOGGER.severe("Failed to load database: " + e.getMessage());
Utils.error("Failed to load database");
System.exit(1);
}
this.loginMask.setBankingManagementSystem(bms);
showLoginScreen();
this.window.pack();
this.window.setResizable(false);
this.window.setLocationRelativeTo(null);
this.window.setVisible(true);
}
public static void main(String[] args) {
@ -181,24 +127,11 @@ public final class Main {
Main.instance = new Main();
}
/**
* Shows the open dialog for selecting a database file. After selection, it then proceeds to prompt login.
* Afterward the selected account can be managed.
* This method is non-blocking and all work described is performed asynchronously on the AWT Event dispatcher.
*/
public void showLoginScreen() {
this.layout.show(this.window.getContentPane(), LOGIN_SCREEN_STRING_IDENT);
}
/**
* Logs the user out of the database, hiding the main window.
*/
public void logout() {
this.loginMask.logout();
this.layout.show(this.window.getContentPane(), LOGIN_SCREEN_STRING_IDENT);
}
public JFrame getWindow() {
return this.window;
return this.window.getWindow();
}
public void logout() {
this.window.logout();
}
}

View File

@ -0,0 +1,101 @@
package me.teridax.jcash.gui;
import me.teridax.jcash.banking.management.BankingManagementSystem;
import me.teridax.jcash.gui.account.AccountController;
import me.teridax.jcash.gui.login.LoginController;
import me.teridax.jcash.lang.Locales;
import javax.swing.*;
import java.awt.*;
import java.util.Objects;
import static me.teridax.jcash.Logging.LOGGER;
import static me.teridax.jcash.lang.Translator.translate;
public class MainFrame {
private static final String LOGIN_SCREEN_STRING_IDENT = "LoginScreen";
private static final String PROFILE_SCREEN_STRING_IDENT = "ProfileScreen";
private static final String VERSION = "v2.0.0";
/**
* Primary window of this program
*/
private final JFrame window;
private final CardLayout layout;
private BankingManagementSystem bms;
private LoginController loginMask;
private AccountController accountController;
public MainFrame() {
// create main window and set defaults
this.window = new JFrame();
this.window.setTitle(translate("Cashmachine") + getInfoString());
this.window.setLocationByPlatform(true);
this.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.window.setIconImage(IconProvider.getWindowIcon());
this.layout = new CardLayout();
this.window.getContentPane().setLayout(this.layout);
initialize();
}
private String getInfoString() {
return " locale: [" + Locales.getDefaultLocale().toString() + "] " + VERSION;
}
private void initialize() {
// create the login mask
this.loginMask = new LoginController();
// when we have logged in set the account viewer as window content
this.loginMask.addAccountSelectionListener(account -> {
LOGGER.finer("account selected: " + Objects.toString(account, "null"));
accountController.setProfile(account, bms);
layout.show(window.getContentPane(), PROFILE_SCREEN_STRING_IDENT);
});
this.window.getContentPane().add(loginMask.getView(), LOGIN_SCREEN_STRING_IDENT);
// create the account viewer
this.accountController = new AccountController();
this.window.getContentPane().add(accountController.getView(), PROFILE_SCREEN_STRING_IDENT);
}
public void setBms(BankingManagementSystem bms) {
this.bms = bms;
this.loginMask.setBankingManagementSystem(bms);
this.showLoginScreen();
this.window.pack();
this.window.setResizable(false);
this.window.setLocationRelativeTo(null);
this.window.setVisible(true);
}
/**
* Shows the open dialog for selecting a database file. After selection, it then proceeds to prompt login.
* Afterward the selected account can be managed.
* This method is non-blocking and all work described is performed asynchronously on the AWT Event dispatcher.
*/
private void showLoginScreen() {
this.layout.show(this.window.getContentPane(), LOGIN_SCREEN_STRING_IDENT);
}
/**
* Logs the user out of the database, hiding the main window.
*/
public void logout() {
this.loginMask.logout();
this.layout.show(this.window.getContentPane(), LOGIN_SCREEN_STRING_IDENT);
}
public JFrame getWindow() {
return this.window;
}
}

View File

@ -58,7 +58,6 @@ public class AccountController {
private void logout() {
Logging.LOGGER.fine("Logging out of account");
Main.getInstance().logout();
Main.getInstance().showLoginScreen();
}
private void changeAccount() {

View File

@ -33,20 +33,8 @@ public class TransferController {
this.transferData = new TransferData(bms);
this.view.getTransfer().addActionListener(e -> transfer());
this.view.getCancel().addActionListener(e -> view.dispose());
this.view.getValue().getDocument().addDocumentListener(new DocumentListener() {
private void validateInputState() {
var balance = account.getBalance();
try {
view.getValue().commitEdit();
var amount = view.getAmount();
view.setCommittedValue(amount, balance - amount);
view.getTransfer().setEnabled(true);
} catch (InvalidInputException | ParseException ex) {
view.setCommittedValue(0, balance);
view.getTransfer().setEnabled(false);
}
}
var validator = new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent documentEvent) {
validateInputState();
@ -61,10 +49,40 @@ public class TransferController {
public void changedUpdate(DocumentEvent documentEvent) {
validateInputState();
}
});
};
this.view.getValue().getDocument().addDocumentListener(validator);
this.view.getIbanTextField().getDocument().addDocumentListener(validator);
this.view.getBlzTextField().getDocument().addDocumentListener(validator);
this.view.showDialog();
}
private boolean validateTargetAccount() {
if (transferData.validateBLZ(this.view.getBlz())) {
return transferData.validateIBAN(this.view.getBlz(), view.getIban());
}
return false;
}
private boolean validateTransferValue() {
var balance = account.getBalance();
try {
view.getValue().commitEdit();
var amount = view.getAmount();
view.setCommittedValue(amount, balance - amount);
return true;
} catch (InvalidInputException | ParseException ex) {
view.setCommittedValue(0, balance);
return false;
}
}
private void validateInputState() {
var valid = validateTargetAccount() && validateTransferValue();
view.getTransfer().setEnabled(valid);
}
private void transfer() {
try {
var amount = view.getAmount();

View File

@ -46,4 +46,18 @@ public class TransferData {
account.get().getPrimaryAccount().deposit(amount);
}
public boolean validateBLZ(String blz) {
return bms.getBank(blz).isPresent();
}
public boolean validateIBAN(String blz, String ibanString) {
var bank = bms.getBank(blz);
try {
var iban = StringDecoder.decodeUniqueIdentificationNumber(ibanString);
return bank.map(value -> value.getAccount(iban).isPresent()).orElse(false);
} catch (Exception e) {
return false;
}
}
}

View File

@ -179,6 +179,14 @@ public class TransferView {
return blz.getText();
}
public JFormattedTextField getIbanTextField() {
return iban;
}
public JFormattedTextField getBlzTextField() {
return blz;
}
public void dispose() {
this.dialog.dispose();
}