diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/AddBudgetController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/AddBudgetController.java index 600d4a370a321d8d144c7d9edb121b5fb81a75d3..8a44c9b34c02e6516c65bdad2149b1a07fbf6dd9 100644 --- a/src/main/java/no/ntnu/idatt1002/demo/controller/AddBudgetController.java +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/AddBudgetController.java @@ -13,6 +13,13 @@ import javafx.stage.Stage; import no.ntnu.idatt1002.demo.data.Budget.BudgetItem; import no.ntnu.idatt1002.demo.data.Economics.ExpenseCategory; +/** + * Class that represents the popup dialog box that appears whenever a budget item is to be added or edited. + * The dialog contains various fields that are used to create a new item or edit an existing item. + * @author Anders Emil Bergan + * @since 24.3.2023 + * + */ public class AddBudgetController { BudgetItem newBudgetItem = null; @@ -27,16 +34,23 @@ public class AddBudgetController { @FXML - private Button addButton; + private Button okBtn; @FXML private Button cancelButton; + /** + * Initializes the category drop box by filling it with all the values from the ExpenseCategory enum. + * It then sets a prompt text on the box. + */ @FXML public void initialize(){ + //Set the possible values in a list. ObservableList<ExpenseCategory> expenseCategories = FXCollections.observableArrayList( ExpenseCategory.values()); + //Set the values inside the dropbox categoryVariable.setItems(expenseCategories); + //Set default value categoryVariable.setPromptText("Category"); } @@ -48,14 +62,42 @@ public class AddBudgetController { return this.newBudgetItem; } + /** + * Binds the item that is taken in as the argument with a budget item declared in this class. The item of this class is instantiated + * as a deep copy of the argument. Each attribute of their attributes are then bounded. The text fields and category boxes + * in the dialog window are then set to the values of the chosen item, as to not display empty values. + * @param item The item that is chosen to be edited. + */ @FXML - public void addBudget(ActionEvent event) { + public void setBudget(BudgetItem item){ + //Deep copying item and then binding the two items + chosenBudgetItem = new BudgetItem(item.getBudgetAmount(), item.getBudgetDescription(), item.getBudgetCategory()); + chosenBudgetItem.getAmountProperty().bindBidirectional(item.getAmountProperty()); + chosenBudgetItem.getDescriptionProperty().bindBidirectional(item.getDescriptionProperty()); + chosenBudgetItem.getCategoryProperty().bindBidirectional(item.getCategoryProperty()); + + //Set the values of the input fields of the dialog box + amountVariable.textProperty().set(String.valueOf(item.getBudgetAmount())); + descriptionVariable.textProperty().set(item.getBudgetDescription()); + categoryVariable.setValue(item.getBudgetCategory()); + } + + /** + * Adds a new to the budget tableview or edits an existing entry in table if the OK button is pressed. + * An entry is edited as the selected entry of the table is bounded to another budget item in this class. If this budget item + * is altered, the budget item in the tableview will automatically respond with the same changes. + * @param event If the OK button is pressed. + */ + @FXML + public void pressOkBtn(ActionEvent event) { + //Instantiates a new budget item if(newBudgetItem == null){ ExpenseCategory category = getCategory(); double amount = Double.parseDouble(amountVariable.getText()); String description = descriptionVariable.getText(); newBudgetItem = new BudgetItem(amount, description, category); } + //Sets the value of the budget(chosenBudgetItem) that is bounded to the chosen budget item (not chosenBudgetItem) in the tableview if(chosenBudgetItem != null){ chosenBudgetItem.setBudgetAmount(Double.parseDouble(amountVariable.getText())); chosenBudgetItem.setBudgetDescription(descriptionVariable.getText()); @@ -66,17 +108,10 @@ public class AddBudgetController { stage.close(); } - @FXML - public void setBudget(BudgetItem item){ - chosenBudgetItem = new BudgetItem(item.getBudgetAmount(), item.getBudgetDescription(), item.getBudgetCategory()); - chosenBudgetItem.getAmountProperty().bindBidirectional(item.getAmountProperty()); - chosenBudgetItem.getDescriptionProperty().bindBidirectional(item.getDescriptionProperty()); - chosenBudgetItem.getCategoryProperty().bindBidirectional(item.getCategoryProperty()); - amountVariable.textProperty().set(String.valueOf(item.getBudgetAmount())); - descriptionVariable.textProperty().set(item.getBudgetDescription()); - categoryVariable.setValue(item.getBudgetCategory()); - } - + /** + * Closes the dialog box. + * @param actionEvent A button click on the close button. + */ public void closeButton(ActionEvent actionEvent) { final Node source = (Node) actionEvent.getSource(); final Stage stage = (Stage) source.getScene().getWindow(); diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/AddExpenseController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/AddExpenseController.java index b4a6ce145c8384a8ecfd3f9b908b4c004f52c319..1356e31ab7f012d75d8d3bc489ea884d9f6c4679 100644 --- a/src/main/java/no/ntnu/idatt1002/demo/controller/AddExpenseController.java +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/AddExpenseController.java @@ -17,8 +17,14 @@ import javafx.scene.control.TextField; import javafx.stage.Stage; import no.ntnu.idatt1002.demo.data.Economics.Expense; import no.ntnu.idatt1002.demo.data.Economics.ExpenseCategory; -import no.ntnu.idatt1002.demo.data.Economics.Income; +import no.ntnu.idatt1002.demo.data.Economics.Expense; +/** + * Class that represents the popup dialog box that appears whenever an expense is to be added or edited. + * The dialog contains various fields that are used to create a new expense or edit an existing expense. + * @author Harry Linrui Xu + * @since 13.3.2023 + */ public class AddExpenseController { Expense newExpense = null; //the expense that is chosen when editing or the expense that is created when adding @@ -48,17 +54,26 @@ public class AddExpenseController { @FXML private ComboBox<Boolean> recurringBox; + /** + * Initializes the category and recurring drop boxes by filling them with all the values from the ExpenseCategory enum, + * and the boolean values respectively, and the datepicker calendar. + * It then sets them to the default values of GIFT, false and today respectively. + */ @FXML public void initialize() { + //Set the possible values in a list. ObservableList<ExpenseCategory> expenseCategories = FXCollections.observableArrayList( ExpenseCategory.values()); + //Set the values inside the dropbox categoryBox.setItems(expenseCategories); + //Set default value categoryBox.setValue(ExpenseCategory.FOOD); ObservableList<Boolean> recurring = FXCollections.observableArrayList(true, false); recurringBox.setItems(recurring); recurringBox.setValue(false); + //Set date to today datePicker.setValue(LocalDate.now()); } @@ -70,7 +85,18 @@ public class AddExpenseController { return recurringBox.getValue();//.equals("Yes"); } - public void setExpense(Expense expense) { //TODO NEED CANCEL BUTTON TO REMOVE THE CHANGES IF CANCEL IS PRESSED + public Expense getNewExpense() { + return this.newExpense; + } + + /** + * Binds the expense that is taken in as the argument with an expense declared in this class. The expense of this class is instantiated + * as a deep copy of the argument. Each attribute of their attributes are then bounded. The text fields and category boxes + * in the dialog window are then set to the values of the chosen expense, as to not display empty values. + * @param expense The expense that is chosen to be edited. + */ + public void setExpense(Expense expense) { + //Deep copying expense and then binding the two expenses chosenExpense = new Expense(expense.getDescription(), expense.getAmount(), expense.isRecurring(), expense.getCategory(), expense.getDate()); chosenExpense.descriptionProperty().bindBidirectional(expense.descriptionProperty()); chosenExpense.amountProperty().bindBidirectional(expense.amountProperty()); @@ -78,6 +104,7 @@ public class AddExpenseController { chosenExpense.expenseCategoryObjectProperty().bindBidirectional(expense.expenseCategoryObjectProperty()); chosenExpense.dateProperty().bindBidirectional(expense.dateProperty()); + //Set the values of the input fields of the dialog box descriptionField.textProperty().set(expense.getDescription()); amountField.textProperty().setValue(String.valueOf(expense.getAmount())); recurringBox.setValue(expense.isRecurring()); @@ -85,8 +112,15 @@ public class AddExpenseController { categoryBox.setValue(expense.getCategory()); } + /** + * Adds a new to the tableview or edits an existing entry in table if the OK button is pressed. + * An entry is edited as the selected entry of the table is bounded to another expense in this class. If this expense + * is altered, the expense in the tableview will automatically respond with the same changes. + * @param event If the OK button is pressed. + */ @FXML public void pressOkBtn(ActionEvent event) { + //Instantiates a new expense if (newExpense == null) { LocalDate date = datePicker.getValue(); double amount = Double.parseDouble(amountField.getText()); @@ -95,6 +129,7 @@ public class AddExpenseController { boolean recurring = isRecurring(); newExpense = new Expense(description, amount, recurring, category, date); } + //Sets the value of the expense(chosen) that is bounded to the chosen expense (not chosenExpense) in the tableview if (chosenExpense != null) { chosenExpense.setDescription((descriptionField.getText())); chosenExpense.setAmount(Double.parseDouble(amountField.getText())); @@ -107,6 +142,10 @@ public class AddExpenseController { ((Stage) source.getScene().getWindow()).close(); } + /** + * Closes the dialog box and cancels any pending changes. + * @param event A button click on the cancel button. + */ @FXML public void pressCancelBtn(ActionEvent event) { final Node source = (Node) event.getSource(); @@ -114,8 +153,4 @@ public class AddExpenseController { stage.close(); } - - public Expense getNewExpense() { - return this.newExpense; - } } \ No newline at end of file diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/AddIncomeController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/AddIncomeController.java index d59604546b8dffc0e021ad82a5dc195d90a0b3db..9c96a53cf7296065ad834b4aeafa223aa9916004 100644 --- a/src/main/java/no/ntnu/idatt1002/demo/controller/AddIncomeController.java +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/AddIncomeController.java @@ -19,6 +19,12 @@ import no.ntnu.idatt1002.demo.data.Economics.Expense; import no.ntnu.idatt1002.demo.data.Economics.Income; import no.ntnu.idatt1002.demo.data.Economics.IncomeCategory; +/** + * Class that represents the popup dialog box that appears whenever an income is to be added or edited. + * The dialog contains various fields that are used to create a new income or edit an existing income. + * @author Harry Linrui Xu + * @since 24.3.2023 + */ public class AddIncomeController { Income newIncome = null; @@ -45,17 +51,26 @@ public class AddIncomeController { @FXML private ComboBox<Boolean> recurringBox; + /** + * Initializes the category and recurring drop boxes by filling them with all the values from the IncomeCategory enum, + * and the boolean values respectively, and the datepicker calendar. + * It then sets them to the default values of GIFT, false and today respectively. + */ @FXML public void initialize() { + //Set the possible values in a list. ObservableList<IncomeCategory> incomeCategories = FXCollections.observableArrayList( IncomeCategory.values()); + //Set the values inside the dropbox categoryBox.setItems(incomeCategories); + //Set default value categoryBox.setValue(IncomeCategory.GIFT); ObservableList<Boolean> recurring = FXCollections.observableArrayList(true, false); recurringBox.setItems(recurring); recurringBox.setValue(false); + //Set date to today datePicker.setValue(LocalDate.now()); } @@ -67,7 +82,18 @@ public class AddIncomeController { return recurringBox.getValue();//.equals("Yes"); } - public void setIncome(Income income) { //TODO NEED CANCEL BUTTON TO REMOVE THE CHANGES IF CANCEL IS PRESSED + public Income getNewIncome() { + return this.newIncome; + } + + /** + * Binds the income that is taken in as the argument with an income declared in this class. The income of this class is instantiated + * as a deep copy of the argument. Each attribute of their attributes are then bounded. The text fields and category boxes + * in the dialog window are then set to the values of the chosen income, as to not display empty values. + * @param income The income that is chosen to be edited. + */ + public void setIncome(Income income) { + //Deep copying income and then binding the two incomes chosenIncome = new Income(income.getDescription(), income.getAmount(), income.isRecurring(), income.getCategory(), income.getDate()); chosenIncome.descriptionProperty().bindBidirectional(income.descriptionProperty()); chosenIncome.amountProperty().bindBidirectional(income.amountProperty()); @@ -78,6 +104,7 @@ public class AddIncomeController { amountField.textProperty().setValue(String.valueOf(income.getAmount())); recurringBox.setValue(income.isRecurring()); + //Set the values of the input fields of the dialog box descriptionField.textProperty().set(income.getDescription()); amountField.textProperty().setValue(String.valueOf(income.getAmount())); recurringBox.setValue(income.isRecurring()); @@ -85,8 +112,15 @@ public class AddIncomeController { categoryBox.setValue(income.getCategory()); } + /** + * Adds a new to the tableview or edits an existing entry in table if the OK button is pressed. + * An entry is edited as the selected entry of the table is bounded to another income in this class. If this income + * is altered, the income in the tableview will automatically respond with the same changes. + * @param event If the OK button is pressed. + */ @FXML public void pressOkBtn(ActionEvent event) { + //Instantiates a new income if (chosenIncome == null) { LocalDate date = datePicker.getValue(); double amount = Double.parseDouble(amountField.getText()); @@ -95,6 +129,7 @@ public class AddIncomeController { boolean recurring = isRecurring(); newIncome = new Income(description, amount, recurring, category, date); } + //Sets the value of the income(chosenIncome) that is bounded to the chosen income (not chosenIncome) in the tableview if (chosenIncome != null) { chosenIncome.setDescription((descriptionField.getText())); chosenIncome.setAmount(Double.parseDouble(amountField.getText())); @@ -107,6 +142,11 @@ public class AddIncomeController { ((Stage) source.getScene().getWindow()).close(); } + + /** + * Closes the dialog box and cancels any pending changes. + * @param event A button click on the cancel button. + */ @FXML public void pressCancelBtn(ActionEvent event) { final Node source = (Node) event.getSource(); @@ -114,8 +154,4 @@ public class AddIncomeController { stage.close(); } - - public Income getNewIncome() { - return this.newIncome; - } } \ No newline at end of file diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/BudgetController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/BudgetController.java index 22215ac760f1d12f6d08ed1c5e4dab30e6ebbfd2..45f7fdeac74a19b620c7ef5cc98788dd9c085d11 100644 --- a/src/main/java/no/ntnu/idatt1002/demo/controller/BudgetController.java +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/BudgetController.java @@ -8,6 +8,8 @@ import javafx.fxml.FXMLLoader; import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.chart.PieChart; +import javafx.scene.chart.PieChart.Data; import javafx.scene.control.*; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.cell.PropertyValueFactory; @@ -22,40 +24,38 @@ import no.ntnu.idatt1002.demo.data.Economics.ExpenseCategory; import java.io.IOException; import java.util.Optional; +import no.ntnu.idatt1002.demo.data.Economics.IncomeCategory; -public class BudgetController { +/** + * Controller for budget scene in the application. This controller manages all actions that relates to the budget tableview (add, edit and delete), the switching + * of scenes from the budget scene to another scene, and the saving of the table, whenever the user switches to another scene. + * + * @author Anders Emil Bergan + * @since 24.3.2023 + */ +public class BudgetController implements FinanceController { private GeneralBudget general; @FXML - private Button addBudget; + private Button addBtn; @FXML - private Button editBudget; - - @FXML - private Button expenseBtn; - - @FXML - private Button incomeBtn; + private Button editBtn; @FXML private Button returnBtn; - @FXML - private Button nextBtn; - - @FXML - private TableColumn<BudgetItem, Double> amountColumn; + private TableColumn<BudgetItem, Double> amountCol; @FXML private TableView<BudgetItem> budgetTableView = new TableView<>(); @FXML - private TableColumn<BudgetItem, ExpenseCategory> categoryColumn; + private TableColumn<BudgetItem, ExpenseCategory> categoryCol; @FXML - private TableColumn<BudgetItem, String> descriptionColumn; + private TableColumn<BudgetItem, String> descriptionCol; @FXML private Text sum; @@ -67,52 +67,88 @@ public class BudgetController { private ObservableList<BudgetItem> budgetList; + /** + * Initializes the budget register, the observable budget list and the tableview, along with the values of the dropbox used for filtering the tableview. + * @throws IOException If there occurs any exception when loading the budget register from a file. + */ + @FXML public void initialize() throws IOException { - categoryColumn.setCellValueFactory(new PropertyValueFactory<BudgetItem, ExpenseCategory>("budgetCategory")); - amountColumn.setCellValueFactory(new PropertyValueFactory<BudgetItem, Double>("budgetAmount")); - descriptionColumn.setCellValueFactory(new PropertyValueFactory<BudgetItem, String>("budgetDescription")); - - general = loadIncomeDataFromFile("Budget"); + //TODO if budget is not empty - disable + //Initialize table columns + categoryCol.setCellValueFactory(new PropertyValueFactory<BudgetItem, ExpenseCategory>("budgetCategory")); + amountCol.setCellValueFactory(new PropertyValueFactory<BudgetItem, Double>("budgetAmount")); + descriptionCol.setCellValueFactory(new PropertyValueFactory<BudgetItem, String>("budgetDescription")); + + //Initialize registers and tableview + general = loadBudgetDataFromFile("Budget"); budgetList = FXCollections.observableArrayList(general.getBudgetItems()); budgetTableView.setItems(budgetList); - sum.setText(String.valueOf(general.totalSum())); + //createBudgetPieChart(); + //Initialize sum field under the tableview + //sum.setText(String.valueOf(general.totalSum())); } - @FXML - public void switchAddBudget(javafx.event.ActionEvent event) throws IOException { + + private ObservableList<PieChart.Data> createBudgetPieChart() { //TODO DOESNT WORK IF BUDGETITEM HAS NO BUDGET + return FXCollections.observableArrayList( + new Data("Food", general.getBudgetItem(ExpenseCategory.FOOD).getBudgetAmount()), + new Data("Books", general.getBudgetItem(ExpenseCategory.BOOKS).getBudgetAmount()), + new Data("Clothes", general.getBudgetItem(ExpenseCategory.CLOTHES).getBudgetAmount()), + new Data("Other", general.getBudgetItem(ExpenseCategory.OTHER).getBudgetAmount()) + ); + } + + @Override + public void handleAddBtn(ActionEvent event) { + handleEditBtn(event); + } + /** + * Adds or edits a budget item, depending on what mode the DialogMode enum is at. The method brings up a dialog box popup in which the user can fill and choose + * values that the budget item will have. Open exiting the popup, the changes the saved to the tableview. + * @param event A button click on either the add or delete button. + */ + @Override + public void handleEditBtn(ActionEvent event) { BudgetItem item = null; String dialogTitle = ""; + DialogMode dialogMode; + FXMLLoader loader = new FXMLLoader(SceneController.class.getResource("/view/AddBudget.fxml")); Dialog<BudgetItem> dialog = new Dialog<>(); dialog.initModality(Modality.APPLICATION_MODAL); + //Try to load the FXML file onto another dialogPane try{ dialog.getDialogPane().setContent(loader.load()); } catch(IOException e) { e.printStackTrace(); } + //Loads the controller for the dialog box that appears whenever one adds or edits a budget item AddBudgetController budgetController = loader.getController(); - DialogMode dialogMode; - if(event.getSource().equals(addBudget)){ + //Sets the title of the dialog box + if(event.getSource().equals(addBtn)){ dialogMode = DialogMode.ADD; dialogTitle = "New Budget"; - } - else if (event.getSource().equals(editBudget) && budgetTableView.getSelectionModel().getSelectedItem() != null) { + else if (event.getSource().equals(editBtn) && budgetTableView.getSelectionModel().getSelectedItem() != null) { dialogMode = DialogMode.EDIT; dialogTitle = "Edit expense"; + //Gets the selected item from the table item = budgetTableView.getSelectionModel().getSelectedItem(); + //Binds the selected item to another item which is defined in the budgetcontroller budgetController.setBudget(item); } else { return; } dialog.setTitle(dialogTitle); + // Show the Dialog and wait for the user to close it dialog.showAndWait(); + //Adds the new item to the register item = budgetController.getNewBudgetItem(); if(item != null && dialogMode == DialogMode.ADD){ try { @@ -121,22 +157,24 @@ public class BudgetController { showIllegalBudgetItemDialog(); } } + //Updates the tableview using the register refreshTableView(); } - @FXML - public void closeButton(javafx.event.ActionEvent actionEvent) { - final Node source = (Node) actionEvent.getSource(); - final Stage stage = (Stage) source.getScene().getWindow(); - stage.close(); - } + /** + * Deletes an entry from the tableview, if an entry has been selected. The method brings up a popup window, asking for confirmation for deleting the entry. + * @param event A button click on the delete button + */ @FXML - public void deleteButton(ActionEvent event) { + public void handleDeleteBtn(ActionEvent event) { + //Gets the selected item from the tableview BudgetItem item = budgetTableView.getSelectionModel().getSelectedItem(); + //Exits the method if nothing is selected if (item == null) { return; } + //Brings up a confirmation popup Optional<ButtonType> isConfirmed = showConfirmationDialog(); if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) { general.deleteItemFromBudget(item.getBudgetCategory()); @@ -144,7 +182,22 @@ public class BudgetController { } } - private Optional<ButtonType> showConfirmationDialog() { + /** + * Method for synching the register with the tableview. The observable list to which the tableview is set, is being refilled with all the entries + * in the register, keeping it updated with new changes. + */ + public void refreshTableView(){ + this.budgetList.setAll(general.getBudgetItems()); + //Refreshing the sum of the amounts of the budget + this.sum.setText(String.valueOf(general.totalSum())); + } + + /** + * Returns an optional, which is a popup alert box, asking for confirmation for deleting an entry. + * @return An alert box, asking for confirmation for deleting the selected entry of the tableview. + */ + @Override + public Optional<ButtonType> showConfirmationDialog() { Alert alert = new Alert(Alert.AlertType.CONFIRMATION); alert.setTitle("Confirm Delete"); alert.setHeaderText("Delete Confirmation"); @@ -153,21 +206,41 @@ public class BudgetController { return alert.showAndWait(); } - private Optional<ButtonType> showIllegalBudgetItemDialog() { - Alert alert = new Alert(AlertType.ERROR); - alert.setTitle("Budget amount exceeded"); - alert.setHeaderText("Your budget exceeds the max limit"); - alert.setContentText("The total budget sum must be below " + general.getMaxAmount()); - - return alert.showAndWait(); + /** + * Saves the changes made to the tableview by writing the information to a file. + * + * @throws IOException If an error occurs while writing to the file. + */ + @Override + public void saveDataToFile() throws IOException { + FileHandlingBudget fileHandlingBudget = new FileHandlingBudget(); + fileHandlingBudget.writeGeneralBudgetToFile("Budget", general); } + /** + * Returns an optional, which is a popup alert box, informing that either the budget amount has + * been exceeded or that the same category has been entered twice in the budget tableview. + */ + private void showIllegalBudgetItemDialog() { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("Budget amount exceeded/Category already exists"); + alert.setHeaderText("Your budget exceeds the max limit OR a budget item of the same category already exists in the table"); + alert.setContentText("The total budget sum must be below " + general.getMaxAmount() + " OR Each category can only have one entry in the budget table"); + alert.showAndWait(); + } - public GeneralBudget loadIncomeDataFromFile(String fileName) throws IOException { + /** + * Method that either reads data from a file with which it fills a budget register, if this is an old budget, or instantiates a budget register if this is a new budget. + * @param fileName The name of the file that is being read from. + * @return An object of type GeneralBudget. + * @throws IOException If an error occurs while reading from the file. + */ + public GeneralBudget loadBudgetDataFromFile(String fileName) throws IOException { FileHandlingBudget fileHandlingBudget = new FileHandlingBudget(); + //Instantiate new budget if (fileHandlingBudget.isEmpty(fileName)) { general = new GeneralBudget(31, 1000); - } else { + } else { //Load previous budget try { general = fileHandlingBudget.readGeneralBudgetFromFile(fileName); } catch (IOException e) { @@ -177,30 +250,19 @@ public class BudgetController { return general; } - public void saveDataToFile(String fileName) throws IOException { - FileHandlingBudget fileHandlingBudget = new FileHandlingBudget(); - fileHandlingBudget.writeGeneralBudgetToFile(fileName, general); - } - - - protected void refreshTableView(){ - this.budgetList.setAll(general.getBudgetItems()); - this.sum.setText(String.valueOf(general.totalSum())); - } - + /** + * Switches scenes from the budget scene to another, by loading a new FXML file and setting the scene to this location. + * The destination depends entirely on which button is pressed. + * @param event A button click on the buttons on the buttonbar or the next button + * @throws IOException If an error occurs with loading any of the FXML files. + */ @FXML - public void switchScene(ActionEvent event) throws IOException { - saveDataToFile("Budget"); + public void returnToMainMenu(ActionEvent event) throws IOException { + //Always saving the data when switching scenes + saveDataToFile(); FXMLLoader loader = new FXMLLoader(); - if (event.getSource() == expenseBtn) { - loader.setLocation(SceneController.class.getResource("/view/Expenses.fxml")); - } else if (event.getSource() == returnBtn) { - loader.setLocation(SceneController.class.getResource("/view/FirstMenu.fxml")); - } else if (event.getSource() == incomeBtn) { - loader.setLocation(SceneController.class.getResource("/view/Income.fxml")); - } else if (event.getSource() == nextBtn) { - loader.setLocation(SceneController.class.getResource("/view/MainMenu.fxml")); - } + loader.setLocation(getClass().getResource("/view/MainMenuNew.fxml")); + Parent root = loader.load(); Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow(); Scene scene = new Scene(root); diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/DialogMode.java b/src/main/java/no/ntnu/idatt1002/demo/controller/DialogMode.java new file mode 100644 index 0000000000000000000000000000000000000000..3ac4c76452fdfca27ca7595211c9bedf7a6fb2e4 --- /dev/null +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/DialogMode.java @@ -0,0 +1,11 @@ +package no.ntnu.idatt1002.demo.controller; + +/** + * Enum for distinguishing between adding or editing an item in a tableview + * + * @author Harry Linrui Xu + * @since 11.3.2023 + */ +enum DialogMode { + ADD, EDIT +} diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/ExpensesController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/ExpensesController.java index 34b0c179e2ed78299250a6723a84e1599efbe074..d3ac8a5ad8cbe7a8374ab5986fef07869f3a1ec1 100644 --- a/src/main/java/no/ntnu/idatt1002/demo/controller/ExpensesController.java +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/ExpensesController.java @@ -32,10 +32,13 @@ import no.ntnu.idatt1002.demo.data.Economics.IncomeRegister; import no.ntnu.idatt1002.demo.data.Economics.Item; import no.ntnu.idatt1002.demo.data.Economics.ItemRegister; -enum DialogMode { - ADD, EDIT, DELETE -} - +/** + * Controller for expense scene in the application. This controller manages all actions that relates to the expense tableview (add, edit and delete), the switching + * of scenes from the expense scene to another scene, and the saving of the table, whenever the user switches to another scene. + * + * @author Harry Linrui Xu + * @since 13.3.2023 + */ public class ExpensesController { @FXML @@ -86,35 +89,54 @@ public class ExpensesController { ObservableList<String> filter; + /** + * Initializes the expense register, the observable expense list and the tableview, along values of the dropbox used for filtering the tableview. + * The method is called each time the FXML of this scene is loaded. + * @throws IOException If there occurs any exception when loading the budget register from a file. + */ @FXML public void initialize() throws IOException { + //Initialize table columns dateColumn.setCellValueFactory(new PropertyValueFactory<Expense, String>("date")); amountColumn.setCellValueFactory(new PropertyValueFactory<Expense, Double>("amount")); categoryColumn.setCellValueFactory(new PropertyValueFactory<Expense, ExpenseCategory>("category")); descriptionColumn.setCellValueFactory(new PropertyValueFactory<Expense, String>("description")); recurringColumn.setCellValueFactory(new PropertyValueFactory<Expense, Boolean>("recurring")); + //Initialize the filter box filter = FXCollections.observableArrayList("All", "Food", "Clothes", "Books", "Other", "Fixed expense"); show.setItems(filter); show.setValue("All"); + //Initialize registers and tableview expenseRegister = loadExpenseDataFromFile("Expense"); expenses = FXCollections.observableArrayList(expenseRegister.getItems()); expenseTableView.setItems(expenses); + //Initialize sum field under the tableview sum.setText(String.valueOf(expenseRegister.getTotalSum())); } + /** + * Method for handling the adding of new entries in the tableview. + * @param event A button click on the add button. + */ @FXML protected void handleAddButton(ActionEvent event) { handleEditButton(event); } + /** + * Method for handling the editing of a chosen entry in the tableview. + * @param event A button click on the edit button. + */ @FXML protected void handleEditButton(ActionEvent event) { + //Instantiate FXML loader and loads the popup for adding expense FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("/view/AddExpense.fxml")); + Expense newExpense = null; String dialogTitle = ""; // Load the FXML file for your dialog box @@ -134,7 +156,8 @@ public class ExpensesController { /** * The mode of the dialog. NEW if new contact, EDIT if edit existing contact. */ - DialogMode dialogMode; + DialogMode dialogMode; + //Sets the title of the dialog box if (event.getSource().equals(addBtn)) { dialogMode = DialogMode.ADD; dialogTitle = "Add expense"; @@ -144,25 +167,32 @@ public class ExpensesController { && expenseTableView.getSelectionModel().getSelectedItem() != null) { dialogMode = DialogMode.EDIT; dialogTitle = "Edit expense"; + //Gets the selected item from the table newExpense = expenseTableView.getSelectionModel().getSelectedItem(); + //Binds the selected item to another item which is defined in the ItemController dialogController.setExpense(newExpense); } else { return; } dialog.setTitle(dialogTitle); - dialog.showAndWait(); - // Show the Dialog and wait for the user to close it + dialog.showAndWait(); + //Get the newly created expense from the dialog pane newExpense = dialogController.getNewExpense(); + //Adds the new item to the register if (newExpense != null && dialogMode == DialogMode.ADD) { expenseRegister.addItem(newExpense); } + //Updates the tableview using the register refreshTableView(); } - //Only add the expense to the tableview, if the expense is not null + /** + * Deletes an entry from the tableview, if an entry has been selected. The method brings up a popup window, asking for confirmation for deleting the entry. + * @param event A button click on the delete button + */ @FXML public void handleDeleteBtn(ActionEvent event) { Expense chosenExpense = expenseTableView.getSelectionModel().getSelectedItem(); @@ -176,12 +206,20 @@ public class ExpensesController { } } + /** + * Method for synching the register with the tableview. The observable list to which the tableview is set, is being refilled with all the entries + * in the register, keeping it updated with new changes. + */ protected void refreshTableView() { this.expenses.setAll(expenseRegister.getItems()); this.sum.setText(String.valueOf(expenseRegister.getTotalSum())); } + /** + * Returns an optional, which is a popup alert box, asking for confirmation for deleting an entry. + * @return An alert box, asking for confirmation for deleting the selected entry of the tableview. + */ private Optional<ButtonType> showConfirmationDialog() { Alert alert = new Alert(AlertType.CONFIRMATION); alert.setTitle("Confirm Delete"); @@ -191,6 +229,12 @@ public class ExpensesController { return alert.showAndWait(); } + /** + * Method that either reads data from a file with which it fills an expense register, if older changes exist, or instantiates an expense register if the file is empty. + * @param fileName The name of the file that is being read from. + * @return An object of type IncomeRegister. + * @throws IOException If an error occurs while reading from the file. + */ public ExpenseRegister loadExpenseDataFromFile(String fileName) throws IOException { //ItemRegister<T extends Item> FileHandling fileHandling = new FileHandling(); @@ -206,11 +250,22 @@ public class ExpensesController { return expenseRegister; } + /** + * Saves the changes made to the expense tableview by writing the information to a file. + * @param fileName The name of the file that is written to. + * @throws IOException If an error occurs while writing to the file. + */ public void saveDataToFile(String fileName) throws IOException { FileHandling fileHandling = new FileHandling(); fileHandling.writeItemRegisterToFile(expenseRegister, fileName); } + /** + * Switches scenes from the expense scene to another, by loading a new FXML file and setting the scene to this location. + * The destination depends entirely on which button is pressed. + * @param event A button click on the buttons on the buttonbar or the next button + * @throws IOException If an error occurs with loading any of the FXML files. + */ @FXML public void switchScene(ActionEvent event) throws IOException { saveDataToFile("Expense"); diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/FinanceController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/FinanceController.java new file mode 100644 index 0000000000000000000000000000000000000000..96efb6519e3b2e44ce77d43580ecf8e48e9524dd --- /dev/null +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/FinanceController.java @@ -0,0 +1,52 @@ +package no.ntnu.idatt1002.demo.controller; + +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.util.Optional; +import javafx.scene.control.ButtonType; + +/** + * Interface for controllers for scenes with finance tableviews. + * + * @author Harry Linrui Xu + * @since 29.3.2023 + */ +public interface FinanceController { + + + /** + * Method for handling the adding of new entries in the tableview. + * @param event A button click on the add button. + */ + void handleAddBtn(javafx.event.ActionEvent event); + + /** + * Method for handling the editing of a chosen entry in the tableview. + * @param event A button click on the edit button. + */ + void handleEditBtn(javafx.event.ActionEvent event); + + /** + * Deletes an entry from the tableview, if an entry has been selected. The method brings up a popup window, asking for confirmation for deleting the entry. + * @param event A button click on the delete button + */ + void handleDeleteBtn(javafx.event.ActionEvent event); + + /** + * Method for synching the register with the tableview. The observable list to which the tableview is set, is being refilled with all the entries + * in the register, keeping it updated with new changes. + */ + void refreshTableView(); + + /** + * Returns an optional, which is a popup alert box, asking for confirmation for deleting an entry. + * @return An alert box, asking for confirmation for deleting the selected entry of the tableview. + */ + Optional<ButtonType> showConfirmationDialog(); + + /** + * Saves the changes made to the tableview by writing the information to a file. + * @throws IOException If an error occurs while writing to the file. + */ + void saveDataToFile() throws IOException; +} diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/IncomeController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/IncomeController.java index 489d98dba005251700af594b22a7870ecf52d110..c25c5ebb849641cf227e291b9ab05e3568cc8cb1 100644 --- a/src/main/java/no/ntnu/idatt1002/demo/controller/IncomeController.java +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/IncomeController.java @@ -28,12 +28,15 @@ import no.ntnu.idatt1002.demo.data.Economics.IncomeCategory; import no.ntnu.idatt1002.demo.data.Economics.IncomeRegister; import no.ntnu.idatt1002.demo.data.Economics.FileHandling; +/** + * Controller for income scene in the application. This controller manages all actions that relates to the income tableview (add, edit and delete), the switching + * of scenes from the income scene to another scene, and the saving of the table, whenever the user switches to another scene. + * + * @author Harry Linrui Xu + * @since 24.3.2023 + */ public class IncomeController { - /** - * The mode of the dialog. NEW if new contact, EDIT if edit existing contact. - */ - private DialogMode dialogMode; @FXML private Button addBtn; @FXML @@ -81,35 +84,54 @@ public class IncomeController { ObservableList<String> filter; + /** + * Initializes the income register, the observable income list and the tableview, along values of the dropbox used for filtering the tableview. + * The method is called each time the FXML of this scene is loaded. + * @throws IOException If there occurs any exception when loading the budget register from a file. + */ @FXML public void initialize() throws IOException { + //Initialize table columns dateColumn.setCellValueFactory(new PropertyValueFactory<Income, String>("date")); amountColumn.setCellValueFactory(new PropertyValueFactory<Income, Double>("amount")); categoryColumn.setCellValueFactory(new PropertyValueFactory<Income, IncomeCategory>("category")); descriptionColumn.setCellValueFactory(new PropertyValueFactory<Income, String>("description")); recurringColumn.setCellValueFactory(new PropertyValueFactory<Income, Boolean>("recurring")); + //Initialize the filter box filter = FXCollections.observableArrayList("All", "Gift", "Salary", "Student loan", "Fixed income"); show.setItems(filter); show.setValue("All"); + //Initialize registers and tableview incomeRegister = loadIncomeDataFromFile("Income"); income = FXCollections.observableArrayList(incomeRegister.getItems()); incomeTableView.setItems(income); + //Initialize sum field under the tableview sum.setText(String.valueOf(incomeRegister.getTotalSum())); //if budget.register isEmpty -> disable expense } + /** + * Method for handling the adding of new entries in the tableview. + * @param event A button click on the add button. + */ @FXML protected void handleAddButton(ActionEvent event) { handleEditButton(event); } + /** + * Method for handling the editing of a chosen entry in the tableview. + * @param event A button click on the edit button. + */ @FXML protected void handleEditButton(ActionEvent event) { + //Instantiate FXML loader and loads the popup for adding income FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("/view/AddIncome.fxml")); + Income newIncome = null; String dialogTitle = ""; // Load the FXML file for your dialog box @@ -126,16 +148,24 @@ public class IncomeController { // Get the controller for the loaded FXML file AddIncomeController dialogController = loader.getController(); + /** + * The mode of the dialog. NEW if new contact, EDIT if edit existing contact. + */ + DialogMode dialogMode; + //Sets the title of the dialog box if (event.getSource().equals(addBtn)) { dialogMode = DialogMode.ADD; dialogTitle = "Add income"; - } else if (event.getSource().equals(editBtn) - && incomeTableView.getSelectionModel().getSelectedItem() != null) { + } + else if (event.getSource().equals(editBtn) && incomeTableView.getSelectionModel().getSelectedItem() != null) { dialogMode = DialogMode.EDIT; dialogTitle = "Edit income"; + //Gets the selected item from the table newIncome = incomeTableView.getSelectionModel().getSelectedItem(); + //Binds the selected item to another item which is defined in the ItemController dialogController.setIncome(newIncome); - } else { + } + else { return; } @@ -145,19 +175,27 @@ public class IncomeController { //Get the newly created income from the dialog pane newIncome = dialogController.getNewIncome(); + //Adds the new item to the register if (newIncome != null && dialogMode == DialogMode.ADD) { incomeRegister.addItem(newIncome); } + //Updates the tableview using the register refreshTableView(); } - //Only add the income to the tableview, if the income is not null + /** + * Deletes an entry from the tableview, if an entry has been selected. The method brings up a popup window, asking for confirmation for deleting the entry. + * @param event A button click on the delete button + */ @FXML public void handleDeleteBtn(ActionEvent event) { + //Gets the selected item from the tableview Income chosenIncome = incomeTableView.getSelectionModel().getSelectedItem(); + //Exits the method if nothing is selected if (chosenIncome == null) { return; } + //Brings up a confirmation popup Optional<ButtonType> isConfirmed = showConfirmationDialog(); if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) { incomeRegister.removeItem(chosenIncome); @@ -165,11 +203,19 @@ public class IncomeController { } } + /** + * Method for synching the register with the tableview. The observable list to which the tableview is set, is being refilled with all the entries + * in the register, keeping it updated with new changes. + */ protected void refreshTableView() { this.income.setAll(incomeRegister.getItems()); this.sum.setText(String.valueOf(incomeRegister.getTotalSum())); } + /** + * Returns an optional, which is a popup alert box, asking for confirmation for deleting an entry. + * @return An alert box, asking for confirmation for deleting the selected entry of the tableview. + */ private Optional<ButtonType> showConfirmationDialog() { Alert alert = new Alert(AlertType.CONFIRMATION); alert.setTitle("Confirm Delete"); @@ -179,12 +225,18 @@ public class IncomeController { return alert.showAndWait(); } + /** + * Method that either reads data from a file with which it fills an income register, if older changes exist, or instantiates an income register if the file is empty. + * @param fileName The name of the file that is being read from. + * @return An object of type IncomeRegister. + * @throws IOException If an error occurs while reading from the file. + */ public IncomeRegister loadIncomeDataFromFile(String fileName) throws IOException { FileHandling fileHandling = new FileHandling(); + //Instantiate new incomeRegister if (fileHandling.isEmpty(fileName)) { incomeRegister = new IncomeRegister(); - System.out.println("hey"); - } else { + } else { //Load previous income register try { incomeRegister = fileHandling.readIncomeRegisterFromFile(fileName); } catch (IOException e) { @@ -194,23 +246,33 @@ public class IncomeController { return incomeRegister; } + /** + * Saves the changes made to the income tableview by writing the information to a file. + * @param fileName The name of the file that is written to. + * @throws IOException If an error occurs while writing to the file. + */ public void saveDataToFile(String fileName) throws IOException { FileHandling fileHandling = new FileHandling(); fileHandling.writeItemRegisterToFile(incomeRegister, fileName); } + /** + * Switches scenes from the income scene to another, by loading a new FXML file and setting the scene to this location. + * The destination depends entirely on which button is pressed. + * @param event A button click on the buttons on the buttonbar or the next button + * @throws IOException If an error occurs with loading any of the FXML files. + */ @FXML public void switchScene(ActionEvent event) throws IOException { + //Always saving the data when switching scenes saveDataToFile("Income"); FXMLLoader loader = new FXMLLoader(); - if (event.getSource() == expenseBtn) { - loader.setLocation(SceneController.class.getResource("/view/Expenses.fxml")); - } else if (event.getSource() == overviewBtn) { + if (event.getSource() == overviewBtn) { loader.setLocation(SceneController.class.getResource("/view/Overview.fxml")); } else if (event.getSource() == returnBtn) { loader.setLocation(SceneController.class.getResource("/view/FirstMenu.fxml")); } else if (event.getSource() == budgetBtn) { - loader.setLocation(SceneController.class.getResource("/view/BudgetNew.fxml")); + loader.setLocation(SceneController.class.getResource("/view/BudgetNewest.fxml")); } Parent root = loader.load(); Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow(); diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/IncomeExpenseController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/IncomeExpenseController.java new file mode 100644 index 0000000000000000000000000000000000000000..4b3014da6cee07ac96b5ecc93cb32f3b41f912de --- /dev/null +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/IncomeExpenseController.java @@ -0,0 +1,516 @@ +package no.ntnu.idatt1002.demo.controller; + +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.util.Optional; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Side; +import javafx.scene.Node; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.chart.PieChart; +import javafx.scene.chart.PieChart.Data; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.ComboBox; +import javafx.scene.control.DatePicker; +import javafx.scene.control.Dialog; +import javafx.scene.control.Label; +import javafx.scene.control.MenuItem; +import javafx.scene.control.ProgressBar; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.text.Text; +import javafx.stage.Modality; +import javafx.stage.Stage; +import no.ntnu.idatt1002.demo.data.Budget.FileHandlingBudget; +import no.ntnu.idatt1002.demo.data.Budget.GeneralBudget; +import no.ntnu.idatt1002.demo.data.Economics.Expense; +import no.ntnu.idatt1002.demo.data.Economics.ExpenseCategory; +import no.ntnu.idatt1002.demo.data.Economics.ExpenseRegister; +import no.ntnu.idatt1002.demo.data.Economics.FileHandling; +import no.ntnu.idatt1002.demo.data.Economics.Income; +import no.ntnu.idatt1002.demo.data.Economics.IncomeCategory; +import no.ntnu.idatt1002.demo.data.Economics.IncomeRegister; + +public class IncomeExpenseController implements FinanceController { + + @FXML + private TableColumn<Expense, Double> expAmountCol; + + @FXML + private TableColumn<Expense, ExpenseCategory> expCategoryCol; + + @FXML + private TableColumn<Expense, String> expDateCol; + + @FXML + private TableColumn<Expense, String> expDescriptionCol; + + @FXML + private TableColumn<Expense, Boolean> expRecurringCol; + + @FXML + private TableColumn<Income, Double> inAmountCol; + + @FXML + private TableColumn<Income, IncomeCategory> inCategoryCol; + + @FXML + private TableColumn<Income, String> inDateCol; + + @FXML + private TableColumn<Income, String> inDescriptionCol; + + @FXML + private TableColumn<Income, Boolean> inRecurringCol; + + @FXML + private TableView<Expense> expenseTableView; + + @FXML + private TableView<Income> incomeTableView; + + @FXML + private Text inSum; + + @FXML + private Text expSum; + + @FXML + private MenuItem addExpense; + + @FXML + private MenuItem addIncome; + + @FXML + private Button deleteBtn; + + @FXML + private Button editBtn; + + @FXML + private ProgressBar budgetProgress; + + @FXML + private DatePicker date; + + @FXML + private Label daysLeftLbl; + + @FXML + private ComboBox<?> filter; + + @FXML + private Button returnBtn; + + @FXML + private Label title; + private IncomeRegister incomeRegister; + + private ExpenseRegister expenseRegister; + + private GeneralBudget generalBudget; + + private ObservableList<Income> income; + + private ObservableList<Expense> expenses; + + @FXML + private PieChart expensePieChart; + + @FXML + private PieChart incomePieChart; + + FileHandling fileHandling; + + @FXML + public void initialize() throws IOException { + fileHandling = new FileHandling(); + + //Initialize columns + setColumns(); + + //Initialize registers and tableview + incomeRegister = loadIncomeDataFromFile("Income"); + income = FXCollections.observableArrayList(incomeRegister.getItems()); + incomeTableView.setItems(income); + + expenseRegister = loadExpenseDataFromFile("Expense"); + expenses = FXCollections.observableArrayList(expenseRegister.getItems()); + expenseTableView.setItems(expenses); + + //Setting pie chart values to correspond with the registers + refreshPieCharts(); + incomePieChart.setLegendSide(Side.RIGHT); + + refreshPieCharts(); + expensePieChart.setLegendSide(Side.RIGHT); + expensePieChart.setLabelLineLength(10); + + refreshProgress(); + + //Initialize sum field under the tableview + // inSum.setText(String.valueOf(incomeRegister.getTotalSum())); + //expSum.setText(String.valueOf(expenseRegister.getTotalSum())); + } + + private void setColumns() { + inDateCol.setCellValueFactory(new PropertyValueFactory<Income, String>("date")); + inAmountCol.setCellValueFactory(new PropertyValueFactory<Income, Double>("amount")); + inCategoryCol.setCellValueFactory(new PropertyValueFactory<Income, IncomeCategory>("category")); + inDescriptionCol.setCellValueFactory(new PropertyValueFactory<Income, String>("description")); + inRecurringCol.setCellValueFactory(new PropertyValueFactory<Income, Boolean>("recurring")); + + expDateCol.setCellValueFactory(new PropertyValueFactory<Expense, String>("date")); + expAmountCol.setCellValueFactory(new PropertyValueFactory<Expense, Double>("amount")); + expCategoryCol.setCellValueFactory(new PropertyValueFactory<Expense, ExpenseCategory>("category")); + expDescriptionCol.setCellValueFactory(new PropertyValueFactory<Expense, String>("description")); + expRecurringCol.setCellValueFactory(new PropertyValueFactory<Expense, Boolean>("recurring")); + } + + private ObservableList<PieChart.Data> createExpensePieChart() { + return FXCollections.observableArrayList( + new Data("Food", expenseRegister.getExpenseByCategory(ExpenseCategory.FOOD).getTotalSum()), + new Data("Books", expenseRegister.getExpenseByCategory(ExpenseCategory.BOOKS).getTotalSum()), + new Data("Clothes", expenseRegister.getExpenseByCategory(ExpenseCategory.CLOTHES).getTotalSum()), + new Data("Other", expenseRegister.getExpenseByCategory(ExpenseCategory.OTHER).getTotalSum()) + ); + } + + private ObservableList<PieChart.Data> createIncomePieChart() { + return FXCollections.observableArrayList( + new Data("Gift", incomeRegister.getIncomeByCategory(IncomeCategory.GIFT).getTotalSum()), + new Data("Salary", incomeRegister.getIncomeByCategory(IncomeCategory.SALARY).getTotalSum()), + new Data("Loans", incomeRegister.getIncomeByCategory(IncomeCategory.STUDENT_LOAN).getTotalSum()) + ); + } + + /** + * Method for handling the adding of new entries in the tableview. + * @param event A button click on the add button. + */ + @Override + public void handleAddBtn(javafx.event.ActionEvent event) { + if (event.getSource() == addIncome) { + handleAddIncome(); + } else if (event.getSource() == addExpense){ + handleAddExpense(); + } + refreshTableView(); + refreshPieCharts(); + refreshProgress(); + } + + /** + * Method for handling the editing of a chosen entry in the tableview. + * + * @param event A button click on the edit button. + */ + @Override + public void handleEditBtn(javafx.event.ActionEvent event) { + Income chosenIncome = incomeTableView.getSelectionModel().getSelectedItem(); + Expense chosenExpense = expenseTableView.getSelectionModel().getSelectedItem(); + + if (event.getSource() == editBtn) { + if (chosenIncome!= null) { + handleEditIncome(chosenIncome); + } else if (chosenExpense != null) { + handleEditExpense(chosenExpense); + } + } else if (event.getSource() == deleteBtn) { + if (chosenIncome != null) { + handleDeleteIncome(chosenIncome); + } else if (chosenExpense != null) { + handleDeleteExpense(chosenExpense); + } + } else return; + //Updates the tableview and pie chart using the register + refreshTableView(); + refreshPieCharts(); + refreshProgress(); + } + + /** + * Deletes an entry from the tableview, if an entry has been selected. The method brings up a + * popup window, asking for confirmation for deleting the entry. + * + * @param event A button click on the delete button + */ + @Override + public void handleDeleteBtn(javafx.event.ActionEvent event) { + handleEditBtn(event); + } + + /** + * Method for synching the register with the tableview. The observable list to which the tableview + * is set, is being refilled with all the entries in the register, keeping it updated with new + * changes. + */ + @Override + public void refreshTableView() { + this.income.setAll(incomeRegister.getItems()); + //this.sum.setText(String.valueOf(incomeRegister.getTotalSum())); + + this.expenses.setAll(expenseRegister.getItems()); + //this.sum.setText(String.valueOf(incomeRegister.getTotalSum())); + } + + private void refreshPieCharts() { + this.incomePieChart.setData(createIncomePieChart()); + this.expensePieChart.setData(createExpensePieChart()); + } + + private void refreshProgress() { + budgetProgress.setProgress(expenseRegister.getTotalSum()/incomeRegister.getTotalSum()); + } + + @FXML + private void handleAddIncome() { + //Instantiate FXML loader and loads the popup for adding income + FXMLLoader loader = new FXMLLoader(); + loader.setLocation(getClass().getResource("/view/AddIncome.fxml")); + + Income newIncome = null; + String dialogTitle = "Add income"; + // Load the FXML file for your dialog box + Dialog<Income> dialog = new Dialog<>(); + dialog.initModality(Modality.APPLICATION_MODAL); + + try { + // Set the Dialog's content to the loaded FXML file + dialog.getDialogPane().setContent(loader.load()); + } catch (IOException e) { + e.printStackTrace(); + } + + // Get the controller for the loaded FXML file + AddIncomeController dialogController = loader.getController(); + //Sets the title of the dialog box + dialog.setTitle(dialogTitle); + // Show the Dialog and wait for the user to close it + dialog.showAndWait(); + //Get the newly created income from the dialog pane + newIncome = dialogController.getNewIncome(); + + //Adds the new item to the register + if (newIncome != null) { + incomeRegister.addItem(newIncome); + } + } + + @FXML + private void handleAddExpense() { + //Instantiate FXML loader and loads the popup for adding expense + FXMLLoader loader = new FXMLLoader(); + loader.setLocation(getClass().getResource("/view/AddExpense.fxml")); + + Expense newExpense = null; + String dialogTitle = "Add expense"; + // Load the FXML file for your dialog box + Dialog<Expense> dialog = new Dialog<>(); + dialog.initModality(Modality.APPLICATION_MODAL); + + try { + // Set the Dialog's content to the loaded FXML file + dialog.getDialogPane().setContent(loader.load()); + } catch (IOException e) { + e.printStackTrace(); + } + + // Get the controller for the loaded FXML file + AddExpenseController dialogController = loader.getController(); + + dialog.setTitle(dialogTitle); + // Show the Dialog and wait for the user to close it + dialog.showAndWait(); + + //Get the newly created expense from the dialog pane + newExpense = dialogController.getNewExpense(); + + //Adds the new item to the register + if (newExpense != null) { + expenseRegister.addItem(newExpense); + } + } + + @FXML + private void handleEditIncome(Income chosenIncome) { + //Instantiate FXML loader and loads the popup for adding income + FXMLLoader loader = new FXMLLoader(); + loader.setLocation(getClass().getResource("/view/AddIncome.fxml")); + + String dialogTitle = "Edit income"; + // Load the FXML file for your dialog box + Dialog<Income> dialog = new Dialog<>(); + dialog.initModality(Modality.APPLICATION_MODAL); + + try { + // Set the Dialog's content to the loaded FXML file + dialog.getDialogPane().setContent(loader.load()); + } catch (IOException e) { + e.printStackTrace(); + } + + // Get the controller for the loaded FXML file + AddIncomeController dialogController = loader.getController(); + //Binds the selected item to another item which is defined in the ItemController + dialogController.setIncome(chosenIncome); + + dialog.setTitle(dialogTitle); + // Show the Dialog and wait for the user to close it + dialog.showAndWait(); + } + + @FXML + private void handleEditExpense(Expense chosenExpense) { + //Instantiate FXML loader and loads the popup for adding expense + FXMLLoader loader = new FXMLLoader(); + loader.setLocation(getClass().getResource("/view/AddExpense.fxml")); + + String dialogTitle = "Edit expense"; + // Load the FXML file for your dialog box + Dialog<Expense> dialog = new Dialog<>(); + dialog.initModality(Modality.APPLICATION_MODAL); + + try { + // Set the Dialog's content to the loaded FXML file + dialog.getDialogPane().setContent(loader.load()); + } catch (IOException e) { + e.printStackTrace(); + } + + // Get the controller for the loaded FXML file + AddExpenseController dialogController = loader.getController(); + //Binds the selected item to another item which is defined in the ItemController + dialogController.setExpense(chosenExpense); + dialog.setTitle(dialogTitle); + // Show the Dialog and wait for the user to close it + dialog.showAndWait(); + } + + @FXML + private void handleDeleteIncome(Income chosenIncome) { + Optional<ButtonType> isConfirmed = showConfirmationDialog(); + if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) { + incomeRegister.removeItem(chosenIncome); + } + } + + @FXML + private void handleDeleteExpense(Expense chosenExpense) { + Optional<ButtonType> isConfirmed = showConfirmationDialog(); + if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) { + expenseRegister.removeItem(chosenExpense); + } + + } + /** + * Returns an optional, which is a popup alert box, asking for confirmation for deleting an + * entry. + * + * @return An alert box, asking for confirmation for deleting the selected entry of the tableview. + */ + @Override + public Optional<ButtonType> showConfirmationDialog() { + Alert alert = new Alert(AlertType.CONFIRMATION); + alert.setTitle("Confirm Delete"); + alert.setHeaderText("Delete Confirmation"); + alert.setContentText("Are you sure you would like to delete the selected entry?"); + + return alert.showAndWait(); + } + + /** + * Saves the changes made to the tableview by writing the information to a file. + * @throws IOException If an error occurs while writing to the file. + */ + @Override + public void saveDataToFile() throws IOException { + fileHandling.writeItemRegisterToFile(incomeRegister, "Income"); + fileHandling.writeItemRegisterToFile(expenseRegister, "Expense"); + } + + /** + * Method that either reads data from a file with which it fills an income register, if older changes exist, or instantiates an income register if the file is empty. + * @param fileName The name of the file that is being read from. + * @return An object of type IncomeRegister. + * @throws IOException If an error occurs while reading from the file. + */ + public IncomeRegister loadIncomeDataFromFile(String fileName) throws IOException { + //Instantiate new incomeRegister + if (fileHandling.isEmpty(fileName)) { + incomeRegister = new IncomeRegister(); + } else { //Load previous income register + try { + incomeRegister = fileHandling.readIncomeRegisterFromFile(fileName); + } catch (IOException e) { + e.printStackTrace(); + } + } + return incomeRegister; + } + + /** + * Method that either reads data from a file with which it fills an expense register, if older changes exist, or instantiates an expense register if the file is empty. + * @param fileName The name of the file that is being read from. + * @return An object of type IncomeRegister. + * @throws IOException If an error occurs while reading from the file. + */ + public ExpenseRegister loadExpenseDataFromFile(String fileName) throws IOException { + //ItemRegister<T extends Item> + if (fileHandling.isEmpty(fileName)) { + expenseRegister = new ExpenseRegister(); + } else { + try { + expenseRegister = fileHandling.readExpenseRegisterFromFile(fileName); + } catch (IOException e) { + e.printStackTrace(); + } + } + return expenseRegister; + } + + /** + * Method that either reads data from a file with which it fills a budget register, if this is an old budget, or instantiates a budget register if this is a new budget. + * @param fileName The name of the file that is being read from. + * @return An object of type GeneralBudget. + * @throws IOException If an error occurs while reading from the file. + */ + public GeneralBudget loadBudgetDataFromFile(String fileName) throws IOException { + FileHandlingBudget fileHandlingBudget = new FileHandlingBudget(); + //Instantiate new budget + if (fileHandlingBudget.isEmpty(fileName)) { + generalBudget = new GeneralBudget(31, 1000); + } else { //Load previous budget + try { + generalBudget = fileHandlingBudget.readGeneralBudgetFromFile(fileName); + } catch (IOException e) { + e.printStackTrace(); + } + } + return generalBudget; + } + + /** + * Switches the scene to the Main Menu scene. + */ + @FXML + private void returnToMainMenu(javafx.event.ActionEvent event) throws IOException { + saveDataToFile(); + FXMLLoader loader = new FXMLLoader(); + loader.setLocation(getClass().getResource("/view/MainMenuNew.fxml")); + + Parent root = loader.load(); + Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow(); + Scene scene = new Scene(root); + stage.setScene(scene); + stage.show(); + } +} diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/MainMenu.java b/src/main/java/no/ntnu/idatt1002/demo/controller/MainMenu.java new file mode 100644 index 0000000000000000000000000000000000000000..c785b25ecb9d941d2dd6bbbafe44bfa3be1ee770 --- /dev/null +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/MainMenu.java @@ -0,0 +1,169 @@ +package no.ntnu.idatt1002.demo.controller; + +import java.io.IOException; +import java.time.LocalDate; +import javafx.collections.FXCollections; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.DatePicker; +import javafx.scene.control.Label; +import javafx.scene.control.ProgressBar; +import javafx.scene.layout.AnchorPane; +import javafx.scene.paint.Color; +import javafx.stage.Stage; +import no.ntnu.idatt1002.demo.data.Budget.FileHandlingBudget; +import no.ntnu.idatt1002.demo.data.Budget.GeneralBudget; +import no.ntnu.idatt1002.demo.data.Economics.ExpenseRegister; +import no.ntnu.idatt1002.demo.data.Economics.IncomeRegister; + +public class MainMenu { + + @FXML + private Label balanceLbl; + @FXML + private ProgressBar bookBar; + + @FXML + private Label bookLbl; + + @FXML + private Button budgetBtn; + + @FXML + private ProgressBar clothesBar; + + @FXML + private Label clothesLbl; + + @FXML + private DatePicker date; + + @FXML + private Button expenseBtn; + + @FXML + private ProgressBar foodBar; + + @FXML + private Button foodBtn; + + @FXML + private Label foodLbl; + + @FXML + private Button incomeBtn; + + @FXML + private ProgressBar mainBar; + + @FXML + private ProgressBar otherBar; + + @FXML + private Label otherLbl; + + @FXML + private Button returnBtn; + + @FXML + private Label title; + + @FXML + private Label usageLbl; + + @FXML + private AnchorPane root; + + @FXML + private Label daysLeftLbl; + + GeneralBudget generalBudget; + + ExpenseRegister expenseRegister; + + IncomeRegister incomeRegister; + + @FXML + public void initialize() throws IOException { //TODO NEED TO SET STATUSBAR VALUES + //Initialize all controllers + initializeControllers(); + + double incomeSum = incomeRegister.getTotalSum(); + double expenseSum = expenseRegister.getTotalSum(); + + //Set progress + mainBar.setProgress(expenseSum/incomeSum); + + //Displaying month + title.setText("BUDGET " + (LocalDate.now().getMonth())); + double balance = incomeSum - expenseSum; + //Set balance + balanceLbl.setText("Balance: " + (balance)); + //Displaying how much of the monthly budget has been spent. + usageLbl.setText("Used " + expenseSum + " out of " + 1000); + + if (balance < 0) { + balanceLbl.setTextFill(Color.RED); + } + + //Make calendar uneditable + formatDatePicker(); + daysLeftLbl.setText("Days left: 31"); + //date.restrict + } + + /** + * Method for initializing all controllers in order to load all necessary data for this screen. + * Made this a separate method in order to make initialize() less cluttered. + * @throws IOException If there is an error with reading the files. + */ + private void initializeControllers() throws IOException { + //Instantiate income controller and register + IncomeController incomeController = new IncomeController(); + incomeRegister = incomeController.loadIncomeDataFromFile("Income"); + + //Instantiate expense controller and register + ExpensesController expensesController = new ExpensesController(); + expenseRegister = expensesController.loadExpenseDataFromFile("Expense"); + + //Instantiate budget controller and register + BudgetController budgetController = new BudgetController(); + generalBudget = budgetController.loadBudgetDataFromFile("Budget"); + } + + /** + * Method for disabling the date picker, yet having its opacity at max. + */ + private void formatDatePicker() { + date.setValue(LocalDate.now()); + date.setDisable(true); + date.setStyle("-fx-opacity: 1"); + date.getEditor().setStyle("-fx-opacity: 1"); + } + @FXML + private void switchScene(ActionEvent event) throws IOException { + FXMLLoader loader = new FXMLLoader(); + if (event.getSource() == foodBtn) { + System.out.println("Food button pressed"); + } else if (event.getSource() == expenseBtn) { + loader.setLocation(getClass().getResource("/view/IncomeAndExpenses.fxml")); + } else if (event.getSource() == incomeBtn) { + loader.setLocation(getClass().getResource("/view/IncomeAndExpenses.fxml")); + } else if (event.getSource() == budgetBtn) { + loader.setLocation(getClass().getResource("/view/BudgetNewest.fxml")); + } else if (event.getSource() == returnBtn) { + loader.setLocation(getClass().getResource("/view/FirstMenu.fxml")); + } + Parent root = loader.load(); + Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow(); + Scene scene = new Scene(root); + stage.setScene(scene); + stage.show(); + } +} + diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/MainMenuController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/MainMenuController.java index f59aedc77d55dec90953454bd5f59e139b8cf3ed..9a0fe9bca61214305b834ce9d82cee0f098a066c 100644 --- a/src/main/java/no/ntnu/idatt1002/demo/controller/MainMenuController.java +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/MainMenuController.java @@ -19,6 +19,10 @@ import no.ntnu.idatt1002.demo.data.Economics.ExpenseRegister; import no.ntnu.idatt1002.demo.data.Economics.FileHandling; import no.ntnu.idatt1002.demo.data.Economics.IncomeRegister; +/** + * Class that acts as both a main menu and monthly budget overview that shows the monthly progress of a users account. + * The main menu act as a hub that branches to numerous other windows, such as adding expenses or looking into food recipes. + */ public class MainMenuController { @FXML @@ -49,24 +53,36 @@ public class MainMenuController { private Label balanceLbl; + /** + * Initializes various classes that relates to income and expense, in order to present the overview that depends on the + * income (money inflow) and expense (money outflow). + * Sets the progress bar, budget month, balance label, date and how much of the monthly budget has been spent. + * @throws IOException Upon errors with file reading/writing. + */ @FXML public void initialize() throws IOException { + //Instantiate the income- controller and register IncomeController incomeController = new IncomeController(); IncomeRegister incomeRegister = incomeController.loadIncomeDataFromFile("Income"); + //Instantiate the expense- controller and register ExpensesController expensesController = new ExpensesController(); ExpenseRegister expenseRegister = expensesController.loadExpenseDataFromFile("Expense"); double incomeSum = incomeRegister.getTotalSum(); double expenseSum = expenseRegister.getTotalSum(); + //Set progress progressbar.setProgress(expenseSum/incomeSum); - progressMarker.setTranslateX(-275 + progressbar.getProgress()); + //progressMarker.setTranslateX(-275 + progressbar.getProgress()); + //Displaying month budgetMonth.setText("BUDGET " + (LocalDate.EPOCH.getMonth())); double balance = incomeSum - expenseSum; + //Set balance balanceLbl.setText("Balance: " + (balance)); + //Displaying how much of the monthly budget has been spent. today.setText("Used " + expenseSum + " out of " + incomeSum + " this month"); if (balance < 0) { @@ -77,15 +93,17 @@ public class MainMenuController { //date.restrict } + /** + * Switches scenes from the main menu scene to another, by loading a new FXML file and setting the scene to this location. + * The destination depends entirely on which button is pressed. + * @param event A button click. + * @throws IOException If an error occurs with loading any of the FXML files. + */ @FXML public void switchScene(ActionEvent event) throws IOException { - //saveDataToFile("Income"); FXMLLoader loader = new FXMLLoader(); - if (event.getSource() == addExpenseBtn) { - loader.setLocation(SceneController.class.getResource("/view/Expenses.fxml")); - } else if (event.getSource() == overviewBtn) { - loader.setLocation(SceneController.class.getResource("/view/Budget.fxml")); - } + loader.setLocation(SceneController.class.getResource("/view/Budget.fxml")); + Parent root = loader.load(); Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow(); diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/SceneController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/SceneController.java index 9d70b03508cdc080c48962db303a8c59cbae45ba..a94b8678d90845c0b2b5eda9b2baa7381d30f8a7 100644 --- a/src/main/java/no/ntnu/idatt1002/demo/controller/SceneController.java +++ b/src/main/java/no/ntnu/idatt1002/demo/controller/SceneController.java @@ -41,15 +41,6 @@ public class SceneController { stage.show(); } - public void switchExpenses(ActionEvent event) throws IOException { - FXMLLoader loader = new FXMLLoader(SceneController.class.getResource("/view/Expenses.fxml")); - Parent root = loader.load(); - stage = (Stage)((Node)event.getSource()).getScene().getWindow(); - scene = new Scene(root); - stage.setScene(scene); - stage.show(); - } - public void switchOverview(ActionEvent event) throws IOException { FXMLLoader loader = new FXMLLoader(SceneController.class.getResource("/view/Overview.fxml")); Parent root = loader.load(); diff --git a/src/main/resources/Economics/Income.register b/src/main/resources/Economics/Income.register index bc73c7799d89fc774ba0303cc1f4d105377d2b98..80d6de630145291c7e1a9fd83856c885274554f2 100644 --- a/src/main/resources/Economics/Income.register +++ b/src/main/resources/Economics/Income.register @@ -1,17 +1,10 @@ -date=2023-03-24 -description=studie -amount=1000.0 -isRecurring=Recurring -category=STUDENT_LOAN - date=2023-03-25 amount=100.0 isRecurring=Not recurring category=GIFT -date=2023-03-25 -description=airbnb -amount=1000.0 +date=2023-03-31 +amount=500.0 isRecurring=Not recurring -category=GIFT +category=SALARY diff --git a/src/main/resources/Images/add.png b/src/main/resources/Images/add.png new file mode 100644 index 0000000000000000000000000000000000000000..b4957672e9a429a49fca6e83ac549ddfd3ff99cd Binary files /dev/null and b/src/main/resources/Images/add.png differ diff --git a/src/main/resources/Images/budget.png b/src/main/resources/Images/budget.png new file mode 100644 index 0000000000000000000000000000000000000000..764daef782c2ce2d90fa12f424a5e168ba30366b Binary files /dev/null and b/src/main/resources/Images/budget.png differ diff --git a/src/main/resources/Images/delete.png b/src/main/resources/Images/delete.png index b23937817cfa4976c74f73288a6c34451934f16b..28a19aca76f168bcdec447a4d724a27de53f4564 100644 Binary files a/src/main/resources/Images/delete.png and b/src/main/resources/Images/delete.png differ diff --git a/src/main/resources/Images/edit.png b/src/main/resources/Images/edit.png index 833b336008545736084b8b7178591740a5bd7ac7..b68f795730330f1ca42c331d5597c7a8abf5c84d 100644 Binary files a/src/main/resources/Images/edit.png and b/src/main/resources/Images/edit.png differ diff --git a/src/main/resources/Images/expense.png b/src/main/resources/Images/expense.png new file mode 100644 index 0000000000000000000000000000000000000000..cd1c0d323814ea34a00dec0e5070fc79c303a0c5 Binary files /dev/null and b/src/main/resources/Images/expense.png differ diff --git a/src/main/resources/Images/income.png b/src/main/resources/Images/income.png new file mode 100644 index 0000000000000000000000000000000000000000..54546ff034dba7f6ab840ac0d7624f36d5ccdf89 Binary files /dev/null and b/src/main/resources/Images/income.png differ diff --git a/src/main/resources/Images/incomeExpense.png b/src/main/resources/Images/incomeExpense.png new file mode 100644 index 0000000000000000000000000000000000000000..e9b445f1d9be0a5f47a7c54734a28462f813a92c Binary files /dev/null and b/src/main/resources/Images/incomeExpense.png differ diff --git a/src/main/resources/Images/pizza.png b/src/main/resources/Images/pizza.png new file mode 100644 index 0000000000000000000000000000000000000000..a3e8efa0d4e59427bdc9fabe55f1453746896262 Binary files /dev/null and b/src/main/resources/Images/pizza.png differ diff --git a/src/main/resources/view/AddBudget.fxml b/src/main/resources/view/AddBudget.fxml index 96e52a73c5c6b258612b7e8a231dd91f8eb5d5fb..e2f1e248b7e200a5a99bce06650ecb46f6f93761 100644 --- a/src/main/resources/view/AddBudget.fxml +++ b/src/main/resources/view/AddBudget.fxml @@ -48,7 +48,7 @@ <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" spacing="15.0" GridPane.columnIndex="3" GridPane.rowIndex="1"> <children> <Button fx:id="cancelButton" mnemonicParsing="false" onAction="#closeButton" text="Cancel" /> - <Button fx:id="addButton" mnemonicParsing="false" onAction="#addBudget" text="Add New Budget" /> + <Button fx:id="okBtn" mnemonicParsing="false" onAction="#pressOkBtn" prefWidth="57.0" text="OK" /> </children> </HBox> </children> diff --git a/src/main/resources/view/Budget.fxml b/src/main/resources/view/Budget.fxml index 461014f8b2813ee9470742d01fcaef55932fa6b0..9b1f0cf23ba191c8a0b4dc9d0f92d13a64b50b07 100644 --- a/src/main/resources/view/Budget.fxml +++ b/src/main/resources/view/Budget.fxml @@ -35,9 +35,9 @@ <children> <HBox alignment="TOP_CENTER" prefHeight="98.0" prefWidth="600.0" spacing="40.0" GridPane.rowIndex="3"> <children> - <Button fx:id="addBudget" minHeight="60.0" minWidth="100.0" mnemonicParsing="false" onAction="#switchAddBudget" prefWidth="100.0" text="Add" /> - <Button fx:id="editBudget" minHeight="60.0" minWidth="100.0" mnemonicParsing="false" onAction="#switchAddBudget" prefWidth="100.0" text="Edit" /> - <Button fx:id="deleteBudget" minHeight="60.0" minWidth="100.0" mnemonicParsing="false" onAction="#deleteButton" prefWidth="100.0" text="Delete" /> + <Button fx:id="addBudget" minHeight="60.0" minWidth="100.0" mnemonicParsing="false" onAction="#handleEditButton" prefWidth="100.0" text="Add" /> + <Button fx:id="editBudget" minHeight="60.0" minWidth="100.0" mnemonicParsing="false" onAction="#handleEditButton" prefWidth="100.0" text="Edit" /> + <Button fx:id="deleteBudget" minHeight="60.0" minWidth="100.0" mnemonicParsing="false" onAction="#handleDeleteBtn" prefWidth="100.0" text="Delete" /> <Button minHeight="60.0" minWidth="100.0" mnemonicParsing="false" prefWidth="100.0" text="Save/Back" /> </children> </HBox> diff --git a/src/main/resources/view/BudgetNew.fxml b/src/main/resources/view/BudgetNew.fxml index 9cda09ce93bc33a044ecfe2a71fc3ff5e4e7edbd..c92fd969abd3faa625d300dd7bc2104fedb61cad 100644 --- a/src/main/resources/view/BudgetNew.fxml +++ b/src/main/resources/view/BudgetNew.fxml @@ -76,7 +76,7 @@ <children> <HBox alignment="BOTTOM_LEFT" prefWidth="410.0" spacing="5.0"> <children> - <Button fx:id="addBudget" alignment="TOP_CENTER" mnemonicParsing="false" onAction="#switchAddBudget" text="Add" textAlignment="CENTER"> + <Button fx:id="addBudget" alignment="TOP_CENTER" mnemonicParsing="false" onAction="#handleAddButton" text="Add" textAlignment="CENTER"> <graphic> <ImageView fitHeight="19.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true"> <image> @@ -85,7 +85,7 @@ </ImageView> </graphic> </Button> - <Button fx:id="editBudget" alignment="TOP_CENTER" mnemonicParsing="false" onAction="#switchAddBudget" text="Edit" textAlignment="CENTER"> + <Button fx:id="editBudget" alignment="TOP_CENTER" mnemonicParsing="false" onAction="#handleEditButton" text="Edit" textAlignment="CENTER"> <graphic> <ImageView fitHeight="19.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true"> <image> @@ -94,7 +94,7 @@ </ImageView> </graphic> </Button> - <Button fx:id="deleteBtn" alignment="TOP_CENTER" mnemonicParsing="false" onAction="#deleteButton" text="Delete" textAlignment="CENTER"> + <Button fx:id="deleteBtn" alignment="TOP_CENTER" mnemonicParsing="false" onAction="#handleDeleteBtn" text="Delete" textAlignment="CENTER"> <graphic> <ImageView fitHeight="19.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true"> <image> diff --git a/src/main/resources/view/BudgetNewest.fxml b/src/main/resources/view/BudgetNewest.fxml new file mode 100644 index 0000000000000000000000000000000000000000..4ec1bfc83b5b596f08919ec4024d25cb84daccf6 --- /dev/null +++ b/src/main/resources/view/BudgetNewest.fxml @@ -0,0 +1,191 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.Cursor?> +<?import javafx.scene.chart.PieChart?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.ComboBox?> +<?import javafx.scene.control.ContextMenu?> +<?import javafx.scene.control.DatePicker?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.MenuItem?> +<?import javafx.scene.control.TableColumn?> +<?import javafx.scene.control.TableView?> +<?import javafx.scene.image.Image?> +<?import javafx.scene.image.ImageView?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.ColumnConstraints?> +<?import javafx.scene.layout.GridPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.RowConstraints?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Font?> + +<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="695.0" prefWidth="1130.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="no.ntnu.idatt1002.demo.controller.BudgetController"> + <children> + <ImageView fitHeight="695.0" fitWidth="1130.0" pickOnBounds="true"> + <image> + <Image url="@../Images/backgroundMini.jpg" /> + </image> + <cursor> + <Cursor fx:constant="DEFAULT" /> + </cursor> + </ImageView> + <VBox prefHeight="695.0" prefWidth="1100.0"> + <children> + <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="143.0" prefWidth="1100.0"> + <right> + <Pane BorderPane.alignment="CENTER"> + <children> + <Label fx:id="daysLeftLbl" layoutX="27.0" layoutY="83.0" text="Days left: 31"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + <DatePicker fx:id="date" layoutX="-4.0" layoutY="55.0" prefWidth="175.0" /> + </children> + </Pane> + </right> + <left> + <Pane prefWidth="175.0" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="returnBtn" alignment="CENTER" layoutX="-2.0" layoutY="58.0" mnemonicParsing="false" onAction="#returnToMainMenu" text="Return to Main Menu"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Button> + </children> + </Pane> + </left> + <center> + <Label fx:id="title" text="Budget" textAlignment="CENTER" BorderPane.alignment="CENTER"> + <font> + <Font name="Lucida Console" size="48.0" /> + </font> + </Label> + </center> + <VBox.margin> + <Insets left="15.0" /> + </VBox.margin> + </BorderPane> + <BorderPane prefHeight="64.0" prefWidth="1100.0"> + <left> + <HBox prefHeight="100.0" prefWidth="200.0" spacing="10.0" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="addBtn" mnemonicParsing="false" onAction="#handleAddBtn" prefHeight="25.0" prefWidth="60.0"> + <font> + <Font name="Lucida Console" size="12.0" /> + </font> + <graphic> + <ImageView fitHeight="30.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../Images/add.png" /> + </image> + </ImageView> + </graphic> + </Button> + <Button fx:id="editBtn" mnemonicParsing="false" onAction="#handleEditBtn" prefHeight="25.0" prefWidth="60.0"> + <font> + <Font name="Lucida Console" size="12.0" /> + </font> + <graphic> + <ImageView fitHeight="30.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../Images/edit.png" /> + </image> + </ImageView> + </graphic> + </Button> + <Button fx:id="deleteBtn" mnemonicParsing="false" onAction="#handleDeleteBtn" prefHeight="25.0" prefWidth="60.0"> + <font> + <Font name="Lucida Console" size="12.0" /> + </font> + <graphic> + <ImageView fitHeight="30.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../Images/delete.png" /> + </image> + </ImageView> + </graphic> + </Button> + </children> + <BorderPane.margin> + <Insets left="30.0" /> + </BorderPane.margin> + </HBox> + </left> + <right> + <Pane BorderPane.alignment="CENTER" /> + </right> + <opaqueInsets> + <Insets /> + </opaqueInsets> + <VBox.margin> + <Insets left="10.0" right="15.0" /> + </VBox.margin> + <center> + <Pane BorderPane.alignment="CENTER"> + <children> + <ComboBox fx:id="filter" layoutX="134.0" layoutY="2.0" prefWidth="150.0" promptText="Show"> + <opaqueInsets> + <Insets /> + </opaqueInsets> + </ComboBox> + </children> + </Pane> + </center> + </BorderPane> + <GridPane prefHeight="473.0" prefWidth="1055.0"> + <columnConstraints> + <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> + <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> + </columnConstraints> + <rowConstraints> + <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> + </rowConstraints> + <children> + <VBox prefHeight="475.0" prefWidth="485.0"> + <children> + <TableView fx:id="budgetTableView" maxHeight="450.0" prefHeight="450.0" prefWidth="523.0"> + <columns> + <TableColumn fx:id="categoryCol" prefWidth="75.0" text="Category" /> + <TableColumn fx:id="amountCol" prefWidth="75.0" text="Amount" /> + <TableColumn fx:id="descriptionCol" prefWidth="75.0" text="Description" /> + </columns> + <columnResizePolicy> + <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> + </columnResizePolicy> + <contextMenu> + <ContextMenu> + <items> + <MenuItem mnemonicParsing="false" text="Unspecified Action" /> + </items> + </ContextMenu> + </contextMenu> + </TableView> + <Label text="Sum: "> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + </children> + </VBox> + <Pane GridPane.columnIndex="1"> + <children> + <PieChart fx:id="budgetPieChart" layoutX="39.0" layoutY="5.0" legendSide="RIGHT" maxHeight="444.0" maxWidth="512.0" prefHeight="444.0" prefWidth="446.0" /> + </children> + </Pane> + </children> + <padding> + <Insets left="10.0" /> + </padding> + <VBox.margin> + <Insets left="30.0" right="30.0" /> + </VBox.margin> + </GridPane> + </children> + </VBox> + </children> +</AnchorPane> diff --git a/src/main/resources/view/Expenses.fxml b/src/main/resources/view/Expenses.fxml deleted file mode 100644 index 0311ce16a0f244f8d9f857479060df084e45edcb..0000000000000000000000000000000000000000 --- a/src/main/resources/view/Expenses.fxml +++ /dev/null @@ -1,188 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<?import javafx.geometry.Insets?> -<?import javafx.scene.Cursor?> -<?import javafx.scene.control.Button?> -<?import javafx.scene.control.ComboBox?> -<?import javafx.scene.control.TableColumn?> -<?import javafx.scene.control.TableView?> -<?import javafx.scene.image.Image?> -<?import javafx.scene.image.ImageView?> -<?import javafx.scene.layout.AnchorPane?> -<?import javafx.scene.layout.BorderPane?> -<?import javafx.scene.layout.ColumnConstraints?> -<?import javafx.scene.layout.GridPane?> -<?import javafx.scene.layout.HBox?> -<?import javafx.scene.layout.Region?> -<?import javafx.scene.layout.RowConstraints?> -<?import javafx.scene.layout.StackPane?> -<?import javafx.scene.layout.VBox?> -<?import javafx.scene.shape.Rectangle?> -<?import javafx.scene.text.Font?> -<?import javafx.scene.text.Text?> - -<AnchorPane xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="no.ntnu.idatt1002.demo.controller.ExpensesController"> - <children> - <ImageView fitHeight="400.0" fitWidth="600.0" pickOnBounds="true"> - <image> - <Image url="@../Images/backgroundMini.jpg" /> - </image> - <cursor> - <Cursor fx:constant="DEFAULT" /> - </cursor> - </ImageView> - <BorderPane prefHeight="400.0" prefWidth="600.0"> - <top> - <HBox BorderPane.alignment="CENTER"> - <children> - <Button fx:id="returnBtn" mnemonicParsing="false" onAction="#switchScene" text="Return "> - <opaqueInsets> - <Insets left="100.0" /> - </opaqueInsets> - <HBox.margin> - <Insets left="10.0" top="10.0" /> - </HBox.margin> - </Button> - <Region prefHeight="70.0" prefWidth="141.0" /> - <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Expenses" textAlignment="CENTER"> - <HBox.margin> - <Insets /> - </HBox.margin> - <font> - <Font size="48.0" /> - </font> - </Text> - </children> - <opaqueInsets> - <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> - </opaqueInsets> - </HBox> - </top> - <center> - <GridPane BorderPane.alignment="CENTER"> - <BorderPane.margin> - <Insets bottom="40.0" left="40.0" right="40.0" /> - </BorderPane.margin> - <columnConstraints> - <ColumnConstraints hgrow="ALWAYS" maxWidth="485.3333231608073" minWidth="10.0" prefWidth="427.33335367838544" /> - <ColumnConstraints hgrow="ALWAYS" maxWidth="111.33333333333331" minWidth="10.0" prefWidth="92.66664632161456" /> - </columnConstraints> - <rowConstraints> - <RowConstraints maxHeight="65.33334064483643" minHeight="10.0" prefHeight="65.33334064483643" vgrow="SOMETIMES" /> - <RowConstraints maxHeight="298.66665744781494" minHeight="10.0" prefHeight="214.00004069010413" vgrow="SOMETIMES" /> - <RowConstraints maxHeight="298.66665744781494" minHeight="10.0" prefHeight="29.999959309895814" vgrow="SOMETIMES" /> - <RowConstraints maxHeight="298.66665744781494" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> - </rowConstraints> - <children> - <HBox alignment="BOTTOM_LEFT" prefWidth="410.0" spacing="5.0"> - <children> - <Button fx:id="addBtn" alignment="TOP_CENTER" mnemonicParsing="false" onAction="#handleAddButton" text="Add" textAlignment="CENTER"> - <graphic> - <ImageView fitHeight="19.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true"> - <image> - <Image url="@../Images/add_image.png" /> - </image> - </ImageView> - </graphic></Button> - <Button fx:id="editBtn" alignment="TOP_CENTER" mnemonicParsing="false" onAction="#handleEditButton" text="Edit" textAlignment="CENTER"> - <graphic> - <ImageView fitHeight="19.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true"> - <image> - <Image url="@../Images/edit.png" /> - </image> - </ImageView> - </graphic></Button> - <Button fx:id="deleteBtn" alignment="TOP_CENTER" mnemonicParsing="false" onAction="#handleDeleteBtn" text="Delete" textAlignment="CENTER"> - <graphic> - <ImageView fitHeight="19.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true"> - <image> - <Image url="@../Images/delete.png" /> - </image> - </ImageView> - </graphic></Button> - </children> - <opaqueInsets> - <Insets /> - </opaqueInsets> - <padding> - <Insets bottom="5.0" /> - </padding> - </HBox> - <VBox alignment="BOTTOM_LEFT" prefHeight="200.0" prefWidth="100.0" spacing="5.0" GridPane.columnIndex="1"> - <children> - <ComboBox fx:id="show" prefWidth="150.0" promptText="Show"> - <opaqueInsets> - <Insets /> - </opaqueInsets> - <VBox.margin> - <Insets bottom="5.0" /> - </VBox.margin> - </ComboBox> - </children> - </VBox> - <HBox prefHeight="100.0" prefWidth="200.0" GridPane.columnSpan="2" GridPane.rowIndex="3"> - <children> - <Button fx:id="incomeBtn" mnemonicParsing="false" onAction="#switchScene" text="Income" /> - <Button fx:id="budgetBtn" mnemonicParsing="false" onAction="#switchScene" text="Budget" /> - <Button disable="true" mnemonicParsing="false" text="Expenses" /> - <Button mnemonicParsing="false" onAction="#switchScene" text="Next"> - <HBox.margin> - <Insets left="170.0" /> - </HBox.margin></Button> - </children> - <padding> - <Insets top="10.0" /> - </padding> - <GridPane.margin> - <Insets top="5.0" /> - </GridPane.margin> - </HBox> - <TableView fx:id="expenseTableView" prefHeight="260.0" prefWidth="485.0" GridPane.columnSpan="2" GridPane.rowIndex="1"> - <columns> - <TableColumn fx:id="dateColumn" prefWidth="75.0" text="Date" /> - <TableColumn fx:id="amountColumn" prefWidth="75.0" text="Amount" /> - <TableColumn fx:id="categoryColumn" prefWidth="75.0" text="Category" /> - <TableColumn fx:id="descriptionColumn" prefWidth="75.0" text="Description" /> - <TableColumn fx:id="recurringColumn" prefWidth="75.0" text="Recurring" /> - </columns> - <columnResizePolicy> - <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> - </columnResizePolicy> - </TableView> - <StackPane GridPane.rowIndex="2"> - <children> - <Rectangle arcHeight="5.0" arcWidth="5.0" fill="#f8f8f8" height="18.0" stroke="#d9cccc" strokeType="INSIDE" width="209.0" StackPane.alignment="CENTER_LEFT" /> - <HBox prefHeight="18.0" prefWidth="517.0"> - <children> - <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Sum: "> - <HBox.margin> - <Insets left="2.0" /> - </HBox.margin> - </Text> - <Region prefHeight="18.0" prefWidth="74.0" /> - <Text fx:id="sum" strokeType="OUTSIDE" strokeWidth="0.0" text="Text" /> - </children> - </HBox> - </children> - </StackPane> - </children> - </GridPane> - </center> - <opaqueInsets> - <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> - </opaqueInsets> - <left> - <Region prefHeight="330.0" prefWidth="1.0" BorderPane.alignment="CENTER" /> - </left> - <right> - <Region prefHeight="357.0" prefWidth="0.0" BorderPane.alignment="CENTER" /> - </right> - <bottom> - <Region prefHeight="0.0" prefWidth="600.0" BorderPane.alignment="CENTER" /> - </bottom> - </BorderPane> - </children> - <opaqueInsets> - <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> - </opaqueInsets> -</AnchorPane> diff --git a/src/main/resources/view/IncomeAndExpenses.fxml b/src/main/resources/view/IncomeAndExpenses.fxml new file mode 100644 index 0000000000000000000000000000000000000000..0680964f6247787cf8fef0e141b544fe53ed596a --- /dev/null +++ b/src/main/resources/view/IncomeAndExpenses.fxml @@ -0,0 +1,255 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.Cursor?> +<?import javafx.scene.chart.PieChart?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.ComboBox?> +<?import javafx.scene.control.ContextMenu?> +<?import javafx.scene.control.DatePicker?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.MenuButton?> +<?import javafx.scene.control.MenuItem?> +<?import javafx.scene.control.ProgressBar?> +<?import javafx.scene.control.TableColumn?> +<?import javafx.scene.control.TableView?> +<?import javafx.scene.image.Image?> +<?import javafx.scene.image.ImageView?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.ColumnConstraints?> +<?import javafx.scene.layout.GridPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.RowConstraints?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Font?> +<?import javafx.scene.text.Text?> + +<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="695.0" prefWidth="1130.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="no.ntnu.idatt1002.demo.controller.IncomeExpenseController"> + <children> + <ImageView fitHeight="695.0" fitWidth="1130.0" pickOnBounds="true"> + <image> + <Image url="@../Images/backgroundMini.jpg" /> + </image> + <cursor> + <Cursor fx:constant="DEFAULT" /> + </cursor> + </ImageView> + <VBox prefHeight="695.0" prefWidth="1100.0"> + <children> + <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="143.0" prefWidth="1100.0"> + <right> + <Pane BorderPane.alignment="CENTER"> + <children> + <Label fx:id="daysLeftLbl" layoutX="27.0" layoutY="83.0" text="Days left: 31"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + <DatePicker fx:id="date" layoutX="-4.0" layoutY="55.0" prefWidth="175.0" /> + </children> + </Pane> + </right> + <left> + <Pane prefWidth="175.0" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="returnBtn" alignment="CENTER" layoutX="-2.0" layoutY="58.0" mnemonicParsing="false" onAction="#returnToMainMenu" text="Return to Main Menu"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Button> + </children> + </Pane> + </left> + <center> + <Label fx:id="title" text="INCOME AND EXPENSES" textAlignment="CENTER" BorderPane.alignment="CENTER"> + <font> + <Font name="Lucida Console" size="48.0" /> + </font> + </Label> + </center> + <VBox.margin> + <Insets left="15.0" /> + </VBox.margin> + </BorderPane> + <BorderPane prefHeight="64.0" prefWidth="1100.0"> + <left> + <HBox prefHeight="100.0" prefWidth="200.0" spacing="10.0" BorderPane.alignment="CENTER"> + <children> + <MenuButton mnemonicParsing="false" prefHeight="25.0" prefWidth="50.0"> + <items> + <MenuItem fx:id="addIncome" mnemonicParsing="false" onAction="#handleAddBtn" text="Income" /> + <MenuItem fx:id="addExpense" mnemonicParsing="false" onAction="#handleAddBtn" text="Expense" /> + </items> + <graphic> + <ImageView fitHeight="30.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../Images/add.png" /> + </image> + </ImageView> + </graphic> + </MenuButton> + <Button fx:id="editBtn" mnemonicParsing="false" onAction="#handleEditBtn" prefHeight="25.0" prefWidth="60.0"> + <font> + <Font name="Lucida Console" size="12.0" /> + </font> + <graphic> + <ImageView fitHeight="30.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../Images/edit.png" /> + </image> + </ImageView> + </graphic> + </Button> + <Button fx:id="deleteBtn" mnemonicParsing="false" onAction="#handleDeleteBtn" prefHeight="25.0" prefWidth="60.0"> + <font> + <Font name="Lucida Console" size="12.0" /> + </font> + <graphic> + <ImageView fitHeight="30.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../Images/delete.png" /> + </image> + </ImageView> + </graphic> + </Button> + </children> + <BorderPane.margin> + <Insets left="30.0" /> + </BorderPane.margin> + </HBox> + </left> + <right> + <Pane BorderPane.alignment="CENTER"> + <children> + <ProgressBar fx:id="budgetProgress" prefWidth="200.0" progress="0.0" /> + </children> + </Pane> + </right> + <opaqueInsets> + <Insets /> + </opaqueInsets> + <VBox.margin> + <Insets left="10.0" right="15.0" /> + </VBox.margin> + <center> + <Pane BorderPane.alignment="CENTER"> + <children> + <ComboBox fx:id="filter" layoutX="134.0" layoutY="2.0" prefWidth="150.0" promptText="Show"> + <opaqueInsets> + <Insets /> + </opaqueInsets> + </ComboBox> + </children> + </Pane> + </center> + </BorderPane> + <GridPane prefHeight="473.0" prefWidth="1055.0"> + <columnConstraints> + <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> + <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> + </columnConstraints> + <rowConstraints> + <RowConstraints minHeight="10.0" percentHeight="5.0" prefHeight="30.0" vgrow="SOMETIMES" /> + <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> + <RowConstraints minHeight="10.0" percentHeight="4.0" prefHeight="30.0" vgrow="SOMETIMES" /> + <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> + </rowConstraints> + <children> + <VBox maxWidth="490.0" prefHeight="215.0" prefWidth="490.0" GridPane.rowIndex="1"> + <children> + <TableView fx:id="incomeTableView" maxHeight="175.0" prefHeight="175.0" prefWidth="264.0"> + <columns> + <TableColumn fx:id="inDateCol" prefWidth="75.0" text="Date" /> + <TableColumn fx:id="inAmountCol" prefWidth="75.0" text="Amount" /> + <TableColumn fx:id="inCategoryCol" prefWidth="75.0" text="Category" /> + <TableColumn fx:id="inDescriptionCol" prefWidth="75.0" text="Description" /> + <TableColumn fx:id="inRecurringCol" prefWidth="75.0" text="Recurring" /> + </columns> + <columnResizePolicy> + <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> + </columnResizePolicy> + <contextMenu> + <ContextMenu> + <items> + <MenuItem mnemonicParsing="false" text="Unspecified Action" /> + </items> + </ContextMenu> + </contextMenu> + </TableView> + <Label text="Sum: "> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + </children> + </VBox> + <Pane GridPane.columnIndex="1" GridPane.rowIndex="1"> + <children> + <PieChart fx:id="incomePieChart" layoutX="4.0" layoutY="-41.0" legendSide="RIGHT" maxHeight="244.0" maxWidth="512.0" prefHeight="244.0" prefWidth="350.0" title="Income" /> + </children> + </Pane> + <Pane GridPane.columnIndex="1" GridPane.rowIndex="3"> + <children> + <PieChart fx:id="expensePieChart" layoutX="-2.0" layoutY="-37.0" legendSide="RIGHT" maxHeight="261.0" maxWidth="519.0" prefHeight="237.0" prefWidth="350.0" title="Expenses" /> + </children> + </Pane> + <Pane prefHeight="20.0" prefWidth="1046.0"> + <children> + <Text layoutY="16.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Income" textAlignment="CENTER"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Text> + </children> + </Pane> + <VBox GridPane.rowIndex="3"> + <children> + <TableView fx:id="expenseTableView" maxHeight="175.0" maxWidth="490.0" prefHeight="172.0" prefWidth="264.0"> + <columns> + <TableColumn fx:id="expDateCol" prefWidth="75.0" text="Date" /> + <TableColumn fx:id="expAmountCol" prefWidth="75.0" text="Amount" /> + <TableColumn fx:id="expCategoryCol" prefWidth="75.0" text="Category" /> + <TableColumn fx:id="expDescriptionCol" prefWidth="75.0" text="Description" /> + <TableColumn fx:id="expRecurringCol" prefWidth="75.0" text="Recurring" /> + </columns> + <columnResizePolicy> + <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" /> + </columnResizePolicy> + <contextMenu> + <ContextMenu> + <items> + <MenuItem mnemonicParsing="false" text="Unspecified Action" /> + </items> + </ContextMenu> + </contextMenu> + </TableView> + <Label text="Sum: "> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + </children> + </VBox> + <Pane prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2"> + <children> + <Text layoutY="14.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Expenses" textAlignment="CENTER"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Text> + </children> + </Pane> + </children> + <padding> + <Insets left="10.0" /> + </padding> + <VBox.margin> + <Insets left="30.0" right="30.0" /> + </VBox.margin> + </GridPane> + </children> + </VBox> + </children> +</AnchorPane> diff --git a/src/main/resources/view/MainMenuNew.fxml b/src/main/resources/view/MainMenuNew.fxml new file mode 100644 index 0000000000000000000000000000000000000000..bf3e93837c42caf2898f69d64926f13043b88507 --- /dev/null +++ b/src/main/resources/view/MainMenuNew.fxml @@ -0,0 +1,245 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.DatePicker?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ProgressBar?> +<?import javafx.scene.image.Image?> +<?import javafx.scene.image.ImageView?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.ColumnConstraints?> +<?import javafx.scene.layout.GridPane?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.RowConstraints?> +<?import javafx.scene.layout.StackPane?> +<?import javafx.scene.layout.TilePane?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Font?> + + +<AnchorPane fx:id="root" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="no.ntnu.idatt1002.demo.controller.MainMenu"> + <children> + <ImageView fitHeight="719.0" fitWidth="1130.0" layoutY="-3.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../Images/backgroundMini.jpg" /> + </image> + </ImageView> + <VBox alignment="TOP_CENTER" prefHeight="695.0" prefWidth="1100.0"> + <children> + <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="164.0" prefWidth="1100.0"> + <left> + <Pane prefWidth="175.0" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="returnBtn" alignment="CENTER" layoutX="-2.0" layoutY="58.0" mnemonicParsing="false" onAction="#switchScene" text="Return to start"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Button> + </children> + </Pane> + </left> + <center> + <Label fx:id="title" text="BUDGET JANUARY" textAlignment="CENTER" BorderPane.alignment="CENTER"> + <font> + <Font name="Lucida Console" size="48.0" /> + </font> + </Label> + </center> + <right> + <Pane BorderPane.alignment="CENTER"> + <children> + <Label fx:id="daysLeftLbl" layoutX="27.0" layoutY="83.0" text="Days left: 31"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + <DatePicker fx:id="date" layoutX="-4.0" layoutY="55.0" prefWidth="175.0" /> + </children> + </Pane> + </right> + <VBox.margin> + <Insets left="15.0" right="15.0" /> + </VBox.margin> + <bottom> + <Label fx:id="balanceLbl" text="Balance: xxx" BorderPane.alignment="CENTER"> + <font> + <Font name="Lucida Console" size="24.0" /> + </font> + </Label> + </bottom> + </BorderPane> + <BorderPane prefHeight="403.0" prefWidth="1131.0"> + <top> + <StackPane BorderPane.alignment="CENTER"> + <children> + <ProgressBar fx:id="mainBar" prefHeight="35.0" prefWidth="750.0" progress="0.54"> + <StackPane.margin> + <Insets top="5.0" /> + </StackPane.margin> + </ProgressBar> + <Label fx:id="usageLbl" text="You have used xxx out of xxx this month"> + <font> + <Font name="Lucida Console" size="12.0" /> + </font> + <StackPane.margin> + <Insets top="5.0" /> + </StackPane.margin> + </Label> + </children> + </StackPane> + </top> + <center> + <GridPane maxWidth="750.0" minHeight="250.0" minWidth="750.0" prefHeight="300.0" prefWidth="750.0" BorderPane.alignment="CENTER"> + <columnConstraints> + <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="25.0" prefWidth="100.0" /> + <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="50.0" prefWidth="100.0" /> + <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="25.0" prefWidth="100.0" /> + </columnConstraints> + <rowConstraints> + <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> + <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> + <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> + <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> + </rowConstraints> + <children> + <ProgressBar fx:id="foodBar" prefHeight="25.0" prefWidth="375.0" progress="0.37" GridPane.columnIndex="1" /> + <ProgressBar fx:id="otherBar" prefHeight="25.0" prefWidth="375.0" progress="0.46" GridPane.columnIndex="1" GridPane.rowIndex="3" /> + <ProgressBar fx:id="bookBar" prefHeight="25.0" prefWidth="375.0" progress="0.19" GridPane.columnIndex="1" GridPane.rowIndex="2" /> + <ProgressBar fx:id="clothesBar" prefHeight="25.0" prefWidth="375.0" progress="0.76" GridPane.columnIndex="1" GridPane.rowIndex="1" /> + <Pane> + <children> + <Label fx:id="foodLbl" alignment="CENTER_RIGHT" layoutX="78.0" layoutY="38.0" text="Food"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + </children> + </Pane> + <Pane GridPane.rowIndex="3"> + <children> + <Label fx:id="otherLbl" alignment="CENTER_RIGHT" layoutX="68.0" layoutY="39.0" text="Other "> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + </children> + </Pane> + <Pane GridPane.rowIndex="2"> + <children> + <Label fx:id="bookLbl" alignment="CENTER_RIGHT" layoutX="68.0" layoutY="36.0" text="Books "> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + </children> + </Pane> + <Pane GridPane.rowIndex="1"> + <children> + <Label fx:id="clothesLbl" alignment="CENTER_RIGHT" layoutX="65.0" layoutY="38.0" text="Clothes"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + </children> + </Pane> + <Pane GridPane.columnIndex="2"> + <children> + <Label alignment="CENTER_RIGHT" layoutX="58.0" layoutY="37.0" text="Left: 50"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + </children> + </Pane> + <Pane GridPane.columnIndex="2" GridPane.rowIndex="3"> + <children> + <Label alignment="CENTER_RIGHT" layoutX="60.0" layoutY="36.0" text="Left: 200"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + </children> + </Pane> + <Pane GridPane.columnIndex="2" GridPane.rowIndex="2"> + <children> + <Label alignment="CENTER_RIGHT" layoutX="59.0" layoutY="38.0" text="Left: 150"> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + </children> + </Pane> + <Pane GridPane.columnIndex="2" GridPane.rowIndex="1"> + <children> + <Label alignment="CENTER_RIGHT" layoutX="53.0" layoutY="38.0" text="Left: 60 "> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Label> + </children> + </Pane> + </children> + <BorderPane.margin> + <Insets top="30.0" /> + </BorderPane.margin> + </GridPane> + </center> + </BorderPane> + <TilePane alignment="CENTER" hgap="50.0" prefHeight="215.0" prefWidth="1131.0"> + <children> + <Button fx:id="foodBtn" alignment="TOP_CENTER" contentDisplay="TOP" mnemonicParsing="false" prefHeight="100.0" prefWidth="150.0" text="Food"> + <graphic> + <ImageView fitHeight="75.0" fitWidth="75.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../Images/pizza.png" /> + </image> + </ImageView> + </graphic> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Button> + <Button fx:id="expenseBtn" contentDisplay="TOP" mnemonicParsing="false" onAction="#switchScene" prefHeight="100.0" prefWidth="150.0" text="View expenses"> + <graphic> + <ImageView fitHeight="75.0" fitWidth="75.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../Images/expense.png" /> + </image> + </ImageView> + </graphic> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Button> + <Button fx:id="incomeBtn" alignment="TOP_CENTER" contentDisplay="TOP" mnemonicParsing="false" onAction="#switchScene" prefHeight="100.0" prefWidth="150.0" text="View income"> + <graphic> + <ImageView fitHeight="75.0" fitWidth="75.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../Images/income.png" /> + </image> + </ImageView> + </graphic> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Button> + <Button fx:id="budgetBtn" contentDisplay="TOP" mnemonicParsing="false" onAction="#switchScene" prefHeight="100.0" prefWidth="150.0" text="View budget"> + <graphic> + <ImageView fitHeight="75.0" fitWidth="75.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../Images/budget.png" /> + </image> + </ImageView> + </graphic> + <font> + <Font name="Lucida Console" size="14.0" /> + </font> + </Button> + </children> + </TilePane> + </children> + </VBox> + </children> +</AnchorPane>