Newer
Older
package no.ntnu.idatt1002.demo.controller;
HSoreide
committed
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import no.ntnu.idatt1002.demo.data.recipes.FileHandler;
import no.ntnu.idatt1002.demo.data.recipes.FoodItem;
import no.ntnu.idatt1002.demo.data.recipes.IngredientsAtHand;
/**
* The AddIngredientController manages a dialog pane used to display a search-field along with a list of all the
* possible food types in the application according to the FoodItem enum class. The food types in the list may be
* selected and added to an up-to-date IngredientsAtHand object that is then written to file. The user may add
* several food types before pressing 'close' and exit the dialog. The food types that are not already contained
* in the IngredientsAtHand are listed underneath the list so that the user can keep track of the newly added
* food types. Upon opening the dialog, the search field is already selected and the user can start typing a search.
* When pressing 'Enter' on the keyboard, the search is performed and matches are displayed in the list. If the search
* field is left blank upon search, all food types are listed again.
*/
public class AddIngredientController implements Initializable {
private ObservableList<String> ingredients;
private String[] ingredientsList;
@FXML
private Button addBtn;
@FXML
private ListView<String> listView;
@FXML
private TextField searchBar;
@FXML
private Button searchBtn;
@FXML
private Label status;
private String statusText = "Added: ";
/**
* The initialize method of the controller takes in a URL (location) and ResourceBundle(resources) to
* initialize the controller once its root element has been processed.
* The method then sets the list items of the list, sets the focus on the search-field and makes sure that the
* label underneath the list that states the added food types to the user can wrap if it fills the full width
* of the window.
* @param url The location to resolve the relative paths to the root object.
* @param resourceBundle Resources used to localize the root object.
*/
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
listView.setItems(FXCollections.observableArrayList(Arrays.stream(FoodItem.values()).map(value -> value.label).toList()));
Platform.runLater(() -> searchBar.requestFocus());
status.setWrapText(true);
}
/**
* The addToFridge method reads an up-to-date instance of the IngredientsAtHand object from file and
* gets hold of the FoodItem constant that is currently selected in the list. If the selected FoodItem is not
* already at hand, it is added and the IngredientAtHand object is written to file. The label beneath the
* list is also updated with the name of the food type to keep track of what has been added. If the
* selected food type was already at hand, it is not added again and the label is not updated.
*
* @throws IOException If the method fails to write or read the Ingredients at hand object to/from file.
*/
void addToFridge() throws IOException {
IngredientsAtHand ingredientsAtHand = FileHandler.readIngredientsAtHand("Fridge");
FoodItem item = FoodItem.valueOf(listView.getSelectionModel().getSelectedItem().replace(" ", "_").toUpperCase());
if(item != null && ingredientsAtHand!= null ) {
if(!ingredientsAtHand.atHand(item)) {
ingredientsAtHand.addIngredient(item);
FileHandler.writeIngredientsAtHand(ingredientsAtHand, "Fridge");
if(status.isVisible() && status.getText().isBlank()) {
statusText += String.format("%s", item.label);
} else if (status.isVisible()){
statusText += String.format(", %s", item.label);
}
status.setText(statusText);
/**
* The search method is fired whenever the 'Search' button is pressed by the user. It clears the list and then
* refills it by adding all the resulting values from the call to the method 'searchList'.
*/
void search() {
listView.getItems().clear();
listView.getItems().addAll(searchList(searchBar.getText(),
Arrays.stream(FoodItem.values()).toList().stream().map(value -> value.label).toArray(String[]::new)));
* The searchList method takes in a string of what the user wrote in the search field and an array of
* Strings that represents every label of the FoodItem enum class. The search word from the user is
* trimmed and split by space and matched against all the constants of the FoodItem enums. Any matches are then
* to a List of strings and returned.
* @param searchWords A String of what the user wrote in the search field.
* @param listOfStrings A list of strings, in this case, each representing a constant of the FoodItem enum class.
* @return A list of strings food types of FoodItem that match the se search word(s).
*/
HSoreide
committed
private List<String> searchList(String searchWords, String[] listOfStrings) {
String[] searchWordsArray = searchWords.trim().split(" ");
return Arrays.stream(listOfStrings).filter((in) -> Arrays.stream(searchWordsArray).allMatch((word) ->
in.toLowerCase().contains(word.toLowerCase()))).collect(Collectors.toList());
HSoreide
committed
}