From bee26a058edbfba04837540f296df63dfa3a7525 Mon Sep 17 00:00:00 2001
From: Lukas Karsch <lk224@hdm-stuttgart.de>
Date: Mon, 15 May 2023 18:31:05 +0200
Subject: [PATCH] introducing components: a way to reuse elements in different
 scenes. modified the Main view to fetch recipes and add them to the UI

---
 src/main/java/mi/hdm/GuiHelper/Dialog.java    |  77 -------
 .../java/mi/hdm/GuiHelper/NumberField.java    |  35 ----
 src/main/java/mi/hdm/TastyPages.java          |   5 +-
 .../mi/hdm/controllers/BaseController.java    |  47 +++--
 .../mi/hdm/controllers/HeaderController.java  |  25 +++
 .../hdm/controllers/MainPageController.java   |  52 +++--
 .../hdm/controllers/RecipeViewController.java |  17 ++
 .../ShoppingListViewController.java           |   4 -
 .../mi/hdm/controllers/ViewComponent.java     |  28 +++
 src/main/java/mi/hdm/screenshots.java         |  20 --
 .../resources/fxml/Tasty_Pages_Main_Page.fxml | 190 +++---------------
 .../resources/fxml/components/header.fxml     |  43 ++++
 src/main/resources/fxml/hello.fxml            |  38 ----
 src/main/resources/fxml/recipe-view.fxml      |  34 +---
 .../resources/fxml/shoppingList-view.fxml     |  71 ++++---
 15 files changed, 261 insertions(+), 425 deletions(-)
 delete mode 100644 src/main/java/mi/hdm/GuiHelper/Dialog.java
 delete mode 100644 src/main/java/mi/hdm/GuiHelper/NumberField.java
 create mode 100644 src/main/java/mi/hdm/controllers/HeaderController.java
 create mode 100644 src/main/java/mi/hdm/controllers/ViewComponent.java
 delete mode 100644 src/main/java/mi/hdm/screenshots.java
 create mode 100644 src/main/resources/fxml/components/header.fxml
 delete mode 100644 src/main/resources/fxml/hello.fxml

diff --git a/src/main/java/mi/hdm/GuiHelper/Dialog.java b/src/main/java/mi/hdm/GuiHelper/Dialog.java
deleted file mode 100644
index 56f8abc..0000000
--- a/src/main/java/mi/hdm/GuiHelper/Dialog.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package mi.hdm.GuiHelper;
-
-import javafx.scene.control.Alert;
-import javafx.scene.control.Alert.AlertType;
-import javafx.scene.control.Label;
-import javafx.scene.control.TextArea;
-import javafx.scene.layout.GridPane;
-import javafx.scene.layout.Priority;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-/**
- * See http://code.makery.ch/blog/javafx-dialogs-official
- * for further explanations.
- */
-public class Dialog {
-
-
-  /**
-   * Show a modal info box
-   *
-   * @param msg A message to be displayed
-   */
-  public static void showInfo(final String msg) {
-    final Alert alert = new Alert(AlertType.INFORMATION);
-    alert.setTitle("Info");
-    alert.setContentText(msg);
-    alert.showAndWait();
-  }
-
-  /**
-   * Showing an error box and terminating without any further error processing
-   *
-   * @param msg      An informative message
-   * @param ex       The exception to be interpreted by an expert
-   * @param exitCode The exit code to be used by e.g. the calling process.
-   */
-  public static void showExceptionAndExit(final String msg, final Exception ex, int exitCode) {
-
-    final Alert alert = new Alert(AlertType.ERROR);
-    alert.setTitle("Unrecoverable error");
-    alert.setHeaderText("Application will be terminated!");
-    alert.setContentText(msg);
-
-
-    // Create expandable Exception.
-
-    if (null != ex) {
-      final StringWriter sw = new StringWriter();
-      final PrintWriter pw = new PrintWriter(sw);
-      ex.printStackTrace(pw);
-      final String exceptionText = sw.toString();
-
-      final Label label = new Label("You may copy and forward this exception stacktrace to an expert:");
-
-      final TextArea textArea = new TextArea(exceptionText);
-      textArea.setEditable(false);
-      textArea.setWrapText(true);
-
-      textArea.setMaxWidth(Double.MAX_VALUE);
-      textArea.setMaxHeight(Double.MAX_VALUE);
-      GridPane.setVgrow(textArea, Priority.ALWAYS);
-      GridPane.setHgrow(textArea, Priority.ALWAYS);
-
-      final GridPane expContent = new GridPane();
-      expContent.setMaxWidth(Double.MAX_VALUE);
-      expContent.add(label, 0, 0);
-      expContent.add(textArea, 0, 1);
-
-      // Set expandable Exception into the dialog pane.
-      alert.getDialogPane().setExpandableContent(expContent);
-    }
-    alert.showAndWait();
-    System.exit(exitCode);
-  }
-}
\ No newline at end of file
diff --git a/src/main/java/mi/hdm/GuiHelper/NumberField.java b/src/main/java/mi/hdm/GuiHelper/NumberField.java
deleted file mode 100644
index 08e758e..0000000
--- a/src/main/java/mi/hdm/GuiHelper/NumberField.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package mi.hdm.GuiHelper;
-
-import javafx.scene.control.TextField;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-public class NumberField extends TextField {
-
-  private static Logger log = LogManager.getLogger(NumberField.class);
-
-  private int value = 0;
-
-  public NumberField() {
-
-    setText("0");
-    textProperty().addListener((event, oldValue, newValue) -> {
-      switch (newValue.trim()) {
-        case "":
-        case "-":
-          return;
-      }
-
-      try {
-        value = Integer.parseInt(newValue);
-      } catch (final NumberFormatException e) {
-        log.warn("Rejecting illegal age input: «" + newValue + "»");
-        setText(oldValue);
-      }
-    });
-  }
-
-  public int getValue() {
-    return value;
-  }
-}
\ No newline at end of file
diff --git a/src/main/java/mi/hdm/TastyPages.java b/src/main/java/mi/hdm/TastyPages.java
index fdee332..eaaaae9 100644
--- a/src/main/java/mi/hdm/TastyPages.java
+++ b/src/main/java/mi/hdm/TastyPages.java
@@ -36,11 +36,12 @@ public class TastyPages extends Application {
     @Override
     public void start(Stage stage) throws IOException {
         TastyPages.stage = stage;
+        final View startupView = View.MAIN;
 
-        Parent parent = View.MAIN.getScene();
+        Parent parent = startupView.getScene();
         final Scene scene = new Scene(parent, 1400, 800);
 
-        stage.setTitle(View.MAIN.getWindowTitle());
+        stage.setTitle(startupView.getWindowTitle());
         stage.setMaximized(true); //open scene in full screen
         stage.setScene(scene);
         stage.show();
diff --git a/src/main/java/mi/hdm/controllers/BaseController.java b/src/main/java/mi/hdm/controllers/BaseController.java
index c379649..7633ad3 100644
--- a/src/main/java/mi/hdm/controllers/BaseController.java
+++ b/src/main/java/mi/hdm/controllers/BaseController.java
@@ -2,6 +2,7 @@ package mi.hdm.controllers;
 
 import javafx.scene.Parent;
 import javafx.scene.Scene;
+import javafx.scene.layout.AnchorPane;
 import javafx.stage.Stage;
 import mi.hdm.TastyPages;
 import org.apache.logging.log4j.LogManager;
@@ -15,19 +16,39 @@ public abstract class BaseController {
 
     protected Scene currentScene;
 
-    protected void changeScene(final View newScene) throws IOException {
-        boolean wasMaximized = stage.isMaximized();
-        double sizeX = stage.getWidth();
-        double sizeY = stage.getHeight();
-        String newWindowTitle = newScene.getWindowTitle();
-
-        log.debug("Attempting to change the scene to {}", newScene);
-        Parent newParent = newScene.getScene();
-
-        currentScene = new Scene(newParent, sizeX, sizeY);
+    protected void changeScene(final View newScene) {
+        try {
+            boolean wasMaximized = stage.isMaximized();
+            double sizeX = stage.getWidth();
+            double sizeY = stage.getHeight();
+            String newWindowTitle = newScene.getWindowTitle();
+
+            log.debug("Attempting to change the scene to {}", newScene);
+            Parent newParent = newScene.getScene();
+
+            currentScene = new Scene(newParent, sizeX, sizeY);
+
+            stage.setTitle(newWindowTitle);
+            stage.setScene(currentScene);
+            stage.setMaximized(wasMaximized);
+        } catch (IOException io) {
+            log.error("IO Exception: something went wrong when changing the scene.");
+            io.printStackTrace();
+        }
+    }
 
-        stage.setTitle(newWindowTitle);
-        stage.setScene(currentScene);
-        stage.setMaximized(wasMaximized);
+    protected void loadHeader(AnchorPane parent) {
+        try {
+            //load the header and constrain it to the borders of the parent element
+            AnchorPane header = (AnchorPane) ViewComponent.HEADER.getParentElement();
+            AnchorPane.setLeftAnchor(header, 0.0);
+            AnchorPane.setTopAnchor(header, 0.0);
+            AnchorPane.setRightAnchor(header, 0.0);
+
+            parent.getChildren().add(header);
+        } catch (IOException e) {
+            log.error("Something went wrong loading the header");
+            e.printStackTrace();
+        }
     }
 }
diff --git a/src/main/java/mi/hdm/controllers/HeaderController.java b/src/main/java/mi/hdm/controllers/HeaderController.java
new file mode 100644
index 0000000..ae522ee
--- /dev/null
+++ b/src/main/java/mi/hdm/controllers/HeaderController.java
@@ -0,0 +1,25 @@
+package mi.hdm.controllers;
+
+import javafx.fxml.FXML;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+
+public class HeaderController extends BaseController {
+    private final static Logger log = LogManager.getLogger(HeaderController.class);
+
+    @FXML
+    public void changeSceneToHome() {
+        changeScene(View.MAIN);
+    }
+
+    @FXML
+    public void changeSceneToShoppingList() {
+        changeScene(View.SHOPPINGLIST_VIEW);
+    }
+
+    @FXML
+    public void changeSceneToMealPlan() {
+        log.error("NOT IMPLEMENTED! Scene meal plan doesn't exist yet!");
+    }
+}
diff --git a/src/main/java/mi/hdm/controllers/MainPageController.java b/src/main/java/mi/hdm/controllers/MainPageController.java
index a846187..5e6826e 100644
--- a/src/main/java/mi/hdm/controllers/MainPageController.java
+++ b/src/main/java/mi/hdm/controllers/MainPageController.java
@@ -1,38 +1,64 @@
 package mi.hdm.controllers;
 
 import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.TilePane;
+import javafx.scene.layout.VBox;
+import mi.hdm.recipes.Recipe;
 import mi.hdm.recipes.RecipeManager;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-import java.io.IOException;
-
 public class MainPageController extends BaseController {
     private final static Logger log = LogManager.getLogger(MainPageController.class);
 
     private final RecipeManager recipeManager;
 
+    @FXML
+    private AnchorPane parent;
+    @FXML
+    private TilePane recipeTilePane;
+
     public MainPageController(RecipeManager recipeManager) {
         this.recipeManager = recipeManager;
     }
 
     @FXML
-    public void changeSceneToHome() throws IOException {
-        changeScene(View.MAIN);
+    public void initialize() {
+        loadHeader(parent);
+        mapRecipes();
+        log.debug("Added {} recipes to GUI", recipeManager.getRecipes().size());
     }
 
     @FXML
-    public void changeSceneToShoppingList() throws IOException {
-        changeScene(View.SHOPPINGLIST_VIEW);
+    public void addRecipe() {
+        log.info("User is trying to add recipe!");
     }
 
-    @FXML
-    public void changeSceneToMealPlan() throws IOException {
-        log.error("NOT IMPLEMENTED! Scene meal plan doesn't exist yet!");
-    }
+    private void mapRecipes() {
+        for (Recipe recipe : recipeManager.getRecipes()) {
+            Label recipeName = new Label(recipe.getName());
+            Label recipeDescription = new Label(recipe.getDescription());
+            VBox currentRecipeBox = new VBox(recipeName, recipeDescription);
 
-    @FXML
-    public void addRecipe() {
-        log.info("User is trying to add recipe!");
+            //TODO: make this recipe box a component class
+            recipeName.setStyle(
+                    "-fx-font-weight: 800;" +
+                            "-fx-font-scale: 16"
+            );
+
+            currentRecipeBox.setPrefWidth(180);
+            currentRecipeBox.setPrefHeight(250);
+            currentRecipeBox.setStyle(
+                    "-fx-background-color: #DEDEDE;" +
+                            "-fx-border-color: #D91C1C;" +
+                            "-fx-border-radius: 8;" +
+                            "-fx-border-width: 2;" +
+                            "-fx-padding: 8"
+            );
+
+            recipeTilePane.getChildren().add(currentRecipeBox);
+        }
     }
 }
diff --git a/src/main/java/mi/hdm/controllers/RecipeViewController.java b/src/main/java/mi/hdm/controllers/RecipeViewController.java
index 86802c3..c698d66 100644
--- a/src/main/java/mi/hdm/controllers/RecipeViewController.java
+++ b/src/main/java/mi/hdm/controllers/RecipeViewController.java
@@ -2,6 +2,7 @@ package mi.hdm.controllers;
 
 import javafx.fxml.FXML;
 import javafx.scene.control.Label;
+import javafx.scene.layout.AnchorPane;
 import javafx.scene.layout.TilePane;
 import javafx.scene.layout.VBox;
 import mi.hdm.recipes.Recipe;
@@ -16,6 +17,8 @@ public class RecipeViewController extends BaseController {
 
     @FXML
     private TilePane recipeTilePane;
+    @FXML
+    private AnchorPane parent;
 
     public RecipeViewController(RecipeManager recipeManager) {
         this.recipeManager = recipeManager;
@@ -33,6 +36,7 @@ public class RecipeViewController extends BaseController {
 
     @FXML
     public void initialize() {
+        loadHeader(parent);
         mapRecipes();
         log.debug("Added {} recipes to GUI", recipeManager.getRecipes().size());
     }
@@ -43,8 +47,21 @@ public class RecipeViewController extends BaseController {
             Label recipeDescription = new Label(recipe.getDescription());
             VBox currentRecipeBox = new VBox(recipeName, recipeDescription);
 
+            //TODO: make this recipe box a component class
+            recipeName.setStyle(
+                    "-fx-font-weight: 800;" +
+                            "-fx-font-scale: 16"
+            );
+
             currentRecipeBox.setPrefWidth(180);
             currentRecipeBox.setPrefHeight(250);
+            currentRecipeBox.setStyle(
+                    "-fx-background-color: #DEDEDE;" +
+                            "-fx-border-color: #D91C1C;" +
+                            "-fx-border-radius: 8;" +
+                            "-fx-border-width: 2;" +
+                            "-fx-padding: 8"
+            );
 
             recipeTilePane.getChildren().add(currentRecipeBox);
         }
diff --git a/src/main/java/mi/hdm/controllers/ShoppingListViewController.java b/src/main/java/mi/hdm/controllers/ShoppingListViewController.java
index 6563a40..d8b8eb0 100644
--- a/src/main/java/mi/hdm/controllers/ShoppingListViewController.java
+++ b/src/main/java/mi/hdm/controllers/ShoppingListViewController.java
@@ -1,11 +1,7 @@
 package mi.hdm.controllers;
 
 import javafx.fxml.FXML;
-import javafx.scene.control.Label;
 import javafx.scene.control.SplitPane;
-import javafx.scene.layout.TilePane;
-import javafx.scene.layout.VBox;
-import mi.hdm.recipes.Recipe;
 import mi.hdm.recipes.RecipeManager;
 import mi.hdm.shoppingList.ShoppingList;
 import org.apache.logging.log4j.LogManager;
diff --git a/src/main/java/mi/hdm/controllers/ViewComponent.java b/src/main/java/mi/hdm/controllers/ViewComponent.java
new file mode 100644
index 0000000..8551e0c
--- /dev/null
+++ b/src/main/java/mi/hdm/controllers/ViewComponent.java
@@ -0,0 +1,28 @@
+package mi.hdm.controllers;
+
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.IOException;
+
+public enum ViewComponent {
+    HEADER("/fxml/components/header.fxml");
+
+    private static final Logger log = LogManager.getLogger(ViewComponent.class);
+
+    private final String path;
+
+    ViewComponent(String path) {
+        this.path = path;
+    }
+
+    public Parent getParentElement() throws IOException {
+        log.info("Loading FXML for '{}' component from: {}", this, path);
+        final FXMLLoader loader = new FXMLLoader(getClass().getResource(path));
+        log.debug("Successfully retrieved resource from {}", path);
+
+        return loader.load();
+    }
+}
diff --git a/src/main/java/mi/hdm/screenshots.java b/src/main/java/mi/hdm/screenshots.java
deleted file mode 100644
index d9ea687..0000000
--- a/src/main/java/mi/hdm/screenshots.java
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-}
diff --git a/src/main/resources/fxml/Tasty_Pages_Main_Page.fxml b/src/main/resources/fxml/Tasty_Pages_Main_Page.fxml
index 3bb8a84..6b52eca 100644
--- a/src/main/resources/fxml/Tasty_Pages_Main_Page.fxml
+++ b/src/main/resources/fxml/Tasty_Pages_Main_Page.fxml
@@ -1,170 +1,34 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<!--
-  Copyright (c) 2015, 2019, Gluon and/or its affiliates.
-  All rights reserved. Use is subject to license terms.
-
-  This file is available and licensed under the following license:
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions
-  are met:
-
-  - Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-  - Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in
-    the documentation and/or other materials provided with the distribution.
-  - Neither the name of Oracle Corporation nor the names of its
-    contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--->
-
-<?import javafx.geometry.*?>
-<?import javafx.scene.control.*?>
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.Button?>
 <?import javafx.scene.Cursor?>
-<?import javafx.scene.image.*?>
+<?import javafx.scene.image.Image?>
+<?import javafx.scene.image.ImageView?>
 <?import javafx.scene.layout.*?>
-<?import javafx.scene.text.*?>
-<AnchorPane prefHeight="400.0" prefWidth="640.0" style="-fx-background-color: ffffff;" VBox.vgrow="ALWAYS"
+<AnchorPane fx:id="parent" prefHeight="400.0" prefWidth="640.0" VBox.vgrow="ALWAYS"
             xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1"
             fx:controller="mi.hdm.controllers.MainPageController">
-    <children>
-        <MenuButton contentDisplay="GRAPHIC_ONLY" graphicTextGap="0.0" layoutX="18.0" layoutY="21.0"
-                    mnemonicParsing="false" style="-fx-background-color: transparent;" textFill="TRANSPARENT">
-            <items>
-                <MenuItem mnemonicParsing="false" onAction="#changeSceneToHome" text="Home"/>
-                <MenuItem mnemonicParsing="false" onAction="#changeSceneToMealPlan" text="Meal Plan"/>
-                <MenuItem mnemonicParsing="false" onAction="#changeSceneToShoppingList" text="Shopping List"/>
-            </items>
-            <graphic>
-                <ImageView fitHeight="30.0" fitWidth="45.0" pickOnBounds="true" preserveRatio="true">
-                    <image>
-                        <Image url="@../images/Tasty_Pages_Menu_Button.png"/>
-                    </image>
-                </ImageView>
-            </graphic>
-            <cursor>
-                <Cursor fx:constant="DEFAULT"/>
-            </cursor>
-            <font>
-                <Font size="1.0E-4"/>
-            </font>
-        </MenuButton>
-        <TextField layoutX="450.0" layoutY="27.0"
-                   style="-fx-border-color: D91c1c; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10;"/>
-        <GridPane layoutX="58.0" layoutY="99.0" prefHeight="390.0" prefWidth="512.0" AnchorPane.leftAnchor="58.0">
-            <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>
-            <children>
-                <Pane prefHeight="192.0" prefWidth="159.0"
-                      style="-fx-background-color: dedede; -fx-background-radius: 15;">
-                    <GridPane.margin>
-                        <Insets bottom="6.0" left="6.0" right="6.0" top="6.0"/>
-                    </GridPane.margin>
-                    <Button contentDisplay="CENTER" layoutX="8.0" layoutY="6.0" mnemonicParsing="false"
-                            onAction="#addRecipe" prefHeight="169.0" prefWidth="144.0"
-                            style="-fx-background-color: transparent;" text="Button" textFill="TRANSPARENT">
-                        <graphic>
-                            <ImageView fitHeight="67.0" fitWidth="64.0" pickOnBounds="true" preserveRatio="true">
-                                <image>
-                                    <Image url="@../images/Tasty_Pages_Plus_Icon.png"/>
-                                </image>
-                            </ImageView>
-                        </graphic>
-                        <cursor>
-                            <Cursor fx:constant="HAND"/>
-                        </cursor>
-                    </Button>
-                </Pane>
-                <Pane prefHeight="155.0" prefWidth="154.0"
-                      style="-fx-background-color: dedede; -fx-background-radius: 15;" GridPane.columnIndex="1">
-                    <GridPane.margin>
-                        <Insets bottom="40.0" left="6.0" right="6.0" top="6.0"/>
-                    </GridPane.margin>
-                </Pane>
-                <Pane prefHeight="155.0" prefWidth="154.0"
-                      style="-fx-background-color: dedede; -fx-background-radius: 15;" GridPane.columnIndex="2">
-                    <GridPane.margin>
-                        <Insets bottom="40.0" left="6.0" right="6.0" top="6.0"/>
-                    </GridPane.margin>
-                </Pane>
-                <Pane prefHeight="198.0" prefWidth="163.0"
-                      style="-fx-background-color: dedede; -fx-background-radius: 15;" GridPane.rowIndex="1">
-                    <GridPane.margin>
-                        <Insets bottom="40.0" left="6.0" right="6.0" top="6.0"/>
-                    </GridPane.margin>
-                </Pane>
-                <Pane prefHeight="155.0" prefWidth="154.0"
-                      style="-fx-background-color: dedede; -fx-background-radius: 15;" GridPane.columnIndex="1"
-                      GridPane.rowIndex="1">
-                    <GridPane.margin>
-                        <Insets bottom="40.0" left="6.0" right="6.0" top="6.0"/>
-                    </GridPane.margin>
-                </Pane>
-                <Pane prefHeight="155.0" prefWidth="154.0"
-                      style="-fx-background-color: dedede; -fx-background-radius: 15;" GridPane.columnIndex="2"
-                      GridPane.rowIndex="1">
-                    <GridPane.margin>
-                        <Insets bottom="40.0" left="6.0" right="6.0" top="6.0"/>
-                    </GridPane.margin>
-                </Pane>
-                <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text" wrappingWidth="122.73394775390625"
-                      GridPane.columnIndex="1" GridPane.valignment="BOTTOM">
-                    <GridPane.margin>
-                        <Insets bottom="18.0" left="6.0"/>
-                    </GridPane.margin>
-                </Text>
-                <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text" wrappingWidth="122.73394775390625"
-                      GridPane.columnIndex="2" GridPane.valignment="BOTTOM">
-                    <GridPane.margin>
-                        <Insets bottom="18.0" left="6.0"/>
-                    </GridPane.margin>
-                </Text>
-                <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text" wrappingWidth="122.73394775390625"
-                      GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
-                    <GridPane.margin>
-                        <Insets bottom="18.0" left="6.0"/>
-                    </GridPane.margin>
-                </Text>
-                <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text" wrappingWidth="122.73394775390625"
-                      GridPane.columnIndex="1" GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
-                    <GridPane.margin>
-                        <Insets bottom="18.0" left="6.0"/>
-                    </GridPane.margin>
-                </Text>
-                <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Text" wrappingWidth="122.73394775390625"
-                      GridPane.columnIndex="2" GridPane.rowIndex="1" GridPane.valignment="BOTTOM">
-                    <GridPane.margin>
-                        <Insets bottom="18.0" left="6.0"/>
-                    </GridPane.margin>
-                </Text>
-            </children>
-        </GridPane>
-        <ImageView fitHeight="28.0" fitWidth="28.0" layoutX="453.0" layoutY="28.0" pickOnBounds="true"
-                   preserveRatio="true">
-            <image>
-                <Image url="@../images/Tasty_Pages_Search_Material_Design_Icons.png"/>
-            </image>
-        </ImageView>
-    </children>
+    <TilePane fx:id="recipeTilePane" hgap="8.0" prefHeight="400.0" prefTileHeight="250.0" prefTileWidth="180.0"
+              prefWidth="640.0" vgap="8.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
+              AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+        <Pane prefHeight="250.0" prefWidth="180.0" style="-fx-background-color: dedede; -fx-background-radius: 15;">
+            <Button contentDisplay="CENTER" mnemonicParsing="false" onAction="#addRecipe" prefHeight="250.0"
+                    prefWidth="180.0" style="-fx-background-color: transparent;" text="Button" textFill="TRANSPARENT">
+                <graphic>
+                    <ImageView fitHeight="67.0" fitWidth="64.0" pickOnBounds="true" preserveRatio="true">
+                        <image>
+                            <Image url="@../images/Tasty_Pages_Plus_Icon.png"/>
+                        </image>
+                    </ImageView>
+                </graphic>
+                <cursor>
+                    <Cursor fx:constant="HAND"/>
+                </cursor>
+            </Button>
+        </Pane>
+        <padding>
+            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
+        </padding>
+    </TilePane>
 </AnchorPane>
diff --git a/src/main/resources/fxml/components/header.fxml b/src/main/resources/fxml/components/header.fxml
new file mode 100644
index 0000000..ba151f6
--- /dev/null
+++ b/src/main/resources/fxml/components/header.fxml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.*?>
+<?import javafx.scene.Cursor?>
+<?import javafx.scene.Group?>
+<?import javafx.scene.image.Image?>
+<?import javafx.scene.image.ImageView?>
+<?import javafx.scene.layout.*?>
+<?import javafx.scene.text.Font?>
+<AnchorPane prefHeight="40" prefWidth="600" xmlns="http://javafx.com/javafx/17.0.2-ea"
+            xmlns:fx="http://javafx.com/fxml/1" fx:controller="mi.hdm.controllers.HeaderController">
+    <MenuButton contentDisplay="GRAPHIC_ONLY" graphicTextGap="0.0" mnemonicParsing="false"
+                style="-fx-background-color: transparent;" textFill="TRANSPARENT" AnchorPane.bottomAnchor="0.0"
+                AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
+        <items>
+            <MenuItem mnemonicParsing="false" onAction="#changeSceneToHome" text="Home"/>
+            <MenuItem mnemonicParsing="false" onAction="#changeSceneToMealPlan" text="Meal Plan"/>
+            <MenuItem mnemonicParsing="false" onAction="#changeSceneToShoppingList" text="Shopping List"/>
+        </items>
+        <graphic>
+            <ImageView fitHeight="30.0" fitWidth="45.0" pickOnBounds="true" preserveRatio="true">
+                <image>
+                    <Image url="@../../images/Tasty_Pages_Menu_Button.png"/>
+                </image>
+            </ImageView>
+        </graphic>
+        <cursor>
+            <Cursor fx:constant="DEFAULT"/>
+        </cursor>
+        <font>
+            <Font size="0.001"/>
+        </font>
+    </MenuButton>
+    <Group AnchorPane.rightAnchor="0.0">
+        <TextField alignment="CENTER" prefHeight="40.0" prefWidth="181.0" promptText="Search for a recipe..."
+                   style="-fx-border-color: D91c1c; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10;"/>
+        <ImageView fitHeight="28.0" fitWidth="28.0" layoutY="6.0" pickOnBounds="true" preserveRatio="true">
+            <image>
+                <Image url="@../../images/Tasty_Pages_Search_Material_Design_Icons.png"/>
+            </image>
+        </ImageView>
+    </Group>
+</AnchorPane>
diff --git a/src/main/resources/fxml/hello.fxml b/src/main/resources/fxml/hello.fxml
deleted file mode 100644
index 48d6369..0000000
--- a/src/main/resources/fxml/hello.fxml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<?import javafx.geometry.*?>
-<?import javafx.scene.control.*?>
-<?import java.lang.*?>
-<?import javafx.scene.layout.*?>
-
-
-<!--
-Adding stylesheets="/styles/styles.css" yet does not work, see FxmlGuiDriver as well.
--->
-
-<GridPane fx:controller="mi.hdm.HelloController"
-   hgap="5.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
-   prefHeight="402.0" prefWidth="600.0" styleClass="main-panel" vgap="5.0"
-   xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" >
-  <columnConstraints>
-    <ColumnConstraints hgrow="SOMETIMES" maxWidth="319.0" minWidth="10.0" prefWidth="279.0" />
-    <ColumnConstraints hgrow="SOMETIMES" maxWidth="470.0" minWidth="10.0" prefWidth="321.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>
-   <children>
-      <Label text="First name:" />
-      <Label text="Last name:" GridPane.rowIndex="1" />
-      <Button mnemonicParsing="false" onAction="#sayHello" text="Say hello" GridPane.rowIndex="2" />
-      <TextField fx:id="firstNameField" GridPane.columnIndex="1" />
-      <TextField fx:id="lastNameField" GridPane.columnIndex="1" GridPane.rowIndex="1" />
-      <Label fx:id="helloLabel" styleClass="hello-message" text="                   "
-               GridPane.columnIndex="1" GridPane.rowIndex="2" />
-   </children>
-   <padding>
-      <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
-   </padding>
-</GridPane>
diff --git a/src/main/resources/fxml/recipe-view.fxml b/src/main/resources/fxml/recipe-view.fxml
index 2ea9e1f..adbce37 100644
--- a/src/main/resources/fxml/recipe-view.fxml
+++ b/src/main/resources/fxml/recipe-view.fxml
@@ -1,37 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <?import javafx.geometry.Insets?>
-<?import javafx.scene.control.*?>
+<?import javafx.scene.control.SplitPane?>
 <?import javafx.scene.layout.*?>
-<AnchorPane prefHeight="400.0" prefWidth="677.0" xmlns="http://javafx.com/javafx/17.0.2-ea"
+<AnchorPane fx:id="parent" prefHeight="400.0" prefWidth="677.0" xmlns="http://javafx.com/javafx/17.0.2-ea"
             xmlns:fx="http://javafx.com/fxml/1" fx:controller="mi.hdm.controllers.RecipeViewController">
-    <SplitPane dividerPositions="0.1" orientation="VERTICAL" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
-               AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
-        <GridPane alignment="CENTER" maxHeight="48.0" prefHeight="48.0" prefWidth="675.0"
-                  style="-fx-background-color: D91C1C;">
-            <columnConstraints>
-                <ColumnConstraints percentWidth="15"/>
-                <ColumnConstraints percentWidth="50"/>
-                <ColumnConstraints percentWidth="35"/>
-            </columnConstraints>
-            <MenuButton mnemonicParsing="false" text="MENU">
-                <items>
-                    <MenuItem mnemonicParsing="false" onAction="#changeSceneToMain" text="Change scene"/>
-                    <MenuItem mnemonicParsing="false" text="Action 2"/>
-                </items>
-            </MenuButton>
-            <Label alignment="CENTER" prefHeight="17.0" prefWidth="352.0" GridPane.columnIndex="1">LOGO</Label>
-            <TextField GridPane.columnIndex="2"/>
-            <rowConstraints>
-                <RowConstraints/>
-            </rowConstraints>
-            <padding>
-                <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
-            </padding>
-        </GridPane>
-
-
-        <TilePane fx:id="recipeTilePane" prefHeight="333.0" prefWidth="675.0">
+    <SplitPane orientation="VERTICAL" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
+               AnchorPane.rightAnchor="0.0">
+        <TilePane fx:id="recipeTilePane" hgap="8.0" prefHeight="333.0" prefWidth="675.0" vgap="8.0">
             <padding>
                 <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
             </padding>
diff --git a/src/main/resources/fxml/shoppingList-view.fxml b/src/main/resources/fxml/shoppingList-view.fxml
index 287a8cf..19bc5a6 100644
--- a/src/main/resources/fxml/shoppingList-view.fxml
+++ b/src/main/resources/fxml/shoppingList-view.fxml
@@ -1,45 +1,54 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
+<?import javafx.geometry.Insets?>
 <?import javafx.scene.control.*?>
 <?import javafx.scene.layout.*?>
 <?import javafx.scene.text.Font?>
 <AnchorPane prefHeight="540.0" prefWidth="872.0" xmlns="http://javafx.com/javafx/17.0.2-ea"
             xmlns:fx="http://javafx.com/fxml/1" fx:controller="mi.hdm.controllers.ShoppingListViewController">
     <children>
-        <ToolBar prefHeight="40.0" prefWidth="606.0" style="-fx-background-color: FFFFFF;" AnchorPane.leftAnchor="0.0"
-                 AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
-            <items>
-                <MenuButton contentDisplay="CENTER" mnemonicParsing="false"
-                            style="-fx-background-color: FFFFFF; -fx-border-color: D91C1C; -fx-border-radius: 10; -fx-border-width: 2;"
-                            text="Menu">
+        <VBox prefHeight="200.0" prefWidth="100.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
+              AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
+            <children>
+                <ToolBar maxHeight="40.0" minHeight="40.0" prefHeight="40.0" style="-fx-background-color: FFFFFF;">
                     <items>
-                        <MenuItem mnemonicParsing="false" text="Meal Plan"/>
-                        <MenuItem mnemonicParsing="false" text="Shopping List"/>
+                        <MenuButton contentDisplay="CENTER" mnemonicParsing="false"
+                                    style="-fx-background-color: FFFFFF; -fx-border-color: D91C1C; -fx-border-radius: 10; -fx-border-width: 2;"
+                                    text="Menu">
+                            <items>
+                                <MenuItem mnemonicParsing="false" text="Meal Plan"/>
+                                <MenuItem mnemonicParsing="false" text="Shopping List"/>
+                            </items>
+                            <font>
+                                <Font name="Inter Regular" size="12.0"/>
+                            </font>
+                        </MenuButton>
+                        <Label alignment="CENTER" style="-fx-background-color: FFFFFF;" text="Tasty Pages">
+                            <font>
+                                <Font name="Inter Regular" size="12.0"/>
+                            </font>
+                        </Label>
                     </items>
+                </ToolBar>
+                <Label text="Shopping List">
                     <font>
-                        <Font name="Inter Regular" size="12.0"/>
+                        <Font name="Inter Regular" size="32.0"/>
                     </font>
-                </MenuButton>
-            <TextField alignment="CENTER" editable="false" style="-fx-background-color: FFFFFF;" text="Tasty Pages">
-               <font>
-                  <Font name="Inter Regular" size="12.0" />
-               </font>
-            </TextField>
-         </items></ToolBar>
-        <SplitPane fx:id="shoppingListSplitPane" dividerPositions="0.6341059602649006" layoutY="40.0"
-                   mouseTransparent="true" prefHeight="360.0" prefWidth="606.0" style="-fx-background-color: FFFFFF;"
-                   AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
-            <items>
-                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="360.0" prefWidth="379.0"
-                            style="-fx-background-color: FFFFFF; -fx-border-color: D91C1C; -fx-border-radius: 10; -fx-border-width: 4; -fx-border-insets: 15;">
-                    <children>
-                        <CheckBox layoutX="78.0" layoutY="42.0" mnemonicParsing="false" prefHeight="17.0"
+                </Label>
+                <SplitPane fx:id="shoppingListSplitPane" dividerPositions="0.6341059602649006" prefHeight="502.0"
+                           prefWidth="872.0" style="-fx-background-color: FFFFFF;" VBox.vgrow="ALWAYS">
+                    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="360.0" prefWidth="379.0"
+                                style="-fx-background-color: FFFFFF; -fx-border-color: D91C1C; -fx-border-radius: 10; -fx-border-width: 4;">
+                        <CheckBox layoutX="14.0" layoutY="14.0" mnemonicParsing="false" prefHeight="17.0"
                                   prefWidth="199.0" text="Ingredient1"/>
-                    </children>
-                </AnchorPane>
-                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="259.0" prefWidth="223.0"
-                            style="-fx-background-color: FFFFFF; -fx-border-color: D91C1C; -fx-border-width: 4; -fx-border-radius: 10; -fx-border-insets: 15;"/>
-            </items>
-        </SplitPane>
-   </children>
+                    </AnchorPane>
+                    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="259.0" prefWidth="223.0"
+                                style="-fx-background-color: FFFFFF; -fx-border-color: D91C1C; -fx-border-width: 4; -fx-border-radius: 10;"/>
+                </SplitPane>
+            </children>
+            <padding>
+                <Insets bottom="16.0" left="16.0" right="16.0" top="16.0"/>
+            </padding>
+        </VBox>
+    </children>
 </AnchorPane>
-- 
GitLab