From 3694d00a72e76970dbabe0b7772c6ac8c3b8fffb Mon Sep 17 00:00:00 2001
From: HSoreide <sofie.scisly@gmail.com>
Date: Sat, 22 Apr 2023 17:57:08 +0200
Subject: [PATCH] Fix background image not filling all views and make
 IngredientTile re-size with content

---
 .../controller/AddIngredientController.java   |  14 --
 .../demo/controller/AllRecipesController.java | 155 ++++++++++++------
 src/main/resources/style.css                  |   1 +
 src/main/resources/view/AllRecipes.fxml       |   2 +-
 src/main/resources/view/IngredientTile.fxml   |   4 +-
 src/main/resources/view/Recipe.fxml           |   4 +-
 6 files changed, 107 insertions(+), 73 deletions(-)

diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/AddIngredientController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/AddIngredientController.java
index a5c67bb4..408a98ed 100644
--- a/src/main/java/no/ntnu/idatt1002/demo/controller/AddIngredientController.java
+++ b/src/main/java/no/ntnu/idatt1002/demo/controller/AddIngredientController.java
@@ -2,7 +2,6 @@ package no.ntnu.idatt1002.demo.controller;
 
 import javafx.application.Platform;
 import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
 import javafx.fxml.FXML;
 import javafx.fxml.Initializable;
 import javafx.scene.control.*;
@@ -31,25 +30,12 @@ import no.ntnu.idatt1002.demo.data.recipes.IngredientsAtHand;
  */
 public class AddIngredientController implements Initializable {
 
-    private ObservableList<String> ingredients;
-    private String[] ingredientsList;
-
-    @FXML
-    private Button addBtn;
-
-    @FXML
-    private Button helpBtn;
-
-
     @FXML
     private ListView<String> listView;
 
     @FXML
     private TextField searchBar;
 
-    @FXML
-    private Button searchBtn;
-
     @FXML
     private Label status;
 
diff --git a/src/main/java/no/ntnu/idatt1002/demo/controller/AllRecipesController.java b/src/main/java/no/ntnu/idatt1002/demo/controller/AllRecipesController.java
index 30e59521..80de931b 100644
--- a/src/main/java/no/ntnu/idatt1002/demo/controller/AllRecipesController.java
+++ b/src/main/java/no/ntnu/idatt1002/demo/controller/AllRecipesController.java
@@ -10,34 +10,101 @@ import javafx.fxml.Initializable;
 import javafx.scene.Node;
 import javafx.scene.Parent;
 import javafx.scene.Scene;
-import javafx.scene.control.Button;
 import javafx.scene.control.ListView;
 import javafx.scene.input.MouseEvent;
 import javafx.stage.Stage;
 import no.ntnu.idatt1002.demo.data.recipes.*;
-
 import java.io.IOException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.ResourceBundle;
 
+/**
+ * The AllRecipesController manages the view named AllRecipes.fxml that displays a scrollable list of all the
+ * recipes that are stored in the recipe register at 'src/main/resources/recipes/Recipes.register'. The controller
+ * holds an instance of the IngredientsAtHand class and the RecipeRegister class and combines the two to
+ * fill the list with recipes sorted by the number of ingredients that are not currently in the 'fridge' of the
+ * user. Each recipe is also lister with a percentage value that shows how many percent of the recipe's
+ * ingredients are actually in the fridge. This information is included so that recipes with a lower number of
+ * ingredients are not given an unfair advantage over others where the user may have a significant number of
+ * the ingredients available. Each listed recipe may be clicked on by the user to open it in a new view in full
+ * detail.
+ *
+ * @author hannesofie
+ */
 public class AllRecipesController implements Initializable {
 
     IngredientsAtHand ingredientsAtHand;
     RecipeRegister recipeRegister;
 
-    @FXML
-    private Button goBackBtn;
-
     @FXML
     private ListView<String> allList;
 
+    private String selectedRecipeName;
+
 
-    private ObservableList<String> recipes;
+    /**
+     * The initialize method of the controller takes in a URL (location) and ResourceBundle(resources) to
+     * initialize the controller once its root element has been processed. The method then reads and creates
+     * an object of the IngredientsAtHand class and one of the RecipesRegister class.
+     * If the recipe register exists, the list is filled with Strings for each recipe at the format:
+     * <Recipe name> - X missing ingredients (XX%)
+     * Finally, a MouseClick event and handler is attached to the list that gets the recipe name of the clicked
+     * list item and runs the method showRecipe() with that name as input to show the recipe in detail in the
+     * view Recipe.fxml.
+     *
+     * @param url The location to resolve the relative paths to the root object.
+     * @param resourceBundle Resources used to localize the root object.
+     */
+    @Override
+    public void initialize(URL url, ResourceBundle resourceBundle) {
 
-    private String selectedRecipeName;
+        ingredientsAtHand = FileHandler.readIngredientsAtHand("Fridge");
+        recipeRegister = FileHandler.readRecipeRegister("Recipes");
+
+        ObservableList<String> recipes;
+
+        if(recipeRegister == null) {
+            recipes = FXCollections.observableArrayList(new ArrayList<>());
+        } else {
+            int numberOfRecipes = recipeRegister.getRecipes().size();
+
+            ArrayList<Recipe> sortedRecipes = recipeRegister.pickBestFits(numberOfRecipes, ingredientsAtHand);
+
+            recipes = FXCollections.observableArrayList(sortedRecipes.stream().map(recipe -> String.format("# %s  -  %d missing ingredients (%2.0f %% covered)", recipe.getName(), recipe.getMissingIngredients(), percent(recipe.getIngredientList().size() - recipe.getMissingIngredients(), recipe.getIngredientList().size()))).toList());
+        }
 
+        allList.setItems(recipes);
+
+        allList.setOnMouseClicked(new EventHandler<>() {
+
+            /**
+             * The handler method takes a MouseEvent(Mouse Click) and uses the list item that was subjected to the
+             * mouse click and extracts the recipe name. That name as a String is then passed to the method
+             * 'showRecipe' that loads the view Recipe.fxml to display this particular recipe in full detail.
+             *
+             * @param mouseEvent A mouse event, in this case a MouseClicked event.
+             */
+            @Override
+            public void handle(MouseEvent mouseEvent) {
+                selectedRecipeName = allList.getSelectionModel()
+                        .getSelectedItem().split("[-#]")[1].strip();
+                try {
+                    showRecipe(selectedRecipeName);
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+    }
 
+
+    /**
+     * The goBack method is fired whenever the user presses the button 'Back To Suggestions'. It loads the location
+     * of the SuggestRecipes.fxml view and sets the new stage.
+     * @param event Action event that triggers this method, in this case a button click.
+     * @throws IOException If the method fails to load the location at the given file path.
+     */
     @FXML
     private void goBack(ActionEvent event) throws IOException {
         FXMLLoader loader = new FXMLLoader();
@@ -50,6 +117,12 @@ public class AllRecipesController implements Initializable {
         stage.show();
     }
 
+    /**
+     * The showRecipe method takes in a recipe name as a String and navigates to the view Recipe.fxml after having
+     * the RecipeController set the data of the view according to this particular recipe.
+     * @param recipeName A case-sensitive string representation of the recipe to open in detail.
+     * @throws IOException If the method fails to load the location of the Recipe.fxml view.
+     */
     private void showRecipe(String recipeName) throws IOException {
         FXMLLoader loader = new FXMLLoader();
         loader.setLocation(getClass().getResource("/view/Recipe.fxml"));
@@ -57,59 +130,33 @@ public class AllRecipesController implements Initializable {
         Recipe recipeOfInterest = recipeRegister.getRecipe(recipeName);
 
         Parent root = loader.load();
-
         RecipeController recipeController = loader.getController();
 
-        recipeController.setData(recipeOfInterest);
-
-        Stage stage = (Stage)allList.getParent().getScene().getWindow();
-        Scene scene = new Scene(root);
-        stage.setScene(scene);
-        stage.show();
+        if(recipeOfInterest != null) {
+            recipeController.setData(recipeOfInterest);
+            Stage stage = (Stage)allList.getParent().getScene().getWindow();
+            Scene scene = new Scene(root);
+            stage.setScene(scene);
+            stage.show();
+        } else {
+            System.out.println("The selected recipe is null.");
+        }
     }
 
-private float percent(int a, int b) {
-        if(b != 0 && a != 0) {
-            return (float) a / b;
+    /**
+     * The percent method takes in two integers(a, b) and performs float-division(a/b) on then and multiplies the
+     * answer by 100 to get the percentage 'a' makes of the total 'b'. If either 'a' or 'b' is zero, zero is returned.
+     * In the current context; 'a' is an int representing a number of ingredients at hand and part of a recipe and 'b'
+     * is an int representing the total number of ingredients in the same recipe.
+     * @param a An int to divide by b and multiply by 100.
+     * @param b An int by which to divide 'a'.
+     * @return A float value presenting the percentage value of 'a' out of 'b'.
+     */
+    private float percent(int a, int b) {
+        if (b != 0 && a != 0) {
+            return (a * 100f / b);
         } else {
             return 0;
         }
-
-
-}
-
-    @Override
-    public void initialize(URL url, ResourceBundle resourceBundle) {
-
-        ingredientsAtHand = FileHandler.readIngredientsAtHand("Fridge");
-        recipeRegister = FileHandler.readRecipeRegister("Recipes");
-
-        int numberOfRecipes = recipeRegister.getRecipes().size();
-
-        ArrayList<Recipe> sortedRecipes = recipeRegister.pickBestFits(numberOfRecipes, ingredientsAtHand);
-
-        recipes = FXCollections.observableArrayList(sortedRecipes.stream().map(recipe -> {
-            return String.format("# %s  -  %d missing ingredients (%.2f %% covered)", recipe.getName(), recipe.getMissingIngredients(), percent(recipe.getIngredientList().size() - recipe.getMissingIngredients(),recipe.getIngredientList().size()));
-        }).toList());
-
-        allList.setItems(recipes);
-
-        allList.setOnMouseClicked(new EventHandler<MouseEvent>() {
-
-            @Override
-            public void handle(MouseEvent mouseEvent) {
-                    selectedRecipeName = allList.getSelectionModel()
-                            .getSelectedItem().split("-|#")[1].strip();
-
-                try {
-                   showRecipe(selectedRecipeName);
-
-                } catch (IOException e) {
-                    throw new RuntimeException(e);
-                }
-
-            }
-        });
-
     }
 }
diff --git a/src/main/resources/style.css b/src/main/resources/style.css
index 0a8075b8..b763b869 100644
--- a/src/main/resources/style.css
+++ b/src/main/resources/style.css
@@ -141,4 +141,5 @@
     -fx-border-width: 5;
     -fx-border-radius: 30;
     -fx-border-color: white;
+    -fx-text-fill: white;
 }
\ No newline at end of file
diff --git a/src/main/resources/view/AllRecipes.fxml b/src/main/resources/view/AllRecipes.fxml
index c1ab05ae..ddb3a64f 100644
--- a/src/main/resources/view/AllRecipes.fxml
+++ b/src/main/resources/view/AllRecipes.fxml
@@ -7,7 +7,7 @@
 
 <AnchorPane prefHeight="695.0" prefWidth="1130.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="no.ntnu.idatt1002.demo.controller.AllRecipesController">
    <children>
-      <ImageView fitHeight="695.0" fitWidth="1130.0" pickOnBounds="true" preserveRatio="true">
+      <ImageView fitHeight="695.0" fitWidth="1130.0" pickOnBounds="true">
          <image>
             <Image url="@../Images/backgroundMini.jpg" />
          </image>
diff --git a/src/main/resources/view/IngredientTile.fxml b/src/main/resources/view/IngredientTile.fxml
index bd749e3a..ebd54256 100644
--- a/src/main/resources/view/IngredientTile.fxml
+++ b/src/main/resources/view/IngredientTile.fxml
@@ -7,12 +7,12 @@
 
 <Pane id="ingredient" fx:id="ingredientPane" mouseTransparent="true" stylesheets="@../style.css" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="no.ntnu.idatt1002.demo.controller.IngredientTileController">
    <children>
-      <Label id="ingredient-label" fx:id="text" prefHeight="40.0" prefWidth="250.0" styleClass="font" stylesheets="@../style.css" text="Ingredient">
+      <Label id="ingredient-label" fx:id="text" styleClass="font" stylesheets="@../style.css" text="Ingredient">
          <font>
             <Font name="Ani" size="18.0" />
          </font>
          <padding>
-            <Insets left="15.0" />
+            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
          </padding>
       </Label>
    </children>
diff --git a/src/main/resources/view/Recipe.fxml b/src/main/resources/view/Recipe.fxml
index 5e71c20a..2ca258be 100644
--- a/src/main/resources/view/Recipe.fxml
+++ b/src/main/resources/view/Recipe.fxml
@@ -6,9 +6,9 @@
 <?import javafx.scene.layout.*?>
 <?import javafx.scene.text.*?>
 
-<AnchorPane prefHeight="695.0" prefWidth="1130.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="no.ntnu.idatt1002.demo.controller.RecipeController">
+<AnchorPane xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="no.ntnu.idatt1002.demo.controller.RecipeController">
    <children>
-      <ImageView fitHeight="695.0" fitWidth="1130.0" pickOnBounds="true" preserveRatio="true">
+      <ImageView fitHeight="695.0" fitWidth="1130.0" pickOnBounds="true">
          <image>
             <Image url="@../Images/backgroundMini.jpg" />
          </image>
-- 
GitLab