Compare commits
No commits in common. "main" and "JCash_2.0.0" have entirely different histories.
main
...
JCash_2.0.
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
Draft program for the Java class of semester 2. The goal was to simulate basic cash machine that can read customer data from a `.csv` file and let the user view the data with crude forms of authentication.
|
Draft program for the Java class of semester 2. The goal was to simulate basic cash machine that can read customer data from a `.csv` file and let the user view the data with crude forms of authentication.
|
||||||
|
|
||||||
> This project was graded with 100,0 out of 100,0 points
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
The program can read `.csv` file from disk and allows the user login to an account specified.
|
The program can read `.csv` file from disk and allows the user login to an account specified.
|
||||||
|
|
|
@ -7,8 +7,6 @@ import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
|
|
||||||
import static java.nio.file.Path.of;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for providing a global logger for the entire application instance at runtime
|
* Utility class for providing a global logger for the entire application instance at runtime
|
||||||
*/
|
*/
|
||||||
|
@ -47,7 +45,7 @@ public final class Logging {
|
||||||
* @param level the level to set the handler to
|
* @param level the level to set the handler to
|
||||||
*/
|
*/
|
||||||
private static void createConsoleLogger(Level level) {
|
private static void createConsoleLogger(Level level) {
|
||||||
ConsoleHandler ch = new ConsoleHandler();
|
var ch = new ConsoleHandler();
|
||||||
ch.setLevel(level);
|
ch.setLevel(level);
|
||||||
LOGGER.addHandler(ch);
|
LOGGER.addHandler(ch);
|
||||||
}
|
}
|
||||||
|
@ -62,15 +60,15 @@ public final class Logging {
|
||||||
*/
|
*/
|
||||||
private static void createFileLogger(Level level) {
|
private static void createFileLogger(Level level) {
|
||||||
// setup log file name
|
// setup log file name
|
||||||
LocalDateTime now = LocalDateTime.now();
|
var now = LocalDateTime.now();
|
||||||
String dateTime = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT).format(now);
|
var dateTime = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT).format(now);
|
||||||
String logFileName = LOG_FOLDER_NAME + dateTime + ".log";
|
var logFileName = LOG_FOLDER_NAME + dateTime + ".log";
|
||||||
|
|
||||||
// setup the folder for the logs
|
// setup the folder for the logs
|
||||||
initializeLogFolder();
|
initializeLogFolder();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FileHandler fh = new FileHandler(logFileName);
|
var fh = new FileHandler(logFileName);
|
||||||
fh.setLevel(level);
|
fh.setLevel(level);
|
||||||
LOGGER.addHandler(fh);
|
LOGGER.addHandler(fh);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -83,7 +81,7 @@ public final class Logging {
|
||||||
* If the folder does not exist, the function will create a new folder.
|
* If the folder does not exist, the function will create a new folder.
|
||||||
*/
|
*/
|
||||||
private static void initializeLogFolder() {
|
private static void initializeLogFolder() {
|
||||||
Path folderPath = of(LOG_FOLDER_NAME);
|
var folderPath = Path.of(LOG_FOLDER_NAME);
|
||||||
|
|
||||||
if (Files.isDirectory(folderPath))
|
if (Files.isDirectory(folderPath))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package me.teridax.jcash;
|
package me.teridax.jcash;
|
||||||
|
|
||||||
|
import me.teridax.jcash.banking.management.BankingManagementSystem;
|
||||||
import me.teridax.jcash.gui.IconProvider;
|
import me.teridax.jcash.gui.IconProvider;
|
||||||
import me.teridax.jcash.gui.Loader;
|
import me.teridax.jcash.gui.Loader;
|
||||||
import me.teridax.jcash.gui.MainFrame;
|
|
||||||
import me.teridax.jcash.gui.Utils;
|
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 me.teridax.jcash.lang.Locales;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
@ -14,38 +16,82 @@ import java.util.logging.Level;
|
||||||
|
|
||||||
import static me.teridax.jcash.Logging.LOGGER;
|
import static me.teridax.jcash.Logging.LOGGER;
|
||||||
import static me.teridax.jcash.Logging.initializeSystemLogger;
|
import static me.teridax.jcash.Logging.initializeSystemLogger;
|
||||||
|
import static me.teridax.jcash.lang.Translator.translate;
|
||||||
|
|
||||||
public final class Main {
|
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.
|
* Main instance of this program. Contains the primary window.
|
||||||
*/
|
*/
|
||||||
private static Main instance;
|
private static Main instance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Primary class for controlling GUI of this application
|
* Primary window of this program
|
||||||
*/
|
*/
|
||||||
private final MainFrame window;
|
private final JFrame window;
|
||||||
|
private final CardLayout layout;
|
||||||
|
|
||||||
|
private BankingManagementSystem bms;
|
||||||
|
|
||||||
|
private LoginController loginMask;
|
||||||
|
private AccountController accountController;
|
||||||
|
|
||||||
private Main() {
|
private Main() {
|
||||||
this.window = new 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Prompts the user a dialog to select a file to load the database from.
|
|
||||||
* If a valid database has been read a login screen will be shown.
|
|
||||||
* If no file was selected or the database was invalid the application will close.
|
|
||||||
*/
|
|
||||||
public void loadDatabase() {
|
public void loadDatabase() {
|
||||||
try {
|
try {
|
||||||
var bms = Loader.load();
|
this.bms = Loader.load();
|
||||||
this.window.setBms(bms);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOGGER.severe("Failed to load database: " + e.getMessage());
|
LOGGER.severe("Failed to load database: " + e.getMessage());
|
||||||
Utils.error("Failed to load database");
|
Utils.error("Failed to load database");
|
||||||
System.exit(1);
|
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) {
|
public static void main(String[] args) {
|
||||||
|
@ -135,16 +181,24 @@ public final class Main {
|
||||||
Main.instance = new Main();
|
Main.instance = new Main();
|
||||||
}
|
}
|
||||||
|
|
||||||
public JFrame getWindow() {
|
/**
|
||||||
return this.window.getWindow();
|
* 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 currently open account.
|
* Logs the user out of the database, hiding the main window.
|
||||||
* This will show the login mask and clear the password field or the previous
|
|
||||||
* login attempt.
|
|
||||||
*/
|
*/
|
||||||
public void logout() {
|
public void logout() {
|
||||||
this.window.logout();
|
this.loginMask.logout();
|
||||||
|
this.layout.show(this.window.getContentPane(), LOGIN_SCREEN_STRING_IDENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JFrame getWindow() {
|
||||||
|
return this.window;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,8 +6,6 @@ import me.teridax.jcash.banking.accounts.Owner;
|
||||||
import me.teridax.jcash.decode.StringDecoder;
|
import me.teridax.jcash.decode.StringDecoder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -25,13 +23,6 @@ public final class BankingManagementSystem {
|
||||||
* Separator used to separate columns of CSV files
|
* Separator used to separate columns of CSV files
|
||||||
*/
|
*/
|
||||||
private static final String SEPARATOR = ";";
|
private static final String SEPARATOR = ";";
|
||||||
/**
|
|
||||||
* Charsets to try when decoding the source file
|
|
||||||
*/
|
|
||||||
private static final Charset[] ENCODINGS = {
|
|
||||||
StandardCharsets.UTF_8,
|
|
||||||
Charset.forName("windows-1252")
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of banks
|
* A set of banks
|
||||||
|
@ -85,7 +76,7 @@ public final class BankingManagementSystem {
|
||||||
LOGGER.fine("parsing banking management system from file: " + Objects.toString(file, "null"));
|
LOGGER.fine("parsing banking management system from file: " + Objects.toString(file, "null"));
|
||||||
try {
|
try {
|
||||||
var bms = new BankingManagementSystem();
|
var bms = new BankingManagementSystem();
|
||||||
var content = getSource(file);
|
var content = Files.readString(file);
|
||||||
|
|
||||||
// read line by line
|
// read line by line
|
||||||
// and skip the first line
|
// and skip the first line
|
||||||
|
@ -123,33 +114,15 @@ public final class BankingManagementSystem {
|
||||||
|
|
||||||
return bms;
|
return bms;
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.severe("Could not read file: " + file + " due to: " + e.getMessage());
|
||||||
|
throw new IllegalArgumentException("Could not read file " + file, e);
|
||||||
} catch (IllegalArgumentException | NullPointerException e) {
|
} catch (IllegalArgumentException | NullPointerException e) {
|
||||||
LOGGER.severe("Could not parse file: " + file + " due to: " + e.getMessage());
|
LOGGER.severe("Could not parse file: " + file + " due to: " + e.getMessage());
|
||||||
throw new IllegalArgumentException("Could not parse file " + file, e);
|
throw new IllegalArgumentException("Could not parse file " + file, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to read the entire file into a string.
|
|
||||||
* This method tires out all encodings in {@link #ENCODINGS}
|
|
||||||
* @param file the file to read
|
|
||||||
* @throws IllegalArgumentException if the file cannot be read
|
|
||||||
* @return the content of the file
|
|
||||||
*/
|
|
||||||
private static String getSource(Path file) throws IllegalArgumentException {
|
|
||||||
Exception lastException = null;
|
|
||||||
for (var encoding : ENCODINGS) {
|
|
||||||
try {
|
|
||||||
return Files.readString(file, encoding);
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOGGER.severe("Could not read file: " + file + " due to: " + e.getMessage());
|
|
||||||
lastException = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert lastException != null;
|
|
||||||
throw new IllegalArgumentException("Invalid encoding, or IO exception: " + lastException.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a bank with the given blz.
|
* Return a bank with the given blz.
|
||||||
*
|
*
|
||||||
|
|
|
@ -18,10 +18,6 @@ public class StringDecoder {
|
||||||
return NumberFormat.getInstance(Locales.getDefaultLocale());
|
return NumberFormat.getInstance(Locales.getDefaultLocale());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a NumberFormatter for parsing double values in the appropriate locale.
|
|
||||||
* @return the number formatter
|
|
||||||
*/
|
|
||||||
public static NumberFormatter getNumberFormatter(double maxValue) {
|
public static NumberFormatter getNumberFormatter(double maxValue) {
|
||||||
var formatter = new NumberFormatter();
|
var formatter = new NumberFormatter();
|
||||||
formatter.setValueClass(Double.class);
|
formatter.setValueClass(Double.class);
|
||||||
|
@ -33,11 +29,7 @@ public class StringDecoder {
|
||||||
return formatter;
|
return formatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static Object getIntegerNumberFormatter() {
|
||||||
* Returns a NumberFormatter for parsing integer values in the appropriate locale.
|
|
||||||
* @return the number formatter
|
|
||||||
*/
|
|
||||||
public static NumberFormatter getIntegerNumberFormatter() {
|
|
||||||
var formatter = new NumberFormatter();
|
var formatter = new NumberFormatter();
|
||||||
formatter.setValueClass(Integer.class);
|
formatter.setValueClass(Integer.class);
|
||||||
formatter.setMinimum(0d);
|
formatter.setMinimum(0d);
|
||||||
|
|
|
@ -7,28 +7,14 @@ import java.util.Objects;
|
||||||
|
|
||||||
import static me.teridax.jcash.Logging.LOGGER;
|
import static me.teridax.jcash.Logging.LOGGER;
|
||||||
|
|
||||||
/**
|
|
||||||
* Static class for providing the capabilities to load images from file.
|
|
||||||
*/
|
|
||||||
public class IconProvider {
|
public class IconProvider {
|
||||||
|
|
||||||
private static final Image DEFAULT_IMAGE = new BufferedImage(256, 256, BufferedImage.TYPE_INT_RGB);
|
private static final Image DEFAULT_IMAGE = new BufferedImage(256, 256, BufferedImage.TYPE_INT_RGB);
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the windows icon.
|
|
||||||
* @return the windows icon
|
|
||||||
*/
|
|
||||||
public static Image getWindowIcon() {
|
public static Image getWindowIcon() {
|
||||||
return loadIcon("res/register.png");
|
return loadIcon("res/register.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the specified image from disk.
|
|
||||||
* If the file cannot be made into an image because its corrupted or the file cannot be read,
|
|
||||||
* the default image is returned {@link #DEFAULT_IMAGE}
|
|
||||||
* @param path the path to the image
|
|
||||||
* @return the specified image or {@link #DEFAULT_IMAGE}
|
|
||||||
*/
|
|
||||||
private static Image loadIcon(String path) {
|
private static Image loadIcon(String path) {
|
||||||
try {
|
try {
|
||||||
var is = Objects.requireNonNull(IconProvider.class.getResourceAsStream(path));
|
var is = Objects.requireNonNull(IconProvider.class.getResourceAsStream(path));
|
||||||
|
@ -40,10 +26,6 @@ public class IconProvider {
|
||||||
return DEFAULT_IMAGE;
|
return DEFAULT_IMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the background image used for the login screen
|
|
||||||
* @return login screen background image
|
|
||||||
*/
|
|
||||||
public static Image getBackground() {
|
public static Image getBackground() {
|
||||||
return loadIcon("res/background.png");
|
return loadIcon("res/background.png");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
package me.teridax.jcash.gui;
|
package me.teridax.jcash.gui;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception thrown when some user input is invalid
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class InvalidInputException extends IllegalStateException {
|
public class InvalidInputException extends IllegalStateException {
|
||||||
|
|
||||||
public InvalidInputException(String message, Exception cause) {
|
public InvalidInputException(String message, Exception cause) {
|
||||||
|
|
|
@ -1,128 +0,0 @@
|
||||||
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 {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constant used to identify the login screen on the cardlayout
|
|
||||||
*/
|
|
||||||
private static final String LOGIN_SCREEN_STRING_IDENT = "LoginScreen";
|
|
||||||
/**
|
|
||||||
* Constant used to identify the profile screen on the cardlayout
|
|
||||||
*/
|
|
||||||
private static final String PROFILE_SCREEN_STRING_IDENT = "ProfileScreen";
|
|
||||||
/**
|
|
||||||
* Version of this application
|
|
||||||
*/
|
|
||||||
private static final String VERSION = "v2.1.0";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Primary window of this program
|
|
||||||
*/
|
|
||||||
private final JFrame window;
|
|
||||||
/**
|
|
||||||
* Primary layout of this application
|
|
||||||
*/
|
|
||||||
private final CardLayout layout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Database containing every bank, account and owner available
|
|
||||||
*/
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a general information string about this application
|
|
||||||
* @return the locale and the current version as string
|
|
||||||
*/
|
|
||||||
private String getInfoString() {
|
|
||||||
return " locale: [" + Locales.getDefaultLocale().toString() + "] " + VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the GUI components of login screen and profile view
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the BMS of this application to use for the GUI.
|
|
||||||
* This method will show the login screen to the user
|
|
||||||
* @param bms the BMS to use for the GUI
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,14 +10,6 @@ import java.text.NumberFormat;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats the string so that it will be displayed as a Heading 1 element by JLabels.
|
|
||||||
* This embeds the given string into two html tags.
|
|
||||||
* Note that eny html entities in the string will be formatted as valid HTML entities.
|
|
||||||
* Meaning they won't show up in as plain text.
|
|
||||||
* @param title the title to format.
|
|
||||||
* @return the given string embedded into <pre><html><h1>$string</h1></html></pre>
|
|
||||||
*/
|
|
||||||
public static String addHeading(String title) {
|
public static String addHeading(String title) {
|
||||||
return String.format("<html><h1>%s</h1></html>", title);
|
return String.format("<html><h1>%s</h1></html>", title);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,11 +25,6 @@ public class AccountController {
|
||||||
this.data = new AccountData();
|
this.data = new AccountData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the profile and BMS used to manage banking.
|
|
||||||
* @param profile the profile used to manage the account
|
|
||||||
* @param bms the BMS used access other banking accounts
|
|
||||||
*/
|
|
||||||
public void setProfile(Profile profile, BankingManagementSystem bms) {
|
public void setProfile(Profile profile, BankingManagementSystem bms) {
|
||||||
this.profile = profile;
|
this.profile = profile;
|
||||||
this.view.setProfile(profile);
|
this.view.setProfile(profile);
|
||||||
|
@ -37,9 +32,6 @@ public class AccountController {
|
||||||
this.createListeners();
|
this.createListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create listeners for GUI components
|
|
||||||
*/
|
|
||||||
private void createListeners() {
|
private void createListeners() {
|
||||||
this.view.getAccountSelection().addActionListener(e -> changeAccount());
|
this.view.getAccountSelection().addActionListener(e -> changeAccount());
|
||||||
this.view.getLogout().addActionListener(e -> logout());
|
this.view.getLogout().addActionListener(e -> logout());
|
||||||
|
@ -48,25 +40,16 @@ public class AccountController {
|
||||||
this.view.getTransfer().addActionListener(e -> transferMoney());
|
this.view.getTransfer().addActionListener(e -> transferMoney());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Open dialog to deposit money
|
|
||||||
*/
|
|
||||||
private void depositMoney() {
|
private void depositMoney() {
|
||||||
new DepositController(profile.getPrimaryAccount());
|
new DepositController(profile.getPrimaryAccount());
|
||||||
this.view.updateAccountVariables(profile);
|
this.view.updateAccountVariables(profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Open dialog to transfer money
|
|
||||||
*/
|
|
||||||
private void transferMoney() {
|
private void transferMoney() {
|
||||||
new TransferController(profile.getPrimaryAccount(), data.getBms());
|
new TransferController(profile.getPrimaryAccount(), data.getBms());
|
||||||
this.view.updateAccountVariables(profile);
|
this.view.updateAccountVariables(profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Open dialog to take off money
|
|
||||||
*/
|
|
||||||
private void takeoffMoney() {
|
private void takeoffMoney() {
|
||||||
new TakeoffController(profile.getPrimaryAccount());
|
new TakeoffController(profile.getPrimaryAccount());
|
||||||
this.view.updateAccountVariables(profile);
|
this.view.updateAccountVariables(profile);
|
||||||
|
@ -75,11 +58,9 @@ public class AccountController {
|
||||||
private void logout() {
|
private void logout() {
|
||||||
Logging.LOGGER.fine("Logging out of account");
|
Logging.LOGGER.fine("Logging out of account");
|
||||||
Main.getInstance().logout();
|
Main.getInstance().logout();
|
||||||
|
Main.getInstance().showLoginScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the selected account.
|
|
||||||
*/
|
|
||||||
private void changeAccount() {
|
private void changeAccount() {
|
||||||
var description = ((String) this.view.getAccountSelection().getSelectedItem());
|
var description = ((String) this.view.getAccountSelection().getSelectedItem());
|
||||||
Logging.LOGGER.fine("Changing primary account selected: " + description);
|
Logging.LOGGER.fine("Changing primary account selected: " + description);
|
||||||
|
|
|
@ -2,9 +2,6 @@ package me.teridax.jcash.gui.account;
|
||||||
|
|
||||||
import me.teridax.jcash.banking.management.BankingManagementSystem;
|
import me.teridax.jcash.banking.management.BankingManagementSystem;
|
||||||
|
|
||||||
/**
|
|
||||||
* Data storage class for account management
|
|
||||||
*/
|
|
||||||
public class AccountData {
|
public class AccountData {
|
||||||
|
|
||||||
private BankingManagementSystem bms;
|
private BankingManagementSystem bms;
|
||||||
|
|
|
@ -40,10 +40,6 @@ public class AccountView extends JPanel {
|
||||||
setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The profile to manage via the GUI.
|
|
||||||
* @param profile the profile to manage
|
|
||||||
*/
|
|
||||||
public void setProfile(Profile profile) {
|
public void setProfile(Profile profile) {
|
||||||
this.updateAccountVariables(profile);
|
this.updateAccountVariables(profile);
|
||||||
|
|
||||||
|
@ -141,15 +137,8 @@ public class AccountView extends JPanel {
|
||||||
return takeoff;
|
return takeoff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the accessible class fields of the primary account
|
|
||||||
* into the text fields. Also updates the combo box for
|
|
||||||
* all associated accounts.
|
|
||||||
* @param profile the profile to update from
|
|
||||||
*/
|
|
||||||
public void updateAccountVariables(Profile profile) {
|
public void updateAccountVariables(Profile profile) {
|
||||||
Logging.LOGGER.finer("Updating account view");
|
Logging.LOGGER.finer("Updating account view");
|
||||||
// temporarily extract data
|
|
||||||
var bank = profile.getBank();
|
var bank = profile.getBank();
|
||||||
var account = profile.getPrimaryAccount();
|
var account = profile.getPrimaryAccount();
|
||||||
var owner = profile.getOwner();
|
var owner = profile.getOwner();
|
||||||
|
@ -163,8 +152,6 @@ public class AccountView extends JPanel {
|
||||||
|
|
||||||
this.balance.setText(StringDecoder.getNumberFormat().format(account.getBalance()) + " €");
|
this.balance.setText(StringDecoder.getNumberFormat().format(account.getBalance()) + " €");
|
||||||
|
|
||||||
// update account type specific fields
|
|
||||||
|
|
||||||
this.type.setText(translate(account.getClass().getSimpleName()));
|
this.type.setText(translate(account.getClass().getSimpleName()));
|
||||||
if (account instanceof CurrentAccount) {
|
if (account instanceof CurrentAccount) {
|
||||||
this.typeSpecialLabel.setText(translate("Overdraft"));
|
this.typeSpecialLabel.setText(translate("Overdraft"));
|
||||||
|
|
|
@ -9,30 +9,21 @@ import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Class for controlling the deposit operation via a dialog.
|
|
||||||
*/
|
|
||||||
public class DepositController {
|
public class DepositController {
|
||||||
|
|
||||||
private final DepositView view;
|
private final DepositView view;
|
||||||
/**
|
|
||||||
* Account to deposit money to.
|
|
||||||
*/
|
|
||||||
private final Account account;
|
private final Account account;
|
||||||
|
private final DepositData data;
|
||||||
|
|
||||||
public DepositController(Account account) {
|
public DepositController(Account account) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
|
|
||||||
this.view = new DepositView(account.getBalance());
|
this.data = new DepositData(account.getBalance());
|
||||||
|
this.view = new DepositView(this.data.getMaxValue());
|
||||||
|
|
||||||
this.view.getDeposit().addActionListener(e -> depositMoney());
|
this.view.getDeposit().addActionListener(e -> depositMoney());
|
||||||
this.view.getCancel().addActionListener(e -> view.dispose());
|
this.view.getCancel().addActionListener(e -> view.dispose());
|
||||||
this.view.getValue().getDocument().addDocumentListener(new DocumentListener() {
|
this.view.getValue().getDocument().addDocumentListener(new DocumentListener() {
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the amount to deposit and update display
|
|
||||||
* variables.
|
|
||||||
*/
|
|
||||||
private void validateInputState() {
|
private void validateInputState() {
|
||||||
var balance = account.getBalance();
|
var balance = account.getBalance();
|
||||||
try {
|
try {
|
||||||
|
@ -64,10 +55,6 @@ public class DepositController {
|
||||||
this.view.showDialog();
|
this.view.showDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deposit the last valid value to the account.
|
|
||||||
* This method may display error dialogs when no money can be deposited.
|
|
||||||
*/
|
|
||||||
private void depositMoney() {
|
private void depositMoney() {
|
||||||
try {
|
try {
|
||||||
var amount = view.getAmount();
|
var amount = view.getAmount();
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package me.teridax.jcash.gui.deposit;
|
||||||
|
|
||||||
|
public class DepositData {
|
||||||
|
|
||||||
|
private double maxValue;
|
||||||
|
|
||||||
|
public DepositData(double maxValue) {
|
||||||
|
this.maxValue = maxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMaxValue() {
|
||||||
|
return maxValue;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,28 +11,12 @@ import java.text.ParseException;
|
||||||
|
|
||||||
import static me.teridax.jcash.lang.Translator.translate;
|
import static me.teridax.jcash.lang.Translator.translate;
|
||||||
|
|
||||||
/**
|
|
||||||
* View class for displaying a dialog prompting the user to
|
|
||||||
* enter a valid amount to deposit at their account
|
|
||||||
*/
|
|
||||||
public class DepositView {
|
public class DepositView {
|
||||||
|
|
||||||
/**
|
|
||||||
* Window to use
|
|
||||||
*/
|
|
||||||
private JDialog dialog;
|
private JDialog dialog;
|
||||||
private JButton cancel;
|
private JButton cancel;
|
||||||
/**
|
|
||||||
* Button for applying the deposit operation
|
|
||||||
*/
|
|
||||||
private JButton deposit;
|
private JButton deposit;
|
||||||
/**
|
|
||||||
* Displays the validated value to deposit
|
|
||||||
*/
|
|
||||||
private JLabel enteredValue;
|
private JLabel enteredValue;
|
||||||
/**
|
|
||||||
* Displays the account balance after the deposit operation
|
|
||||||
*/
|
|
||||||
private JLabel balanceAfterDeposit;
|
private JLabel balanceAfterDeposit;
|
||||||
private JFormattedTextField value;
|
private JFormattedTextField value;
|
||||||
|
|
||||||
|
@ -135,12 +119,6 @@ public class DepositView {
|
||||||
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the amount of money that should be deposited
|
|
||||||
* This value derives from the input of the user.
|
|
||||||
* @return the value to deposit
|
|
||||||
* @throws InvalidInputException if the user entered something invalid
|
|
||||||
*/
|
|
||||||
public double getAmount() throws InvalidInputException {
|
public double getAmount() throws InvalidInputException {
|
||||||
if (value.getText().isBlank())
|
if (value.getText().isBlank())
|
||||||
throw new InvalidInputException("currency value is blank or has been invalid whilst entered");
|
throw new InvalidInputException("currency value is blank or has been invalid whilst entered");
|
||||||
|
@ -169,11 +147,6 @@ public class DepositView {
|
||||||
this.dialog.dispose();
|
this.dialog.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the supplied amount to the preview GUI fields.
|
|
||||||
* @param amount the value to display for value to deposit
|
|
||||||
* @param after the value to display for balance after deposit
|
|
||||||
*/
|
|
||||||
public void setCommittedValue(double amount, double after) {
|
public void setCommittedValue(double amount, double after) {
|
||||||
enteredValue.setText(StringDecoder.getNumberFormat().format(amount));
|
enteredValue.setText(StringDecoder.getNumberFormat().format(amount));
|
||||||
balanceAfterDeposit.setText(StringDecoder.getNumberFormat().format(after));
|
balanceAfterDeposit.setText(StringDecoder.getNumberFormat().format(after));
|
||||||
|
|
|
@ -7,6 +7,10 @@ import me.teridax.jcash.gui.Utils;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||||
|
import static javax.swing.JOptionPane.showMessageDialog;
|
||||||
|
import static me.teridax.jcash.lang.Translator.translate;
|
||||||
|
|
||||||
public class LoginController {
|
public class LoginController {
|
||||||
|
|
||||||
private final LoginView view;
|
private final LoginView view;
|
||||||
|
|
|
@ -46,6 +46,10 @@ public class LoginData {
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BankingManagementSystem getBms() {
|
||||||
|
return bms;
|
||||||
|
}
|
||||||
|
|
||||||
public void setBms(BankingManagementSystem bms) {
|
public void setBms(BankingManagementSystem bms) {
|
||||||
this.bms = bms;
|
this.bms = bms;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package me.teridax.jcash.gui.login;
|
package me.teridax.jcash.gui.login;
|
||||||
|
|
||||||
|
import me.teridax.jcash.decode.StringDecoder;
|
||||||
import me.teridax.jcash.gui.IconProvider;
|
import me.teridax.jcash.gui.IconProvider;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
@ -10,9 +11,6 @@ import static me.teridax.jcash.gui.Utils.addGridBagRow;
|
||||||
import static me.teridax.jcash.gui.Utils.addHeading;
|
import static me.teridax.jcash.gui.Utils.addHeading;
|
||||||
import static me.teridax.jcash.lang.Translator.translate;
|
import static me.teridax.jcash.lang.Translator.translate;
|
||||||
|
|
||||||
/**
|
|
||||||
* GUI class for login into an account
|
|
||||||
*/
|
|
||||||
public class LoginView extends JPanel {
|
public class LoginView extends JPanel {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,10 +18,6 @@ public class LoginView extends JPanel {
|
||||||
* N = log10(2^32-1) = 9,632959861146281
|
* N = log10(2^32-1) = 9,632959861146281
|
||||||
*/
|
*/
|
||||||
private static final int MAX_PIN_DECIMAL_DIGITS = 9;
|
private static final int MAX_PIN_DECIMAL_DIGITS = 9;
|
||||||
/**
|
|
||||||
* Number of pixels the banner image should be in width
|
|
||||||
*/
|
|
||||||
public static final int BANNER_WIDTH = 400;
|
|
||||||
|
|
||||||
private JFormattedTextField blz;
|
private JFormattedTextField blz;
|
||||||
private JFormattedTextField iban;
|
private JFormattedTextField iban;
|
||||||
|
@ -43,7 +37,7 @@ public class LoginView extends JPanel {
|
||||||
var loginPane = new JPanel(new GridBagLayout());
|
var loginPane = new JPanel(new GridBagLayout());
|
||||||
loginPane.setOpaque(true);
|
loginPane.setOpaque(true);
|
||||||
content.add(loginPane, BorderLayout.CENTER);
|
content.add(loginPane, BorderLayout.CENTER);
|
||||||
content.add(Box.createHorizontalStrut(BANNER_WIDTH), BorderLayout.WEST);
|
content.add(Box.createHorizontalStrut(400), BorderLayout.WEST);
|
||||||
|
|
||||||
this.setLayout(new BorderLayout(32, 32));
|
this.setLayout(new BorderLayout(32, 32));
|
||||||
this.add(new JScrollPane(content), BorderLayout.CENTER);
|
this.add(new JScrollPane(content), BorderLayout.CENTER);
|
||||||
|
@ -72,8 +66,6 @@ public class LoginView extends JPanel {
|
||||||
this.pin = new JPasswordField();
|
this.pin = new JPasswordField();
|
||||||
this.login = new JButton(translate("Login"));
|
this.login = new JButton(translate("Login"));
|
||||||
|
|
||||||
// customize login button
|
|
||||||
// this may not work with every swing look and feel
|
|
||||||
this.login.setFont(new Font("Circus", Font.PLAIN, 28));
|
this.login.setFont(new Font("Circus", Font.PLAIN, 28));
|
||||||
this.login.setBackground(Color.CYAN);
|
this.login.setBackground(Color.CYAN);
|
||||||
|
|
||||||
|
|
|
@ -10,32 +10,22 @@ import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Controller class for handling bank account take off.
|
|
||||||
*/
|
|
||||||
public class TakeoffController {
|
public class TakeoffController {
|
||||||
|
|
||||||
/**
|
|
||||||
* Account to take off
|
|
||||||
*/
|
|
||||||
private final Account account;
|
private final Account account;
|
||||||
/**
|
|
||||||
* GUI object
|
|
||||||
*/
|
|
||||||
private final TakeoffView view;
|
private final TakeoffView view;
|
||||||
|
private final TakeoffData data;
|
||||||
|
|
||||||
public TakeoffController(Account account) {
|
public TakeoffController(Account account) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
|
|
||||||
// add overdraft on top of the maximum amount
|
|
||||||
// a user is allowed to take off
|
|
||||||
var overdraft = 0.0;
|
var overdraft = 0.0;
|
||||||
if (account instanceof CurrentAccount) {
|
if (account instanceof CurrentAccount) {
|
||||||
overdraft += ((CurrentAccount) account).getOverdraft();
|
overdraft += ((CurrentAccount) account).getOverdraft();
|
||||||
}
|
}
|
||||||
|
|
||||||
TakeoffData data = new TakeoffData(account.getBalance());
|
this.data = new TakeoffData(account.getBalance());
|
||||||
this.view = new TakeoffView(data.getMaxValue() + overdraft);
|
this.view = new TakeoffView(this.data.getMaxValue() + overdraft);
|
||||||
|
|
||||||
this.view.getTakeoff().addActionListener(e -> takeOff());
|
this.view.getTakeoff().addActionListener(e -> takeOff());
|
||||||
this.view.getCancel().addActionListener(e -> view.dispose());
|
this.view.getCancel().addActionListener(e -> view.dispose());
|
||||||
|
@ -71,9 +61,6 @@ public class TakeoffController {
|
||||||
this.view.showDialog();
|
this.view.showDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to take off some money from an account.
|
|
||||||
*/
|
|
||||||
private void takeOff() {
|
private void takeOff() {
|
||||||
try {
|
try {
|
||||||
account.takeoff(view.getAmount());
|
account.takeoff(view.getAmount());
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
package me.teridax.jcash.gui.takeoff;
|
package me.teridax.jcash.gui.takeoff;
|
||||||
|
|
||||||
/**
|
|
||||||
* Data class for taking off value from a certain account
|
|
||||||
*/
|
|
||||||
public class TakeoffData {
|
public class TakeoffData {
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum value a user is allowed to take off
|
|
||||||
*/
|
|
||||||
private final double maxValue;
|
private final double maxValue;
|
||||||
|
|
||||||
public TakeoffData(double maxValue) {
|
public TakeoffData(double maxValue) {
|
||||||
|
|
|
@ -11,9 +11,6 @@ import java.text.ParseException;
|
||||||
|
|
||||||
import static me.teridax.jcash.lang.Translator.translate;
|
import static me.teridax.jcash.lang.Translator.translate;
|
||||||
|
|
||||||
/**
|
|
||||||
* Dialog for taking off money of an account.
|
|
||||||
*/
|
|
||||||
public class TakeoffView {
|
public class TakeoffView {
|
||||||
|
|
||||||
private JDialog dialog;
|
private JDialog dialog;
|
||||||
|
@ -28,9 +25,6 @@ public class TakeoffView {
|
||||||
layoutComponents();
|
layoutComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes this dialog visible.
|
|
||||||
*/
|
|
||||||
public void showDialog() {
|
public void showDialog() {
|
||||||
dialog.setIconImage(IconProvider.getWindowIcon());
|
dialog.setIconImage(IconProvider.getWindowIcon());
|
||||||
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||||
|
@ -110,10 +104,6 @@ public class TakeoffView {
|
||||||
dialog.getContentPane().add(buttonPanel, c);
|
dialog.getContentPane().add(buttonPanel, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The createComponents function creates the components of the dialog.
|
|
||||||
* @param maxValue Set the maximum value of the jformattedtextfield
|
|
||||||
*/
|
|
||||||
private void createComponents(double maxValue) {
|
private void createComponents(double maxValue) {
|
||||||
this.dialog = new JDialog();
|
this.dialog = new JDialog();
|
||||||
|
|
||||||
|
@ -126,10 +116,6 @@ public class TakeoffView {
|
||||||
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The getAmount function is used to get the amount of currency that has been entered into the text field.
|
|
||||||
* @return A double value, which is the parsed amount from the text field
|
|
||||||
*/
|
|
||||||
public double getAmount() throws InvalidInputException {
|
public double getAmount() throws InvalidInputException {
|
||||||
if (value.getText().isBlank())
|
if (value.getText().isBlank())
|
||||||
throw new InvalidInputException("currency value is blank or has been invalid whilst entered");
|
throw new InvalidInputException("currency value is blank or has been invalid whilst entered");
|
||||||
|
@ -142,13 +128,6 @@ public class TakeoffView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The setCommittedValue function sets the text of the enteredValue and balanceAfterDeposit TextFields to
|
|
||||||
* a String representation of amount and after, respectively.
|
|
||||||
* @param amount Set the text of enteredvalue
|
|
||||||
* @param after Set the balance after deposit
|
|
||||||
*/
|
|
||||||
public void setCommittedValue(double amount, double after) {
|
public void setCommittedValue(double amount, double after) {
|
||||||
enteredValue.setText(StringDecoder.getNumberFormat().format(amount));
|
enteredValue.setText(StringDecoder.getNumberFormat().format(amount));
|
||||||
balanceAfterDeposit.setText(StringDecoder.getNumberFormat().format(after));
|
balanceAfterDeposit.setText(StringDecoder.getNumberFormat().format(after));
|
||||||
|
|
|
@ -33,9 +33,20 @@ public class TransferController {
|
||||||
this.transferData = new TransferData(bms);
|
this.transferData = new TransferData(bms);
|
||||||
this.view.getTransfer().addActionListener(e -> transfer());
|
this.view.getTransfer().addActionListener(e -> transfer());
|
||||||
this.view.getCancel().addActionListener(e -> view.dispose());
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// validates the users input
|
|
||||||
var validator = new DocumentListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void insertUpdate(DocumentEvent documentEvent) {
|
public void insertUpdate(DocumentEvent documentEvent) {
|
||||||
validateInputState();
|
validateInputState();
|
||||||
|
@ -50,53 +61,10 @@ public class TransferController {
|
||||||
public void changedUpdate(DocumentEvent documentEvent) {
|
public void changedUpdate(DocumentEvent documentEvent) {
|
||||||
validateInputState();
|
validateInputState();
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
this.view.getValue().getDocument().addDocumentListener(validator);
|
|
||||||
this.view.getIbanTextField().getDocument().addDocumentListener(validator);
|
|
||||||
this.view.getBlzTextField().getDocument().addDocumentListener(validator);
|
|
||||||
|
|
||||||
this.view.showDialog();
|
this.view.showDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the target bank account is valid.
|
|
||||||
* @return true if the target bank account is valid false otherwise
|
|
||||||
*/
|
|
||||||
private boolean validateTargetAccount() {
|
|
||||||
if (transferData.validateBLZ(this.view.getBlz())) {
|
|
||||||
return transferData.validateIBAN(this.view.getBlz(), view.getIban());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the entered value to transfer is valid.
|
|
||||||
* This method will also commit the valid value back to the text field.
|
|
||||||
* @return true if the value to transfer is valid, false otherwise
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to transfer the balance from one account to another
|
|
||||||
* This method will close the dialog.
|
|
||||||
*/
|
|
||||||
private void transfer() {
|
private void transfer() {
|
||||||
try {
|
try {
|
||||||
var amount = view.getAmount();
|
var amount = view.getAmount();
|
||||||
|
|
|
@ -46,32 +46,4 @@ public class TransferData {
|
||||||
|
|
||||||
account.get().getPrimaryAccount().deposit(amount);
|
account.get().getPrimaryAccount().deposit(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the given BLZ. If no bank with the given BLZ can be found
|
|
||||||
* this method returns false. Otherwise, true is returned.
|
|
||||||
* @param blz the BLZ to validate
|
|
||||||
* @return true if the BLZ is valid and false otherwise
|
|
||||||
*/
|
|
||||||
public boolean validateBLZ(String blz) {
|
|
||||||
return bms.getBank(blz).isPresent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the given IBAN for the given BLZ. This method assumes the BLZ to be valid.
|
|
||||||
* If this is not the case, this function will throw an exception.
|
|
||||||
* Returns true if an account with the given IBAN was found for bank of the given BLZ.
|
|
||||||
* @param blz bank to search in
|
|
||||||
* @param ibanString account to search for
|
|
||||||
* @return true if the account was found false otherwise
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,24 +11,6 @@ import java.text.ParseException;
|
||||||
|
|
||||||
import static me.teridax.jcash.lang.Translator.translate;
|
import static me.teridax.jcash.lang.Translator.translate;
|
||||||
|
|
||||||
/**
|
|
||||||
* JDialog for displaying the GUI for a transfer dialog
|
|
||||||
* with the following crude layout:
|
|
||||||
* <pre>
|
|
||||||
┌───────────────────────────────────────────────┐
|
|
||||||
│ ┌─────────────┐ ┌────────────────┐ │
|
|
||||||
│ BLZ │ │ IBAN │ │ │
|
|
||||||
│ └─────────────┘ └────────────────┘ │
|
|
||||||
│ │
|
|
||||||
│ ┌─────────────┐ │
|
|
||||||
│ VALUE │ │ │
|
|
||||||
│ └─────────────┘ │
|
|
||||||
│ ┌───────┐ ┌────────┐ │
|
|
||||||
│ │Cancel │ │Transfer│ │
|
|
||||||
│ └───────┘ └────────┘ │
|
|
||||||
└───────────────────────────────────────────────┘
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
public class TransferView {
|
public class TransferView {
|
||||||
|
|
||||||
private JDialog dialog;
|
private JDialog dialog;
|
||||||
|
@ -37,6 +19,7 @@ public class TransferView {
|
||||||
private JFormattedTextField iban;
|
private JFormattedTextField iban;
|
||||||
private JFormattedTextField blz;
|
private JFormattedTextField blz;
|
||||||
private JFormattedTextField value;
|
private JFormattedTextField value;
|
||||||
|
|
||||||
private JLabel balanceAfterTransfer;
|
private JLabel balanceAfterTransfer;
|
||||||
private JLabel enteredValue;
|
private JLabel enteredValue;
|
||||||
|
|
||||||
|
@ -45,9 +28,6 @@ public class TransferView {
|
||||||
layoutComponents();
|
layoutComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes this dialog visible to the user
|
|
||||||
*/
|
|
||||||
public void showDialog() {
|
public void showDialog() {
|
||||||
dialog.setIconImage(IconProvider.getWindowIcon());
|
dialog.setIconImage(IconProvider.getWindowIcon());
|
||||||
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||||
|
@ -60,9 +40,6 @@ public class TransferView {
|
||||||
dialog.setVisible(true);
|
dialog.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Layout all components of this dialog.
|
|
||||||
*/
|
|
||||||
private void layoutComponents() {
|
private void layoutComponents() {
|
||||||
var c = new GridBagConstraints();
|
var c = new GridBagConstraints();
|
||||||
|
|
||||||
|
@ -165,11 +142,6 @@ public class TransferView {
|
||||||
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the entered amount parsed into a double value.
|
|
||||||
* @return the amount parsed into a double
|
|
||||||
* @throws InvalidInputException if the text in {@link #value} is not a valid double value.
|
|
||||||
*/
|
|
||||||
public double getAmount() throws InvalidInputException {
|
public double getAmount() throws InvalidInputException {
|
||||||
if (value.getText().isBlank())
|
if (value.getText().isBlank())
|
||||||
throw new InvalidInputException("currency value is blank or has been invalid whilst entered");
|
throw new InvalidInputException("currency value is blank or has been invalid whilst entered");
|
||||||
|
@ -182,11 +154,6 @@ public class TransferView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the values to display in the dialog labels as overview information.
|
|
||||||
* @param amount the amount to transfer
|
|
||||||
* @param after balance after the transfer
|
|
||||||
*/
|
|
||||||
public void setCommittedValue(double amount, double after) {
|
public void setCommittedValue(double amount, double after) {
|
||||||
enteredValue.setText(StringDecoder.getNumberFormat().format(amount));
|
enteredValue.setText(StringDecoder.getNumberFormat().format(amount));
|
||||||
balanceAfterTransfer.setText(StringDecoder.getNumberFormat().format(after));
|
balanceAfterTransfer.setText(StringDecoder.getNumberFormat().format(after));
|
||||||
|
@ -212,14 +179,6 @@ public class TransferView {
|
||||||
return blz.getText();
|
return blz.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public JFormattedTextField getIbanTextField() {
|
|
||||||
return iban;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JFormattedTextField getBlzTextField() {
|
|
||||||
return blz;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
this.dialog.dispose();
|
this.dialog.dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,6 @@ import java.util.Locale;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class Locales {
|
public class Locales {
|
||||||
|
|
||||||
/**
|
|
||||||
* Default locale initialized to the fallback locale used by this application.
|
|
||||||
*/
|
|
||||||
private static Locale defaultLocale = new Locale("en", "EN");
|
private static Locale defaultLocale = new Locale("en", "EN");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,11 +6,6 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
|
||||||
* Static translator class.
|
|
||||||
* This is a very simple translator able to translate base tokens from english into a variety of
|
|
||||||
* configured languages.
|
|
||||||
*/
|
|
||||||
public final class Translator {
|
public final class Translator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue