diff --git a/src/main/java/ch/zhaw/gartenverwaltung/CropDetailController.java b/src/main/java/ch/zhaw/gartenverwaltung/CropDetailController.java index 622992c..bf5a7bf 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/CropDetailController.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/CropDetailController.java @@ -1,14 +1,15 @@ package ch.zhaw.gartenverwaltung; +import ch.zhaw.gartenverwaltung.bootstrap.Inject; +import ch.zhaw.gartenverwaltung.io.PlantList; import ch.zhaw.gartenverwaltung.models.Garden; import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException; -import ch.zhaw.gartenverwaltung.models.PlantListModel; import ch.zhaw.gartenverwaltung.models.GardenSchedule; +import ch.zhaw.gartenverwaltung.models.PlantNotFoundException; import ch.zhaw.gartenverwaltung.types.Crop; import ch.zhaw.gartenverwaltung.types.Pest; import ch.zhaw.gartenverwaltung.types.Plant; import ch.zhaw.gartenverwaltung.types.Task; -import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.geometry.Pos; import javafx.scene.control.Button; @@ -20,12 +21,20 @@ import javafx.stage.Stage; import java.io.IOException; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; public class CropDetailController { - private Crop crop = null; - private final PlantListModel plantListModel = new PlantListModel(); - private final GardenSchedule gardenSchedule = new GardenSchedule(); - private final Garden garden = new Garden(gardenSchedule); + private Crop crop; + + @Inject + private PlantList plantList; + @Inject + private GardenSchedule gardenSchedule; + @Inject + private Garden garden; + + private static final Logger LOG = Logger.getLogger(CropDetailController.class.getName()); @FXML private ImageView imageView; @@ -63,33 +72,32 @@ public class CropDetailController { @FXML private Label spacing_label; - public CropDetailController() throws IOException { - } - @FXML - void editTaskList(ActionEvent event) { + void editTaskList() { } @FXML - void goBack(ActionEvent event) { + void goBack() { Stage stage = (Stage) imageView.getScene().getWindow(); stage.close(); } @FXML - void setArea(ActionEvent event) { + void setArea() { } @FXML - void setLocation(ActionEvent event) { + void setLocation() { } - public void setPlantFromCrop(Crop crop) throws HardinessZoneNotSetException, IOException { + public void setPlantFromCrop(Crop crop) throws HardinessZoneNotSetException, IOException, PlantNotFoundException { this.crop = crop; - Plant plant = plantListModel.getFilteredPlantListById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()).get(0); + Plant plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()) + .orElseThrow(PlantNotFoundException::new); + cropName_label.setText(plant.name()); description_label.setText(plant.description()); light_label.setText(String.valueOf(plant.light())); @@ -104,12 +112,20 @@ public class CropDetailController { createPestList(plant); } - private void createTaskLists(Crop crop) throws IOException { - List taskList = gardenSchedule.getTaskListForCrop(crop.getCropId().get()); - for (Task task : taskList) { - Label label = new Label(task.getDescription()); - growthPhases_vbox.getChildren().add(label); - } + private void createTaskLists(Crop crop) { + crop.getCropId().ifPresent(id -> { + List taskList; + try { + taskList = gardenSchedule.getTaskListForCrop(id); + for (Task task : taskList) { + Label label = new Label(task.getDescription()); + growthPhases_vbox.getChildren().add(label); + } + } catch (IOException e) { + // TODO: Alert + LOG.log(Level.SEVERE, "Could not get task list for crop", e.getCause()); + } + }); } private void createPestList(Plant plant) { diff --git a/src/main/java/ch/zhaw/gartenverwaltung/HelloApplication.java b/src/main/java/ch/zhaw/gartenverwaltung/HelloApplication.java index fd31017..9018a31 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/HelloApplication.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/HelloApplication.java @@ -1,8 +1,7 @@ package ch.zhaw.gartenverwaltung; +import ch.zhaw.gartenverwaltung.bootstrap.AppLoader; import javafx.application.Application; -import javafx.fxml.FXMLLoader; -import javafx.scene.Scene; import javafx.stage.Stage; import java.io.IOException; @@ -10,10 +9,11 @@ import java.io.IOException; public class HelloApplication extends Application { @Override public void start(Stage stage) throws IOException { - FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("MainFXML.fxml")); - Scene scene = new Scene(fxmlLoader.load()); + AppLoader appLoader = new AppLoader(); + + appLoader.loadSceneToStage("MainFXML.fxml", stage); + stage.setTitle("Gartenverwaltung"); - stage.setScene(scene); stage.show(); } diff --git a/src/main/java/ch/zhaw/gartenverwaltung/MainFXMLController.java b/src/main/java/ch/zhaw/gartenverwaltung/MainFXMLController.java index 032bdb8..fca8b69 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/MainFXMLController.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/MainFXMLController.java @@ -1,28 +1,25 @@ package ch.zhaw.gartenverwaltung; -import javafx.event.ActionEvent; +import ch.zhaw.gartenverwaltung.bootstrap.AfterInject; +import ch.zhaw.gartenverwaltung.bootstrap.AppLoader; +import ch.zhaw.gartenverwaltung.bootstrap.ChangeViewEvent; +import ch.zhaw.gartenverwaltung.bootstrap.Inject; +import javafx.event.EventHandler; import javafx.fxml.FXML; -import javafx.fxml.FXMLLoader; -import javafx.fxml.Initializable; import javafx.scene.control.Button; import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.Pane; import java.io.IOException; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.ResourceBundle; import java.util.logging.Level; import java.util.logging.Logger; -public class MainFXMLController implements Initializable { - /** - * Caching the panes - */ - private final Map panes = new HashMap<>(); +public class MainFXMLController { private static final Logger LOG = Logger.getLogger(MainFXMLController.class.getName()); + @Inject + AppLoader appLoader; + @FXML private Button home_button; @@ -30,7 +27,7 @@ public class MainFXMLController implements Initializable { private AnchorPane mainPane; @FXML - private Button myPlants_button; + private Button myGarden_button; @FXML private Button mySchedule_button; @@ -39,26 +36,26 @@ public class MainFXMLController implements Initializable { private Button plants_button; @FXML - void goToHome(ActionEvent event) throws IOException { - loadPane("Home.fxml"); + void goToHome() { + showPaneAsMainView("Home.fxml"); styleChangeButton(home_button); } @FXML - void goToMyPlants(ActionEvent event) throws IOException { - loadPane("MyPlants.fxml"); - styleChangeButton(myPlants_button); + void goToMyPlants() { + showPaneAsMainView("MyGarden.fxml"); + styleChangeButton(myGarden_button); } @FXML - void goToMySchedule(ActionEvent event) throws IOException { - loadPane("MySchedule.fxml"); + void goToMySchedule() { + showPaneAsMainView("MySchedule.fxml"); styleChangeButton(mySchedule_button); } @FXML - void goToPlants(ActionEvent event) throws IOException { - loadPane("Plants.fxml"); + void goToPlants() { + showPaneAsMainView("Plants.fxml"); styleChangeButton(plants_button); } @@ -67,25 +64,27 @@ public class MainFXMLController implements Initializable { * set HGrow and VGrow to parent AnchorPane. * Sends MainController to other Controllers. * @param fxmlFile string of fxml file - * @throws IOException exception when file does not exist */ - public void loadPane(String fxmlFile) throws IOException { + public void showPaneAsMainView(String fxmlFile) { + try { + Pane anchorPane = appLoader.loadPane(fxmlFile); + mainPane.getChildren().setAll(anchorPane); + anchorPane.prefWidthProperty().bind(mainPane.widthProperty()); + anchorPane.prefHeightProperty().bind(mainPane.heightProperty()); - AnchorPane anchorPane = panes.get(fxmlFile); - if (anchorPane == null) { - FXMLLoader loader = new FXMLLoader(Objects.requireNonNull(HelloApplication.class.getResource(fxmlFile))); - anchorPane = loader.load(); - panes.put(fxmlFile, anchorPane); - - if(fxmlFile.equals("MyPlants.fxml")) { - MyPlantsController myPlantsController = loader.getController(); - myPlantsController.getMainController(this); - } + anchorPane.removeEventHandler(ChangeViewEvent.CHANGE_MAIN_VIEW, changeMainViewHandler); + anchorPane.addEventHandler(ChangeViewEvent.CHANGE_MAIN_VIEW, changeMainViewHandler); + } catch (IOException e) { + LOG.log(Level.SEVERE, "Could not load pane.", e); } - mainPane.getChildren().setAll(anchorPane); - anchorPane.prefWidthProperty().bind(mainPane.widthProperty()); - anchorPane.prefHeightProperty().bind(mainPane.heightProperty()); + } + private final EventHandler changeMainViewHandler = (ChangeViewEvent event) -> showPaneAsMainView(event.view()); + + private void preloadPanes() throws IOException { + appLoader.loadAndCacheFxml("MyGarden.fxml"); + appLoader.loadAndCacheFxml("MySchedule.fxml"); + appLoader.loadAndCacheFxml("Plants.fxml"); } private void styleChangeButton(Button button) { @@ -96,10 +95,12 @@ public class MainFXMLController implements Initializable { * loads the default FXML File * {@inheritDoc} */ - @Override - public void initialize(URL url, ResourceBundle resourceBundle) { + @AfterInject + @SuppressWarnings("unused") + public void init() { try { - loadPane("Home.fxml"); + preloadPanes(); + showPaneAsMainView("Home.fxml"); styleChangeButton(home_button); } catch (IOException e) { LOG.log(Level.SEVERE, "Failed to load FXML-Pane!", e); diff --git a/src/main/java/ch/zhaw/gartenverwaltung/MyGardenController.java b/src/main/java/ch/zhaw/gartenverwaltung/MyGardenController.java new file mode 100644 index 0000000..3568b50 --- /dev/null +++ b/src/main/java/ch/zhaw/gartenverwaltung/MyGardenController.java @@ -0,0 +1,146 @@ +package ch.zhaw.gartenverwaltung; + +import ch.zhaw.gartenverwaltung.bootstrap.AfterInject; +import ch.zhaw.gartenverwaltung.bootstrap.AppLoader; +import ch.zhaw.gartenverwaltung.bootstrap.ChangeViewEvent; +import ch.zhaw.gartenverwaltung.bootstrap.Inject; +import ch.zhaw.gartenverwaltung.io.PlantList; +import ch.zhaw.gartenverwaltung.models.Garden; +import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException; +import ch.zhaw.gartenverwaltung.models.PlantNotFoundException; +import ch.zhaw.gartenverwaltung.types.Crop; +import ch.zhaw.gartenverwaltung.types.Plant; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Label; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.stage.Modality; +import javafx.stage.Stage; + +import java.io.IOException; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class MyGardenController { + private static final Logger LOG = Logger.getLogger(MyGardenController.class.getName()); + @Inject + AppLoader appLoader; + @Inject + private Garden garden; + @Inject + private PlantList plantList; + + @FXML + public AnchorPane myGardenRoot; + @FXML + private VBox myPlants_vbox; + + @AfterInject + @SuppressWarnings("unused") + public void init() { + garden.getPlantedCrops().addListener((observable, oldValue, newValue) -> { + try { + createPlantView(newValue); + } catch (HardinessZoneNotSetException | IOException e) { + LOG.log(Level.SEVERE, "Could not update view of croplist!", e); + } + }); + try { + createPlantView(garden.getPlantedCrops()); + } catch (HardinessZoneNotSetException | IOException e) { + LOG.log(Level.SEVERE, "Could not update view of croplist!", e); + } + } + + @FXML + void addPlant() { + myGardenRoot.fireEvent(new ChangeViewEvent(ChangeViewEvent.CHANGE_MAIN_VIEW, "Plants.fxml")); + } + + private void createPlantView(List crops) throws HardinessZoneNotSetException, IOException { + myPlants_vbox.getChildren().clear(); + for (Crop crop : crops) { + HBox hBox = createPlantView(crop); + myPlants_vbox.getChildren().add(hBox); + } + } + + private HBox createPlantView(Crop crop) throws HardinessZoneNotSetException, IOException { + //ToDo add better design + Plant plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()).get(); + HBox hBox = new HBox(10); + ImageView imageView = new ImageView(); + imageView.setPreserveRatio(false); + imageView.setFitHeight(100); + imageView.setFitWidth(100); + imageView.maxHeight(100); + if (plant.image() != null) { + imageView.setImage(plant.image()); + } + hBox.setMinHeight(100); + Label label = new Label(plant.name()); + label.setMaxWidth(2000); + HBox.setHgrow(label, Priority.ALWAYS); + Button details = new Button("Details"); + Button delete = new Button("delete"); + details.setOnAction(getGoToCropDetailEvent(crop)); + delete.setOnAction(getDeleteCropEvent(crop)); + hBox.getChildren().addAll(imageView, label, details, delete); + return hBox; + } + + private EventHandler getGoToCropDetailEvent(Crop crop) { + return (event) -> { + try { + Stage stage = new Stage(); + if (appLoader.loadSceneToStage("CropDetail.fxml", stage) instanceof CropDetailController controller) { + controller.setPlantFromCrop(crop); + } + stage.initModality(Modality.APPLICATION_MODAL); + stage.setResizable(true); + stage.showAndWait(); + } catch (IOException | HardinessZoneNotSetException | PlantNotFoundException e) { + // TODO: show error alert + LOG.log(Level.SEVERE, "Could not load plant details.", e); + } + }; + } + + private EventHandler getDeleteCropEvent(Crop crop) { + return (event) -> { + try { + showConfirmation(crop); + } catch (IOException | HardinessZoneNotSetException e) { + e.printStackTrace(); + } + }; + } + + private void showConfirmation(Crop crop) throws IOException, HardinessZoneNotSetException { + Alert alert = new Alert(Alert.AlertType.CONFIRMATION); + alert.setTitle("Delete Crop"); + alert.setHeaderText("Are you sure want to delete this Crop?"); + alert.setContentText("Deleting this crop will remove all associated tasks from your schedule."); + + alert.showAndWait() + .ifPresent(buttonType -> { + if (buttonType == ButtonType.OK) { + try { + garden.removeCrop(crop); + } catch (IOException e) { + // TODO: Show error alert + LOG.log(Level.SEVERE, "Could not remove crop.", e); + } + } + }); + } +} diff --git a/src/main/java/ch/zhaw/gartenverwaltung/MyPlantsController.java b/src/main/java/ch/zhaw/gartenverwaltung/MyPlantsController.java deleted file mode 100644 index 1639134..0000000 --- a/src/main/java/ch/zhaw/gartenverwaltung/MyPlantsController.java +++ /dev/null @@ -1,160 +0,0 @@ -package ch.zhaw.gartenverwaltung; - -import ch.zhaw.gartenverwaltung.models.Garden; -import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException; -import ch.zhaw.gartenverwaltung.models.PlantListModel; -import ch.zhaw.gartenverwaltung.models.GardenSchedule; -import ch.zhaw.gartenverwaltung.types.Crop; -import ch.zhaw.gartenverwaltung.types.Plant; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.fxml.FXML; -import javafx.fxml.FXMLLoader; -import javafx.fxml.Initializable; -import javafx.scene.Parent; -import javafx.scene.Scene; -import javafx.scene.control.Alert; -import javafx.scene.control.Button; -import javafx.scene.control.ButtonType; -import javafx.scene.control.Label; -import javafx.scene.image.ImageView; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; -import javafx.stage.Modality; -import javafx.stage.Stage; - -import java.io.IOException; -import java.net.URL; -import java.util.*; - -public class MyPlantsController implements Initializable { - MainFXMLController mainController; - private final GardenSchedule gardenSchedule = new GardenSchedule(); - private final Garden garden = new Garden(gardenSchedule); - private final PlantListModel plantListModel = new PlantListModel(); - - @FXML - private VBox myPlants_vbox; - - public MyPlantsController() throws IOException { - } - - @FXML - void addPlant(ActionEvent event) throws IOException { - mainController.loadPane("Plants.fxml"); - } - - @Override - public void initialize(URL url, ResourceBundle resourceBundle) { - //ToDo update, when new crops are added - try { - loadCropList(); - } catch (HardinessZoneNotSetException | IOException e) { - e.printStackTrace(); - } - } - - private void loadCropList() throws HardinessZoneNotSetException, IOException { - List cropList = new LinkedList<>(); - try { - cropList = getCropList(); - } catch (IOException e) { - e.printStackTrace(); - } - createPlantView(cropList); - } - - private void createPlantView(List crops) throws HardinessZoneNotSetException, IOException { - myPlants_vbox.getChildren().clear(); - for(Crop crop : crops) { - HBox hBox = createPlantView(crop); - myPlants_vbox.getChildren().add(hBox); - } - } - - public void getMainController(MainFXMLController controller) { - mainController = controller; - } - - private List getCropList() throws IOException { - List cropList; - cropList = garden.getCrops(); - return cropList; - } - - private HBox createPlantView(Crop crop) throws HardinessZoneNotSetException, IOException { - //ToDo add better design - Plant plant = plantListModel.getFilteredPlantListById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()).get(0); - HBox hBox = new HBox(10); - ImageView imageView = new ImageView(); - imageView.setPreserveRatio(false); - imageView.setFitHeight(100); - imageView.setFitWidth(100); - imageView.maxHeight(100); - if (plant.image() != null) { - imageView.setImage(plant.image()); - } - hBox.setMinHeight(100); - Label label = new Label(plant.name()); - label.setMaxWidth(2000); - HBox.setHgrow(label, Priority.ALWAYS); - Button details = new Button("Details"); - Button delete = new Button("delete"); - details.setOnAction(getGoToCropDetailEvent(crop)); - delete.setOnAction(getDeleteCropEvent(crop)); - hBox.getChildren().addAll(imageView, label, details, delete); - return hBox; - } - - private EventHandler getGoToCropDetailEvent(Crop crop) { - EventHandler event = new EventHandler() { - @Override - public void handle(ActionEvent event) { - Parent root; - FXMLLoader fxmlLoader = new FXMLLoader(Objects.requireNonNull(getClass().getResource("CropDetail.fxml"))); - try { - root = fxmlLoader.load(); - CropDetailController controller = fxmlLoader.getController(); - controller.setPlantFromCrop(crop); - Stage stage = new Stage(); - stage.setScene(new Scene(root)); - stage.initModality(Modality.APPLICATION_MODAL); - stage.setResizable(true); - stage.showAndWait(); - } catch (IOException | HardinessZoneNotSetException e) { - e.printStackTrace(); - } - } - }; - return event; - } - - private EventHandler getDeleteCropEvent(Crop crop) { - EventHandler event = new EventHandler() { - @Override - public void handle(ActionEvent event) { - try { - showConfirmation(crop); - } catch (IOException | HardinessZoneNotSetException e) { - e.printStackTrace(); - } - } - }; - return event; - } - - private void showConfirmation(Crop crop) throws IOException, HardinessZoneNotSetException { - Alert alert = new Alert(Alert.AlertType.CONFIRMATION); - alert.setTitle("Delete Crop"); - alert.setHeaderText("Are you sure want to delete this Crop?"); - alert.setContentText("placeholder"); - - Optional option = alert.showAndWait(); - - if (option.get() == ButtonType.OK) { - garden.removeCrop(crop); - loadCropList(); - } - } -} diff --git a/src/main/java/ch/zhaw/gartenverwaltung/MyScheduleController.java b/src/main/java/ch/zhaw/gartenverwaltung/MyScheduleController.java index a763754..417722a 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/MyScheduleController.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/MyScheduleController.java @@ -1,18 +1,18 @@ package ch.zhaw.gartenverwaltung; +import ch.zhaw.gartenverwaltung.bootstrap.AfterInject; +import ch.zhaw.gartenverwaltung.bootstrap.Inject; +import ch.zhaw.gartenverwaltung.io.PlantList; import ch.zhaw.gartenverwaltung.models.Garden; import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException; -import ch.zhaw.gartenverwaltung.models.PlantListModel; import ch.zhaw.gartenverwaltung.models.GardenSchedule; import ch.zhaw.gartenverwaltung.types.Crop; +import ch.zhaw.gartenverwaltung.types.Plant; import ch.zhaw.gartenverwaltung.types.Task; import javafx.beans.property.ListProperty; import javafx.beans.property.SimpleListProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.fxml.FXML; -import javafx.fxml.Initializable; import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; @@ -20,17 +20,22 @@ import javafx.scene.layout.Pane; import javafx.scene.layout.VBox; import java.io.IOException; -import java.net.URL; import java.time.LocalDate; -import java.util.LinkedList; import java.util.List; -import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class MyScheduleController { + private static final Logger LOG = Logger.getLogger(MyScheduleController.class.getName()); -public class MyScheduleController implements Initializable { private Crop selectedCrop = null; - private final GardenSchedule gardenSchedule = new GardenSchedule(); - private final Garden garden = new Garden(gardenSchedule); - private final PlantListModel plantListModel = new PlantListModel(); + + @Inject + private GardenSchedule gardenSchedule; + @Inject + private Garden garden; + @Inject + private PlantList plantList; private final ListProperty cropListProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); @@ -82,11 +87,9 @@ public class MyScheduleController implements Initializable { @FXML private ListView scheduledPlants_listview; - public MyScheduleController() throws IOException { - } - - @Override - public void initialize(URL location, ResourceBundle resources) { + @AfterInject + @SuppressWarnings("unused") + public void init() { List cropList; try { cropList = garden.getCrops(); @@ -107,15 +110,12 @@ public class MyScheduleController implements Initializable { } private void lookForSelectedListEntries() { - scheduledPlants_listview.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue observable, Crop oldValue, Crop newValue) { - selectedCrop = newValue; - try { - loadTaskList(); - } catch (IOException e) { - e.printStackTrace(); - } + scheduledPlants_listview.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + selectedCrop = newValue; + try { + loadTaskList(); + } catch (IOException e) { + e.printStackTrace(); } }); } @@ -132,7 +132,7 @@ public class MyScheduleController implements Initializable { } private void setCellFactoryListView() { - scheduledPlants_listview.setCellFactory(param -> new ListCell() { + scheduledPlants_listview.setCellFactory(param -> new ListCell<>() { @Override protected void updateItem(Crop crop, boolean empty) { super.updateItem(crop, empty); @@ -141,9 +141,12 @@ public class MyScheduleController implements Initializable { setText(null); } else { try { - setText(plantListModel.getFilteredPlantListById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()).get(0).name()); + String text = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()) + .map(Plant::name) + .orElse(""); + setText(text); } catch (HardinessZoneNotSetException | IOException e) { - e.printStackTrace(); + LOG.log(Level.WARNING, "Could not get plant for Cell", e); } } } @@ -151,7 +154,7 @@ public class MyScheduleController implements Initializable { } private void loadTaskList() throws IOException { - List> taskLists = new LinkedList<>(); + List> taskLists; if (selectedCrop != null) { taskLists = gardenSchedule.getTasksUpcomingWeekForCrop(selectedCrop.getCropId().get()); } else { diff --git a/src/main/java/ch/zhaw/gartenverwaltung/PlantsController.java b/src/main/java/ch/zhaw/gartenverwaltung/PlantsController.java index 1d832ef..200ccf9 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/PlantsController.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/PlantsController.java @@ -1,44 +1,53 @@ package ch.zhaw.gartenverwaltung; +import ch.zhaw.gartenverwaltung.bootstrap.AfterInject; +import ch.zhaw.gartenverwaltung.bootstrap.AppLoader; +import ch.zhaw.gartenverwaltung.bootstrap.ChangeViewEvent; +import ch.zhaw.gartenverwaltung.bootstrap.Inject; import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException; +import ch.zhaw.gartenverwaltung.models.Garden; import ch.zhaw.gartenverwaltung.models.PlantListModel; +import ch.zhaw.gartenverwaltung.models.PlantNotFoundException; import ch.zhaw.gartenverwaltung.types.HardinessZone; import ch.zhaw.gartenverwaltung.types.Plant; import ch.zhaw.gartenverwaltung.types.Seasons; import javafx.beans.property.ListProperty; import javafx.beans.property.SimpleListProperty; import javafx.collections.FXCollections; -import javafx.event.ActionEvent; import javafx.fxml.FXML; -import javafx.fxml.FXMLLoader; -import javafx.fxml.Initializable; import javafx.geometry.Insets; -import javafx.scene.Parent; -import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.image.Image; import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; import javafx.scene.layout.VBox; -import javafx.stage.Modality; import javafx.stage.Stage; import java.io.IOException; -import java.net.URL; +import java.time.LocalDate; import java.util.List; -import java.util.Objects; -import java.util.ResourceBundle; import java.util.logging.Level; import java.util.logging.Logger; -public class PlantsController implements Initializable { +public class PlantsController { private static final Logger LOG = Logger.getLogger(PlantsController.class.getName()); - private final PlantListModel plantListModel = new PlantListModel(); + + @Inject + private PlantListModel plantListModel; + @Inject + private AppLoader appLoader; + @Inject + private Garden garden; + private Plant selectedPlant = null; private final HardinessZone DEFAULT_HARDINESS_ZONE = HardinessZone.ZONE_8A; // TODO: move to model private final ListProperty plantListProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); + @FXML + public AnchorPane plantsRoot; + @FXML private VBox seasons; @@ -62,20 +71,36 @@ public class PlantsController implements Initializable { /** * open new window to select sow or harvest day to save the crop - * @param event event */ @FXML - void selectSowDate(ActionEvent event) throws IOException { - Parent root; - FXMLLoader fxmlLoader = new FXMLLoader(Objects.requireNonNull(getClass().getResource("SelectSowDay.fxml"))); - root = fxmlLoader.load(); - SelectSowDayController controller = fxmlLoader.getController(); - controller.getSelectedPlant(selectedPlant); + void selectSowDate() throws IOException { Stage stage = new Stage(); - stage.setScene(new Scene(root)); - stage.initModality(Modality.APPLICATION_MODAL); - stage.setResizable(false); - stage.showAndWait(); + Dialog dateSelection = new Dialog<>(); + dateSelection.setTitle("Select Date"); + dateSelection.setHeaderText(String.format("Select Harvest/Sow Date for %s:", selectedPlant.name())); + dateSelection.setResizable(false); + + DialogPane dialogPane = dateSelection.getDialogPane(); + + ButtonType sowButton = new ButtonType("Save", ButtonBar.ButtonData.OK_DONE); + dialogPane.getButtonTypes().addAll(sowButton, ButtonType.CANCEL); + + if (appLoader.loadSceneToStage("SelectSowDay.fxml", stage) instanceof SelectSowDayController controller) { + controller.initSaveButton((Button) dialogPane.lookupButton(sowButton)); + controller.setSelectedPlant(selectedPlant); + dateSelection.setResultConverter(button -> button.equals(sowButton) ? controller.retrieveResult() : null); + } + dialogPane.setContent(stage.getScene().getRoot()); + + dateSelection.showAndWait() + .ifPresent(date -> { + try { + garden.plantAsCrop(selectedPlant, date); + } catch (IOException | HardinessZoneNotSetException | PlantNotFoundException e) { + LOG.log(Level.SEVERE, "Couldn't save Crop", e); + } + plantsRoot.fireEvent(new ChangeViewEvent(ChangeViewEvent.CHANGE_MAIN_VIEW, "MyGarden.fxml")); + }); } /** @@ -85,8 +110,9 @@ public class PlantsController implements Initializable { * create event listener for selected list entry and search by query * {@inheritDoc} */ - @Override - public void initialize(URL url, ResourceBundle resourceBundle) { + @AfterInject + @SuppressWarnings("unused") + public void init() { setListCellFactory(); fillPlantListWithHardinessZone(); list_plants.itemsProperty().bind(plantListProperty); @@ -97,6 +123,7 @@ public class PlantsController implements Initializable { createFilterSeasons(); createFilterHardinessZone(); lookForSelectedListEntry(); + try { viewFilteredListBySearch(); } catch (HardinessZoneNotSetException e) { @@ -107,7 +134,7 @@ public class PlantsController implements Initializable { } /** - * set text of list view to plant name + * set text of list view to plant name */ private void setListCellFactory() { list_plants.setCellFactory(param -> new ListCell<>() { @@ -127,9 +154,10 @@ public class PlantsController implements Initializable { /** * get plant list according to param season and hardiness zone * fill list view with plant list + * * @param season enum of seasons * @throws HardinessZoneNotSetException throws exception - * @throws IOException throws exception + * @throws IOException throws exception */ private void viewFilteredListBySeason(Seasons season) throws HardinessZoneNotSetException, IOException { clearListView(); @@ -139,8 +167,9 @@ public class PlantsController implements Initializable { /** * get plant list filtered by search plant entry and hardiness zone * fill list view with plant list + * * @throws HardinessZoneNotSetException throws exception when no hardiness zone is defined - * @throws IOException throws exception + * @throws IOException throws exception */ private void viewFilteredListBySearch() throws HardinessZoneNotSetException, IOException { search_plants.textProperty().addListener((observable, oldValue, newValue) -> { @@ -185,7 +214,7 @@ public class PlantsController implements Initializable { for (HardinessZone zone : HardinessZone.values()) { RadioButton radioButton = new RadioButton(zone.name()); radioButton.setToggleGroup(hardinessGroup); - radioButton.setPadding(new Insets(0,0,10,0)); + radioButton.setPadding(new Insets(0, 0, 10, 0)); if (zone.equals(DEFAULT_HARDINESS_ZONE)) { radioButton.setSelected(true); } @@ -207,7 +236,7 @@ public class PlantsController implements Initializable { for (Seasons season : Seasons.values()) { RadioButton radioButton = new RadioButton(season.getName()); radioButton.setToggleGroup(seasonGroup); - radioButton.setPadding(new Insets(0,0,10,0)); + radioButton.setPadding(new Insets(0, 0, 10, 0)); if (season.equals(Seasons.AllSEASONS)) { radioButton.setSelected(true); } @@ -241,12 +270,12 @@ public class PlantsController implements Initializable { Image img = new Image(String.valueOf(PlantsController.class.getResource("placeholder.png"))); img_plant.setImage(img); list_plants.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { - if(newValue != null) { + if (newValue != null) { selectedPlant = newValue; description_plant.setText(selectedPlant.description()); selectSowDay_button.setDisable(false); Image img1; - if(selectedPlant.image() != null) { + if (selectedPlant.image() != null) { img1 = selectedPlant.image(); } else { img1 = new Image(String.valueOf(PlantsController.class.getResource("placeholder.png"))); diff --git a/src/main/java/ch/zhaw/gartenverwaltung/SelectSowDayController.java b/src/main/java/ch/zhaw/gartenverwaltung/SelectSowDayController.java index f00ba59..67338be 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/SelectSowDayController.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/SelectSowDayController.java @@ -1,101 +1,62 @@ package ch.zhaw.gartenverwaltung; -import ch.zhaw.gartenverwaltung.models.Garden; -import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException; -import ch.zhaw.gartenverwaltung.models.PlantNotFoundException; -import ch.zhaw.gartenverwaltung.models.GardenSchedule; import ch.zhaw.gartenverwaltung.types.GrowthPhaseType; import ch.zhaw.gartenverwaltung.types.Plant; -import javafx.event.ActionEvent; import javafx.fxml.FXML; -import javafx.fxml.Initializable; import javafx.scene.control.*; -import javafx.stage.Stage; import javafx.util.Callback; -import java.io.IOException; -import java.net.URL; import java.time.LocalDate; import java.util.List; -import java.util.ResourceBundle; -public class SelectSowDayController implements Initializable { - private Plant selectedPlant = null; - private final GardenSchedule gardenSchedule = new GardenSchedule(); - private final Garden garden = new Garden(gardenSchedule); +public class SelectSowDayController { + private Plant selectedPlant; @FXML private DatePicker datepicker; @FXML - private Label popup_label; + private RadioButton harvest_radio; - @FXML - private Button save_button; - - @FXML - private RadioButton sow_radio; - - public SelectSowDayController() throws IOException {} - - /** - * close the date selector window - * @param event event - */ - @FXML - void cancel(ActionEvent event) { - closeWindow(); - } - - /** - * get sow date from datePicker or calculate sow date from harvest date - * save selected plant and sow date - * @param event event - */ - @FXML - void save(ActionEvent event) throws HardinessZoneNotSetException, IOException, PlantNotFoundException { - LocalDate sowDate; - if (sow_radio.isSelected()) { - sowDate = datepicker.getValue(); - } else { + public LocalDate retrieveResult() { + LocalDate sowDate = datepicker.getValue(); + if (harvest_radio.isSelected()) { //ToDo method to get current lifecycle group in plant sowDate = selectedPlant.sowDateFromHarvestDate(datepicker.getValue(), 0); } - garden.plantAsCrop(selectedPlant, sowDate); - closeWindow(); + return sowDate; } /** - * save the plant which will be planted and update label + * Set the {@link Plant} for which a date should be selected. + * * @param plant Plant */ - public void getSelectedPlant(Plant plant) { + public void setSelectedPlant(Plant plant) { selectedPlant = plant; - popup_label.setText("Select Harvest/Sow Date for" + selectedPlant.name()); } /** * add listener and set default values - * {@inheritDoc} - * @param location location - * @param resources resources */ - @Override - public void initialize(URL location, ResourceBundle resources) { + @FXML + public void initialize() { clearDatePickerEntries(); - Callback dayCellFactory= getDayCellFactory(); + Callback dayCellFactory = getDayCellFactory(); datepicker.setDayCellFactory(dayCellFactory); - datepicker.getEditor().setEditable(false); + datepicker.setEditable(false); + } - enableDisableSaveButton(); + public void initSaveButton(Button saveButton) { + saveButton.disableProperty().bind(datepicker.valueProperty().isNull()); } /** * clear date picker editor when radio button is changed */ private void clearDatePickerEntries() { - sow_radio.selectedProperty().addListener((observable, oldValue, isNowSelected) -> datepicker.getEditor().clear()); + harvest_radio.selectedProperty().addListener((observable, oldValue, isNowSelected) -> datepicker.setValue(null)); } /** @@ -104,61 +65,32 @@ public class SelectSowDayController implements Initializable { */ private Callback getDayCellFactory() { - final Callback dayCellFactory = new Callback() { - + return (datePicker) -> new DateCell() { @Override - public DateCell call(final DatePicker datePicker) { - return new DateCell() { - @Override - public void updateItem(LocalDate item, boolean empty) { - super.updateItem(item, empty); - setDisable(true); - setStyle("-fx-background-color: #ffc0cb;"); - List dates; - LocalDate today = LocalDate.now(); - if (sow_radio.isSelected()) { - dates = selectedPlant.getDateListOfGrowthPhase(GrowthPhaseType.SOW); - } else { - dates = selectedPlant.getDateListOfGrowthPhase(GrowthPhaseType.HARVEST); - } - for (LocalDate date : dates) { - if (item.getMonth() == date.getMonth() - && item.getDayOfMonth() == date.getDayOfMonth() - && item.compareTo(today) > 0) { - setDisable(false); - setStyle("-fx-background-color: #32CD32;"); - } - } - if ((!sow_radio.isSelected() && selectedPlant.sowDateFromHarvestDate(item, 0).compareTo(today) < 0)) { - setDisable(true); - setStyle("-fx-background-color: #ffc0cb;"); - } + public void updateItem(LocalDate item, boolean empty) { + super.updateItem(item, empty); + setDisable(true); + setStyle("-fx-background-color: #ffc0cb;"); + List dates; + LocalDate today = LocalDate.now(); + if (harvest_radio.isSelected()) { + dates = selectedPlant.getDateListOfGrowthPhase(GrowthPhaseType.HARVEST); + } else { + dates = selectedPlant.getDateListOfGrowthPhase(GrowthPhaseType.SOW); + } + for (LocalDate date : dates) { + if (item.getMonth() == date.getMonth() + && item.getDayOfMonth() == date.getDayOfMonth() + && item.compareTo(today) > 0) { + setDisable(false); + setStyle("-fx-background-color: #32CD32;"); } - }; + } + if ((harvest_radio.isSelected() && selectedPlant.sowDateFromHarvestDate(item, 0).compareTo(today) < 0)) { + setDisable(true); + setStyle("-fx-background-color: #ffc0cb;"); + } } }; - return dayCellFactory; - } - - /** - * close date picker window - */ - private void closeWindow() { - Stage stage = (Stage) save_button.getScene().getWindow(); - stage.close(); - } - - /** - * disable save button, when there is no date selected in date picker - */ - private void enableDisableSaveButton() { - save_button.setDisable(true); - datepicker.getEditor().textProperty().addListener((observable, oldValue, newValue) -> { - if (newValue == null || newValue.equals("")) { - save_button.setDisable(true); - } else { - save_button.setDisable(false); - } - }); } } diff --git a/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/AfterInject.java b/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/AfterInject.java new file mode 100644 index 0000000..72a88fd --- /dev/null +++ b/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/AfterInject.java @@ -0,0 +1,14 @@ +package ch.zhaw.gartenverwaltung.bootstrap; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates a method to be executed after all dependencies annotates with {@link Inject} + * have been injected. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface AfterInject { } diff --git a/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/AppLoader.java b/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/AppLoader.java new file mode 100644 index 0000000..f55f6d5 --- /dev/null +++ b/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/AppLoader.java @@ -0,0 +1,138 @@ +package ch.zhaw.gartenverwaltung.bootstrap; + +import ch.zhaw.gartenverwaltung.HelloApplication; +import ch.zhaw.gartenverwaltung.io.CropList; +import ch.zhaw.gartenverwaltung.io.JsonCropList; +import ch.zhaw.gartenverwaltung.io.JsonPlantList; +import ch.zhaw.gartenverwaltung.io.JsonTaskList; +import ch.zhaw.gartenverwaltung.io.PlantList; +import ch.zhaw.gartenverwaltung.io.TaskList; +import ch.zhaw.gartenverwaltung.models.Garden; +import ch.zhaw.gartenverwaltung.models.GardenSchedule; +import ch.zhaw.gartenverwaltung.models.PlantListModel; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.layout.Pane; +import javafx.stage.Stage; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class AppLoader { + /** + * Caching the panes + */ + private final Map panes = new HashMap<>(); + + /** + * Application-wide dependencies + */ + private final PlantList plantList = new JsonPlantList(); + private final CropList cropList = new JsonCropList(); + private final TaskList taskList = new JsonTaskList(); + + private final GardenSchedule gardenSchedule = new GardenSchedule(taskList, plantList); + private final Garden garden = new Garden(gardenSchedule, cropList); + + + public AppLoader() throws IOException { + } + + + /** + * Loads and returns a {@link Pane} (cached). + * + * @param fxmlFile The file name to be loaded + * @return The loaded Pane + * @throws IOException if the file could not be loaded + */ + public Pane loadPane(String fxmlFile) throws IOException { + Pane pane = panes.get(fxmlFile); + if (pane == null) { + loadAndCacheFxml(fxmlFile); + pane = panes.get(fxmlFile); + } + return pane; + } + + /** + * Loads the given fxml-file from resources (no caching) and creates a new {@link Scene}, + * which is then appended to the given {@link Stage}. + * Performs dependency-injection. + * + * @param fxmlFile The file name to be loaded + * @param appendee The {@link Stage} to which the new {@link Scene} is appended. + * @return The controller of the loaded scene. + * @throws IOException if the file could not be loaded + */ + public Object loadSceneToStage(String fxmlFile, Stage appendee) throws IOException { + FXMLLoader loader = new FXMLLoader(Objects.requireNonNull(HelloApplication.class.getResource(fxmlFile))); + Pane root = loader.load(); + appendee.setScene(new Scene(root)); + Object controller = loader.getController(); + annotationInject(controller); + return controller; + } + + /** + * Loads the given fxml-file from resources and caches the pane. + * Performs dependency-injection. + * + * @param fxmlFile The file name to be loaded + * @throws IOException if the file could not be loaded + */ + public void loadAndCacheFxml(String fxmlFile) throws IOException { + FXMLLoader loader = new FXMLLoader(Objects.requireNonNull(HelloApplication.class.getResource(fxmlFile))); + Pane pane = loader.load(); + panes.put(fxmlFile, pane); + annotationInject(loader.getController()); + } + + /** + * Injects the applications dependencies into the given object's fields annotated with {@link Inject}. + * Afterwards, all methods on the objects annotated with {@link AfterInject} are executed. + * (Success of the injections is not guaranteed!) + * + * @param controller The class containing the injectable fields + */ + public void annotationInject(Object controller) { + Arrays.stream(controller.getClass().getDeclaredFields()) + .filter(field -> field.isAnnotationPresent(Inject.class)) + .forEach(field -> { + field.setAccessible(true); + try { + field.set(controller, getAppDependency(field.getType())); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + field.setAccessible(false); + }); + + Arrays.stream(controller.getClass().getMethods()) + .filter(method -> method.isAnnotationPresent(AfterInject.class)) + .forEach(afterInjectMethod -> { + if (afterInjectMethod.getParameterCount() == 0) { + try { + afterInjectMethod.invoke(controller); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + } + }); + } + + private Object getAppDependency(Class type) { + return switch (type.getSimpleName()) { + case "Garden" -> garden; + case "PlantList" -> plantList; + case "PlantListModel" -> new PlantListModel(plantList); + case "GardenSchedule" -> gardenSchedule; + case "AppLoader" -> this; + default -> null; + }; + } +} diff --git a/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/ChangeViewEvent.java b/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/ChangeViewEvent.java new file mode 100644 index 0000000..4388ebe --- /dev/null +++ b/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/ChangeViewEvent.java @@ -0,0 +1,19 @@ +package ch.zhaw.gartenverwaltung.bootstrap; + +import javafx.event.Event; +import javafx.event.EventType; + +public class ChangeViewEvent extends Event { + private final String view; + + public static final EventType CHANGE_MAIN_VIEW = new EventType<>("CHANGE_MAIN_VIEW"); + + public ChangeViewEvent(EventType eventType, String view) { + super(eventType); + this.view = view; + } + + public String view() { + return view; + } +} diff --git a/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/Inject.java b/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/Inject.java new file mode 100644 index 0000000..02409d5 --- /dev/null +++ b/src/main/java/ch/zhaw/gartenverwaltung/bootstrap/Inject.java @@ -0,0 +1,13 @@ +package ch.zhaw.gartenverwaltung.bootstrap; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates a Field to be injected from the application-dependencies + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Inject { } diff --git a/src/main/java/ch/zhaw/gartenverwaltung/models/Garden.java b/src/main/java/ch/zhaw/gartenverwaltung/models/Garden.java index 3d6032a..fd25b2a 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/models/Garden.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/models/Garden.java @@ -2,12 +2,12 @@ package ch.zhaw.gartenverwaltung.models; import ch.zhaw.gartenverwaltung.io.CropList; import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException; -import ch.zhaw.gartenverwaltung.io.JsonCropList; import ch.zhaw.gartenverwaltung.types.Crop; import ch.zhaw.gartenverwaltung.types.Plant; import ch.zhaw.gartenverwaltung.types.Task; +import javafx.beans.property.ListProperty; +import javafx.beans.property.SimpleListProperty; import javafx.collections.FXCollections; -import javafx.collections.ObservableList; import java.io.IOException; import java.time.LocalDate; @@ -19,21 +19,25 @@ import java.util.Optional; * The Gardenplan model manages the crops in the gardenplan. */ public class Garden { - private CropList cropList; - private final ObservableList plantedCrops = FXCollections.observableArrayList(); - private GardenSchedule gardenSchedule; + private final CropList cropList; + private final ListProperty plantedCrops = new SimpleListProperty<>(FXCollections.observableArrayList()); + private final GardenSchedule gardenSchedule; /** * Constructor of Gardenplan model * * @param gardenSchedule holds a reference to the task list object. */ - public Garden(GardenSchedule gardenSchedule) throws IOException { + public Garden(GardenSchedule gardenSchedule, CropList cropList) throws IOException { this.gardenSchedule = gardenSchedule; - cropList = new JsonCropList(); + this.cropList = cropList; plantedCrops.addAll(cropList.getCrops()); } + public ListProperty getPlantedCrops() { + return plantedCrops; + } + /** * Creates a Crop with a {@link Plant} and the planting date of the plant. Then let the Tasklistmodel create the * gardening {@link Task} for the crop. Store the crop in the gardenplan file and the cache. diff --git a/src/main/java/ch/zhaw/gartenverwaltung/models/GardenSchedule.java b/src/main/java/ch/zhaw/gartenverwaltung/models/GardenSchedule.java index 30a0a50..9195d51 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/models/GardenSchedule.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/models/GardenSchedule.java @@ -12,19 +12,14 @@ import java.util.List; import java.util.stream.Collectors; public class GardenSchedule { - private TaskList taskList; - private PlantList plantList; + private final TaskList taskList; + private final PlantList plantList; /** * Comparators to create sorted Task List */ static final Comparator sortByStartDate = Comparator.comparing(Task::getStartDate); - public GardenSchedule(){ - taskList = new JsonTaskList(); - plantList = new JsonPlantList(); - } - /** * Constructor to create Database Objects. */ diff --git a/src/main/java/ch/zhaw/gartenverwaltung/models/PlantListModel.java b/src/main/java/ch/zhaw/gartenverwaltung/models/PlantListModel.java index 6b96bee..19cce96 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/models/PlantListModel.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/models/PlantListModel.java @@ -1,7 +1,6 @@ package ch.zhaw.gartenverwaltung.models; import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException; -import ch.zhaw.gartenverwaltung.io.JsonPlantList; import ch.zhaw.gartenverwaltung.io.PlantList; import ch.zhaw.gartenverwaltung.types.GrowthPhaseType; import ch.zhaw.gartenverwaltung.types.HardinessZone; @@ -16,7 +15,7 @@ import java.util.function.Predicate; import java.util.stream.Collectors; public class PlantListModel { - private PlantList plantList; + private final PlantList plantList; private HardinessZone currentZone; /** @@ -28,11 +27,6 @@ public class PlantListModel { /** * Constructor to create Database Object. */ - public PlantListModel() { - plantList = new JsonPlantList(); - setDefaultZone(); - } - public PlantListModel(PlantList plantList) { this.plantList = plantList; setDefaultZone(); diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 6900f7f..44103dd 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -9,6 +9,8 @@ module ch.zhaw.gartenverwaltung { opens ch.zhaw.gartenverwaltung to javafx.fxml; opens ch.zhaw.gartenverwaltung.types to com.fasterxml.jackson.databind; exports ch.zhaw.gartenverwaltung; + exports ch.zhaw.gartenverwaltung.io; exports ch.zhaw.gartenverwaltung.types; + exports ch.zhaw.gartenverwaltung.models; exports ch.zhaw.gartenverwaltung.json; } \ No newline at end of file diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/MainFXML.fxml b/src/main/resources/ch/zhaw/gartenverwaltung/MainFXML.fxml index 569a89d..7fa27e1 100644 --- a/src/main/resources/ch/zhaw/gartenverwaltung/MainFXML.fxml +++ b/src/main/resources/ch/zhaw/gartenverwaltung/MainFXML.fxml @@ -11,8 +11,8 @@ -