Merge branch 'feature/shopping-list-crud' into 'main'
CRUD functionality for shopping list Closes #80 See merge request cse1105/2025-2026/teams/csep-team-76!85
This commit is contained in:
commit
1fd3b26faa
14 changed files with 362 additions and 37 deletions
|
|
@ -21,8 +21,10 @@ import client.scenes.nutrition.NutritionDetailsCtrl;
|
|||
import client.scenes.nutrition.NutritionViewCtrl;
|
||||
import client.scenes.recipe.IngredientListCtrl;
|
||||
import client.scenes.recipe.RecipeStepListCtrl;
|
||||
import client.service.NonFunctionalShoppingListService;
|
||||
import client.scenes.shopping.ShoppingListCtrl;
|
||||
import client.scenes.shopping.ShoppingListNewItemPromptCtrl;
|
||||
import client.service.ShoppingListService;
|
||||
import client.service.ShoppingListServiceImpl;
|
||||
import client.service.ShoppingListViewModel;
|
||||
import client.utils.ConfigService;
|
||||
import client.utils.LocaleManager;
|
||||
|
|
@ -60,8 +62,10 @@ public class MyModule implements Module {
|
|||
binder.bind(new TypeLiteral<WebSocketDataService<Long, Recipe>>() {}).toInstance(
|
||||
new WebSocketDataService<>()
|
||||
);
|
||||
binder.bind(ShoppingListNewItemPromptCtrl.class).in(Scopes.SINGLETON);
|
||||
binder.bind(ShoppingListCtrl.class).in(Scopes.SINGLETON);
|
||||
binder.bind(ShoppingListViewModel.class).toInstance(new ShoppingListViewModel());
|
||||
binder.bind(ShoppingListService.class).to(NonFunctionalShoppingListService.class);
|
||||
binder.bind(ShoppingListService.class).to(ShoppingListServiceImpl.class);
|
||||
binder.bind(new TypeLiteral<WebSocketDataService<Long, Ingredient>>() {}).toInstance(
|
||||
new WebSocketDataService<>()
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,10 +7,12 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import client.UI;
|
||||
import client.exception.InvalidModificationException;
|
||||
import client.scenes.nutrition.NutritionViewCtrl;
|
||||
import client.scenes.recipe.RecipeDetailCtrl;
|
||||
|
||||
import client.scenes.shopping.ShoppingListCtrl;
|
||||
import client.utils.Config;
|
||||
import client.utils.ConfigService;
|
||||
import client.utils.DefaultValueFactory;
|
||||
|
|
@ -34,8 +36,6 @@ import javafx.beans.property.SimpleListProperty;
|
|||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Button;
|
||||
|
|
@ -515,11 +515,10 @@ public class FoodpalApplicationCtrl implements LocaleAware {
|
|||
}
|
||||
|
||||
public void openShoppingListWindow() throws IOException {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("shopping/ShoppingList.fxml"));
|
||||
Parent root = (Parent)loader.load();
|
||||
var root = UI.getFXML().load(ShoppingListCtrl.class, "client", "scenes", "shopping", "ShoppingList.fxml");
|
||||
Stage stage = new Stage();
|
||||
stage.setTitle(this.getLocaleString("menu.shopping.title"));
|
||||
stage.setScene(new Scene(root));
|
||||
stage.setScene(new Scene(root.getValue()));
|
||||
stage.show();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package client.scenes.recipe;
|
|||
|
||||
import client.exception.UpdateException;
|
||||
import client.scenes.FoodpalApplicationCtrl;
|
||||
import client.service.ShoppingListService;
|
||||
import client.utils.Config;
|
||||
import client.utils.ConfigService;
|
||||
import client.utils.LocaleAware;
|
||||
|
|
@ -10,6 +11,7 @@ import client.utils.PrintExportService;
|
|||
import client.utils.server.ServerUtils;
|
||||
import client.utils.WebSocketDataService;
|
||||
import com.google.inject.Inject;
|
||||
import commons.FormalIngredient;
|
||||
import commons.Recipe;
|
||||
|
||||
import java.io.File;
|
||||
|
|
@ -20,6 +22,7 @@ import java.util.function.BiConsumer;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ComboBox;
|
||||
|
|
@ -46,6 +49,7 @@ public class RecipeDetailCtrl implements LocaleAware {
|
|||
private final FoodpalApplicationCtrl appCtrl;
|
||||
private final ConfigService configService;
|
||||
private final WebSocketDataService<Long, Recipe> webSocketDataService;
|
||||
private final ShoppingListService shoppingListService;
|
||||
|
||||
public Spinner<Double> scaleSpinner;
|
||||
public Label inferredKcalLabel;
|
||||
|
|
@ -67,12 +71,14 @@ public class RecipeDetailCtrl implements LocaleAware {
|
|||
ServerUtils server,
|
||||
FoodpalApplicationCtrl appCtrl,
|
||||
ConfigService configService,
|
||||
ShoppingListService listService,
|
||||
WebSocketDataService<Long, Recipe> webSocketDataService) {
|
||||
this.localeManager = localeManager;
|
||||
this.server = server;
|
||||
this.appCtrl = appCtrl;
|
||||
this.configService = configService;
|
||||
this.webSocketDataService = webSocketDataService;
|
||||
this.shoppingListService = listService;
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
|
@ -418,4 +424,13 @@ public class RecipeDetailCtrl implements LocaleAware {
|
|||
});
|
||||
langSelector.getItems().addAll("en", "nl", "pl", "tok");
|
||||
}
|
||||
|
||||
public void handleAddAllToShoppingList(ActionEvent actionEvent) {
|
||||
System.out.println("handleAddAllToShoppingList");
|
||||
// TODO BACKLOG Add overview screen
|
||||
recipe.getIngredients().stream()
|
||||
.filter(x -> x.getClass().equals(FormalIngredient.class))
|
||||
.map(FormalIngredient.class::cast)
|
||||
.forEach(x -> shoppingListService.putIngredient(x, recipe));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
package client.scenes.shopping;
|
||||
|
||||
import client.scenes.recipe.OrderedEditableListCell;
|
||||
import commons.FormalIngredient;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Spinner;
|
||||
import javafx.scene.control.SpinnerValueFactory;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.util.Pair;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ShoppingListCell extends OrderedEditableListCell<Pair<FormalIngredient, Optional<String>>> {
|
||||
private Node makeEditor() {
|
||||
HBox editor = new HBox();
|
||||
Spinner<Double> amountInput = new Spinner<>();
|
||||
FormalIngredient ingredient = getItem().getKey();
|
||||
amountInput.setEditable(true);
|
||||
amountInput.setValueFactory(new SpinnerValueFactory.DoubleSpinnerValueFactory(0, Double.MAX_VALUE, ingredient.getAmount()));
|
||||
Label textLabel = new Label(getItem().getKey().getUnitSuffix() + " of " + getItem().getKey().getIngredient().getName());
|
||||
editor.getChildren().addAll(amountInput, textLabel);
|
||||
editor.addEventHandler(KeyEvent.KEY_RELEASED, e -> {
|
||||
if (e.getCode() != KeyCode.ENTER) {
|
||||
return;
|
||||
}
|
||||
Pair<FormalIngredient, Optional<String>> pair = getItem();
|
||||
pair.getKey().setAmount(amountInput.getValue());
|
||||
commitEdit(pair);
|
||||
});
|
||||
return editor;
|
||||
}
|
||||
@Override
|
||||
public void startEdit() {
|
||||
super.startEdit();
|
||||
this.setText("");
|
||||
this.setGraphic(makeEditor());
|
||||
}
|
||||
@Override
|
||||
protected void updateItem(Pair<FormalIngredient, Optional<String>> item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (empty) {
|
||||
this.setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
String display = item.getKey().toString() +
|
||||
item.getValue().map(recipe -> {
|
||||
return " (" + recipe + ")";
|
||||
}).orElse("");
|
||||
|
||||
this.setText(display);
|
||||
}
|
||||
@Override
|
||||
public void cancelEdit() {
|
||||
super.cancelEdit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitEdit(Pair<FormalIngredient, Optional<String>> newValue) {
|
||||
super.commitEdit(newValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,13 +1,19 @@
|
|||
package client.scenes.shopping;
|
||||
|
||||
import client.UI;
|
||||
import client.service.ShoppingListService;
|
||||
import client.utils.LocaleAware;
|
||||
import client.utils.LocaleManager;
|
||||
import com.google.inject.Inject;
|
||||
import commons.FormalIngredient;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.ListCell;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.Pair;
|
||||
|
||||
import java.util.Optional;
|
||||
|
|
@ -19,7 +25,6 @@ public class ShoppingListCtrl implements LocaleAware {
|
|||
|
||||
@FXML
|
||||
private ListView<Pair<FormalIngredient, Optional<String>>> shoppingListView;
|
||||
|
||||
@Inject
|
||||
public ShoppingListCtrl(
|
||||
ShoppingListService shopping,
|
||||
|
|
@ -40,27 +45,37 @@ public class ShoppingListCtrl implements LocaleAware {
|
|||
}
|
||||
|
||||
public void initializeComponents() {
|
||||
this.shoppingListView.setCellFactory(l -> new ListCell<>() {
|
||||
@Override
|
||||
protected void updateItem(Pair<FormalIngredient, Optional<String>> item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (empty) {
|
||||
this.setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
String display = item.getKey().toString() +
|
||||
item.getValue().map(recipe -> {
|
||||
return " (" + recipe + ")";
|
||||
}).orElse("");
|
||||
|
||||
this.setText(display);
|
||||
}
|
||||
});
|
||||
|
||||
this.shoppingListView.setEditable(true);
|
||||
this.shoppingListView.setCellFactory(l -> new ShoppingListCell());
|
||||
this.shoppingListView.getItems().setAll(
|
||||
this.shopping.getItems()
|
||||
);
|
||||
}
|
||||
private void refreshList() {
|
||||
this.shoppingListView.getItems().setAll(
|
||||
this.shopping.getItems()
|
||||
);
|
||||
}
|
||||
|
||||
public void handleAddItem(ActionEvent actionEvent) {
|
||||
Stage stage = new Stage();
|
||||
Pair<ShoppingListNewItemPromptCtrl, Parent> root = UI.getFXML().load(ShoppingListNewItemPromptCtrl.class,
|
||||
"client", "scenes", "shopping", "ShoppingListItemAddModal.fxml");
|
||||
root.getKey().setNewValueConsumer(fi -> {
|
||||
this.shopping.putIngredient(fi);
|
||||
refreshList();
|
||||
});
|
||||
stage.setScene(new Scene(root.getValue()));
|
||||
stage.setTitle("My modal window");
|
||||
stage.initModality(Modality.WINDOW_MODAL);
|
||||
stage.initOwner(
|
||||
((Node)actionEvent.getSource()).getScene().getWindow() );
|
||||
stage.show();
|
||||
}
|
||||
|
||||
public void handleRemoveItem(ActionEvent actionEvent) {
|
||||
var x = this.shoppingListView.getSelectionModel().getSelectedItem();
|
||||
this.shopping.getItems().remove(x);
|
||||
refreshList();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
package client.scenes.shopping;
|
||||
|
||||
import client.utils.LocaleAware;
|
||||
import client.utils.LocaleManager;
|
||||
import client.utils.server.ServerUtils;
|
||||
import com.google.inject.Inject;
|
||||
import commons.FormalIngredient;
|
||||
import commons.Ingredient;
|
||||
import commons.Unit;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.scene.control.MenuButton;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.control.Spinner;
|
||||
import javafx.scene.control.SpinnerValueFactory;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ShoppingListNewItemPromptCtrl implements LocaleAware {
|
||||
public MenuButton ingredientSelection;
|
||||
private final ObjectProperty<Ingredient> selected = new SimpleObjectProperty<>();
|
||||
private final ObjectProperty<Unit> selectedUnit = new SimpleObjectProperty<>();
|
||||
private final ServerUtils server;
|
||||
private final LocaleManager localeManager;
|
||||
private Consumer<FormalIngredient> newValueConsumer;
|
||||
public MenuButton unitSelect;
|
||||
public Spinner<Double> amountSelect;
|
||||
|
||||
@Inject
|
||||
public ShoppingListNewItemPromptCtrl(ServerUtils server, LocaleManager localeManager) {
|
||||
this.server = server;
|
||||
this.localeManager = localeManager;
|
||||
}
|
||||
|
||||
public void setNewValueConsumer(Consumer<FormalIngredient> consumer) {
|
||||
this.newValueConsumer = consumer;
|
||||
}
|
||||
|
||||
public void confirmAdd(ActionEvent actionEvent) {
|
||||
if (selected.get() == null || selectedUnit.get() == null) {
|
||||
System.err.println("You must select both an ingredient and an unit");
|
||||
return;
|
||||
}
|
||||
FormalIngredient fi = new FormalIngredient(selected.get(), amountSelect.getValue(), selectedUnit.get().suffix);
|
||||
newValueConsumer.accept(fi);
|
||||
Stage stage = (Stage) ingredientSelection.getScene().getWindow();
|
||||
stage.close();
|
||||
}
|
||||
|
||||
public void cancelAdd(ActionEvent actionEvent) {
|
||||
}
|
||||
private <T> void makeMenuItems(
|
||||
MenuButton menu,
|
||||
Iterable<T> items,
|
||||
Function<T, String> labelMapper,
|
||||
Consumer<T> onSelect) {
|
||||
// Iterates over the list of items and applies the label and onSelect handlers.
|
||||
for (T item : items) {
|
||||
MenuItem mi = new MenuItem();
|
||||
mi.setText(labelMapper.apply(item));
|
||||
mi.setOnAction(_ -> {
|
||||
menu.setText(labelMapper.apply(item));
|
||||
onSelect.accept(item);
|
||||
});
|
||||
menu.getItems().add(mi);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void updateText() {
|
||||
|
||||
}
|
||||
@Override
|
||||
public void initializeComponents() {
|
||||
try {
|
||||
amountSelect.setValueFactory(
|
||||
new SpinnerValueFactory.DoubleSpinnerValueFactory(0, Double.MAX_VALUE, 0));
|
||||
amountSelect.setEditable(true);
|
||||
makeMenuItems(ingredientSelection, server.getIngredients(), Ingredient::getName, selected::set);
|
||||
makeMenuItems(unitSelect,
|
||||
Arrays.stream(Unit.values()).filter(u -> u.formal).toList(),
|
||||
Unit::toString, selectedUnit::set);
|
||||
} catch (IOException | InterruptedException e) {
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleManager getLocaleManager() {
|
||||
return localeManager;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package client.service;
|
||||
|
||||
import commons.FormalIngredient;
|
||||
public class ShoppingListItem {
|
||||
private FormalIngredient i;
|
||||
}
|
||||
|
|
@ -14,6 +14,15 @@ public abstract class ShoppingListService {
|
|||
public ShoppingListService(ShoppingListViewModel viewModel) {
|
||||
this.viewModel = viewModel;
|
||||
}
|
||||
|
||||
public ShoppingListViewModel getViewModel() {
|
||||
return viewModel;
|
||||
}
|
||||
|
||||
public void setViewModel(ShoppingListViewModel viewModel) {
|
||||
this.viewModel = viewModel;
|
||||
}
|
||||
|
||||
public abstract void putIngredient(FormalIngredient ingredient);
|
||||
public abstract void putIngredient(FormalIngredient ingredient, Recipe recipe);
|
||||
public abstract void putIngredient(FormalIngredient ingredient, String recipeName);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
package client.service;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import commons.FormalIngredient;
|
||||
import commons.Recipe;
|
||||
import javafx.util.Pair;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class ShoppingListServiceImpl extends ShoppingListService {
|
||||
private final Logger logger = Logger.getLogger(ShoppingListServiceImpl.class.getName());
|
||||
@Inject
|
||||
public ShoppingListServiceImpl(
|
||||
ShoppingListViewModel model
|
||||
) {
|
||||
super(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putIngredient(FormalIngredient ingredient) {
|
||||
getViewModel().getListItems().add(new Pair<>(ingredient, Optional.empty()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putIngredient(FormalIngredient ingredient, Recipe recipe) {
|
||||
Pair<FormalIngredient, Optional<String>> val = new Pair<>(ingredient, Optional.of(recipe.getName()));
|
||||
logger.info("putting ingredients into shopping list: " + val);
|
||||
getViewModel().getListItems().add(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putIngredient(FormalIngredient ingredient, String recipeName) {
|
||||
getViewModel().getListItems().add(new Pair<>(ingredient, Optional.of(recipeName)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putArbitraryItem(String name) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormalIngredient purgeIngredient(Long id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FormalIngredient purgeIngredient(String ingredientName) {
|
||||
FormalIngredient fi = getViewModel().getListItems().stream()
|
||||
.filter(i ->
|
||||
i.getKey().getIngredient().getName().equals(ingredientName))
|
||||
.findFirst().orElseThrow(NullPointerException::new).getKey();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
getViewModel().getListItems().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pair<FormalIngredient, Optional<String>>> getItems() {
|
||||
return getViewModel().getListItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String makePrintable() {
|
||||
return "TODO";
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import commons.FormalIngredient;
|
|||
import javafx.beans.property.ListProperty;
|
||||
import javafx.beans.property.SimpleListProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.util.Pair;
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
|
||||
|
|
@ -19,4 +20,7 @@ public class ShoppingListViewModel {
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ObservableList<Pair<FormalIngredient, Optional<String>>> getListItems() {
|
||||
return listItems.get();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
<Button fx:id="removeRecipeButton" mnemonicParsing="false" onAction="#removeSelectedRecipe" text="Remove Recipe" />
|
||||
<Button fx:id="printRecipeButton" mnemonicParsing="false" onAction="#printRecipe" text="Print Recipe" />
|
||||
<Button fx:id="favouriteButton" onAction="#toggleFavourite" text="☆" />
|
||||
<Button onAction="#handleAddAllToShoppingList">Shop</Button>
|
||||
</HBox>
|
||||
|
||||
<HBox>
|
||||
|
|
|
|||
|
|
@ -4,12 +4,20 @@
|
|||
<?import javafx.scene.control.TitledPane?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
|
||||
<TitledPane animated="false" collapsible="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" text="Shopping List" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/25">
|
||||
<content>
|
||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||
<children>
|
||||
<ListView fx:id="shoppingListView" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||
</children>
|
||||
</AnchorPane>
|
||||
</content>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<TitledPane animated="false" collapsible="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
|
||||
minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" text="Shopping List"
|
||||
fx:controller="client.scenes.shopping.ShoppingListCtrl"
|
||||
xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/25">
|
||||
<VBox>
|
||||
<ListView fx:id="shoppingListView" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
|
||||
AnchorPane.topAnchor="0.0"/>
|
||||
<HBox>
|
||||
<Button onAction="#handleAddItem">Add</Button>
|
||||
<Button onAction="#handleRemoveItem">Delete</Button>
|
||||
</HBox>
|
||||
</VBox>
|
||||
</TitledPane>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import java.util.*?>
|
||||
<?import javafx.scene.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
|
||||
<AnchorPane xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="client.scenes.shopping.ShoppingListNewItemPromptCtrl"
|
||||
prefHeight="400.0" prefWidth="600.0">
|
||||
<VBox>
|
||||
<HBox>
|
||||
<Spinner fx:id="amountSelect" />
|
||||
<MenuButton fx:id="unitSelect">Unit...</MenuButton>
|
||||
<MenuButton fx:id="ingredientSelection">Your ingredient...</MenuButton>
|
||||
</HBox>
|
||||
<HBox>
|
||||
<Button onAction="#confirmAdd">Confirm</Button>
|
||||
<Button onAction="#cancelAdd">Cancel</Button>
|
||||
</HBox>
|
||||
</VBox>
|
||||
</AnchorPane>
|
||||
Loading…
Add table
Add a link
Reference in a new issue