diff --git a/src/main/java/edu/ntnu/idatt2003/controller/MainPageController.java b/src/main/java/edu/ntnu/idatt2003/controller/MainPageController.java
index 0ba835e2c06a4219a5adc968ffadcedb99cf3dee..d8fdeea82ca86ade8da6993d8e23822dc1228180 100644
--- a/src/main/java/edu/ntnu/idatt2003/controller/MainPageController.java
+++ b/src/main/java/edu/ntnu/idatt2003/controller/MainPageController.java
@@ -1,31 +1,37 @@
 package edu.ntnu.idatt2003.controller;
 
+import edu.ntnu.idatt2003.model.AffineTransform2D;
 import edu.ntnu.idatt2003.model.ChaosGame;
 import edu.ntnu.idatt2003.model.ChaosGameDescription;
 import edu.ntnu.idatt2003.model.ChaosGameDescriptionFactory;
 import edu.ntnu.idatt2003.model.ChaosGameFileHandler;
 import edu.ntnu.idatt2003.model.Complex;
 import edu.ntnu.idatt2003.model.JuliaTransform;
+import edu.ntnu.idatt2003.model.Matrix2x2;
 import edu.ntnu.idatt2003.model.Transform2D;
 import edu.ntnu.idatt2003.model.Vector2d;
 import edu.ntnu.idatt2003.view.MainPageView;
-import java.util.ArrayList;
-import java.util.List;
+
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.io.FileNotFoundException;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
 import java.util.InputMismatchException;
+import java.util.List;
 import java.util.logging.FileHandler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.SimpleFormatter;
+import java.util.stream.DoubleStream;
+import java.util.stream.Stream;
 
 /**
  * The controller class for the main page of the ChaosGame application.
@@ -35,7 +41,8 @@ import java.util.logging.SimpleFormatter;
 public class MainPageController {
   private final ChaosGame game;
   private final MainPageView view;
-  private List<String> customTransformations = new ArrayList<>();
+  private final List<String> customTransformations;
+  private boolean addingCustomTransformation;
   private static final String TRANSFORMATIONS_PATH = "src/main/resources/transformations/";
   private static final String SERIALIZED_GAME_PATH = "src/main/resources/savedTransformation.ser";
   private static final Logger LOGGER = Logger.getLogger(MainPageController.class.getName());
@@ -64,6 +71,8 @@ public class MainPageController {
     this.game = loadGameState();
     this.view = new MainPageView(this);
     this.game.registerObserver(view);
+    this.customTransformations = new ArrayList<>(getAllCustomTransforms());
+    this.addingCustomTransformation = false;
     this.view.render();
     Runtime.getRuntime().addShutdownHook(new Thread(this::saveGameState));
     LOGGER.log(Level.INFO, "MainPageController initialized successfully.");
@@ -87,6 +96,64 @@ public class MainPageController {
     return game;
   }
 
+  public double[] getMinCoordsX() {
+    return game.getMinCoordsList();
+  }
+
+  public double[] getMaxCoordsX() {
+    return game.getMaxCoordsList();
+  }
+
+  public String getCurrentTransformationName() {
+    return game.getDescriptionName();
+  }
+
+  public boolean isAddingCustomTransformation() {
+    return addingCustomTransformation;
+  }
+  /**
+   * Get the list of coordinate-arrays of the game.
+   *
+   * @return the list of coordinate-arrays of the game.
+   */
+  public List<double[]> getTransformList() {
+    if (transformationIsJulia()) {
+      return getTransformListJulia();
+    } else {
+      return getTransformListAffine();
+    }
+  }
+
+  private List<double[]> getTransformListJulia() {
+    List<double[]> transformList = new ArrayList<>();
+    transformList.add(((JuliaTransform) game.getTransformList().get(0)).getPointAsList());
+    return transformList;
+  }
+
+  private List<double[]> getTransformListAffine() {
+    List<double[]> transformList = new ArrayList<>();
+    for (Transform2D transform : game.getTransformList()) {
+      transformList.add(DoubleStream.concat(DoubleStream.of(((AffineTransform2D) transform)
+              .getMatrixCoordsList()), DoubleStream.of(((AffineTransform2D) transform)
+              .getVectorCoordsList())).toArray());
+    }
+    return transformList;
+  }
+
+  /**
+   * Check if the current transformation is a Julia set. If it is,
+   * return true and false otherwise.
+   *
+   * @return true if the transformation is a Julia set, false otherwise.
+   */
+  public boolean transformationIsJulia() {
+    try {
+      return game.getTransformList().get(0) instanceof JuliaTransform;
+    } catch (IndexOutOfBoundsException e) {
+      return false;
+    }
+  }
+
   /**
    * Run the chaos game simulation for the specified number of steps. If
    * the number of steps is negative, the canvas will be cleared.
@@ -98,6 +165,24 @@ public class MainPageController {
     LOGGER.log(Level.INFO, "Chaos game simulation ran {0} steps successfully.", steps);
   }
 
+  /**
+   * Run the chaos game simulation for the specified number of steps. If
+   * the number of steps is negative, the canvas will be cleared. If the
+   * input cant be converted to an integer, an alert will be shown. And
+   * no steps will be run.
+   *
+   * @param steps The number of steps to run the simulation.
+   */
+  public void runCustomSteps(String steps) {
+    try {
+      int stepsInt = Integer.parseInt(steps);
+      runSteps(stepsInt);
+    } catch (NumberFormatException e) {
+      view.showAlert("Invalid input. Please enter a valid integer.");
+      LOGGER.log(Level.WARNING, "Invalid input. Chaos game simulation was not run.");
+    }
+  }
+
   /**
    * Validates the file that is uploaded., and calls storeFile if the
    * file exists and is formatted correctly.
@@ -107,20 +192,23 @@ public class MainPageController {
    */
   public void uploadFile(File file) {
     LOGGER.log(Level.INFO, "Uploading file: {0}", file.getName());
-    validateFile(file);
-    if (!Files.exists(Path.of(TRANSFORMATIONS_PATH + file.getName()))
-            || view.askConfirmation("File already exists. Do you want to overwrite it?")) {
+    if (validateFile(file)
+            && (!Files.exists(Path.of(TRANSFORMATIONS_PATH + file.getName()))
+            || view.askConfirmation("File already exists. Do you want to overwrite it?"))) {
       storeFile(file);
+      LOGGER.log(Level.INFO, "File {0} uploaded successfully.", file.getName());
+      view.showAlert("File " + file.getName() + " uploaded successfully.");
     }
-
   }
 
-  private void validateFile(File file) {
+  private boolean validateFile(File file) {
     try {
       new ChaosGameFileHandler().readFromFile(file);
+      return true;
     } catch (InputMismatchException | FileNotFoundException e) {
       view.showAlert(e.getMessage());
       LOGGER.log(Level.WARNING, "Error uploading file. File was not uploaded.");
+      return false;
     }
   }
 
@@ -149,16 +237,36 @@ public class MainPageController {
    */
   public void changeTransformation(ChaosGameDescriptionFactory
                                            .descriptionTypeEnum descriptionType) {
-    game.changeTransformation(descriptionType);
+    addingCustomTransformation = false;
+    game.changeTransformation(ChaosGameDescriptionFactory.get(descriptionType),
+            descriptionType.toString());
+
     LOGGER.log(Level.INFO, "Transformation was changed successfully to {0}",
-        descriptionType);
+            descriptionType);
+  }
+
+  /**
+   * Changes the current transformation based on the given custom name.
+   *
+   * @param customName the name of the custom transformation to be applied
+   */
+  public void changeTransformation(String customName) {
+    if (customName.equalsIgnoreCase("add new")) {
+      addingCustomTransformation = true;
+      this.view.render();
+    } else {
+      addingCustomTransformation = false;
+      game.changeTransformation(ChaosGameDescriptionFactory.getCustom(customName), customName);
+      LOGGER.log(Level.INFO, "Transformation was changed successfully to {0}",
+              customName);
+    }
   }
 
   private void saveGameState() {
     LOGGER.log(Level.INFO, "Saving game state.");
     game.removeObserver(view);
     try (ObjectOutputStream oos = new ObjectOutputStream(
-        new FileOutputStream(SERIALIZED_GAME_PATH))) {
+            new FileOutputStream(SERIALIZED_GAME_PATH))) {
       oos.writeObject(game);
       LOGGER.log(Level.INFO, "Game state saved successfully in {0}", SERIALIZED_GAME_PATH);
     } catch (IOException e) {
@@ -187,51 +295,162 @@ public class MainPageController {
     } else {
       LOGGER.log(Level.WARNING, "No saved game state found. Creating new game.");
     }
-    return new ChaosGame(ChaosGameDescriptionFactory
+    ChaosGame newGame = new ChaosGame(ChaosGameDescriptionFactory
             .get(ChaosGameDescriptionFactory.descriptionTypeEnum.SIERPINSKI_TRIANGLE),
-            600, 600);
+            650, 650);
+    newGame.setDescriptionName(ChaosGameDescriptionFactory.descriptionTypeEnum
+            .SIERPINSKI_TRIANGLE.toString());
+    return newGame;
   }
 
   /**
-   * Changes the current custom transformation based on the given custom name.
+   * Adds a new custom transformation with the specified parameters and writes it to a file.
    *
-   * @param customName the name of the custom transformation to be applied
+   * @param minCoords          the minimum coordinates for the transformation
+   * @param maxCoords          the maximum coordinates for the transformation
+   * @param transform          the list of 2D transformations to be applied
+   * @param transformationName the name of the custom transformation
    */
 
-  public void changeCustomTransformation(String customName) {
-    ChaosGameDescription chaosGameDescription = customNameHandle(customName);
-    game.changeCustomTransformation(chaosGameDescription);
+  public void addCustomTransformation(String[] minCoords, String[] maxCoords,
+                                      List<String[]> transform, String transformationName) {
+    ChaosGameFileHandler chaosGameFileHandler = new ChaosGameFileHandler();
+    try {
+      ChaosGameDescription newChaosGameDescription =
+              new ChaosGameDescription(
+                      getVector2dFromStringList(minCoords),
+                      getVector2dFromStringList(maxCoords),
+                      getTransformListFromStringList(transform)
+              );
+      if (!Files.exists(Path.of(TRANSFORMATIONS_PATH + transformationName + ".txt"))
+      || view.askConfirmation("Custom transformation with the same name already exists. "
+              + "Do you want to overwrite it?")) {
+        chaosGameFileHandler
+                .writeToFile(newChaosGameDescription,
+                        TRANSFORMATIONS_PATH + transformationName + ".txt");
+        customTransformations.add(transformationName);
+        view.render();
+        view.showAlert("Custom transformation " + transformationName + " added successfully.");
+      }
+
+    } catch (IllegalArgumentException e) {
+      view.showAlert(e.getMessage());
+    }
+
+
   }
 
   /**
-   * Retrieves the ChaosGameDescription associated with the given custom name.
+   * Creates a Vector2d object from a string array, containing the x and y coordinates.
    *
-   * @param customName the name of the custom transformation
-   * @return the ChaosGameDescription corresponding to the custom name
+   * @param vector the string array containing the x and y coordinates
+   * @return the Vector2d object created from the string array
    */
+  private Vector2d getVector2dFromStringList(String[] vector) {
+    try {
+      return new Vector2d(Double.parseDouble(vector[0]), Double.parseDouble(vector[1]));
+    } catch (NumberFormatException e) {
+      throw new IllegalArgumentException("Invalid coordinates. Please enter valid integers.");
+    }
+  }
+
+  /**
+   * Creates a list of Transform2D objects from a list of string arrays.
+   *
+   * @param transform the list of string arrays containing the transformation parameters
+   * @return the list of Transform2D objects created from the string arrays
+   */
+  private List<Transform2D> getTransformListFromStringList(List<String[]> transform)
+          throws NumberFormatException {
+    try {
+      List<Transform2D> transformList = new ArrayList<>();
+      for (String[] transformation : transform) {
+        if (transformation.length == 2) {
+          transformList.addAll(parseJuliaTransform(transformation));
+        } else if (transformation.length == 6) {
+          transformList.add(parseAffineTransform(transformation));
+        }
+      }
+      return transformList;
+    } catch (NumberFormatException e) {
+      throw new IllegalArgumentException("Invalid coordinates. Please "
+              + "enter valid decimal numbers.");
+    }
 
-  public ChaosGameDescription customNameHandle(String customName) {
-    return ChaosGameDescriptionFactory.getCustom(customName);
   }
 
   /**
-   * Adds a new custom transformation with the specified parameters and writes it to a file.
+   * Parses the Julia transformations and returns a List of Julia Transformations.
    *
-   * @param minCoords the minimum coordinates for the transformation
-   * @param maxCoords the maximum coordinates for the transformation
-   * @param transform the list of 2D transformations to be applied
-   * @param transformationName the name of the custom transformation
+   * @param transformation the string array containing the transformation parameters
+   * @return the list of Julia Transformations
    */
+  private List<Transform2D> parseJuliaTransform(String[] transformation) {
+    return List.of(
+            new JuliaTransform(
+                    new Complex(
+                            Double.parseDouble(transformation[0]),
+                            Double.parseDouble(transformation[1])
+                    ),
+                    1),
+            new JuliaTransform(
+                    new Complex(
+                            Double.parseDouble(transformation[0]),
+                            Double.parseDouble(transformation[1])
+                    ),
+                    1)
+    );
+  }
 
-  public void addCustomTransformation(Vector2d minCoords, Vector2d maxCoords,
-      List<Transform2D> transform, String transformationName) {
-    ChaosGameFileHandler chaosGameFileHandler = new ChaosGameFileHandler();
-    ChaosGameDescription newChaosGameDescription =
-        new ChaosGameDescription(minCoords, maxCoords, transform);
-    chaosGameFileHandler
-        .writeToFile(newChaosGameDescription, TRANSFORMATIONS_PATH + transformationName + ".txt");
-    customTransformations.add(transformationName);
-    view.render();
+  /**
+   * Parses the Affine transformations and returns a List of Julia Transformations.
+   *
+   * @param transformation the string array containing the transformation parameters
+   * @return the list of Affine Transformations
+   */
+  private AffineTransform2D parseAffineTransform(String[] transformation) {
+    return new AffineTransform2D(
+            new Matrix2x2(
+                    Double.parseDouble(transformation[0]),
+                    Double.parseDouble(transformation[1]),
+                    Double.parseDouble(transformation[2]),
+                    Double.parseDouble(transformation[3])
+            ),
+            new Vector2d(
+                    Double.parseDouble(transformation[4]),
+                    Double.parseDouble(transformation[5])
+            ));
+
+  }
+
+  /**
+   * Retrieves a list of all custom transformation files in the transformations directory
+   * and updates the customTransformations list.*
+   *
+   * @return the updated list of custom transformation file names.
+   */
+  public List<String> getAllCustomTransforms() {
+    List<String> transformations = new ArrayList<>();
+    Path transformationsPath = Paths.get(TRANSFORMATIONS_PATH);
+
+    if (Files.exists(transformationsPath) && Files.isDirectory(transformationsPath)) {
+      try (Stream<Path> paths = Files.list(transformationsPath)) {
+        transformations = paths
+                .filter(Files::isRegularFile)
+                .map(Path::getFileName)
+                .map(Path::toString)
+                .map(name -> name.replace(".txt", ""))
+                .toList();
+        LOGGER.log(Level.INFO, "All custom transformations retrieved successfully.");
+      } catch (IOException e) {
+        LOGGER.log(Level.WARNING, "Error retrieving custom transformation files.", e);
+      }
+    } else {
+      LOGGER.log(Level.WARNING, "Transformations directory does not exist or is not a " +
+              "directory.");
+    }
+
+    return transformations;
   }
 
   /**
diff --git a/src/main/java/edu/ntnu/idatt2003/model/AffineTransform2D.java b/src/main/java/edu/ntnu/idatt2003/model/AffineTransform2D.java
index 35d5520f4b2cee57bfb19fdbd9a89c2785e34289..88cc39d9bbd9aff4118ac9cc3f3522a58bb77b3d 100644
--- a/src/main/java/edu/ntnu/idatt2003/model/AffineTransform2D.java
+++ b/src/main/java/edu/ntnu/idatt2003/model/AffineTransform2D.java
@@ -46,6 +46,12 @@ public class AffineTransform2D implements Transform2D, Serializable {
     return matrix.multiply(point).add(vector);
   }
 
+  public double[] getMatrixCoordsList() {
+    return matrix.getCoordsList();
+  }
+  public double[] getVectorCoordsList() {
+    return vector.getCoordsList();
+  }
   /**
    * Returns a string representation of the AffineTransform2D, by combining the strings
    * of the matrix and vector separated by a ','.
diff --git a/src/main/java/edu/ntnu/idatt2003/model/ChaosGame.java b/src/main/java/edu/ntnu/idatt2003/model/ChaosGame.java
index 14bd40bf85ed3f46dd2a2859d56c0548ee0919db..c977f328a9367261b908cbd8407c342303bab75c 100644
--- a/src/main/java/edu/ntnu/idatt2003/model/ChaosGame.java
+++ b/src/main/java/edu/ntnu/idatt2003/model/ChaosGame.java
@@ -16,6 +16,7 @@ public class ChaosGame implements Serializable {
 
   private ChaosCanvas canvas;
   private ChaosGameDescription description;
+  private String descriptionName;
   private Vector2d currentPoint;
   private final int width;
   private final int height;
@@ -35,6 +36,7 @@ public class ChaosGame implements Serializable {
     this.observers = new ArrayList<>();
     this.width = width;
     this.height = height;
+    this.descriptionName = "";
     setDescription(description);
     randomGenerator = new Random();
     this.totalSteps = 0;
@@ -45,26 +47,84 @@ public class ChaosGame implements Serializable {
    *
    * @return The canvas of the chaos game.
    */
-
   public ChaosCanvas getCanvas() {
     return canvas;
   }
 
+  /**
+   * Returns the minimum coordinates of the chaos game.
+   *
+   * @return The minimum coordinates of the chaos game.
+   */
+  public double[] getMinCoordsList() {
+    return description.getMinCoordsList();
+  }
+
+  /**
+   * Returns the maximum coordinates of the chaos game.
+   *
+   * @return The maximum coordinates of the chaos game.
+   */
+  public double[] getMaxCoordsList() {
+    return description.getMaxCoordsList();
+  }
+
+  /**
+   * Returns the list of transformations of the chaos game.
+   *
+   * @return The list of transformations of the chaos game.
+   */
+  public List<Transform2D> getTransformList() {
+    return description.getTransform();
+  }
+
+  /**
+   * Returns the total number of steps run in the chaos game.
+   *
+   * @return The total number of steps run in the chaos game.
+   */
   public int getTotalSteps() {
     return totalSteps;
   }
+
+  public String getDescriptionName() {
+    return descriptionName;
+  }
+
+  public void setDescriptionName(String descriptionName) {
+    this.descriptionName = descriptionName;
+  }
+
+  /**
+   * Runs the chaos game simulation for the specified number of steps, by
+   * calling the runSteps-method and passing true as the second parameter
+   * to also update totalSteps.
+   *
+   * @param steps The number of steps to run the simulation.
+   */
   public void runStepsAndUpdateTotal(int steps) {
     runSteps(steps, true);
   }
+
+  /**
+   * Runs the chaos game simulation for the specified number of steps, by
+   * calling the runSteps-method and passing false as the second parameter
+   * to not update totalSteps.
+   *
+   * @param steps The number of steps to run the simulation.
+   */
   public void runStepsWithoutUpdatingTotal(int steps) {
     runSteps(steps, false);
   }
+
   /**
-   * Runs the chaos game simulation for the specified number of steps.
-   * Generates points on the canvas based on random chosen transformation.
-   * The current point is replaced with the new, which gets transformed by a random transformation.
+   * Runs the chaos game simulation for the specified number of steps or cleared
+   * if steps is negative. Generates points on the canvas based on random chosen
+   * transformation. If addSteps is true, the totalSteps is updated, if false,
+   * the totalSteps is not updated. In the end, the observers are notified.
    *
-   * @param steps The number of steps to run the simulation.
+   * @param steps    The number of steps to run the simulation.
+   * @param addSteps Whether to update the totalSteps or not.
    */
   private void runSteps(int steps, boolean addSteps) {
     if (steps < 0) {
@@ -81,6 +141,10 @@ public class ChaosGame implements Serializable {
     notifyObservers();
   }
 
+  /**
+   * Generates a point on the canvas based on a random transformation, and puts
+   * the point on the canvas. It also updates the current point to the new point.
+   */
   private void applyRandomTransformation() {
     int randomIndex = randomGenerator.nextInt(description.getTransform().size());
     currentPoint = description.getTransform().get(randomIndex).transform(currentPoint);
@@ -91,15 +155,13 @@ public class ChaosGame implements Serializable {
    * Changes the transformation of the chaos game. Calls the setDescription-method
    * and notifies the observers that it has changed.
    *
-   * @param descriptionType The type of fractal description to retrieve.
+   * @param chaosGameDescription The type of fractal description to retrieve.
    */
-  public void changeTransformation(ChaosGameDescriptionFactory
-                                           .descriptionTypeEnum descriptionType) {
-    setDescription(ChaosGameDescriptionFactory.get(descriptionType));
-    notifyObservers();
-  }
-  public void changeCustomTransformation(ChaosGameDescription customDescription) {
-    setDescription(customDescription);
+  public void changeTransformation(ChaosGameDescription chaosGameDescription,
+                                   String descriptionName) {
+    setDescription(chaosGameDescription);
+    setDescriptionName(descriptionName);
+    totalSteps = 0;
     notifyObservers();
   }
 
diff --git a/src/main/java/edu/ntnu/idatt2003/model/ChaosGameDescription.java b/src/main/java/edu/ntnu/idatt2003/model/ChaosGameDescription.java
index 877d9e5b75e77699c87239104147246c7a133693..1ac83190e11ed57c7cde292419bd7977c2cdf77f 100644
--- a/src/main/java/edu/ntnu/idatt2003/model/ChaosGameDescription.java
+++ b/src/main/java/edu/ntnu/idatt2003/model/ChaosGameDescription.java
@@ -54,6 +54,12 @@ public class ChaosGameDescription implements Serializable {
     return maxCoords;
   }
 
+  public double[] getMinCoordsList() {
+    return minCoords.getCoordsList();
+  }
+  public double[] getMaxCoordsList() {
+    return maxCoords.getCoordsList();
+  }
   /**
    * Get the list of transformations to be used.
    *
diff --git a/src/main/java/edu/ntnu/idatt2003/model/JuliaTransform.java b/src/main/java/edu/ntnu/idatt2003/model/JuliaTransform.java
index 0ed9503bec436190bd53b27b5387c0757c865a40..47a342b4d1050328cd8beddcb7fb304153825378 100644
--- a/src/main/java/edu/ntnu/idatt2003/model/JuliaTransform.java
+++ b/src/main/java/edu/ntnu/idatt2003/model/JuliaTransform.java
@@ -32,6 +32,9 @@ public class JuliaTransform implements Transform2D, Serializable {
     this.sign = sign;
   }
 
+  public double[] getPointAsList() {
+    return new double[]{point.getX0(), point.getX1()};
+  }
   /**
    * Transforms a 2D vector by taking adding/subtracting based on the sign
    * and taking the square root.
diff --git a/src/main/java/edu/ntnu/idatt2003/model/Matrix2x2.java b/src/main/java/edu/ntnu/idatt2003/model/Matrix2x2.java
index 139a41fe61be2de8a28ac0dc357c646e3cbde9f8..fab4921812b3d03a447a64ababc990de1e40fe45 100644
--- a/src/main/java/edu/ntnu/idatt2003/model/Matrix2x2.java
+++ b/src/main/java/edu/ntnu/idatt2003/model/Matrix2x2.java
@@ -42,6 +42,9 @@ public class Matrix2x2 implements Serializable {
     double x1 = a10 * vector.getX0() + a11 * vector.getX1();
     return new Vector2d(x0, x1);
   }
+  public double[] getCoordsList() {
+    return new double[]{a00, a01, a10, a11};
+  }
 
   /**
    * Returns a string representation of the Matrix2x2, that separates the
diff --git a/src/main/java/edu/ntnu/idatt2003/model/Vector2d.java b/src/main/java/edu/ntnu/idatt2003/model/Vector2d.java
index b6b449797a71dd80cb9f5dd0863204b5bd62e68e..04b78c8b98f11eeae65902240095d37fcf81f59c 100644
--- a/src/main/java/edu/ntnu/idatt2003/model/Vector2d.java
+++ b/src/main/java/edu/ntnu/idatt2003/model/Vector2d.java
@@ -51,6 +51,9 @@ public class Vector2d implements Serializable {
     return x1;
   }
 
+  public double[] getCoordsList() {
+    return new double[]{x0, x1};
+  }
   /**
    * Adds another vector to this vector.
    *
diff --git a/src/main/java/edu/ntnu/idatt2003/view/MainPageView.java b/src/main/java/edu/ntnu/idatt2003/view/MainPageView.java
index 1c666cb8de2deb679fad65ba0c3a3195b7fe7ef6..19c2a003e018dfbcba5992efd0a061a09e04a7b1 100644
--- a/src/main/java/edu/ntnu/idatt2003/view/MainPageView.java
+++ b/src/main/java/edu/ntnu/idatt2003/view/MainPageView.java
@@ -1,33 +1,31 @@
 package edu.ntnu.idatt2003.view;
 
 import edu.ntnu.idatt2003.controller.MainPageController;
-import edu.ntnu.idatt2003.model.AffineTransform2D;
 import edu.ntnu.idatt2003.model.ChaosGameDescriptionFactory;
 import edu.ntnu.idatt2003.model.ChaosGameObserver;
-import edu.ntnu.idatt2003.model.Complex;
-import edu.ntnu.idatt2003.model.JuliaTransform;
-import edu.ntnu.idatt2003.model.Matrix2x2;
-import edu.ntnu.idatt2003.model.Transform2D;
-import edu.ntnu.idatt2003.model.Vector2d;
 import edu.ntnu.idatt2003.utils.Sizes;
+import edu.ntnu.idatt2003.view.components.ChaosImage;
+import edu.ntnu.idatt2003.view.components.StyledButton;
+import edu.ntnu.idatt2003.view.components.StyledComboBox;
+import edu.ntnu.idatt2003.view.components.StyledTextField;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Locale;
 import java.util.Objects;
-import javafx.event.ActionEvent;
-import javafx.event.EventHandler;
 import javafx.geometry.Pos;
 import javafx.scene.Node;
 import javafx.scene.Scene;
 import javafx.scene.control.Alert;
-import javafx.scene.control.Button;
 import javafx.scene.control.ButtonType;
 import javafx.scene.control.ComboBox;
+import javafx.scene.control.Label;
 import javafx.scene.control.TextField;
 import javafx.scene.layout.BorderPane;
 import javafx.scene.layout.HBox;
 import javafx.scene.layout.Pane;
+import javafx.scene.layout.Priority;
 import javafx.scene.layout.Region;
 import javafx.scene.layout.StackPane;
 import javafx.scene.layout.VBox;
@@ -42,16 +40,14 @@ import javafx.stage.Stage;
  */
 public class MainPageView extends Scene implements ChaosGameObserver {
   private final BorderPane root;
-  private final StackPane pageContainer;
   private final MainPageController controller;
-  private static final int PAGE_CONTAINER_MARGIN = 50;
-  private static final int BUTTON_COUNT = 6;
-  private static final int BUTTON_HEIGHT = 40;
-  private static final int BUTTON_WIDTH = (int) (Sizes.SCREEN_WIDTH - PAGE_CONTAINER_MARGIN)
-          / BUTTON_COUNT;
-  private static TextField xField;
-  private static TextField yField;
-
+  private static final int BUTTON_COUNT = 7;
+  private static final int COMPONENT_HEIGHT = 40;
+  private static final int BUTTON_WIDTH = (int) (Sizes.SCREEN_WIDTH) / BUTTON_COUNT;
+  private static final int DEFAULT_SPACING = 10;
+  private TextField x0Field;
+  private TextField x1Field;
+  private TransformationType selectedTransformation;
 
 
   /**
@@ -63,9 +59,11 @@ public class MainPageView extends Scene implements ChaosGameObserver {
     super(new BorderPane(), Sizes.SCREEN_WIDTH, Sizes.SCREEN_HEIGHT);
     this.getStylesheets().add(Objects.requireNonNull(getClass()
             .getResource("/styles/mainPage.css")).toExternalForm());
+    this.getStylesheets().add(Objects.requireNonNull(getClass()
+            .getResource("/styles/components.css")).toExternalForm());
 
     root = (BorderPane) this.getRoot();
-    pageContainer = new StackPane();
+    this.selectedTransformation = TransformationType.AFFINE;
     this.controller = mainPageController;
   }
 
@@ -75,8 +73,8 @@ public class MainPageView extends Scene implements ChaosGameObserver {
    */
   public void render() {
     root.getStyleClass().add("main-page");
-    pageContainer.getChildren().clear();
-    createPageContainer();
+    root.getChildren().clear();
+    createPage();
   }
 
   /**
@@ -87,22 +85,140 @@ public class MainPageView extends Scene implements ChaosGameObserver {
   }
 
   /**
-   * Creates the page container with a button container.
-   * The button container contains 7 buttons.
+   * Creates the page with a button container at the top and an edit panel,
+   * dynamic julia container and the canvas at the bottom.
+   */
+  private void createPage() {
+    root.setTop(createButtonContainer());
+    root.setCenter(createCenterContainer());
+  }
+
+  /**
+   * Creates the center container with the edit panel and the dynamic julia container.
+   *
+   * @return The center container.
+   */
+  private HBox createCenterContainer() {
+    HBox centerContainer = new HBox(DEFAULT_SPACING);
+    centerContainer.getStyleClass().add("center-container");
+    centerContainer.getChildren().addAll(
+            createEditPanelAndDynamicJuliaContainer(),
+            ChaosImage.createImageFromCanvas(controller.getGame().getCanvas())
+    );
+    return centerContainer;
+  }
+
+  /**
+   * Creates the edit panel and the dynamic julia container.
+   *
+   * @return The edit panel and the dynamic julia container.
+   */
+  private VBox createEditPanelAndDynamicJuliaContainer() {
+    VBox editPanelAndDynamicJuliaContainer = new VBox(DEFAULT_SPACING);
+    HBox.setHgrow(editPanelAndDynamicJuliaContainer, Priority.ALWAYS);
+
+    editPanelAndDynamicJuliaContainer.getStyleClass().add("canvas-and-dynamic-julia-container");
+    editPanelAndDynamicJuliaContainer.getChildren().addAll(
+            createAddTransformationPanel(),
+            createVboxSpacing(),
+            createDynamicJuliaContainer()
+    );
+    return editPanelAndDynamicJuliaContainer;
+  }
+
+  /**
+   * Creates the dynamic julia container with the julia information and the mouse box.
+   *
+   * @return The dynamic julia container.
+   */
+  private HBox createDynamicJuliaContainer() {
+    HBox dynamicJuliaContainer = new HBox(DEFAULT_SPACING);
+    dynamicJuliaContainer.setAlignment(Pos.BOTTOM_CENTER);
+    x0Field = new StyledTextField("x: ", 100, 20);
+    x1Field = new StyledTextField("y: ", 100, 20);
+    if (controller.transformationIsJulia()) {
+      VBox juliaInformationContainer = new VBox(DEFAULT_SPACING);
+      HBox.setHgrow(juliaInformationContainer, Priority.ALWAYS);
+      juliaInformationContainer.getChildren().addAll(
+              createTextBox("Total steps: " + controller.getGame().getTotalSteps()),
+              new HBox(10, createTextBox("X-value: "), x0Field),
+              new HBox(10, createTextBox("Y-value: "), x1Field)
+      );
+      dynamicJuliaContainer.getChildren().addAll(
+              juliaInformationContainer,
+              mouseBox()
+      );
+    }
+    return dynamicJuliaContainer;
+  }
+
+  /**
+   * Creates a Region that fills the remaining space in a VBoc.
+   *
+   * @return The Region that fills the VBox.
+   */
+  private Region createVboxSpacing() {
+    Region spacing = new Region();
+    VBox.setVgrow(spacing, Priority.ALWAYS);
+    return spacing;
+  }
+
+  /**
+   * Creates a text box with the specified text. The text box is styled with the
+   * "text-box" style class. The text box is a StackPane with a Label as a child.
+   * The text box is configured to grow horizontally.
+   *
+   * @param text The text to display in the text box.
+   * @return The text box.
+   */
+  private StackPane createTextBox(String text) {
+    StackPane textBox = new StackPane();
+    textBox.getStyleClass().add("text-box");
+    HBox.setHgrow(textBox, Priority.ALWAYS);
+    textBox.getChildren().add(new Label(text));
+    return textBox;
+  }
+
+  /**
+   * Creates a HBox containing a text box with the specified text and as many text fields
+   * as specified is given prompt text to, which gets the size given as parameters.
+   *
+   * @param text        The text to display in the text box.
+   * @param width       The width of the text field.
+   * @param height      The height of the text field.
+   * @param promptTexts The prompt texts for the text fields.
+   * @return The HBox containing the text box and text fields.
+   */
+  private HBox createTextBoxWithTextField(String text, int width,
+                                          int height, String... promptTexts) {
+    HBox container = new HBox(DEFAULT_SPACING);
+    container.getChildren().add(createTextBox(text));
+    for (String promptText : promptTexts) {
+      container.getChildren().add(new StyledTextField(promptText, width, height));
+    }
+    return container;
+  }
+
+  /**
+   * Creates a HBox containing a text box with the specified text and as many text fields
+   * as the length of the doubles array, which gets the height and with given as parameters.
+   *
+   * @param text   The text to display in the text box.
+   * @param width  The width of the text field.
+   * @param height The height of the text field.
+   * @param coords The text for the StyledTextField.
+   * @return The HBox containing the text box and text fields.
    */
-  private void createPageContainer() {
-    HBox contentContainer = new HBox(
-        createAddTransformationPanel(),
-        ChaosImage.createImageFromCanvas(controller.getGame().getCanvas()), 
-        mouseBox()
-        );
-    pageContainer.getChildren().addAll(contentContainer, createButtonContainer());
-    pageContainer.getStyleClass().add("page-container");
-    pageContainer.setMaxHeight(Sizes.SCREEN_HEIGHT - PAGE_CONTAINER_MARGIN);
-    pageContainer.setMaxWidth(Sizes.SCREEN_WIDTH - PAGE_CONTAINER_MARGIN);
-    root.setCenter(pageContainer);
+  private HBox createTextBoxWithTextField(String text, int width, int height, double[] coords) {
+    HBox container = new HBox(DEFAULT_SPACING);
+    container.getChildren().add(createTextBox(text));
+    for (double coordinate : coords) {
+      container.getChildren().add(new StyledTextField(coordinate, width, height));
+    }
+    return container;
   }
 
+
   /**
    * Creates a button container with a ComboBox to change the type
    * of transformation, buttons for running steps/resetting, the
@@ -112,7 +228,7 @@ public class MainPageView extends Scene implements ChaosGameObserver {
    */
 
   private HBox createButtonContainer() {
-    HBox buttonContainer = new HBox();
+    HBox buttonContainer = new HBox(DEFAULT_SPACING);
     buttonContainer.getStyleClass().add("button-container");
     buttonContainer.setMaxHeight(Region.USE_PREF_SIZE);
     buttonContainer.setAlignment(Pos.CENTER);
@@ -121,88 +237,51 @@ public class MainPageView extends Scene implements ChaosGameObserver {
     buttonContainer.getChildren().addAll(
             createComboBox(),
             createCustomComboBox(),
-            createButton(10),
-            createButton(100),
-            createButton(1000),
-            createInputField(),
-            createButton(-1)
+            new StyledButton("10 Steps", BUTTON_WIDTH, COMPONENT_HEIGHT,
+                    e -> controller.runSteps(10)),
+            new StyledButton("100 Steps", BUTTON_WIDTH, COMPONENT_HEIGHT,
+                    e -> controller.runSteps(100)),
+            new StyledButton("1000 Steps", BUTTON_WIDTH, COMPONENT_HEIGHT,
+                    e -> controller.runSteps(1000)),
+            createStepsTextField(),
+            new StyledButton("Reset", BUTTON_WIDTH, COMPONENT_HEIGHT,
+                    e -> controller.runSteps(-1))
     );
 
     return buttonContainer;
   }
 
   private ComboBox<ChaosGameDescriptionFactory.descriptionTypeEnum> createComboBox() {
-    ComboBox<ChaosGameDescriptionFactory.descriptionTypeEnum> transformMenu = new ComboBox<>();
-    transformMenu.getStyleClass().add("combo-box");
-    transformMenu.setPrefSize(BUTTON_WIDTH, BUTTON_HEIGHT);
-    transformMenu.setPromptText("Transformation");
-
-    transformMenu.getItems().addAll(
-            ChaosGameDescriptionFactory.descriptionTypeEnum.values()
-    );
+    StyledComboBox<ChaosGameDescriptionFactory.descriptionTypeEnum> transformMenu =
+            new StyledComboBox<>("Transformation", BUTTON_WIDTH, COMPONENT_HEIGHT,
+                    Arrays.asList(ChaosGameDescriptionFactory.descriptionTypeEnum.values())
+            );
     transformMenu.setOnAction(e -> controller.changeTransformation(transformMenu.getValue()));
-
     return transformMenu;
   }
 
-  private ComboBox<String> createCustomComboBox() {
-    ComboBox<String> customMenu = new ComboBox<>();
-    customMenu.getStyleClass().add("combo-box");
-    customMenu.setPrefSize(BUTTON_WIDTH, BUTTON_HEIGHT);
-    customMenu.setPromptText("Custom Transformations");
-
-    List<String> customTransformations = controller.getCustomTransformation();
-
-    if (customTransformations != null && !customTransformations.isEmpty()) {
-      customMenu.getItems().addAll(customTransformations);
-    }
-
-    customMenu.setOnAction(e -> controller.changeCustomTransformation(customMenu.getValue()));
-
-    return customMenu;
-  }
-
-  /**
-   * Creates a button with a specified number of steps. If -1 it's
-   * a reset button
-   *
-   * @param steps The number of steps for the button.
-   * @return The button.
-   */
-  private Button createButton(int steps) {
-    Button button;
-    if (steps == -1) {
-      button = new Button("Reset");
-    } else {
-      button = new Button("Steps: " + steps);
-    }
-    button.getStyleClass().add("button");
-    button.setPrefSize(BUTTON_WIDTH, BUTTON_HEIGHT);
-
-    button.setOnAction(e -> controller.runSteps(steps));
-
-    return button;
+  private StyledTextField createStepsTextField() {
+    StyledTextField stepsField = new StyledTextField("Steps", BUTTON_WIDTH, COMPONENT_HEIGHT);
+    stepsField.getStyleClass().set(0, "button");
+    stepsField.setOnAction(e -> {
+      controller.runCustomSteps(stepsField.getText());
+      stepsField.clear();
+    });
+    return stepsField;
   }
 
   /**
-   * Creates an input field for custom number of steps.
+   * Creates a StyledComboBox with setOnAction to change the transformation based on
+   * the selected value.
    *
-   * @return The input field.
+   * @return The ComboBox with custom transformations.
    */
-  private TextField createInputField() {
-    TextField inputField = new TextField();
-    inputField.setPromptText("Steps");
-    inputField.getStyleClass().add("input-field");
-    inputField.setPrefSize(BUTTON_WIDTH, BUTTON_HEIGHT);
-    inputField.setOnAction(e -> {
-      try {
-        controller.runSteps(Integer.parseInt(inputField.getText()));
-      } catch (Exception ex) {
-        showAlert("Invalid input. Please enter an integer.");
-        inputField.clear();
-      }
-    });
-    return inputField;
+  private ComboBox<String> createCustomComboBox() {
+    StyledComboBox<String> customMenu = new StyledComboBox<>("Custom Transformations",
+            BUTTON_WIDTH, COMPONENT_HEIGHT, controller.getCustomTransformation());
+    customMenu.getItems().add("Add new");
+    customMenu.setOnAction(e -> controller.changeTransformation(customMenu.getValue()));
+    return customMenu;
   }
 
   /**
@@ -259,181 +338,155 @@ public class MainPageView extends Scene implements ChaosGameObserver {
    */
   public VBox createAddTransformationPanel() {
     VBox addPanel = createMainPanel();
-    TextField transformationName = createTextField("transformation name");
-    ComboBox<TransformationType> transformationComboBox = createTransformationComboBox();
-    HBox transformationInputField = createTransformationInputField(transformationComboBox);
-    HBox startVectorField = createVectorHbox(Arrays.asList("x0", "y0"));
-    HBox endVectorField = createVectorHbox(Arrays.asList("x0", "y0"));
+    TextField transformationName = new StyledTextField("Transformation name", 210, 20);
+    transformationName.setText(controller.getCurrentTransformationName());
+    ComboBox<TransformationType> transformationComboBox = createAddComboBox();
+    HBox startVectorField;
+    HBox endVectorField;
+    if (controller.isAddingCustomTransformation()) {
+      startVectorField = createTextBoxWithTextField("Start vector:", 100, 20,
+              "x0", "x1");
+      endVectorField = createTextBoxWithTextField("End vector:", 100, 20,
+              "x0", "x1");
+    } else {
+      startVectorField = createTextBoxWithTextField("Min vector:", 100, 20,
+              controller.getMinCoordsX());
+      endVectorField = createTextBoxWithTextField("Max vector:", 100, 20,
+              controller.getMaxCoordsX());
+    }
 
-    addPanel.getChildren().addAll(
-        transformationName,
-        transformationComboBox,
-        transformationInputField,
-        startVectorField,
-        endVectorField,
-        createButton("Save", e -> saveTransformation(
-            transformationName, transformationComboBox, transformationInputField, startVectorField,
-            endVectorField)),
-        createButton("Cancel", e -> render()),
-        createButton("Add File", e -> uploadFile()));
-    StackPane.setAlignment(addPanel, Pos.BOTTOM_LEFT);
+    VBox transformationVbox = createTransformationVbox(transformationComboBox);
 
-    return addPanel;
-  }
+    addPanel.getChildren().addAll(
+            new HBox(DEFAULT_SPACING,
+                    createTextBox("Transformation name:"),
+                    transformationName
+            ),
+            new HBox(DEFAULT_SPACING,
+                    createTextBox("Transformation type:"),
+                    transformationComboBox
+            ),
+            startVectorField,
+            endVectorField,
+            transformationVbox,
+            new HBox(
+                    DEFAULT_SPACING,
+                    new StyledButton("Save", 20,
+                            e -> saveTransformation(transformationName, transformationComboBox,
+                                    transformationVbox, startVectorField, endVectorField)),
+                    new StyledButton("Cancel", 20, e -> render()),
+                    new StyledButton("Add File", 100, 20, e -> uploadFile())
+            )
 
-  /**
-   * Creates a generic VBox panel with spacing and alignment.
-   *
-   * @return a VBox configured as the main panel.
-   */
-  private VBox createMainPanel() {
-    VBox panel = new VBox(10);
-    panel.getStyleClass().add("add-panel");
-    panel.setAlignment(Pos.CENTER);
-    return panel;
-  }
+    );
 
-  /**
-   * Creates a ComboBox populated with transformation types.
-   *
-   * @return a ComboBox populated with transformation types.
-   */
-  private ComboBox<TransformationType> createTransformationComboBox() {
-    ComboBox<TransformationType> comboBox = new ComboBox<>();
-    comboBox.getItems().addAll(TransformationType.values());
-    comboBox.setPromptText("Select Transformation");
-    return comboBox;
-  }
+    StackPane.setAlignment(addPanel, Pos.BOTTOM_LEFT);
 
-  /**
-   * Enum representing the types of transformations.
-   */
-  public enum TransformationType {
-    JULIA, AFFINE
+    return addPanel;
   }
 
-  /**
-   * Creates the transformation input field container and sets up its update behavior.
-   *
-   * @param transformationComboBox the ComboBox for selecting transformation types.
-   * @return an HBox containing the input fields for transformations.
-   */
-  private HBox createTransformationInputField(ComboBox<TransformationType> transformationComboBox) {
-    HBox inputField = new HBox(10);
-    transformationComboBox.setOnAction(
-        e -> updateTransformationFields(transformationComboBox, inputField));
-    updateTransformationFields(transformationComboBox, inputField);
-    return inputField;
+  private ComboBox<TransformationType> createAddComboBox() {
+    StyledComboBox<TransformationType> transformMenu = new StyledComboBox<>("Transformation",
+            210, COMPONENT_HEIGHT, Arrays.asList(TransformationType.values()));
+    transformMenu.setOnAction(e -> {
+      selectedTransformation = transformMenu.getValue();
+      controller.changeTransformation("add new");
+    });
+    if (controller.isAddingCustomTransformation()) {
+      transformMenu.setValue(this.selectedTransformation);
+    } else if (controller.transformationIsJulia()) {
+      transformMenu.setValue(TransformationType.JULIA);
+    } else {
+      transformMenu.setValue(TransformationType.AFFINE);
+    }
+    return transformMenu;
   }
 
   /**
-   * Updates the transformation input fields based on the selected transformation type.
+   * Creates a VBox containing input fields for transformations.
    *
-   * @param comboBox the ComboBox for selecting transformation types.
-   * @param inputField the HBox containing the input fields for transformations.
+   * @return a VBox configured with input TextFields.
    */
-  private void updateTransformationFields(ComboBox<TransformationType> comboBox, HBox inputField) {
-    inputField.getChildren().clear();
-    if (comboBox.getValue() != null) {
-      inputField.getChildren().add(createTransformationVbox(
-          comboBox.getValue() == TransformationType.AFFINE,
-          comboBox.getValue() == TransformationType.JULIA
-              ? Arrays.asList("Real part", "Imaginary part") : null));
+  private VBox createTransformationVbox(ComboBox<TransformationType> transformationComboBox) {
+    VBox vbox = new VBox(10);
+    vbox.setFillWidth(true);
+    vbox.setAlignment(Pos.CENTER);
+    if (transformationComboBox.getValue() == TransformationType.AFFINE) {
+      vbox.getChildren().add(
+              new StyledButton("Add Transformation", 250, 20,
+                      e -> vbox.getChildren().add(createTextBoxWithTextField("Transformation:",
+                              55, 20, "a00", "a01", "a10", "a11", "v0", "v1"))
+              )
+      );
     }
-  }
+    if (!controller.isAddingCustomTransformation()) {
+      for (double[] coords : controller.getTransformList()) {
+        vbox.getChildren().add(createTextBoxWithTextField("Transformation:",
+                55, 20, coords));
+      }
+    } else if (controller.isAddingCustomTransformation()
+            && transformationComboBox.getValue() == TransformationType.JULIA) {
+      vbox.getChildren().add(createTextBoxWithTextField("Transformation:",
+              55, 20, "c0", "c1"));
 
-  /**
-   * Creates a TextField with the specified prompt text.
-   *
-   * @param promptText the prompt text for the TextField.
-   * @return a configured TextField.
-   */
-  private TextField createTextField(String promptText) {
-    TextField textField = new TextField();
-    textField.setPromptText(promptText);
-    return textField;
-  }
+    }
 
-  /**
-   * Creates a generic button with the specified label and action.
-   *
-   * @param label the label for the button.
-   * @param eventHandler the event handler for the button action.
-   * @return a configured Button.
-   */
-  private Button createButton(String label, EventHandler<ActionEvent> eventHandler) {
-    Button button = new Button(label);
-    button.getStyleClass().add("button");
-    button.setOnAction(eventHandler);
-    return button;
+    return vbox;
   }
 
   /**
-   * Creates a VBox containing input fields for transformations.
+   * Creates a generic VBox panel with spacing and alignment.
    *
-   * @param isAffine indicates if the VBox is for affine transformations.
-   * @param promptTexts list of prompt texts for the TextFields.
-   * @return a VBox configured with input TextFields.
+   * @return a VBox configured as the main panel.
    */
-  private VBox createTransformationVbox(boolean isAffine, List<String> promptTexts) {
-    VBox vbox = new VBox(isAffine ? 5 : 10);
-    if (isAffine) {
-      vbox.getChildren().add(createButton("Add Transformation",
-          e -> vbox.getChildren().add(createVectorHbox(
-              Arrays.asList("X0", "Y0", "X1", "Y1", "V0", "V1")))));
-    } else if (promptTexts != null) {
-      vbox.getChildren().add(createVectorHbox(promptTexts));
-    }
-    return vbox;
+  private VBox createMainPanel() {
+    VBox panel = new VBox(10);
+    panel.getStyleClass().add("add-panel");
+    panel.setAlignment(Pos.CENTER);
+    return panel;
   }
 
   /**
-   * Creates an HBox containing input fields for transformations.
-   *
-   * @param promptTexts list of prompt texts for the TextFields.
-   * @return an HBox configured with input TextFields.
+   * Enum representing the types of transformations.
    */
-  private HBox createVectorHbox(List<String> promptTexts) {
-    HBox hbox = new HBox(10);
-    for (String promptText : promptTexts) {
-      hbox.getChildren().add(createTextField(promptText));
-    }
-    return hbox;
+  public enum TransformationType {
+    JULIA, AFFINE
   }
 
   /**
    * Saves the transformation with the given parameters.
    *
-   * @param transformationName the name of the transformation.
+   * @param transformationName     the name of the transformation.
    * @param transformationComboBox the ComboBox for selecting transformation types.
-   * @param transformationInputField the HBox containing the input fields for transformations.
-   * @param startVectorField the TextField for the start vector.
-   * @param endVectorField the TextField for the end vector.
+   * @param transformationVbox     the HBox containing the input fields for transformations.
+   * @param startVectorField       the TextField for the start vector.
+   * @param endVectorField         the TextField for the end vector.
    */
   private void saveTransformation(TextField transformationName,
-      ComboBox<TransformationType> transformationComboBox, HBox transformationInputField,
-      HBox startVectorField, HBox endVectorField) {
-    List<Transform2D> transformations = getInputInformation(transformationComboBox.getValue(),
-        transformationInputField);
-    Vector2d startVector = getInputVector(startVectorField);
-    Vector2d endVector = getInputVector(endVectorField);
+                                  ComboBox<TransformationType> transformationComboBox,
+                                  VBox transformationVbox, HBox startVectorField,
+                                  HBox endVectorField) {
+    List<String[]> transformations = getInputInformation(transformationComboBox.getValue(),
+            transformationVbox);
+    String[] startVector = getInputVector(startVectorField);
+    String[] endVector = getInputVector(endVectorField);
     controller.addCustomTransformation(
-        startVector, endVector, transformations, transformationName.getText());
+            startVector, endVector, transformations, transformationName.getText());
   }
 
   /**
    * Retrieves input information based on the selected transformation type.
    *
    * @param selectedTransformation the selected transformation type.
-   * @param transformationInputField the HBox containing the input fields for transformations.
+   * @param transformationVbox     the HBox containing the input fields for transformations.
    * @return a list of Transform2D objects.
    */
-  private List<Transform2D> getInputInformation(TransformationType selectedTransformation,
-      HBox transformationInputField) {
+  private List<String[]> getInputInformation(TransformationType selectedTransformation,
+                                             VBox transformationVbox) {
     if (selectedTransformation == TransformationType.JULIA) {
-      return getJuliaTransformation(transformationInputField);
+      return getJuliaTransformation(transformationVbox);
     } else if (selectedTransformation == TransformationType.AFFINE) {
-      return getAffineTransformation(transformationInputField);
+      return getAffineTransformation(transformationVbox);
     }
     return new ArrayList<>();
   }
@@ -441,18 +494,16 @@ public class MainPageView extends Scene implements ChaosGameObserver {
   /**
    * Retrieves input information for the Julia transformation.
    *
-   * @param transformationInputField the HBox containing the input fields for the Julia
-   *                                 transformation.
+   * @param transformationVbox the HBox containing the input fields for the Julia
+   *                           transformation.
    * @return a list of Transform2D objects for the Julia transformation.
    */
-  private List<Transform2D> getJuliaTransformation(HBox transformationInputField) {
-    List<Transform2D> list = new ArrayList<>();
-    if (!transformationInputField.getChildren().isEmpty()) {
-      VBox juliaVbox = (VBox) transformationInputField.getChildren().get(0);
-      HBox juliaFields = (HBox) juliaVbox.getChildren().get(0);
-      list.add(new JuliaTransform(
-          new Complex(parseDoubleFromTextField(juliaFields, 0),
-              parseDoubleFromTextField(juliaFields, 1)), 1));
+  private List<String[]> getJuliaTransformation(VBox transformationVbox) {
+    List<String[]> list = new ArrayList<>();
+    if (!transformationVbox.getChildren().isEmpty()) {
+      HBox juliaFields = (HBox) transformationVbox.getChildren().get(0);
+      list.add(new String[]{((TextField) juliaFields.getChildren().get(1)).getText(),
+              ((TextField) juliaFields.getChildren().get(2)).getText()});
     }
     return list;
   }
@@ -464,23 +515,17 @@ public class MainPageView extends Scene implements ChaosGameObserver {
    *                                 transformation.
    * @return a list of Transform2D objects for the Affine transformation.
    */
-  private List<Transform2D> getAffineTransformation(HBox transformationInputField) {
-    List<Transform2D> list = new ArrayList<>();
+  private List<String[]> getAffineTransformation(VBox transformationInputField) {
+    List<String[]> list = new ArrayList<>();
     if (!transformationInputField.getChildren().isEmpty()) {
-      VBox affineVbox = (VBox) transformationInputField.getChildren().get(0);
-      for (Node node : affineVbox.getChildren().subList(1, affineVbox.getChildren().size())) {
+      for (Node node : transformationInputField.getChildren()
+              .subList(1, transformationInputField.getChildren().size())) {
         HBox matrixFields = (HBox) node;
-
-        double x0 = parseDoubleFromTextField(matrixFields, 0);
-        double y0 = parseDoubleFromTextField(matrixFields, 1);
-        double x1 = parseDoubleFromTextField(matrixFields, 2);
-        double y1 = parseDoubleFromTextField(matrixFields, 3);
-        double v0 = parseDoubleFromTextField(matrixFields, 4);
-        double v1 = parseDoubleFromTextField(matrixFields, 5);
-
-        Matrix2x2 matrix2x2 = new Matrix2x2(x0, y0, x1, y1);
-        Vector2d vector2d = new Vector2d(v0, v1);
-        list.add(new AffineTransform2D(matrix2x2, vector2d));
+        String[] coordinateList = new String[matrixFields.getChildren().size() - 1];
+        for (int i = 1; i < matrixFields.getChildren().size(); i++) {
+          coordinateList[i - 1] = ((TextField) matrixFields.getChildren().get(i)).getText();
+        }
+        list.add(coordinateList);
       }
     }
     return list;
@@ -489,23 +534,12 @@ public class MainPageView extends Scene implements ChaosGameObserver {
   /**
    * Retrieves the input vector from an HBox.
    *
-   * @param vectorHbox the HBox containing the input fields for the vector.
+   * @param vectorHBox the HBox containing the input fields for the vector.
    * @return a Vector2d object representing the input vector.
    */
-  private Vector2d getInputVector(HBox vectorHbox) {
-    return new Vector2d(parseDoubleFromTextField(vectorHbox, 0),
-        parseDoubleFromTextField(vectorHbox, 1));
-  }
-
-  /**
-   * Parses a double value from the TextField at the specified index in the HBox.
-   *
-   * @param hbox the HBox containing the TextField.
-   * @param index the index of the TextField in the HBox.
-   * @return the parsed double value.
-   */
-  private double parseDoubleFromTextField(HBox hbox, int index) {
-    return Double.parseDouble(((TextField) hbox.getChildren().get(index)).getText());
+  private String[] getInputVector(HBox vectorHBox) {
+    return new String[]{((TextField) vectorHBox.getChildren().get(1)).getText(),
+            ((TextField) vectorHBox.getChildren().get(2)).getText()};
   }
 
   /**
@@ -517,15 +551,12 @@ public class MainPageView extends Scene implements ChaosGameObserver {
    *
    * @return a VBox containing the Pane and the TextFields
    */
-  private VBox mouseBox() {
-    Pane box = new Pane();
-    box.setPrefSize(400, 400);
+  private Pane mouseBox() {
+    StackPane box = new StackPane();
+    box.setPrefWidth(125);
+    box.getStyleClass().add("mouse-box");
 
-    xField = new TextField();
-    yField = new TextField();
-
-    VBox vbox = new VBox(xField, yField);
-    vbox.setSpacing(10);
+    box.getChildren().add(new Label("Hover over me!"));
 
     box.setOnMouseMoved(e -> {
       double mouseX = e.getX();
@@ -535,10 +566,7 @@ public class MainPageView extends Scene implements ChaosGameObserver {
       updateValues(normalizedX, normalizedY);
     });
 
-    VBox root = new VBox(box, vbox);
-    root.setSpacing(10);
-
-    return root;
+    return box;
   }
 
   /**
@@ -550,8 +578,8 @@ public class MainPageView extends Scene implements ChaosGameObserver {
    */
   private void updateValues(double x, double y) {
     controller.changeJuliaTransformationDynamic(x, y);
-    xField.setText(String.format("X: %.1f", x));
-    yField.setText(String.format("Y: %.1f", y));
+    x0Field.setText(String.format(Locale.ENGLISH, "%.5f", x));
+    x1Field.setText(String.format(Locale.ENGLISH, "%.5f", y));
   }
 
 }
diff --git a/src/main/java/edu/ntnu/idatt2003/view/ChaosImage.java b/src/main/java/edu/ntnu/idatt2003/view/components/ChaosImage.java
similarity index 91%
rename from src/main/java/edu/ntnu/idatt2003/view/ChaosImage.java
rename to src/main/java/edu/ntnu/idatt2003/view/components/ChaosImage.java
index e4d5c8880b8aeef2c41182237f8d78c6a139f37f..97d0e25f58b913f00cfc7f7fcc24494748d0fe8b 100644
--- a/src/main/java/edu/ntnu/idatt2003/view/ChaosImage.java
+++ b/src/main/java/edu/ntnu/idatt2003/view/components/ChaosImage.java
@@ -1,4 +1,4 @@
-package edu.ntnu.idatt2003.view;
+package edu.ntnu.idatt2003.view.components;
 
 import edu.ntnu.idatt2003.model.ChaosCanvas;
 import javafx.beans.property.ObjectProperty;
@@ -19,7 +19,7 @@ import javafx.scene.transform.Scale;
  * an image by a specified factor.
  */
 
-class ChaosImage {
+public class ChaosImage {
   private static final int MAX_SCALE = 5;
   private static final int MIN_SCALE = 1;
   private static final double ZOOM_FACTOR = 1.05;
@@ -51,13 +51,13 @@ class ChaosImage {
       }
     }
     ImageView imageView = new ImageView(image);
-    imageView.setFitWidth(600);
-    imageView.setFitHeight(600);
+    imageView.setFitWidth(width);
+    imageView.setFitHeight(height);
     Pane pane = new Pane(imageView);
     pane.setMaxHeight(height);
     pane.setMaxWidth(width);
     StackPane.setAlignment(imageView, javafx.geometry.Pos.CENTER);
-    pane.setClip(new Rectangle(600, 600));
+    pane.setClip(new Rectangle(width, height));
     enableZoom(imageView);
     enablePan(imageView);
     return pane;
@@ -106,8 +106,7 @@ class ChaosImage {
     final double scaleBefore = imageView.getScaleX();
     double scale = imageView.getScaleX() * zoomFactor;
 
-    scale = clamp(scale, MIN_SCALE, MAX_SCALE);
-
+    scale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));
     imageView.setScaleX(scale);
     imageView.setScaleY(scale);
 
@@ -136,13 +135,13 @@ class ChaosImage {
     if ((newX + imageWidthHalf) / imageView.getScaleX() <= imageWidthHalf
             && (newX - imageWidthHalf) / imageView.getScaleX() >= -imageWidthHalf) {
       imageView.setTranslateX(newX);
-    } else if (imageView.getScaleX() <= 1) {
+    } else {
       imageView.setTranslateX(0);
     }
     if ((newY + imageHeightHalf) / imageView.getScaleY() <= imageHeightHalf
             && (newY - imageHeightHalf) / imageView.getScaleY() >= -imageHeightHalf) {
       imageView.setTranslateY(newY);
-    } else if (imageView.getScaleY() <= 1) {
+    } else {
       imageView.setTranslateY(0);
     }
   }
@@ -196,16 +195,4 @@ class ChaosImage {
                                               double scaleBefore, double translateBefore) {
     return -mousePosition * scale + mousePosition * scaleBefore + translateBefore;
   }
-
-  /**
-   * Clamp a value between a minimum and maximum value. Makes sure the value is within the bounds.
-   *
-   * @param value The value to clamp.
-   * @param min   The minimum value.
-   * @param max   The maximum value.
-   * @return The clamped value.
-   */
-  private static double clamp(double value, double min, double max) {
-    return Math.max(min, Math.min(max, value));
-  }
 }
\ No newline at end of file
diff --git a/src/main/java/edu/ntnu/idatt2003/view/components/StyledButton.java b/src/main/java/edu/ntnu/idatt2003/view/components/StyledButton.java
new file mode 100644
index 0000000000000000000000000000000000000000..c43ed0e8cf2278f4c4efed130f1295cc1e394149
--- /dev/null
+++ b/src/main/java/edu/ntnu/idatt2003/view/components/StyledButton.java
@@ -0,0 +1,52 @@
+package edu.ntnu.idatt2003.view.components;
+
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.scene.control.Button;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+
+/**
+ * A styled button with a specified tet width, height and event handler.
+ * The button has a style class "button" and the event handler is set to the
+ * specified event handler.
+ * Goal: Create a styled button with a specified text, width, height and event handler.
+ */
+public class StyledButton extends Button {
+
+  /**
+   * Creates a styled button with a specified text, width, height and event handler.
+   * The button has a style class "button" and the event handler is set to the
+   * specified event handler.
+   *
+   * @param text         The text to display on the button.
+   * @param width        The width of the button.
+   * @param height       The height of the button.
+   * @param eventHandler The event handler to set on the button.
+   */
+  public StyledButton(String text, int width, int height,
+                      EventHandler<ActionEvent> eventHandler) {
+    super(text);
+    setPrefSize(width, height);
+    getStyleClass().add("button");
+    setOnAction(eventHandler);
+  }
+
+  /**
+   * Creates a styled button with a specified text, height and event handler.
+   * The button has a style class "button" and the event handler is set to the
+   * specified event handler.
+   * The button's width is set to grow with the HBox.
+   *
+   * @param text The text to display on the button.
+   * @param height The height of the button.
+   * @param eventHandler The event handler to set on the button.
+   */
+  public StyledButton(String text, int height, EventHandler<ActionEvent> eventHandler) {
+    super(text);
+    HBox.setHgrow(this, Priority.ALWAYS);
+    setPrefHeight(height);
+    getStyleClass().add("button");
+    setOnAction(eventHandler);
+  }
+}
diff --git a/src/main/java/edu/ntnu/idatt2003/view/components/StyledComboBox.java b/src/main/java/edu/ntnu/idatt2003/view/components/StyledComboBox.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f17b9ebc83e0d40c80042bf3eb45096bf57c53a
--- /dev/null
+++ b/src/main/java/edu/ntnu/idatt2003/view/components/StyledComboBox.java
@@ -0,0 +1,30 @@
+package edu.ntnu.idatt2003.view.components;
+
+import java.util.List;
+import javafx.scene.control.ComboBox;
+
+/**
+ * A styled combo box with a specified prompt text, width, height and values.
+ * The combo box has a style class "combo-box" and the values are set to the specified values.
+ * Goal: Create a styled combo box with a specified prompt text, width, height and values.
+ */
+public class StyledComboBox<T> extends ComboBox<T> {
+  /**
+   * Creates a styled combo box with a specified prompt text, width, height and values.
+   * The combo box has a style class "combo-box" and the values are set to the specified values.
+   *
+   * @param promptText The text to display in the combo box when it is empty.
+   * @param width      The preferred width of the combo box.
+   * @param height     The preferred height of the combo box.
+   * @param values     The values to set in the combo box.
+   */
+  public StyledComboBox(String promptText, int width, int height, List<T> values) {
+    super();
+    this.setPromptText(promptText);
+    this.setPrefSize(width, height);
+    this.getStyleClass().add("combo-box");
+    if (values != null) {
+      this.getItems().addAll(values);
+    }
+  }
+}
diff --git a/src/main/java/edu/ntnu/idatt2003/view/components/StyledTextField.java b/src/main/java/edu/ntnu/idatt2003/view/components/StyledTextField.java
new file mode 100644
index 0000000000000000000000000000000000000000..b74a2422bbfab27e9e6c63a21fa7c330bc0b304e
--- /dev/null
+++ b/src/main/java/edu/ntnu/idatt2003/view/components/StyledTextField.java
@@ -0,0 +1,43 @@
+package edu.ntnu.idatt2003.view.components;
+
+import javafx.scene.control.TextField;
+
+import java.util.Locale;
+
+/**
+ * A styled text field with a specified prompt text, width and height.
+ * The text field has a style class "text-field".
+ * Goal: Create a styled text field with a specified prompt text, width and height.
+ */
+public class StyledTextField extends TextField {
+  /**
+   * Creates a styled text field with a specified prompt text, width and height.
+   * The text field has a style class "text-field".
+   *
+   * @param promptText The text to display in the text field when it is empty.
+   * @param width The preferred width of the text field.
+   * @param height The preferred height of the text field.
+   */
+  public StyledTextField(String promptText, int width, int height) {
+    super();
+    this.setPromptText(promptText);
+    this.setPrefSize(width, height);
+    this.getStyleClass().add("text-field");
+  }
+
+  /**
+   * Creates a styled text field with a specified coordinate, width and height.
+   * The coordinate is formatted to two decimal places, and is set as the text
+   * of the text field.
+   *
+   * @param coordinate the coordinate to display in the text field.
+   * @param width the preferred width of the text field.
+   * @param height the preferred height of the text field.
+   */
+  public StyledTextField(double coordinate, int width, int height) {
+    super(String.format(Locale.US, "%.2f", coordinate));
+    this.setPrefSize(width, height);
+    this.getStyleClass().add("text-field");
+  }
+
+}
diff --git a/src/main/resources/styles/components.css b/src/main/resources/styles/components.css
new file mode 100644
index 0000000000000000000000000000000000000000..4060f2607fa1bd2872981559c86175e859675958
--- /dev/null
+++ b/src/main/resources/styles/components.css
@@ -0,0 +1,28 @@
+.text-field {
+    -fx-background-color: white;
+    -fx-background-radius: 0;
+    -fx-border-radius: 0;
+    -fx-font-size: 16px;
+}
+
+.button {
+    -fx-background-color: #D9D9D9;
+    -fx-background-radius: 5px;
+    -fx-border-radius: 5px;
+    -fx-font-size: 16px;
+}
+
+.button:hover {
+    -fx-background-color: #C8C8C8;
+}
+
+.combo-box {
+    -fx-background-color: #D9D9D9;
+    -fx-background-radius: 5px;
+    -fx-border-radius: 5px;
+    -fx-font-size: 16px;
+}
+.combo-box:hover {
+    -fx-background-color: #C8C8C8;
+}
+
diff --git a/src/main/resources/styles/mainPage.css b/src/main/resources/styles/mainPage.css
index d449b672acd8f7bacb6055319b2cb3fcf81612d8..ade600d7aede831550c0ffa6c1d998be712fdefb 100644
--- a/src/main/resources/styles/mainPage.css
+++ b/src/main/resources/styles/mainPage.css
@@ -1,55 +1,34 @@
-.button {
-    -fx-background-color: #D9D9D9;
-    -fx-background-insets: 5px;
-    -fx-border-insets: 5px;
-    -fx-background-radius: 5px;
-    -fx-border-radius: 5px;
-    -fx-font-size: 16px;
-}
-
-.button:hover {
-    -fx-background-color: #C8C8C8;
-}
-
-.combo-box {
-    -fx-background-color: #D9D9D9;
-    -fx-background-insets: 5px;
-    -fx-border-insets: 5px;
-    -fx-background-radius: 5px;
-    -fx-border-radius: 5px;
-    -fx-font-size: 16px;
-}
-.combo-box:hover {
-    -fx-background-color: #C8C8C8;
-}
 
-.input-field {
+.text-box {
     -fx-background-color: #D9D9D9;
-    -fx-background-insets: 5px;
-    -fx-border-insets: 5px;
-    -fx-background-radius: 5px;
-    -fx-border-radius: 5px;
+    -fx-background-radius: 0;
+    -fx-border-radius: 0;
     -fx-font-size: 16px;
 }
 
 .button-container {
     -fx-background-color: white;
-    -fx-background-radius: 10px;
     -fx-padding: 10px;
 }
 
-.page-container {
-    -fx-background-color: blue;
-    -fx-background-radius: 10px;
+.center-container {
     -fx-padding: 10px;
 }
 
+.canvas-and-dynamic-julia-container {
+    -fx-padding: 20px;
+    -fx-border-color: #848484;
+    -fx-border-width: 4px;
+}
+.mouse-box {
+    -fx-background-color: #D9D9D9;
+}
+
 .main-page {
     -fx-background-color: #AFAFAF;
     -fx-border-radius: 10px;
-    -fx-padding: 20px;
 }
-/* Editing Panel Styling */
+
 .editing-panel {
     -fx-background-color: white;
     -fx-background-radius: 10px;