From 20d5c48bdd0d278699f48a6d91ab71370033c3ad Mon Sep 17 00:00:00 2001
From: Harry Linrui XU <xulr0820@hotmail.com>
Date: Fri, 31 Mar 2023 13:01:17 +0200
Subject: [PATCH] "Implemented add, edit and delete functionalities. Synch
 piecharts to register"

---
 .../controller/IncomeExpenseController.java   | 226 ++++++++++++++++--
 .../resources/view/IncomeAndExpenses.fxml     | 137 +++++------
 2 files changed, 277 insertions(+), 86 deletions(-)

diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/IncomeExpenseController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/IncomeExpenseController.java
index e51d3b3a..53d9223d 100644
--- a/src/main/java/no/ntnu/idatt1002/demo/controller/IncomeExpenseController.java
+++ b/src/main/java/no/ntnu/idatt1002/demo/controller/IncomeExpenseController.java
@@ -3,7 +3,6 @@ package no.ntnu.idatt1002.demo.controller;
 import java.awt.event.ActionEvent;
 import java.io.IOException;
 import java.util.Optional;
-import javafx.beans.binding.Bindings;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 import javafx.fxml.FXML;
@@ -14,16 +13,21 @@ 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;
@@ -80,7 +84,10 @@ public class IncomeExpenseController implements FinanceController {
   private Text expSum;
 
   @FXML
-  private Button addBtn;
+  private MenuItem addExpense;
+
+  @FXML
+  private MenuItem addIncome;
 
   @FXML
   private Button deleteBtn;
@@ -105,8 +112,6 @@ public class IncomeExpenseController implements FinanceController {
 
   @FXML
   private Label title;
-
-  private FinanceMode financeMode;
   private IncomeRegister incomeRegister;
 
   private ExpenseRegister expenseRegister;
@@ -141,12 +146,10 @@ public class IncomeExpenseController implements FinanceController {
     expenses = FXCollections.observableArrayList(expenseRegister.getItems());
     expenseTableView.setItems(expenses);
 
-    incomePieChart.getData().addAll(createIncomePyChart());
-    incomePieChart.setTitle("Income");
+    refreshPieCharts(); //TODO THIS IS FUCKED. DISPLAYS EXPENSE CATEGORIES
     incomePieChart.setLegendSide(Side.RIGHT);
 
-    expensePieChart.setData(createExpensePyChart());
-    expensePieChart.setTitle("Expenses");
+    refreshPieCharts();
     expensePieChart.setLegendSide(Side.RIGHT);
     expensePieChart.setLabelLineLength(10);
 
@@ -169,7 +172,7 @@ public class IncomeExpenseController implements FinanceController {
     expRecurringCol.setCellValueFactory(new PropertyValueFactory<Expense, Boolean>("recurring"));
   }
 
-  private ObservableList<PieChart.Data> createExpensePyChart() {
+  private ObservableList<PieChart.Data> createExpensePieChart() {
     return FXCollections.observableArrayList(
         new Data("Food", expenseRegister.getExpenseByCategory(ExpenseCategory.FOOD).getTotalSum()),
         new Data("Books", expenseRegister.getExpenseByCategory(ExpenseCategory.BOOKS).getTotalSum()),
@@ -178,10 +181,11 @@ public class IncomeExpenseController implements FinanceController {
     );
   }
 
-  private ObservableList<PieChart.Data> createIncomePyChart() {
+  private ObservableList<PieChart.Data> createIncomePieChart() {
     return FXCollections.observableArrayList(
-        new Data("Food", incomeRegister.getIncomeByCategory(IncomeCategory.STUDENT_LOAN).getTotalSum()),
-        new Data("Books", incomeRegister.getIncomeByCategory(IncomeCategory.SALARY).getTotalSum())
+        new Data("Loans", incomeRegister.getIncomeByCategory(IncomeCategory.GIFT).getTotalSum()),
+        new Data("Salary", incomeRegister.getIncomeByCategory(IncomeCategory.SALARY).getTotalSum()),
+        new Data("Salary", incomeRegister.getIncomeByCategory(IncomeCategory.STUDENT_LOAN).getTotalSum())
     );
   }
 
@@ -190,8 +194,12 @@ public class IncomeExpenseController implements FinanceController {
    * @param event A button click on the add button.
    */
   @Override
-  public void handleAddBtn(ActionEvent event) {
-    handleEditBtn(event);
+  public void handleAddBtn(javafx.event.ActionEvent event) {
+    if (event.getSource() == addIncome) {
+      handleAddIncome();
+    } else if (event.getSource() == addExpense){
+      handleAddExpense();
+    }
   }
 
   /**
@@ -200,8 +208,15 @@ public class IncomeExpenseController implements FinanceController {
    * @param event A button click on the edit button.
    */
   @Override
-  public void handleEditBtn(ActionEvent event) {
-
+  public void handleEditBtn(javafx.event.ActionEvent event) {
+    Income chosenIncome = incomeTableView.getSelectionModel().getSelectedItem();
+    Expense chosenExpense = expenseTableView.getSelectionModel().getSelectedItem();
+
+    if (chosenIncome!= null) {
+      handleEditIncome(chosenIncome);
+    } else if (chosenExpense != null) {
+      handleEditExpense(chosenExpense);
+    }
   }
 
   /**
@@ -211,7 +226,15 @@ public class IncomeExpenseController implements FinanceController {
    * @param event A button click on the delete button
    */
   @Override
-  public void handleDeleteBtn(ActionEvent event) {
+  public void handleDeleteBtn(javafx.event.ActionEvent event) {
+    Income chosenIncome = incomeTableView.getSelectionModel().getSelectedItem();
+    Expense chosenExpense = expenseTableView.getSelectionModel().getSelectedItem();
+    
+    if (chosenIncome != null) {
+      handleDeleteIncome(chosenIncome);
+    } else if (chosenExpense != null) {
+      handleDeleteExpense(chosenExpense);
+    }
   }
 
   /**
@@ -227,8 +250,168 @@ public class IncomeExpenseController implements FinanceController {
     this.expenses.setAll(expenseRegister.getItems());
     //this.sum.setText(String.valueOf(incomeRegister.getTotalSum()));
   }
+  
+  private void refreshPieCharts() {
+    this.refreshPieCharts();
+    this.refreshPieCharts();
+  }
 
-  /**
+  @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);
+    }
+    //Updates the tableview using the register
+    refreshTableView();
+    refreshPieCharts();
+  }
+
+  @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);
+    }
+    //Updates the tableview using the register
+    refreshTableView();
+    refreshPieCharts();
+  }
+
+  @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();
+    //Updates the tableview using the register
+    refreshTableView();
+    refreshPieCharts();
+  }
+
+  @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();
+    //Updates the tableview using the register
+    refreshTableView();
+    refreshPieCharts();
+  }
+  
+  @FXML
+  private void handleDeleteIncome(Income chosenIncome) {
+    Optional<ButtonType> isConfirmed = showConfirmationDialog();
+    if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) {
+      incomeRegister.removeItem(chosenIncome);
+      refreshTableView();
+      
+    }
+  }
+
+  @FXML
+  private void handleDeleteExpense(Expense chosenExpense) {
+    Optional<ButtonType> isConfirmed = showConfirmationDialog();
+    if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) {
+      expenseRegister.removeItem(chosenExpense);
+      refreshTableView();
+    }
+
+  }
+   /**
    * Returns an optional, which is a popup alert box, asking for confirmation for deleting an
    * entry.
    *
@@ -236,7 +419,12 @@ public class IncomeExpenseController implements FinanceController {
    */
   @Override
   public Optional<ButtonType> showConfirmationDialog() {
-    return Optional.empty();
+    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();
   }
 
   /**
diff --git a/src/main/resources/view/IncomeAndExpenses.fxml b/src/main/resources/view/IncomeAndExpenses.fxml
index 33e54922..480b937c 100644
--- a/src/main/resources/view/IncomeAndExpenses.fxml
+++ b/src/main/resources/view/IncomeAndExpenses.fxml
@@ -8,6 +8,7 @@
 <?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?>
@@ -23,6 +24,7 @@
 <?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>
@@ -75,10 +77,11 @@
                <left>
                   <HBox prefHeight="100.0" prefWidth="200.0" spacing="10.0" BorderPane.alignment="CENTER">
                      <children>
-                        <Button fx:id="addBtn" mnemonicParsing="false" prefHeight="25.0" prefWidth="60.0">
-                           <font>
-                              <Font name="Lucida Console" size="12.0" />
-                           </font>
+                        <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>
@@ -86,16 +89,8 @@
                                  </image>
                               </ImageView>
                            </graphic>
-                           <contextMenu>
-                              <ContextMenu>
-                                <items>
-                                  <MenuItem mnemonicParsing="false" text="Unspecified Action" />
-                                    <MenuItem mnemonicParsing="false" text="Unspecified Action" />
-                                </items>
-                              </ContextMenu>
-                           </contextMenu>
-                        </Button>
-                        <Button fx:id="editBtn" mnemonicParsing="false" prefHeight="25.0" prefWidth="60.0">
+                        </MenuButton>
+                        <Button fx:id="editBtn" mnemonicParsing="false" onAction="#handleEditBtn" prefHeight="25.0" prefWidth="60.0">
                            <font>
                               <Font name="Lucida Console" size="12.0" />
                            </font>
@@ -106,16 +101,8 @@
                                  </image>
                               </ImageView>
                            </graphic>
-                           <contextMenu>
-                              <ContextMenu>
-                                <items>
-                                  <MenuItem mnemonicParsing="false" text="Unspecified Action" />
-                                    <MenuItem mnemonicParsing="false" text="Unspecified Action" />
-                                </items>
-                              </ContextMenu>
-                           </contextMenu>
                         </Button>
-                        <Button fx:id="deleteBtn" mnemonicParsing="false" prefHeight="25.0" prefWidth="50.0">
+                        <Button fx:id="deleteBtn" mnemonicParsing="false" prefHeight="25.0" prefWidth="60.0">
                            <font>
                               <Font name="Lucida Console" size="12.0" />
                            </font>
@@ -126,14 +113,6 @@
                                  </image>
                               </ImageView>
                            </graphic>
-                           <contextMenu>
-                              <ContextMenu>
-                                <items>
-                                  <MenuItem mnemonicParsing="false" text="Unspecified Action" />
-                                    <MenuItem mnemonicParsing="false" text="Unspecified Action" />
-                                </items>
-                              </ContextMenu>
-                           </contextMenu>
                         </Button>
                      </children>
                      <BorderPane.margin>
@@ -166,17 +145,19 @@
                   </Pane>
                </center>
             </BorderPane>
-            <GridPane prefHeight="473.0" prefWidth="1100.0">
+            <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" 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>
-                  <GridPane>
+                  <GridPane GridPane.rowIndex="1">
                      <columnConstraints>
                         <ColumnConstraints hgrow="ALWAYS" maxWidth="485.3333231608073" minWidth="10.0" prefWidth="427.33335367838544" />
                      </columnConstraints>
@@ -197,6 +178,13 @@
                                  <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>
@@ -207,45 +195,60 @@
                         </VBox>
                      </children>
                   </GridPane>
-                  <GridPane GridPane.rowIndex="1">
-                     <columnConstraints>
-                        <ColumnConstraints hgrow="ALWAYS" maxWidth="485.3333231608073" minWidth="10.0" prefWidth="427.33335367838544" />
-                     </columnConstraints>
-                     <rowConstraints>
-                        <RowConstraints maxHeight="298.66665744781494" minHeight="10.0" prefHeight="214.00004069010413" vgrow="SOMETIMES" />
-                     </rowConstraints>
+                  <Pane GridPane.columnIndex="1" GridPane.rowIndex="1">
                      <children>
-                        <VBox>
-                           <children>
-                              <TableView fx:id="expenseTableView" maxHeight="175.0" prefHeight="172.0" prefWidth="545.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>
-                              </TableView>
-                              <Label text="Sum: ">
-                                 <font>
-                                    <Font name="Lucida Console" size="14.0" />
-                                 </font>
-                              </Label>
-                           </children>
-                        </VBox>
+                        <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>
-                  </GridPane>
-                  <Pane GridPane.columnIndex="1">
+                  </Pane>
+                  <Pane GridPane.columnIndex="1" GridPane.rowIndex="3">
                      <children>
-                        <PieChart fx:id="incomePieChart" layoutX="4.0" layoutY="-18.0" legendSide="RIGHT" maxHeight="226.0" maxWidth="512.0" prefHeight="214.0" prefWidth="350.0" title="Income" />
+                        <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 GridPane.columnIndex="1" GridPane.rowIndex="1">
+                  <Pane prefHeight="20.0" prefWidth="1046.0">
                      <children>
-                        <PieChart fx:id="expensePieChart" layoutX="-2.0" layoutY="-27.0" legendSide="RIGHT" maxHeight="247.0" maxWidth="519.0" prefHeight="227.0" prefWidth="350.0" title="Expenses" />
+                        <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>
-- 
GitLab