Skip to content
Snippets Groups Projects
Commit 231cf319 authored by Harry Linrui XU's avatar Harry Linrui XU
Browse files

Attempted to make expense and income the same class. Made new dialog box for...

Attempted to make expense and income the same class. Made new dialog box for income. Made new enum to distinguish between incoem and expense
parent 25f5f3d2
No related branches found
No related tags found
10 merge requests!43Merging frontend-testing into master,!38"Made progressbar dynamic in accordance to spending. Added balance field....,!37Made the sub progress bars respond to changes in expense,!32Added input validation to add dialog boxes.,!30Redesigned scenes,!29Redesigned scenes,!28Redesigned scenes,!26Redesigned Main menu and expense/income windows,!24Merging frontend-testing with master,!23Merging frontend-testing and master
......@@ -17,10 +17,18 @@ 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;
public class AddExpenseController {
Expense newExpense = null; //the expense that is chosen when editing or the expense that is created when adding
Expense chosenExpense = null; //an expense that is meant to track the old state of an expense before editing, in case cancel bugtton is clicked
Income newIncome = null;
Income chosenIncome = null;
private ItemMode itemMode;
@FXML
private Button cancelBtn;
......@@ -55,9 +63,6 @@ public class AddExpenseController {
ObservableList<Boolean> recurring = FXCollections.observableArrayList(true, false);
recurringBox.setItems(recurring);
recurringBox.setValue(false);
System.out.print("This is in initialize");
System.out.println(descriptionField);
}
public ExpenseCategory getCategory() {
......@@ -79,7 +84,6 @@ public class AddExpenseController {
amountField.textProperty().setValue(String.valueOf(expense.getAmount()));
recurringBox.setValue(expense.isRecurring());
//new SimpleStringProperty(datePicker.getValue().toString()).bindBidirectional(new SimpleStringProperty(expense.getDate().toString()));
//Bind this expense's fields with the argument object's fields. If cancel is pressed - do nothing. If ok is pressed, bind the textfields with this expsense
......
package no.ntnu.idatt1002.demo.controller;
import java.text.NumberFormat;
import java.time.LocalDate;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import no.ntnu.idatt1002.demo.data.Economics.Expense;
import no.ntnu.idatt1002.demo.data.Economics.Income;
import no.ntnu.idatt1002.demo.data.Economics.IncomeCategory;
public class AddIncomeController {
Income newIncome = null;
Income chosenIncome = null;
private ItemMode itemMode;
@FXML
private Button cancelBtn;
@FXML
private Button okBtn;
@FXML
private TextField dateField;
@FXML
private DatePicker datePicker;
@FXML
private TextField descriptionField;
@FXML
private TextField amountField;
@FXML
private ComboBox<IncomeCategory> categoryBox;
@FXML
private ComboBox<Boolean> recurringBox;
@FXML
public void initialize() {
ObservableList<IncomeCategory> incomeCategories = FXCollections.observableArrayList(
IncomeCategory.values());
categoryBox.setItems(incomeCategories);
categoryBox.setValue(IncomeCategory.GIFT);
ObservableList<Boolean> recurring = FXCollections.observableArrayList(true, false);
recurringBox.setItems(recurring);
recurringBox.setValue(false);
}
public IncomeCategory getCategory() {
return categoryBox.getValue();
}
public boolean isRecurring() {
return recurringBox.getValue();//.equals("Yes");
}
public void setIncome(Income income) { //TODO NEED CANCEL BUTTON TO REMOVE THE CHANGES IF CANCEL IS PRESSED
chosenIncome = new Income(income.getDescription(), income.getAmount(), income.isRecurring(), income.getCategory(), income.getDate());
chosenIncome.descriptionProperty().bindBidirectional(income.descriptionProperty());
chosenIncome.amountProperty().bindBidirectional(income.amountProperty());
chosenIncome.recurringProperty().bindBidirectional(income.recurringProperty());
//chosenExpense.().bindBidirectional(income.descriptionProperty());
//chosenExpense.().bindBidirectional(income.descriptionProperty());
descriptionField.textProperty().set(income.getDescription());
amountField.textProperty().setValue(String.valueOf(income.getAmount()));
recurringBox.setValue(income.isRecurring());
//new SimpleStringProperty(datePicker.getValue().toString()).bindBidirectional(new SimpleStringProperty(income.getDate().toString()));
//Bind this income's fields with the argument object's fields. If cancel is pressed - do nothing. If ok is pressed, bind the textfields with this expsense
/*amountField.textProperty().bindBidirectional(income.amountProperty(), NumberFormat.getNumberInstance()); //TODO AMOUNT IS STORED WITH COMMA, WHICH IS NOT ALLOWED
descriptionField.textProperty().bindBidirectional(income.descriptionProperty());
//categoryBox.valueProperty().bindBidirectional(income.getCategory());
recurringBox.valueProperty().bindBidirectional(income.recurringProperty());*/
}
@FXML
public void pressOkBtn(ActionEvent event) {
if (chosenIncome == null) {
LocalDate date = datePicker.getValue();
double amount = Double.parseDouble(amountField.getText());
String description = descriptionField.getText();
IncomeCategory category = getCategory();
boolean recurring = isRecurring();
newIncome = new Income(description, amount, recurring, category, date);
}
if (chosenIncome != null) {
chosenIncome.setDescription((descriptionField.getText()));
chosenIncome.setAmount(Double.parseDouble(amountField.getText()));
chosenIncome.setRecurring(recurringBox.getValue());
}
final Node source = (Node) event.getSource();
((Stage) source.getScene().getWindow()).close();
}
@FXML
public void pressCancelBtn(ActionEvent event) {
final Node source = (Node) event.getSource();
final Stage stage = (Stage) source.getScene().getWindow();
stage.close();
}
public Income getNewIncome() {
return this.chosenIncome;
}
}
\ No newline at end of file
package no.ntnu.idatt1002.demo.controller;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.Month;
import java.util.Optional;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
......@@ -22,7 +19,6 @@ import javafx.scene.control.ComboBox;
import javafx.scene.control.Dialog;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Modality;
import javafx.stage.Stage;
......@@ -32,17 +28,25 @@ 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.IncomeRegister;
import no.ntnu.idatt1002.demo.data.Economics.Item;
import no.ntnu.idatt1002.demo.data.Economics.ItemRegister;
enum DialogMode {
ADD, EDIT, DELETE
}
enum ItemMode {
INCOME, EXPENSE
}
public class ExpensesController {
/**
* The mode of the dialog. NEW if new contact, EDIT if edit existing contact.
*/
private DialogMode mode;
private DialogMode dialogMode;
private ItemMode itemMode;
@FXML
private Button addBtn;
@FXML
......@@ -81,47 +85,40 @@ public class ExpensesController {
private TableView<Expense> expenseTableView;
@FXML
private TableView<Expense> incomeTableView;
private TableView<Income> incomeTableView;
ExpenseRegister expenseRegister;
ObservableList<Expense> expenses;
ObservableList<String> filter;
//ItemRegister itemRegister;
IncomeRegister incomeRegister;
ObservableList<Income> income;
@FXML
public void initialize() throws IOException { //TODO SAME REGISTER FOR BOTH, BUT LOAD DIFFERENT DATA DEPENDING ON WHICH IT IS
if (expenseTableView.getColumns() != null) {
ObservableList<String> filter = FXCollections.observableArrayList("All", "Food", "Clothes", "Books", "Other", "Fixed expense");
show.setItems(filter);
show.setValue("All");
expenseRegister = loadDataFromFile("Expense");
expenses = FXCollections.observableArrayList(expenseRegister.getItems());
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"));
expenseTableView.setItems(expenses);
} else {
ObservableList<String> filter = FXCollections.observableArrayList("All", "Salary", "Student loan", "Gift", "Fixed expense");
show.setItems(filter);
show.setValue("All");
expenseRegister = loadDataFromFile("Income");
if (expenseTableView != null) {
itemMode = ItemMode.EXPENSE;
filter = FXCollections.observableArrayList("All", "Food", "Clothes", "Books", "Other", "Fixed expense");
expenseRegister = loadExpenseDataFromFile("Expense");
expenses = FXCollections.observableArrayList(expenseRegister.getItems());
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"));
expenseTableView.setItems(expenses);
} else {
itemMode = ItemMode.INCOME;
filter = FXCollections.observableArrayList("All", "Salary", "Student loan", "Gift", "Fixed expense");
incomeRegister = loadIncomeDataFromFile("Income");
income = FXCollections.observableArrayList(incomeRegister.getItems());
incomeTableView.setItems(income);
}
show.setItems(filter);
show.setValue("All");
}
@FXML
......@@ -130,10 +127,16 @@ public class ExpensesController {
}
@FXML
protected void handleEditButton(ActionEvent event) {
FXMLLoader loader = new FXMLLoader();
if (itemMode == ItemMode.EXPENSE) {
loader.setLocation(getClass().getResource("/view/AddExpense.fxml"));
} else {
loader.setLocation(getClass().getResource("/view/AddIncome.fxml"));
}
Expense newExpense = null;
Income newIncome = null;
String dialogTitle = "";
// Load the FXML file for your dialog box
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/AddExpense.fxml"));
Dialog<Expense> dialog = new Dialog<>();
dialog.initModality(Modality.APPLICATION_MODAL);
......@@ -146,51 +149,88 @@ public class ExpensesController {
// Get the controller for the loaded FXML file
AddExpenseController dialogController = loader.getController();
AddIncomeController dialogController1 = loader.getController();
if (event.getSource().equals(addBtn)) {
mode = DialogMode.ADD;
dialogTitle = "Add expense";
if (itemMode == ItemMode.EXPENSE) {
if (event.getSource().equals(addBtn)) {
dialogMode = DialogMode.ADD;
dialogTitle = "Add expense";
} else if (event.getSource().equals(editBtn) && expenseTableView.getSelectionModel().getSelectedItem() != null) {
mode = DialogMode.EDIT;
dialogTitle = "Edit expense";
newExpense = expenseTableView.getSelectionModel().getSelectedItem();
dialogController.setExpense(newExpense);
dialogMode = DialogMode.EDIT;
dialogTitle = "Edit expense";
newExpense = expenseTableView.getSelectionModel().getSelectedItem();
dialogController.setExpense(newExpense);
} else {
return;
}
} else {
return;
if (event.getSource().equals(addBtn)) {
dialogMode = DialogMode.ADD;
dialogTitle = "Income";
} else if (event.getSource().equals(editBtn) && incomeTableView.getSelectionModel().getSelectedItem() != null) {
dialogMode = DialogMode.EDIT;
dialogTitle = "Edit income";
newIncome = incomeTableView.getSelectionModel().getSelectedItem();
dialogController1.setIncome(newIncome); //TODO NEED TO FXI THIS TO INCOME
} else {
return;
}
}
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();
//Only add the expense to the tableview, if the expense is not null
if (newExpense != null && mode == DialogMode.ADD) {
expenseRegister.addItem(newExpense);
refreshObservableList();
if (itemMode == ItemMode.EXPENSE) {
newExpense = dialogController.getNewExpense();
if (newExpense != null && dialogMode == DialogMode.ADD) {
expenseRegister.addItem(newExpense);
refreshObservableList();
}
} else {
newIncome = dialogController1.getNewIncome(); //TODO NEED TO FIX to newIncome
if (newIncome != null && dialogMode == DialogMode.ADD) { //TODO NEED TO FIX TO NEW INCOME
incomeRegister.addItem(newIncome); //TODO NEED TO FIX TO NEW INCOME
refreshObservableList();
}
}
//Only add the expense to the tableview, if the expense is not null
}
@FXML
public void handleDeleteBtn(ActionEvent event) {
Expense chosenExpense = expenseTableView.getSelectionModel().getSelectedItem();
if (chosenExpense == null) {
return;
}
Optional<ButtonType> isConfirmed = showConfirmationDialog();
if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) {
expenseRegister.removeItem(chosenExpense);
refreshObservableList();
if (itemMode == ItemMode.EXPENSE) {
Expense chosenExpense = expenseTableView.getSelectionModel().getSelectedItem();
if (chosenExpense == null) {
return;
}
Optional<ButtonType> isConfirmed = showConfirmationDialog();
if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) {
expenseRegister.removeItem(chosenExpense);
refreshObservableList();
}
} else {
Income chosenIncome = incomeTableView.getSelectionModel().getSelectedItem();
if (chosenIncome == null) {
return;
}
Optional<ButtonType> isConfirmed = showConfirmationDialog();
if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) {
incomeRegister.removeItem(chosenIncome);
refreshObservableList();
}
}
}
protected void refreshObservableList() {
this.expenses.setAll(expenseRegister.getItems());
if (itemMode == ItemMode.EXPENSE) {
this.expenses.setAll(expenseRegister.getItems());
} else {
this.income.setAll(incomeRegister.getItems());
}
}
......@@ -203,7 +243,8 @@ public class ExpensesController {
return alert.showAndWait();
}
public ExpenseRegister loadDataFromFile(String fileName) throws IOException {
public ExpenseRegister loadExpenseDataFromFile(String fileName) throws IOException {
//ItemRegister<T extends Item>
FileHandling fileHandling = new FileHandling();
if (fileHandling.isEmpty(fileName)) {
expenseRegister = new ExpenseRegister();
......@@ -217,14 +258,39 @@ public class ExpensesController {
return expenseRegister;
}
public IncomeRegister loadIncomeDataFromFile(String fileName) throws IOException {
FileHandling fileHandling = new FileHandling();
if (fileHandling.isEmpty(fileName)) {
incomeRegister = new IncomeRegister();
} else {
try {
incomeRegister = fileHandling.readIncomeRegisterFromFile(fileName);
} catch (IOException e) {
e.printStackTrace();
}
}
return incomeRegister;
}
public void saveDataToFile(String fileName) throws IOException {
FileHandling fileHandling = new FileHandling();
fileHandling.writeItemRegisterToFile(expenseRegister, fileName);
if (itemMode == ItemMode.EXPENSE) {
fileHandling.writeItemRegisterToFile(expenseRegister, fileName); }
else {
fileHandling.writeItemRegisterToFile(incomeRegister, fileName); }
}
@FXML
public void switchScene(ActionEvent event) throws IOException {
saveDataToFile("Expense");
if (itemMode == ItemMode.EXPENSE) {
saveDataToFile("Expense");
}
else {
saveDataToFile("Income");
}
FXMLLoader loader = new FXMLLoader();
if (event.getSource() == incomeBtn) {
loader.setLocation(SceneController.class.getResource("/view/Income.fxml"));
......@@ -233,10 +299,12 @@ public class ExpensesController {
} else if (event.getSource() == returnBtn) {
loader.setLocation(SceneController.class.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();
}
}
}
......@@ -3,55 +3,52 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.DialogPane?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane hgap="10.0" vgap="10.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="no.ntnu.idatt1002.demo.controller.SceneController">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="95.0" minWidth="10.0" prefWidth="11.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="189.0" minWidth="10.0" prefWidth="189.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 minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<padding>
<Insets bottom="10.0" left="10.0" top="20.0" />
</padding>
<children>
<Label text="Date:" />
<Label text="Amount:" GridPane.rowIndex="1" />
<Label text="Description:" GridPane.rowIndex="2" />
<Label text="Category" GridPane.rowIndex="3">
<GridPane.margin>
<Insets />
</GridPane.margin>
</Label>
<TextField promptText="Date" GridPane.columnIndex="1" GridPane.columnSpan="2" />
<TextField promptText="Amount" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="1" />
<TextField promptText="Description (optional)" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="2" />
<ComboBox prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="3">
<GridPane.margin>
<Insets />
</GridPane.margin>
</ComboBox>
<Button mnemonicParsing="false" onAction="#closeButton" text="Cancel" GridPane.columnIndex="3" GridPane.rowIndex="4">
<GridPane.margin>
<Insets left="75.0" />
</GridPane.margin>
</Button>
<Button mnemonicParsing="false" onAction="#closeButton" text="Button" GridPane.columnIndex="3" GridPane.rowIndex="4">
<GridPane.margin>
<Insets left="130.0" />
</GridPane.margin>
</Button>
</children>
</GridPane>
<DialogPane expanded="true" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="no.ntnu.idatt1002.demo.controller.AddExpenseController">
<content>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<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 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 minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="Date:" />
<Label text="Amount:" GridPane.rowIndex="1" />
<Label text="Description:" GridPane.rowIndex="2" />
<Label text="Category" GridPane.rowIndex="3" />
<Label text="Recurring" GridPane.rowIndex="4" />
<TextField fx:id="amountField" promptText="100" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<TextField fx:id="descriptionField" promptText="(optional)" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<ComboBox fx:id="categoryBox" prefWidth="150.0" promptText="Choose" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<ComboBox fx:id="recurringBox" prefWidth="150.0" promptText="No" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<HBox alignment="BOTTOM_RIGHT" prefHeight="100.0" prefWidth="200.0" spacing="10.0" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="5">
<children>
<Button fx:id="cancelBtn" mnemonicParsing="false" onAction="#pressCancelBtn" prefHeight="25.0" prefWidth="60.0" text="Cancel" />
<Button fx:id="okBtn" mnemonicParsing="false" onAction="#pressOkBtn" prefHeight="25.0" prefWidth="60.0" text="OK" />
</children>
<GridPane.margin>
<Insets top="20.0" />
</GridPane.margin>
</HBox>
<DatePicker fx:id="datePicker" GridPane.columnIndex="1" />
</children>
</GridPane>
</content>
</DialogPane>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment