From 805c8fd6eadb0fb5e0b0a1771a1c641d49a587ea Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 13:32:32 +0100
Subject: [PATCH 01/15] feat: refactor the element tree to make inline recipe
name change possible
---
.../main/resources/client/scenes/FoodpalApplication.fxml | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/client/src/main/resources/client/scenes/FoodpalApplication.fxml b/client/src/main/resources/client/scenes/FoodpalApplication.fxml
index 57ad5f9..d1bfe0e 100644
--- a/client/src/main/resources/client/scenes/FoodpalApplication.fxml
+++ b/client/src/main/resources/client/scenes/FoodpalApplication.fxml
@@ -101,17 +101,16 @@
-
+
-
-
-
-
+
+
+
From d42e6ff74cec3429a1229c2bacd9a7b8a3c5f39a Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 13:34:28 +0100
Subject: [PATCH 02/15] feat: new UX for add/edit/update recipes
Revised adding recipes to have untitled recipes with inline name editing
(name edit box autofocused upon recipe creation)
---
.../client/exception/UpdateException.java | 7 ++
.../client/scenes/FoodpalApplicationCtrl.java | 86 ++++++++++++++++---
.../client/utils/DefaultRecipeFactory.java | 15 ++++
3 files changed, 96 insertions(+), 12 deletions(-)
create mode 100644 client/src/main/java/client/exception/UpdateException.java
create mode 100644 client/src/main/java/client/utils/DefaultRecipeFactory.java
diff --git a/client/src/main/java/client/exception/UpdateException.java b/client/src/main/java/client/exception/UpdateException.java
new file mode 100644
index 0000000..5439018
--- /dev/null
+++ b/client/src/main/java/client/exception/UpdateException.java
@@ -0,0 +1,7 @@
+package client.exception;
+
+public class UpdateException extends RuntimeException {
+ public UpdateException(String message) {
+ super(message);
+ }
+}
diff --git a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
index 93a2507..bc39741 100644
--- a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
+++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
@@ -4,20 +4,30 @@ package client.scenes;
import java.io.IOException;
import java.util.List;
+import client.exception.UpdateException;
+import client.utils.DefaultRecipeFactory;
import client.utils.ServerUtils;
import commons.Recipe;
import jakarta.inject.Inject;
import javafx.fxml.FXML;
+import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
+import javafx.scene.control.TextField;
+import javafx.scene.input.KeyCode;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
public class FoodpalApplicationCtrl {
private final MainCtrl mainCtrl;
private final ServerUtils server;
+ public VBox detailsScreen;
+ public HBox editableTitleArea;
+
// all of these aren't used with only my part of the code
// everything in the top bar ===
@@ -103,10 +113,13 @@ public class FoodpalApplicationCtrl {
refresh();
}
-
+ private void showName(String name) {
+ editableTitleArea.getChildren().clear();
+ editableTitleArea.getChildren().add(new Label(name));
+ }
// till the all the code from everyone is implemented for now to not have errors
private void showRecipeDetails(Recipe newRecipe) {
- recipeNameLabel.setText(newRecipe.getName());
+ showName(newRecipe.getName());
ingredientsListView.getItems().setAll(newRecipe.getIngredients());
preparationListView.getItems().setAll(newRecipe.getPreparationSteps());
@@ -123,17 +136,40 @@ public class FoodpalApplicationCtrl {
// Select first recipe in the list by default
if (!recipes.isEmpty()) {
recipeList.getSelectionModel().selectFirst();
+ detailsScreen.visibleProperty().set(true);
}
}
-
+ private void printError(String msg) {
+ Alert alert = new Alert(Alert.AlertType.ERROR);
+ alert.setContentText(msg);
+ alert.showAndWait();
+ }
/**
- * Adds a recipe, by going to a different scene, there you insert the title and bam recipe created
+ * Adds a recipe, by providing a default name "Untitled recipe (n)"
+ * The UX flow is now:
+ *
+ * User creates an untitled recipe
+ * The application autofocuses on the edit box (not exactly automagically yet)
+ * User edits the name to whatever they want
+ * Profit??
+ *
*/
@FXML
private void addRecipe() {
- // Navigate to "create recipe" screen (should be like a pop-up or new screen or just another place in the app)
- mainCtrl.showAddName();
+ // a default factory provides the value
+ Recipe newRecipe = DefaultRecipeFactory.getDefaultRecipe();
+ try {
+ server.addRecipe(newRecipe);
+ refresh();
+ // the list focuses on the new recipe
+ // otherwise strange issues occur when the autofocus on edit box is called
+ recipeList.getFocusModel().focus(recipeList.getItems().indexOf(newRecipe));
+ } catch (IOException | InterruptedException e) {
+ printError("Error occurred when adding recipe!");
+ }
+ // Calls edit after the recipe has been created, seamless name editing
+ editRecipeTitle();
}
@FXML
@@ -145,7 +181,10 @@ public class FoodpalApplicationCtrl {
server.deleteRecipe(selected.getId());
- recipeList.getItems().remove(selected);
+ // prefer a global refresh (or WS-based update upon its impl)
+ // rather than recipeList.getItems().remove(selected);
+ // to maintain single source of truth from the server.
+ refresh();
}
@FXML
@@ -154,15 +193,38 @@ public class FoodpalApplicationCtrl {
if (selected == null) {
return;
}
- // Let MainCtrl open the full detail screen
- mainCtrl.showAddName(); //I had showrecipedetail but intelij says showoverview
+ detailsScreen.visibleProperty().set(true);
}
+ /**
+ * Revised edit recipe control flow, deprecates the use of a separate AddNameCtrl
+ * This is automagically called when a new recipe is created, making for a more seamless UX
+ */
@FXML
private void editRecipeTitle() {
- // TODO: someone else todo
- // For now reuse openSelectedRecipe()
- openSelectedRecipe();
+ editableTitleArea.getChildren().clear();
+ TextField edit = new TextField();
+ edit.setOnKeyPressed(event -> {
+ if (event.getCode() != KeyCode.ENTER) {
+ return;
+ }
+ String newName = edit.getText();
+ Recipe selected = recipeList.getSelectionModel().getSelectedItem();
+ if (selected == null) {
+ // edge case, prob won't happen but best to handle it later
+ throw new NullPointerException("No recipe selected while name was changed!");
+ }
+ selected.setName(newName);
+ try {
+ server.updateRecipe(selected);
+ refresh();
+ } catch (IOException | InterruptedException e) {
+ // throw a nice blanket UpdateException
+ throw new UpdateException("Error occurred when updating recipe name!");
+ }
+ showName(edit.getText());
+ });
+ editableTitleArea.getChildren().add(edit);
}
/**
diff --git a/client/src/main/java/client/utils/DefaultRecipeFactory.java b/client/src/main/java/client/utils/DefaultRecipeFactory.java
new file mode 100644
index 0000000..0a94786
--- /dev/null
+++ b/client/src/main/java/client/utils/DefaultRecipeFactory.java
@@ -0,0 +1,15 @@
+package client.utils;
+
+import commons.Recipe;
+
+import java.util.List;
+
+public class DefaultRecipeFactory {
+ public static Recipe getDefaultRecipe() {
+ return new Recipe(
+ null,
+ "Untitled recipe",
+ List.of(),
+ List.of());
+ }
+}
From bc3744aee58527333c9de0b5fa3ad62ad6edb94a Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 17:00:49 +0100
Subject: [PATCH 03/15] fix: use proper ServerUtils for the availability check
---
client/src/main/java/client/Main.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/client/src/main/java/client/Main.java b/client/src/main/java/client/Main.java
index e722b2d..e2f58d6 100644
--- a/client/src/main/java/client/Main.java
+++ b/client/src/main/java/client/Main.java
@@ -22,9 +22,9 @@ import client.scenes.MainCtrl;
import client.scenes.AddIngredientCtrl;
import client.scenes.AddNameCtrl;
import client.scenes.FoodpalApplicationCtrl;
+import client.utils.ServerUtils;
import com.google.inject.Injector;
-import client.utils.ServerUtilsExample;
import javafx.application.Application;
import javafx.stage.Stage;
@@ -40,7 +40,7 @@ public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
- var serverUtils = INJECTOR.getInstance(ServerUtilsExample.class);
+ var serverUtils = INJECTOR.getInstance(ServerUtils.class);
if (!serverUtils.isServerAvailable()) {
var msg = "Server needs to be started before the client, but it does not seem to be available. Shutting down.";
System.err.println(msg);
From 2ce855aa3df0d4a33f470bcb5c25440ecb05a7ee Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 17:31:34 +0100
Subject: [PATCH 04/15] feat: integrate ingredient list updates
---
client/src/main/java/client/MyModule.java | 3 +-
.../client/scenes/FoodpalApplicationCtrl.java | 32 ++++++++++++++++---
.../scenes/recipe/IngredientListCtrl.java | 22 ++++++-------
.../client/scenes/FoodpalApplication.fxml | 10 +-----
.../client/scenes/recipe/IngredientList.fxml | 2 +-
5 files changed, 42 insertions(+), 27 deletions(-)
diff --git a/client/src/main/java/client/MyModule.java b/client/src/main/java/client/MyModule.java
index f0d95ed..9f27a8c 100644
--- a/client/src/main/java/client/MyModule.java
+++ b/client/src/main/java/client/MyModule.java
@@ -16,6 +16,7 @@
package client;
import client.scenes.FoodpalApplicationCtrl;
+import client.scenes.recipe.IngredientListCtrl;
import client.utils.LocaleManager;
import com.google.inject.Binder;
import com.google.inject.Module;
@@ -31,7 +32,7 @@ public class MyModule implements Module {
binder.bind(MainCtrl.class).in(Scopes.SINGLETON);
binder.bind(AddNameCtrl.class).in(Scopes.SINGLETON);
binder.bind(FoodpalApplicationCtrl.class).in(Scopes.SINGLETON);
-
+ binder.bind(IngredientListCtrl.class).in(Scopes.SINGLETON);
binder.bind(LocaleManager.class).in(Scopes.SINGLETON);
}
}
\ No newline at end of file
diff --git a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
index e2b8abf..7fcf49b 100644
--- a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
+++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
@@ -7,6 +7,7 @@ import java.util.List;
import java.util.Locale;
import client.exception.UpdateException;
+import client.scenes.recipe.IngredientListCtrl;
import client.utils.DefaultRecipeFactory;
import client.utils.LocaleAware;
import client.utils.LocaleManager;
@@ -31,6 +32,7 @@ public class FoodpalApplicationCtrl implements LocaleAware {
private final MainCtrl mainCtrl;
private final ServerUtils server;
private final LocaleManager localeManager;
+ private final IngredientListCtrl ingredientListCtrl;
public VBox detailsScreen;
public HBox editableTitleArea;
@@ -93,14 +95,35 @@ public class FoodpalApplicationCtrl implements LocaleAware {
private Button addPreparationStepButton;
@Inject
- public FoodpalApplicationCtrl(MainCtrl mainCtrl, ServerUtils server, LocaleManager localeManager) {
+ public FoodpalApplicationCtrl(
+ MainCtrl mainCtrl,
+ ServerUtils server,
+ LocaleManager localeManager,
+ IngredientListCtrl ingredientListCtrl
+ ) {
this.mainCtrl = mainCtrl;
this.server = server;
this.localeManager = localeManager;
+ this.ingredientListCtrl = ingredientListCtrl;
}
@Override
public void initializeComponents() {
+ // Initialize callback for ingredient list updates
+ this.ingredientListCtrl.setUpdateCallback(newList -> {
+ Recipe focusedRecipe = recipeList.getFocusModel().getFocusedItem();
+ if (focusedRecipe == null) {
+ // edge case error for NPE.
+ throw new NullPointerException("Null recipe whereas ingredients are edited");
+ }
+ focusedRecipe.setIngredients(newList);
+ try {
+ // propagate changes to server
+ server.updateRecipe(focusedRecipe);
+ } catch (IOException | InterruptedException e) {
+ throw new UpdateException("Unable to update recipe to server for " + focusedRecipe);
+ }
+ });
// Show recipe name in the list
recipeList.setCellFactory(list -> new ListCell<>() {
@Override
@@ -140,10 +163,10 @@ public class FoodpalApplicationCtrl implements LocaleAware {
printRecipeButton.setText(getLocaleString("menu.button.print"));
recipesLabel.setText(getLocaleString("menu.label.recipes"));
- ingredientsLabel.setText(getLocaleString("menu.label.ingredients"));
+ // ingredientsLabel.setText(getLocaleString("menu.label.ingredients"));
preparationLabel.setText(getLocaleString("menu.label.preparation"));
- addIngredientButton.setText(getLocaleString("menu.button.add.ingredient"));
+ // addIngredientButton.setText(getLocaleString("menu.button.add.ingredient"));
addPreparationStepButton.setText(getLocaleString("menu.button.add.step"));
}
@@ -154,12 +177,11 @@ public class FoodpalApplicationCtrl implements LocaleAware {
private void showRecipeDetails(Recipe recipe) {
if (recipe == null) {
- ingredientsListView.getItems().clear();
preparationListView.getItems().clear();
return;
}
showName(recipe.getName());
- ingredientsListView.getItems().setAll(recipe.getIngredients());
+ ingredientListCtrl.refetchFromRecipe(recipe);
preparationListView.getItems().setAll(recipe.getPreparationSteps());
}
diff --git a/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java b/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
index 74193e6..a772913 100644
--- a/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
+++ b/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
@@ -5,7 +5,7 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
-import java.util.function.Function;
+import java.util.function.Consumer;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
@@ -29,7 +29,7 @@ public class IngredientListCtrl implements Initializable {
* As the ingredient list in {@link Recipe} is immutable,
* this copies that list upon initialization to this mutable list.
*
- * Please use the {@link #setUpdateCallback(Function)} function to listen for
+ * Please use the {@link #setUpdateCallback(Consumer)} function to listen for
* changes and update the recipe accordingly.
*
*/
@@ -38,15 +38,15 @@ public class IngredientListCtrl implements Initializable {
/**
* A callback function that is called when the ingredient list is updated.
*/
- private Function, Void> updateCallback;
+ private Consumer> updateCallback;
@FXML
- ListView ingredientListView;
+ public ListView ingredientListView;
@FXML
- Button addIngredientButton;
+ public Button addIngredientButton;
@FXML
- Button deleteIngredientButton;
+ public Button deleteIngredientButton;
/**
* Set the recipe and refetch data from it.
@@ -59,6 +59,7 @@ public class IngredientListCtrl implements Initializable {
if (recipe == null) {
this.ingredients = FXCollections.observableArrayList(new ArrayList<>());
} else {
+ System.out.println("refetched");
List ingredientList = recipe.getIngredients();
this.ingredients = FXCollections.observableArrayList(ingredientList);
}
@@ -72,7 +73,7 @@ public class IngredientListCtrl implements Initializable {
*
* @param callback The function to call upon each update.
*/
- public void setUpdateCallback(Function, Void> callback) {
+ public void setUpdateCallback(Consumer> callback) {
this.updateCallback = callback;
}
@@ -91,7 +92,7 @@ public class IngredientListCtrl implements Initializable {
private void handleIngredientAdd(ActionEvent event) {
this.ingredients.add("Ingredient " + (this.ingredients.size() + 1));
this.refresh();
- this.updateCallback.apply(this.ingredients);
+ this.updateCallback.accept(this.ingredients);
var select = this.ingredientListView.getSelectionModel();
select.select(this.ingredients.size() - 1);
@@ -108,7 +109,7 @@ public class IngredientListCtrl implements Initializable {
this.ingredients.set(index, newValue);
this.refresh();
- this.updateCallback.apply(this.ingredients);
+ this.updateCallback.accept(this.ingredients);
}
/**
@@ -126,7 +127,7 @@ public class IngredientListCtrl implements Initializable {
this.ingredients.remove(selectedIndex);
this.refresh();
- this.updateCallback.apply(this.ingredients);
+ this.updateCallback.accept(this.ingredients);
}
@FXML
@@ -134,7 +135,6 @@ public class IngredientListCtrl implements Initializable {
// TODO: set up communication with the server
// this would probably be best done with the callback (so this class doesn't
// interact with the server at all)
-
this.ingredientListView.setEditable(true);
this.ingredientListView.setCellFactory(
list -> {
diff --git a/client/src/main/resources/client/scenes/FoodpalApplication.fxml b/client/src/main/resources/client/scenes/FoodpalApplication.fxml
index 9599c90..8fe9bc9 100644
--- a/client/src/main/resources/client/scenes/FoodpalApplication.fxml
+++ b/client/src/main/resources/client/scenes/FoodpalApplication.fxml
@@ -116,15 +116,7 @@
-
-
-
-
-
-
-
-
-
+
diff --git a/client/src/main/resources/client/scenes/recipe/IngredientList.fxml b/client/src/main/resources/client/scenes/recipe/IngredientList.fxml
index 72ea2a9..1ad02e4 100644
--- a/client/src/main/resources/client/scenes/recipe/IngredientList.fxml
+++ b/client/src/main/resources/client/scenes/recipe/IngredientList.fxml
@@ -9,7 +9,7 @@
-
+
From 0bec62b9a38469ff94bb410334d22df419197af2 Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 17:46:38 +0100
Subject: [PATCH 05/15] feat: integrate steps list updates
uses JavaFX includes to incorporate a nested controller
---
client/src/main/java/client/MyModule.java | 2 ++
.../client/scenes/FoodpalApplicationCtrl.java | 30 +++++++++++++++----
.../scenes/recipe/RecipeStepListCtrl.java | 14 ++++-----
.../client/scenes/FoodpalApplication.fxml | 21 ++-----------
4 files changed, 36 insertions(+), 31 deletions(-)
diff --git a/client/src/main/java/client/MyModule.java b/client/src/main/java/client/MyModule.java
index 9f27a8c..a5dd197 100644
--- a/client/src/main/java/client/MyModule.java
+++ b/client/src/main/java/client/MyModule.java
@@ -17,6 +17,7 @@ package client;
import client.scenes.FoodpalApplicationCtrl;
import client.scenes.recipe.IngredientListCtrl;
+import client.scenes.recipe.RecipeStepListCtrl;
import client.utils.LocaleManager;
import com.google.inject.Binder;
import com.google.inject.Module;
@@ -33,6 +34,7 @@ public class MyModule implements Module {
binder.bind(AddNameCtrl.class).in(Scopes.SINGLETON);
binder.bind(FoodpalApplicationCtrl.class).in(Scopes.SINGLETON);
binder.bind(IngredientListCtrl.class).in(Scopes.SINGLETON);
+ binder.bind(RecipeStepListCtrl.class).in(Scopes.SINGLETON);
binder.bind(LocaleManager.class).in(Scopes.SINGLETON);
}
}
\ No newline at end of file
diff --git a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
index 7fcf49b..c0aecfc 100644
--- a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
+++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
@@ -8,6 +8,7 @@ import java.util.Locale;
import client.exception.UpdateException;
import client.scenes.recipe.IngredientListCtrl;
+import client.scenes.recipe.RecipeStepListCtrl;
import client.utils.DefaultRecipeFactory;
import client.utils.LocaleAware;
import client.utils.LocaleManager;
@@ -33,6 +34,7 @@ public class FoodpalApplicationCtrl implements LocaleAware {
private final ServerUtils server;
private final LocaleManager localeManager;
private final IngredientListCtrl ingredientListCtrl;
+ private final RecipeStepListCtrl stepListCtrl;
public VBox detailsScreen;
public HBox editableTitleArea;
@@ -99,16 +101,19 @@ public class FoodpalApplicationCtrl implements LocaleAware {
MainCtrl mainCtrl,
ServerUtils server,
LocaleManager localeManager,
- IngredientListCtrl ingredientListCtrl
+ IngredientListCtrl ingredientListCtrl,
+ RecipeStepListCtrl stepListCtrl
) {
this.mainCtrl = mainCtrl;
this.server = server;
this.localeManager = localeManager;
this.ingredientListCtrl = ingredientListCtrl;
+ this.stepListCtrl = stepListCtrl;
}
@Override
public void initializeComponents() {
+ // TODO Reduce code duplication??
// Initialize callback for ingredient list updates
this.ingredientListCtrl.setUpdateCallback(newList -> {
Recipe focusedRecipe = recipeList.getFocusModel().getFocusedItem();
@@ -124,6 +129,20 @@ public class FoodpalApplicationCtrl implements LocaleAware {
throw new UpdateException("Unable to update recipe to server for " + focusedRecipe);
}
});
+ this.stepListCtrl.setUpdateCallback(newList -> {
+ Recipe focusedRecipe = recipeList.getFocusModel().getFocusedItem();
+ if (focusedRecipe == null) {
+ // edge case error for NPE.
+ throw new NullPointerException("Null recipe whereas ingredients are edited");
+ }
+ focusedRecipe.setPreparationSteps(newList);
+ try {
+ // propagate changes to server
+ server.updateRecipe(focusedRecipe);
+ } catch (IOException | InterruptedException e) {
+ throw new UpdateException("Unable to update recipe to server for " + focusedRecipe);
+ }
+ });
// Show recipe name in the list
recipeList.setCellFactory(list -> new ListCell<>() {
@Override
@@ -163,11 +182,13 @@ public class FoodpalApplicationCtrl implements LocaleAware {
printRecipeButton.setText(getLocaleString("menu.button.print"));
recipesLabel.setText(getLocaleString("menu.label.recipes"));
+
+ // TODO propagate ResourceBundle lang changes to nested controller
// ingredientsLabel.setText(getLocaleString("menu.label.ingredients"));
- preparationLabel.setText(getLocaleString("menu.label.preparation"));
+ // preparationLabel.setText(getLocaleString("menu.label.preparation"));
// addIngredientButton.setText(getLocaleString("menu.button.add.ingredient"));
- addPreparationStepButton.setText(getLocaleString("menu.button.add.step"));
+ // addPreparationStepButton.setText(getLocaleString("menu.button.add.step"));
}
@Override
@@ -177,12 +198,11 @@ public class FoodpalApplicationCtrl implements LocaleAware {
private void showRecipeDetails(Recipe recipe) {
if (recipe == null) {
- preparationListView.getItems().clear();
return;
}
showName(recipe.getName());
ingredientListCtrl.refetchFromRecipe(recipe);
- preparationListView.getItems().setAll(recipe.getPreparationSteps());
+ stepListCtrl.refetchFromRecipe(recipe);
}
// Button handlers
diff --git a/client/src/main/java/client/scenes/recipe/RecipeStepListCtrl.java b/client/src/main/java/client/scenes/recipe/RecipeStepListCtrl.java
index 7ed9c36..2839028 100644
--- a/client/src/main/java/client/scenes/recipe/RecipeStepListCtrl.java
+++ b/client/src/main/java/client/scenes/recipe/RecipeStepListCtrl.java
@@ -5,7 +5,7 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
-import java.util.function.Function;
+import java.util.function.Consumer;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
@@ -29,7 +29,7 @@ public class RecipeStepListCtrl implements Initializable {
* As the step list in {@link Recipe} is immutable,
* this copies that list upon initialization to this mutable list.
*
- * Please use the {@link #setUpdateCallback(Function)} function to listen for
+ * Please use the {@link #setUpdateCallback(Consumer)} function to listen for
* changes and update the recipe accordingly.
*
*/
@@ -38,7 +38,7 @@ public class RecipeStepListCtrl implements Initializable {
/**
* A callback function that is called when the step list is updated.
*/
- private Function, Void> updateCallback;
+ private Consumer> updateCallback;
@FXML
ListView recipeStepListView;
@@ -72,7 +72,7 @@ public class RecipeStepListCtrl implements Initializable {
*
* @param callback The function to call upon each update.
*/
- public void setUpdateCallback(Function, Void> callback) {
+ public void setUpdateCallback(Consumer> callback) {
this.updateCallback = callback;
}
@@ -91,7 +91,7 @@ public class RecipeStepListCtrl implements Initializable {
private void handleIngredientAdd(ActionEvent event) {
this.steps.add("Step " + (this.steps.size() + 1));
this.refresh();
- this.updateCallback.apply(this.steps);
+ this.updateCallback.accept(this.steps);
var select = this.recipeStepListView.getSelectionModel();
select.select(this.steps.size() - 1);
@@ -108,7 +108,7 @@ public class RecipeStepListCtrl implements Initializable {
this.steps.set(index, newValue);
this.refresh();
- this.updateCallback.apply(this.steps);
+ this.updateCallback.accept(this.steps);
}
/**
@@ -126,7 +126,7 @@ public class RecipeStepListCtrl implements Initializable {
this.steps.remove(selectedIndex);
this.refresh();
- this.updateCallback.apply(this.steps);
+ this.updateCallback.accept(this.steps);
}
@FXML
diff --git a/client/src/main/resources/client/scenes/FoodpalApplication.fxml b/client/src/main/resources/client/scenes/FoodpalApplication.fxml
index 8fe9bc9..27b5bc2 100644
--- a/client/src/main/resources/client/scenes/FoodpalApplication.fxml
+++ b/client/src/main/resources/client/scenes/FoodpalApplication.fxml
@@ -116,27 +116,10 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
From 874753790143877c3201c85dbaf4d94077de666d Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 17:46:52 +0100
Subject: [PATCH 06/15] chore: purge dead weight code
---
client/src/main/java/client/Main.java | 9 +-
client/src/main/java/client/MyModule.java | 2 -
.../java/client/scenes/AddIngredientCtrl.java | 115 ------------------
.../main/java/client/scenes/AddNameCtrl.java | 112 -----------------
.../main/java/client/scenes/AddStepsCtrl.java | 114 -----------------
.../client/scenes/FoodpalApplicationCtrl.java | 48 --------
.../src/main/java/client/scenes/MainCtrl.java | 72 +----------
7 files changed, 3 insertions(+), 469 deletions(-)
delete mode 100644 client/src/main/java/client/scenes/AddIngredientCtrl.java
delete mode 100644 client/src/main/java/client/scenes/AddNameCtrl.java
delete mode 100644 client/src/main/java/client/scenes/AddStepsCtrl.java
diff --git a/client/src/main/java/client/Main.java b/client/src/main/java/client/Main.java
index e2f58d6..55d7fa7 100644
--- a/client/src/main/java/client/Main.java
+++ b/client/src/main/java/client/Main.java
@@ -17,10 +17,7 @@ package client;
import static com.google.inject.Guice.createInjector;
-import client.scenes.AddStepsCtrl;
import client.scenes.MainCtrl;
-import client.scenes.AddIngredientCtrl;
-import client.scenes.AddNameCtrl;
import client.scenes.FoodpalApplicationCtrl;
import client.utils.ServerUtils;
import com.google.inject.Injector;
@@ -46,13 +43,9 @@ public class Main extends Application {
System.err.println(msg);
return;
}
-
- var addName = FXML.load(AddNameCtrl.class, "client", "scenes", "AddName.fxml");
var foodpal = FXML.load(FoodpalApplicationCtrl.class, "client", "scenes", "FoodpalApplication.fxml");
- var addIngredient = FXML.load(AddIngredientCtrl.class, "client", "scenes", "AddIngredient.fxml");
- var addStep = FXML.load(AddStepsCtrl.class, "client", "scenes", "AddSteps.fxml");
var mainCtrl = INJECTOR.getInstance(MainCtrl.class);
- mainCtrl.setup(primaryStage, addName, foodpal, addIngredient, addStep);
+ mainCtrl.setup(primaryStage, foodpal);
}
}
\ No newline at end of file
diff --git a/client/src/main/java/client/MyModule.java b/client/src/main/java/client/MyModule.java
index a5dd197..4f3464e 100644
--- a/client/src/main/java/client/MyModule.java
+++ b/client/src/main/java/client/MyModule.java
@@ -23,7 +23,6 @@ import com.google.inject.Binder;
import com.google.inject.Module;
import com.google.inject.Scopes;
-import client.scenes.AddNameCtrl;
import client.scenes.MainCtrl;
public class MyModule implements Module {
@@ -31,7 +30,6 @@ public class MyModule implements Module {
@Override
public void configure(Binder binder) {
binder.bind(MainCtrl.class).in(Scopes.SINGLETON);
- binder.bind(AddNameCtrl.class).in(Scopes.SINGLETON);
binder.bind(FoodpalApplicationCtrl.class).in(Scopes.SINGLETON);
binder.bind(IngredientListCtrl.class).in(Scopes.SINGLETON);
binder.bind(RecipeStepListCtrl.class).in(Scopes.SINGLETON);
diff --git a/client/src/main/java/client/scenes/AddIngredientCtrl.java b/client/src/main/java/client/scenes/AddIngredientCtrl.java
deleted file mode 100644
index 70d6924..0000000
--- a/client/src/main/java/client/scenes/AddIngredientCtrl.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2021 Delft University of Technology
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package client.scenes;
-
-import client.utils.LocaleAware;
-import client.utils.LocaleManager;
-import client.utils.ServerUtils;
-import com.google.inject.Inject;
-import commons.Recipe;
-import jakarta.ws.rs.WebApplicationException;
-import javafx.fxml.FXML;
-import javafx.scene.control.Alert;
-import javafx.scene.control.Button;
-import javafx.scene.control.Label;
-import javafx.scene.control.TextField;
-import javafx.scene.input.KeyEvent;
-import javafx.stage.Modality;
-
-import java.io.IOException;
-
-public class AddIngredientCtrl implements LocaleAware {
-
- private final ServerUtils server;
- private final MainCtrl mainCtrl;
- private final FoodpalApplicationCtrl foodpalCtrl;
-
- private final LocaleManager localeManager;
-
- @FXML
- public TextField ingredient;
-
- @FXML
- public Button okButton;
-
- @FXML
- public Button cancelButton;
-
- @FXML
- public Label ingredientLabel;
-
- @Inject
- public AddIngredientCtrl(ServerUtils server, MainCtrl mainCtrl,
- FoodpalApplicationCtrl foodpalCtrl, LocaleManager localeManager) {
- this.mainCtrl = mainCtrl;
- this.server = server;
- this.foodpalCtrl = foodpalCtrl;
- this.localeManager = localeManager;
- }
-
- @Override
- public void updateText() {
- ingredientLabel.setText(getLocaleString("add.ingredient.label"));
- okButton.setText(getLocaleString("button.ok"));
- cancelButton.setText(getLocaleString("button.cancel"));
- }
-
- @Override
- public LocaleManager getLocaleManager() {
- return localeManager;
- }
-
- public void cancel() throws IOException, InterruptedException {
- clearFields();
- mainCtrl.showFoodpal();
- }
-
- public void ok() throws IOException, InterruptedException {
- try {
- Recipe selected = foodpalCtrl.getSelectedRecipe();
- server.addRecipeIngredient(selected, ingredient.getText());
- } catch (WebApplicationException e) {
-
- var alert = new Alert(Alert.AlertType.ERROR);
- alert.initModality(Modality.APPLICATION_MODAL);
- alert.setContentText(e.getMessage());
- alert.showAndWait();
- return;
- }
-
-
- clearFields();
- mainCtrl.showFoodpal();
- }
-
- private void clearFields() {
- ingredient.clear();
- }
-
- public void keyPressed(KeyEvent e) throws IOException, InterruptedException {
- switch (e.getCode()) {
- case ENTER:
- ok();
- break;
- case ESCAPE:
- cancel();
- break;
- default:
- break;
- }
- }
-
-}
\ No newline at end of file
diff --git a/client/src/main/java/client/scenes/AddNameCtrl.java b/client/src/main/java/client/scenes/AddNameCtrl.java
deleted file mode 100644
index 73f86e6..0000000
--- a/client/src/main/java/client/scenes/AddNameCtrl.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2021 Delft University of Technology
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package client.scenes;
-
-import client.utils.LocaleAware;
-import client.utils.LocaleManager;
-import client.utils.ServerUtils;
-import com.google.inject.Inject;
-
-import jakarta.ws.rs.WebApplicationException;
-import javafx.fxml.FXML;
-import javafx.scene.control.Alert;
-import javafx.scene.control.Button;
-import javafx.scene.control.Label;
-import javafx.scene.control.TextField;
-import javafx.scene.input.KeyEvent;
-import javafx.stage.Modality;
-
-import java.io.IOException;
-
-public class AddNameCtrl implements LocaleAware {
-
- private final ServerUtils server;
- private final MainCtrl mainCtrl;
-
- private final LocaleManager localeManager;
-
- @FXML
- public TextField recipeName;
-
- @FXML
- public Label recipeNameLabel;
-
- @FXML
- public Button cancelButton;
-
- @FXML
- public Button okButton;
-
- @Inject
- public AddNameCtrl(ServerUtils server, MainCtrl mainCtrl, LocaleManager localeManager) {
- this.mainCtrl = mainCtrl;
- this.server = server;
- this.localeManager = localeManager;
- }
-
- @Override
- public void updateText() {
- recipeNameLabel.setText(getLocaleString("add.recipe.label"));
- okButton.setText(getLocaleString("button.ok"));
- cancelButton.setText(getLocaleString("button.cancel"));
- }
-
- @Override
- public LocaleManager getLocaleManager() {
- return localeManager;
- }
-
- public void cancel() throws IOException, InterruptedException {
- clearFields();
- mainCtrl.showFoodpal();
- }
-
- public void ok() throws IOException, InterruptedException {
- try {
- server.addRecipeName(recipeName.getText());
- } catch (WebApplicationException e) {
-
- var alert = new Alert(Alert.AlertType.ERROR);
- alert.initModality(Modality.APPLICATION_MODAL);
- alert.setContentText(e.getMessage());
- alert.showAndWait();
- return;
- } catch (IOException | InterruptedException e) {
- throw new RuntimeException(e);
- }
-
- clearFields();
- mainCtrl.showFoodpal();
- }
-
- private void clearFields() {
- recipeName.clear();
- }
-
- public void keyPressed(KeyEvent e) throws IOException, InterruptedException {
- switch (e.getCode()) {
- case ENTER:
- ok();
- break;
- case ESCAPE:
- cancel();
- break;
- default:
- break;
- }
- }
-
-}
\ No newline at end of file
diff --git a/client/src/main/java/client/scenes/AddStepsCtrl.java b/client/src/main/java/client/scenes/AddStepsCtrl.java
deleted file mode 100644
index abd9f51..0000000
--- a/client/src/main/java/client/scenes/AddStepsCtrl.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2021 Delft University of Technology
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package client.scenes;
-
-import client.utils.LocaleAware;
-import client.utils.LocaleManager;
-import client.utils.ServerUtils;
-import com.google.inject.Inject;
-import commons.Recipe;
-import jakarta.ws.rs.WebApplicationException;
-import javafx.fxml.FXML;
-import javafx.scene.control.Alert;
-import javafx.scene.control.Button;
-import javafx.scene.control.Label;
-import javafx.scene.control.TextField;
-import javafx.scene.input.KeyEvent;
-import javafx.stage.Modality;
-
-import java.io.IOException;
-
-public class AddStepsCtrl implements LocaleAware {
-
- private final ServerUtils server;
- private final MainCtrl mainCtrl;
- private final FoodpalApplicationCtrl foodpalCtrl;
- private final LocaleManager localeManager;
-
- @FXML
- public TextField preparationStep;
-
- @FXML
- public Button okButton;
-
- @FXML
- public Button cancelButton;
-
- @FXML
- public Label preparationStepLabel;
-
- @Inject
- public AddStepsCtrl(ServerUtils server, MainCtrl mainCtrl,
- FoodpalApplicationCtrl foodpalCtrl, LocaleManager localeManager) {
- this.mainCtrl = mainCtrl;
- this.server = server;
- this.foodpalCtrl = foodpalCtrl;
- this.localeManager = localeManager;
- }
-
- @Override
- public void updateText() {
- preparationStepLabel.setText(getLocaleString("add.step.label"));
- okButton.setText(getLocaleString("button.ok"));
- cancelButton.setText(getLocaleString("button.cancel"));
- }
-
- @Override
- public LocaleManager getLocaleManager() {
- return localeManager;
- }
-
- public void cancel() throws IOException, InterruptedException {
- clearFields();
- mainCtrl.showFoodpal();
- }
-
- public void ok() throws IOException, InterruptedException {
- try {
- Recipe selected = foodpalCtrl.getSelectedRecipe();
- server.addRecipeStep(selected, preparationStep.getText());
- } catch (WebApplicationException e) {
-
- var alert = new Alert(Alert.AlertType.ERROR);
- alert.initModality(Modality.APPLICATION_MODAL);
- alert.setContentText(e.getMessage());
- alert.showAndWait();
- return;
- }
-
-
- clearFields();
- mainCtrl.showFoodpal();
- }
-
- private void clearFields() {
- preparationStep.clear();
- }
-
- public void keyPressed(KeyEvent e) throws IOException, InterruptedException {
- switch (e.getCode()) {
- case ENTER:
- ok();
- break;
- case ESCAPE:
- cancel();
- break;
- default:
- break;
- }
- }
-
-}
\ No newline at end of file
diff --git a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
index c0aecfc..e50a983 100644
--- a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
+++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
@@ -78,24 +78,6 @@ public class FoodpalApplicationCtrl implements LocaleAware {
@FXML
public Button printRecipeButton;
- @FXML
- public Label ingredientsLabel;
-
- @FXML
- public Label preparationLabel;
-
- @FXML
- private ListView ingredientsListView;
-
- @FXML
- private Button addIngredientButton;
-
- @FXML
- private ListView preparationListView;
-
- @FXML
- private Button addPreparationStepButton;
-
@Inject
public FoodpalApplicationCtrl(
MainCtrl mainCtrl,
@@ -311,28 +293,6 @@ public class FoodpalApplicationCtrl implements LocaleAware {
editableTitleArea.getChildren().add(edit);
}
- /**
- * You can add ingredients. you get send to a different scene that creates the ingredient
- * It doesn't automatically refresh yet so before you can see the new ingredient you have to first click on a
- * different recipe and come back after
- */
- @FXML
- private void addIngredient() {
- System.out.println("Add ingredient clicked");
- mainCtrl.showAddIngredient();
- }
-
- /**
- * You can add steps. you get send to a different scene that creates the Step
- * It doesn't automatically refresh yet so before you can see the new step you have to first click on a
- * different recipe and come back after
- */
- @FXML
- private void addPreparationStep() {
- System.out.println("Add preparation step clicked");
- mainCtrl.showAddSteps();
-
- }
// Language buttons
@FXML
@@ -347,14 +307,6 @@ public class FoodpalApplicationCtrl implements LocaleAware {
System.out.println("Recipe printed");
}
- /**
- * Get the recipe that was selected
- * @return the selected recipe
- */
- public Recipe getSelectedRecipe() {
- return recipeList.getSelectionModel().getSelectedItem();
- }
-
/**
* Clones a recipe, when clicking on the button "clone"
*/
diff --git a/client/src/main/java/client/scenes/MainCtrl.java b/client/src/main/java/client/scenes/MainCtrl.java
index 0ad2f49..1f439c9 100644
--- a/client/src/main/java/client/scenes/MainCtrl.java
+++ b/client/src/main/java/client/scenes/MainCtrl.java
@@ -32,51 +32,23 @@ public class MainCtrl implements LocaleAware {
@FXML
private Stage primaryStage;
- @FXML
- private AddNameCtrl addNameCtrl;
- private Scene addName;
-
@FXML
private FoodpalApplicationCtrl foodpalCtrl;
private Scene foodpal;
- @FXML
- private AddIngredientCtrl addIngredientCtrl;
- private Scene addIngredient;
-
- @FXML
- private AddStepsCtrl addStepsCtrl;
- private Scene addStep;
-
- private String addNameTitle = "add.name.title";
- private String addIngredientTitle = "add.step.title";
- private String addStepTitle = "add.ingredient.title";
-
@Inject
public MainCtrl(LocaleManager localeManager) {
this.localeManager = localeManager;
}
public void setup(Stage primaryStage,
- Pair addName,
- Pair foodpal,
- Pair addIngredient,
- Pair addStep) throws IOException, InterruptedException {
+ Pair foodpal) throws IOException, InterruptedException {
this.primaryStage = primaryStage;
- this.addNameCtrl = addName.getKey();
- this.addName = new Scene(addName.getValue());
-
this.foodpalCtrl = foodpal.getKey();
this.foodpal = new Scene(foodpal.getValue());
- this.addIngredientCtrl = addIngredient.getKey();
- this.addIngredient = new Scene(addIngredient.getValue());
-
- this.addStepsCtrl = addStep.getKey();
- this.addStep = new Scene(addStep.getValue());
-
showFoodpal();
primaryStage.show();
@@ -85,9 +57,7 @@ public class MainCtrl implements LocaleAware {
@Override
public void updateText() {
- addNameTitle = getLocaleString("add.recipe.title");
- addStepTitle = getLocaleString("add.step.title");
- addIngredientTitle = getLocaleString("add.ingredient.title");
+ // nothing here, no actual text objects managed by MainCtrl
}
@Override
@@ -95,47 +65,9 @@ public class MainCtrl implements LocaleAware {
return localeManager;
}
- public void showAddName() {
- primaryStage.setTitle(addNameTitle);
- primaryStage.setScene(addName);
- addName.setOnKeyPressed(e -> {
- try {
- addNameCtrl.keyPressed(e);
- } catch (IOException | InterruptedException ex) {
- throw new RuntimeException(ex);
- }
- });
- }
-
public void showFoodpal() {
primaryStage.setTitle("FoodPal");
primaryStage.setScene(foodpal);
foodpalCtrl.refresh();
}
-
- public void showAddIngredient() {
- primaryStage.setTitle(addIngredientTitle);
- primaryStage.setScene(addIngredient);
- addIngredient.setOnKeyPressed(e -> {
- try {
- addIngredientCtrl.keyPressed(e);
- } catch (IOException | InterruptedException ex) {
- throw new RuntimeException(ex);
- }
- });
-
- }
-
- public void showAddSteps() {
- primaryStage.setTitle(addStepTitle);
- primaryStage.setScene(addStep);
- addStep.setOnKeyPressed(e -> {
- try {
- addStepsCtrl.keyPressed(e);
- } catch (IOException | InterruptedException ex) {
- throw new RuntimeException(ex);
- }
- });
-
- }
}
\ No newline at end of file
From 73324022b00fbf4a39310a758ab33d05b9fcc476 Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 18:21:02 +0100
Subject: [PATCH 07/15] chore: cleanup debug sout (oops)
---
.../src/main/java/client/scenes/recipe/IngredientListCtrl.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java b/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
index a772913..6db8fb5 100644
--- a/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
+++ b/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
@@ -59,7 +59,6 @@ public class IngredientListCtrl implements Initializable {
if (recipe == null) {
this.ingredients = FXCollections.observableArrayList(new ArrayList<>());
} else {
- System.out.println("refetched");
List ingredientList = recipe.getIngredients();
this.ingredients = FXCollections.observableArrayList(ingredientList);
}
From 30cbfbc45466be6beca90b8b572037402c768152 Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 18:22:10 +0100
Subject: [PATCH 08/15] fix: rectify a NPE caused by wrong ListView model
Apparently a thing can be selected but not focused. Oops.
---
.../client/scenes/FoodpalApplicationCtrl.java | 22 +++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
index e50a983..0e80969 100644
--- a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
+++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
@@ -92,37 +92,36 @@ public class FoodpalApplicationCtrl implements LocaleAware {
this.ingredientListCtrl = ingredientListCtrl;
this.stepListCtrl = stepListCtrl;
}
-
@Override
public void initializeComponents() {
// TODO Reduce code duplication??
// Initialize callback for ingredient list updates
this.ingredientListCtrl.setUpdateCallback(newList -> {
- Recipe focusedRecipe = recipeList.getFocusModel().getFocusedItem();
- if (focusedRecipe == null) {
+ Recipe selectedRecipe = recipeList.getSelectionModel().getSelectedItem();
+ if (selectedRecipe == null) {
// edge case error for NPE.
throw new NullPointerException("Null recipe whereas ingredients are edited");
}
- focusedRecipe.setIngredients(newList);
+ selectedRecipe.setIngredients(newList);
try {
// propagate changes to server
- server.updateRecipe(focusedRecipe);
+ server.updateRecipe(selectedRecipe);
} catch (IOException | InterruptedException e) {
- throw new UpdateException("Unable to update recipe to server for " + focusedRecipe);
+ throw new UpdateException("Unable to update recipe to server for " + selectedRecipe);
}
});
this.stepListCtrl.setUpdateCallback(newList -> {
- Recipe focusedRecipe = recipeList.getFocusModel().getFocusedItem();
- if (focusedRecipe == null) {
+ Recipe selectedRecipe = recipeList.getSelectionModel().getSelectedItem();
+ if (selectedRecipe == null) {
// edge case error for NPE.
throw new NullPointerException("Null recipe whereas ingredients are edited");
}
- focusedRecipe.setPreparationSteps(newList);
+ selectedRecipe.setPreparationSteps(newList);
try {
// propagate changes to server
- server.updateRecipe(focusedRecipe);
+ server.updateRecipe(selectedRecipe);
} catch (IOException | InterruptedException e) {
- throw new UpdateException("Unable to update recipe to server for " + focusedRecipe);
+ throw new UpdateException("Unable to update recipe to server for " + selectedRecipe);
}
});
// Show recipe name in the list
@@ -284,6 +283,7 @@ public class FoodpalApplicationCtrl implements LocaleAware {
try {
server.updateRecipe(selected);
refresh();
+ recipeList.getSelectionModel().select(selected);
} catch (IOException | InterruptedException e) {
// throw a nice blanket UpdateException
throw new UpdateException("Error occurred when updating recipe name!");
From ccb72481fd249ba3466fc811c4133e048970d31a Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 18:22:26 +0100
Subject: [PATCH 09/15] feat: resolve TODO autofocus edit box
---
client/src/main/java/client/scenes/FoodpalApplicationCtrl.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
index 0e80969..9ba7585 100644
--- a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
+++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
@@ -291,6 +291,7 @@ public class FoodpalApplicationCtrl implements LocaleAware {
showName(edit.getText());
});
editableTitleArea.getChildren().add(edit);
+ edit.requestFocus();
}
From 40d157cc6c8825703ba203c98c2e2e5d750b022a Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 21:09:12 +0100
Subject: [PATCH 10/15] fix: remove LocaleAware constraint from MainCtrl
---
.../src/main/java/client/scenes/MainCtrl.java | 25 +------------------
.../test/java/client/scenes/MainCtrlTest.java | 3 +--
2 files changed, 2 insertions(+), 26 deletions(-)
diff --git a/client/src/main/java/client/scenes/MainCtrl.java b/client/src/main/java/client/scenes/MainCtrl.java
index 1f439c9..6499420 100644
--- a/client/src/main/java/client/scenes/MainCtrl.java
+++ b/client/src/main/java/client/scenes/MainCtrl.java
@@ -15,9 +15,6 @@
*/
package client.scenes;
-import client.utils.LocaleAware;
-import client.utils.LocaleManager;
-import jakarta.inject.Inject;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.Scene;
@@ -26,9 +23,7 @@ import javafx.util.Pair;
import java.io.IOException;
-public class MainCtrl implements LocaleAware {
- private final LocaleManager localeManager;
-
+public class MainCtrl {
@FXML
private Stage primaryStage;
@@ -36,11 +31,6 @@ public class MainCtrl implements LocaleAware {
private FoodpalApplicationCtrl foodpalCtrl;
private Scene foodpal;
- @Inject
- public MainCtrl(LocaleManager localeManager) {
- this.localeManager = localeManager;
- }
-
public void setup(Stage primaryStage,
Pair foodpal) throws IOException, InterruptedException {
@@ -51,20 +41,7 @@ public class MainCtrl implements LocaleAware {
showFoodpal();
primaryStage.show();
-
- initialize(); // Initialize LocaleManager stuff manually since MainCtrl isn't loaded from FXML.
}
-
- @Override
- public void updateText() {
- // nothing here, no actual text objects managed by MainCtrl
- }
-
- @Override
- public LocaleManager getLocaleManager() {
- return localeManager;
- }
-
public void showFoodpal() {
primaryStage.setTitle("FoodPal");
primaryStage.setScene(foodpal);
diff --git a/client/src/test/java/client/scenes/MainCtrlTest.java b/client/src/test/java/client/scenes/MainCtrlTest.java
index 63481c6..2709982 100644
--- a/client/src/test/java/client/scenes/MainCtrlTest.java
+++ b/client/src/test/java/client/scenes/MainCtrlTest.java
@@ -15,7 +15,6 @@
*/
package client.scenes;
-import client.utils.LocaleManager;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -24,7 +23,7 @@ public class MainCtrlTest {
@BeforeEach
public void setup() {
- sut = new MainCtrl(new LocaleManager());
+ sut = new MainCtrl();
}
@Test
From 5dd6c89f73463a1fddecea41c44fdce22d9c7cd9 Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 21:39:55 +0100
Subject: [PATCH 11/15] feat: extract abstract OrderedEditableListCell
Abstracts the editable list cell code to make it extendable.
Also includes fix for index (now starts at 1)
---
.../scenes/recipe/IngredientListCell.java | 68 +--------------
.../scenes/recipe/IngredientListCtrl.java | 2 +-
.../recipe/OrderedEditableListCell.java | 78 +++++++++++++++++
.../scenes/recipe/RecipeStepListCell.java | 87 +------------------
4 files changed, 86 insertions(+), 149 deletions(-)
create mode 100644 client/src/main/java/client/scenes/recipe/OrderedEditableListCell.java
diff --git a/client/src/main/java/client/scenes/recipe/IngredientListCell.java b/client/src/main/java/client/scenes/recipe/IngredientListCell.java
index ac317d8..f420bff 100644
--- a/client/src/main/java/client/scenes/recipe/IngredientListCell.java
+++ b/client/src/main/java/client/scenes/recipe/IngredientListCell.java
@@ -1,78 +1,18 @@
package client.scenes.recipe;
-import javafx.scene.control.ListCell;
import javafx.scene.control.TextField;
-import javafx.scene.input.KeyCode;
/**
- * A custom ListCell for displaying and editing ingredients in an
+ * A custom {@link OrderedEditableListCell} for displaying and editing ingredients in an
* IngredientList. Allows inline editing of ingredient names.
*
* @see IngredientListCtrl
*/
-public class IngredientListCell extends ListCell {
+public class IngredientListCell extends OrderedEditableListCell {
// TODO: change all this to use actual Ingredient objects
// and all that :)
-
@Override
- protected void updateItem(String item, boolean empty) {
- super.updateItem(item, empty);
-
- if (empty || item == null) {
- this.setText(null);
- } else {
- this.setText(item);
- }
- }
-
- @Override
- public void startEdit() {
- super.startEdit();
-
- TextField textField = new TextField(this.getItem());
-
- // Commit edit on Enter key press
- textField.setOnAction(event -> {
- this.commitEdit(textField.getText());
- });
-
- // Cancel edit on Escape key press
- textField.setOnKeyReleased(event -> {
- if (event.getCode() == KeyCode.ESCAPE) {
- this.cancelEdit();
- }
- });
-
- this.setText(null);
- this.setGraphic(textField);
- }
-
- /**
- * Check if the input is valid (non-empty).
- *
- * @param input The input string to validate.
- * @return true if valid, false otherwise.
- */
- private boolean isInputValid(String input) {
- return input != null && !input.trim().isEmpty();
- }
-
- @Override
- public void cancelEdit() {
- super.cancelEdit();
-
- this.setText(this.getItem());
- this.setGraphic(null);
- }
-
- @Override
- public void commitEdit(String newValue) {
- this.setGraphic(null);
-
- if (!isInputValid(newValue)) {
- newValue = this.getItem(); // Revert to old value if input is invalid
- }
-
- super.commitEdit(newValue);
+ protected String fromInput(TextField inputField) {
+ return inputField.getText();
}
}
diff --git a/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java b/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
index 6db8fb5..aa33ed2 100644
--- a/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
+++ b/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
@@ -137,7 +137,7 @@ public class IngredientListCtrl implements Initializable {
this.ingredientListView.setEditable(true);
this.ingredientListView.setCellFactory(
list -> {
- return new RecipeStepListCell();
+ return new IngredientListCell();
});
this.ingredientListView.setOnEditCommit(this::handleIngredientEdit);
diff --git a/client/src/main/java/client/scenes/recipe/OrderedEditableListCell.java b/client/src/main/java/client/scenes/recipe/OrderedEditableListCell.java
new file mode 100644
index 0000000..8716c3a
--- /dev/null
+++ b/client/src/main/java/client/scenes/recipe/OrderedEditableListCell.java
@@ -0,0 +1,78 @@
+package client.scenes.recipe;
+
+import javafx.scene.control.ListCell;
+import javafx.scene.control.TextField;
+import javafx.scene.input.KeyCode;
+
+public abstract class OrderedEditableListCell extends ListCell {
+ /**
+ * Get the display text for the given item, prefixed with its index.
+ * Looks like "1. description".
+ *
+ * @param item The description.
+ * @return The display text.
+ */
+ private String getDisplayText(String item) {
+ return (this.getIndex() + 1) + ". " + item;
+ }
+ @Override
+ protected void updateItem(T item, boolean empty) {
+ super.updateItem(item, empty);
+
+ if (empty || item == null) {
+ this.setText(null);
+ } else {
+ this.setText(this.getDisplayText(item.toString()));
+ }
+ }
+ public void startEdit() {
+ super.startEdit();
+
+ TextField textField = new TextField(this.getItem().toString());
+
+ // Commit edit on Enter key press
+ textField.setOnAction(event -> {
+ this.commitEdit(fromInput(textField));
+ });
+
+ // Cancel edit on Escape key press
+ textField.setOnKeyReleased(event -> {
+ if (event.getCode() == KeyCode.ESCAPE) {
+ this.cancelEdit();
+ }
+ });
+
+ this.setText(null);
+ this.setGraphic(textField);
+ }
+
+ protected abstract T fromInput(TextField inputField);
+ /**
+ * Check if the input is valid (non-empty).
+ *
+ * @param input The input string to validate.
+ * @return true if valid, false otherwise.
+ */
+ private boolean isInputValid(String input) {
+ return input != null && !input.trim().isEmpty();
+ }
+
+ @Override
+ public void cancelEdit() {
+ super.cancelEdit();
+
+ this.setText(this.getItem().toString());
+ this.setGraphic(null);
+ }
+
+ @Override
+ public void commitEdit(T newValue) {
+ this.setGraphic(null);
+
+ if (!isInputValid(newValue.toString())) {
+ newValue = this.getItem(); // Revert to old value if input is invalid
+ }
+
+ super.commitEdit(newValue);
+ }
+}
diff --git a/client/src/main/java/client/scenes/recipe/RecipeStepListCell.java b/client/src/main/java/client/scenes/recipe/RecipeStepListCell.java
index 6d6e992..bf57c13 100644
--- a/client/src/main/java/client/scenes/recipe/RecipeStepListCell.java
+++ b/client/src/main/java/client/scenes/recipe/RecipeStepListCell.java
@@ -1,96 +1,15 @@
package client.scenes.recipe;
-import javafx.scene.control.ListCell;
import javafx.scene.control.TextField;
-import javafx.scene.input.KeyCode;
-
/**
* A custom ListCell for displaying and editing ingredients in an
* RecipeStepList. Allows inline editing of ingredient names.
*
* @see RecipeStepListCtrl
*/
-public class RecipeStepListCell extends ListCell {
- /**
- * Get the display text for the given item, prefixed with its index.
- * Looks like "1. Step description".
- *
- * @param item The step description.
- * @return The display text.
- */
- private String getDisplayText(String item) {
- return this.getIndex() + ". " + item;
- }
-
- /**
- * Get the display text for the current item.
- * Looks like "1. Step description".
- *
- * @return The display text.
- */
- private String getDisplayText() {
- return this.getDisplayText(this.getItem());
- }
-
+public class RecipeStepListCell extends OrderedEditableListCell {
@Override
- protected void updateItem(String item, boolean empty) {
- super.updateItem(item, empty);
-
- if (empty || item == null) {
- this.setText(null);
- } else {
- this.setText(this.getDisplayText(item));
- }
- }
-
- @Override
- public void startEdit() {
- super.startEdit();
-
- TextField textField = new TextField(this.getItem());
-
- // Commit edit on Enter key press
- textField.setOnAction(event -> {
- this.commitEdit(textField.getText());
- });
-
- // Cancel edit on Escape key press
- textField.setOnKeyReleased(event -> {
- if (event.getCode() == KeyCode.ESCAPE) {
- this.cancelEdit();
- }
- });
-
- this.setText(null);
- this.setGraphic(textField);
- }
-
- /**
- * Check if the input is valid (non-empty).
- *
- * @param input The input string to validate.
- * @return true if valid, false otherwise.
- */
- private boolean isInputValid(String input) {
- return input != null && !input.trim().isEmpty();
- }
-
- @Override
- public void cancelEdit() {
- super.cancelEdit();
-
- this.setText(this.getDisplayText());
- this.setGraphic(null);
- }
-
- @Override
- public void commitEdit(String newValue) {
- this.setGraphic(null);
-
- if (!isInputValid(newValue)) {
- newValue = this.getItem(); // Revert to old value if input is invalid
- }
-
- super.commitEdit(newValue);
+ protected String fromInput(TextField inputField) {
+ return inputField.getText();
}
}
From 603de94870622d9ea5b8a3a87b1a824d86deff6c Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 22:08:39 +0100
Subject: [PATCH 12/15] feat: bold font recipe name + i18n for controllers
---
.../client/scenes/FoodpalApplicationCtrl.java | 9 +++--
.../scenes/recipe/IngredientListCtrl.java | 37 +++++++++++++++----
.../scenes/recipe/RecipeStepListCtrl.java | 37 ++++++++++++++-----
.../client/scenes/recipe/IngredientList.fxml | 2 +-
.../client/scenes/recipe/RecipeStepList.fxml | 2 +-
5 files changed, 64 insertions(+), 23 deletions(-)
diff --git a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
index 9ba7585..cf5dc49 100644
--- a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
+++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
@@ -28,9 +28,9 @@ import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
+import javafx.scene.text.Font;
public class FoodpalApplicationCtrl implements LocaleAware {
- private final MainCtrl mainCtrl;
private final ServerUtils server;
private final LocaleManager localeManager;
private final IngredientListCtrl ingredientListCtrl;
@@ -80,13 +80,11 @@ public class FoodpalApplicationCtrl implements LocaleAware {
@Inject
public FoodpalApplicationCtrl(
- MainCtrl mainCtrl,
ServerUtils server,
LocaleManager localeManager,
IngredientListCtrl ingredientListCtrl,
RecipeStepListCtrl stepListCtrl
) {
- this.mainCtrl = mainCtrl;
this.server = server;
this.localeManager = localeManager;
this.ingredientListCtrl = ingredientListCtrl;
@@ -149,8 +147,11 @@ public class FoodpalApplicationCtrl implements LocaleAware {
refresh();
}
private void showName(String name) {
+ final int NAME_FONT_SIZE = 20;
editableTitleArea.getChildren().clear();
- editableTitleArea.getChildren().add(new Label(name));
+ Label nameLabel = new Label(name);
+ nameLabel.setFont(new Font("System Bold", NAME_FONT_SIZE));
+ editableTitleArea.getChildren().add(nameLabel);
}
@Override
public void updateText() {
diff --git a/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java b/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
index aa33ed2..859c28a 100644
--- a/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
+++ b/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java
@@ -1,17 +1,18 @@
package client.scenes.recipe;
+import client.utils.LocaleAware;
+import client.utils.LocaleManager;
+import com.google.inject.Inject;
import commons.Recipe;
-import java.net.URL;
import java.util.ArrayList;
import java.util.List;
-import java.util.ResourceBundle;
import java.util.function.Consumer;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
-import javafx.fxml.Initializable;
import javafx.scene.control.Button;
+import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ListView.EditEvent;
@@ -19,9 +20,15 @@ import javafx.scene.control.ListView.EditEvent;
* Controller for the ingredient list view in the recipe detail scene.
* Manages displaying, adding, editing, and deleting ingredients.
*
- * @see RecipeStepListCell The custom cell implementation.
+ * @see IngredientListCell The custom cell implementation.
*/
-public class IngredientListCtrl implements Initializable {
+public class IngredientListCtrl implements LocaleAware {
+ private final LocaleManager localeManager;
+ @Inject
+ public IngredientListCtrl(LocaleManager localeManager) {
+ this.localeManager = localeManager;
+ }
+
/**
*
* The list of ingredients currently displayed.
@@ -43,6 +50,9 @@ public class IngredientListCtrl implements Initializable {
@FXML
public ListView ingredientListView;
+ @FXML
+ public Label ingredientsLabel;
+
@FXML
public Button addIngredientButton;
@FXML
@@ -129,8 +139,21 @@ public class IngredientListCtrl implements Initializable {
this.updateCallback.accept(this.ingredients);
}
- @FXML
- public void initialize(URL location, ResourceBundle resources) {
+ @Override
+ public void updateText() {
+ System.out.println("updatetext called on ingredientListCtrl");
+ ingredientsLabel.setText(getLocaleString("menu.label.ingredients"));
+ addIngredientButton.setText(getLocaleString("menu.button.add.ingredient"));
+ deleteIngredientButton.setText(getLocaleString("menu.button.remove.ingredient"));
+ }
+
+ @Override
+ public LocaleManager getLocaleManager() {
+ return localeManager;
+ }
+
+ @Override
+ public void initializeComponents() {
// TODO: set up communication with the server
// this would probably be best done with the callback (so this class doesn't
// interact with the server at all)
diff --git a/client/src/main/java/client/scenes/recipe/RecipeStepListCtrl.java b/client/src/main/java/client/scenes/recipe/RecipeStepListCtrl.java
index 2839028..8bfcce4 100644
--- a/client/src/main/java/client/scenes/recipe/RecipeStepListCtrl.java
+++ b/client/src/main/java/client/scenes/recipe/RecipeStepListCtrl.java
@@ -1,17 +1,18 @@
package client.scenes.recipe;
+import client.utils.LocaleAware;
+import client.utils.LocaleManager;
+import com.google.inject.Inject;
import commons.Recipe;
-import java.net.URL;
import java.util.ArrayList;
import java.util.List;
-import java.util.ResourceBundle;
import java.util.function.Consumer;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
-import javafx.fxml.Initializable;
import javafx.scene.control.Button;
+import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ListView.EditEvent;
@@ -21,7 +22,16 @@ import javafx.scene.control.ListView.EditEvent;
*
* @see RecipeStepListCell The custom cell implementation.
*/
-public class RecipeStepListCtrl implements Initializable {
+public class RecipeStepListCtrl implements LocaleAware {
+ private final LocaleManager localeManager;
+
+ @FXML
+ public Label stepsLabel;
+
+ @Inject
+ public RecipeStepListCtrl(LocaleManager localeManager) {
+ this.localeManager = localeManager;
+ }
/**
*
* The list of recipe steps currently displayed.
@@ -129,18 +139,25 @@ public class RecipeStepListCtrl implements Initializable {
this.updateCallback.accept(this.steps);
}
- @FXML
- public void initialize(URL location, ResourceBundle resources) {
- // TODO: set up communication with the server
- // this would probably be best done with the callback (so this class doesn't
- // interact with the server at all)
+ @Override
+ public void updateText() {
+ stepsLabel.setText(getLocaleString("menu.label.preparation"));
+ addStepButton.setText(getLocaleString("menu.button.add.step"));
+ deleteStepButton.setText(getLocaleString("menu.button.remove.step"));
+ }
+ @Override
+ public LocaleManager getLocaleManager() {
+ return localeManager;
+ }
+
+ @Override
+ public void initializeComponents() {
this.recipeStepListView.setEditable(true);
this.recipeStepListView.setCellFactory(
list -> {
return new RecipeStepListCell();
});
-
this.recipeStepListView.setOnEditCommit(this::handleIngredientEdit);
this.addStepButton.setOnAction(this::handleIngredientAdd);
this.deleteStepButton.setOnAction(this::handleIngredientDelete);
diff --git a/client/src/main/resources/client/scenes/recipe/IngredientList.fxml b/client/src/main/resources/client/scenes/recipe/IngredientList.fxml
index 1ad02e4..1a032ea 100644
--- a/client/src/main/resources/client/scenes/recipe/IngredientList.fxml
+++ b/client/src/main/resources/client/scenes/recipe/IngredientList.fxml
@@ -15,7 +15,7 @@
-
+
diff --git a/client/src/main/resources/client/scenes/recipe/RecipeStepList.fxml b/client/src/main/resources/client/scenes/recipe/RecipeStepList.fxml
index 1b5e936..7c6fec6 100644
--- a/client/src/main/resources/client/scenes/recipe/RecipeStepList.fxml
+++ b/client/src/main/resources/client/scenes/recipe/RecipeStepList.fxml
@@ -15,7 +15,7 @@
-
+
From c2fa31aa9f5c27f6881da11f1f77e14474e75bd1 Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 22:13:22 +0100
Subject: [PATCH 13/15] fix: no null pointer exceptions if the user can't see
anything :)
---
client/src/main/java/client/scenes/FoodpalApplicationCtrl.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
index cf5dc49..a182619 100644
--- a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
+++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
@@ -203,8 +203,8 @@ public class FoodpalApplicationCtrl implements LocaleAware {
// Select first recipe in the list by default
if (!recipes.isEmpty()) {
recipeList.getSelectionModel().selectFirst();
- detailsScreen.visibleProperty().set(true);
}
+ detailsScreen.visibleProperty().set(!recipes.isEmpty());
}
private void printError(String msg) {
Alert alert = new Alert(Alert.AlertType.ERROR);
From 409877a6fb50088bc7ef0b51cae1ccd18692c57b Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 22:20:54 +0100
Subject: [PATCH 14/15] chore: a farewell to Add* UI elements
---
.../resources/client/scenes/AddIngredient.fxml | 15 ---------------
.../src/main/resources/client/scenes/AddName.fxml | 15 ---------------
.../main/resources/client/scenes/AddSteps.fxml | 15 ---------------
3 files changed, 45 deletions(-)
delete mode 100644 client/src/main/resources/client/scenes/AddIngredient.fxml
delete mode 100644 client/src/main/resources/client/scenes/AddName.fxml
delete mode 100644 client/src/main/resources/client/scenes/AddSteps.fxml
diff --git a/client/src/main/resources/client/scenes/AddIngredient.fxml b/client/src/main/resources/client/scenes/AddIngredient.fxml
deleted file mode 100644
index 5aaddde..0000000
--- a/client/src/main/resources/client/scenes/AddIngredient.fxml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/client/src/main/resources/client/scenes/AddName.fxml b/client/src/main/resources/client/scenes/AddName.fxml
deleted file mode 100644
index 8273c33..0000000
--- a/client/src/main/resources/client/scenes/AddName.fxml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/client/src/main/resources/client/scenes/AddSteps.fxml b/client/src/main/resources/client/scenes/AddSteps.fxml
deleted file mode 100644
index adc4259..0000000
--- a/client/src/main/resources/client/scenes/AddSteps.fxml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
From 10868134b07dc672b0b39d4e879c5c2922fcbdf0 Mon Sep 17 00:00:00 2001
From: Steven Liu
Date: Thu, 4 Dec 2025 23:11:16 +0100
Subject: [PATCH 15/15] fix: autoselect cloned recipe after cloning operation
---
.../src/main/java/client/scenes/FoodpalApplicationCtrl.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
index a182619..ed97139 100644
--- a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
+++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java
@@ -318,9 +318,9 @@ public class FoodpalApplicationCtrl implements LocaleAware {
return;
}
- server.cloneRecipe(selected.getId());
+ Recipe cloned = server.cloneRecipe(selected.getId());
refresh();
-
+ recipeList.getSelectionModel().select(cloned);
}
}