diff --git a/src/main/java/ch/zhaw/gartenverwaltung/CropDetailController.java b/src/main/java/ch/zhaw/gartenverwaltung/CropDetailController.java index bbe7cea..c644865 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/CropDetailController.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/CropDetailController.java @@ -22,6 +22,7 @@ import javafx.scene.control.*; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; import javafx.scene.layout.Priority; import javafx.stage.Stage; @@ -87,7 +88,7 @@ public class CropDetailController { private ListView pests_listView; @FXML - void addTask() throws IOException { + void addTask() throws IOException, HardinessZoneNotSetException { createTaskDialog(true, null); } @@ -136,7 +137,7 @@ public class CropDetailController { if (plant.image() != null) { imageView.setImage(plant.image()); } - area_label.setText(""); + area_label.setText(String.valueOf(crop.getArea())); location_label.setText(""); setTaskListProperty(crop); @@ -205,22 +206,28 @@ public class CropDetailController { } private HBox createTaskHBox(Task task) { - HBox hBox = new HBox(); + HBox hBox = new HBox(10); Label taskName = new Label(task.getName()+": "); + taskName.setMinWidth(100); + taskName.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); taskName.setStyle("-fx-font-weight: bold"); Label taskDescription = new Label(task.getDescription()); taskDescription.setWrapText(true); - taskDescription.setMaxWidth(2000); - HBox.setHgrow(taskDescription, Priority.ALWAYS); + taskDescription.setMaxSize(600, Double.MAX_VALUE); + Pane puffer = new Pane(); + HBox.setHgrow(puffer, Priority.ALWAYS); + Button edit = new Button(); Button delete = new Button(); + HBox.setHgrow(edit, Priority.NEVER); + HBox.setHgrow(delete, Priority.NEVER); setIconToButton(edit, "editIcon.png"); setIconToButton(delete, "deleteIcon.png"); edit.setOnAction(getEditTaskEvent(task)); delete.setOnAction(deleteTask(task)); - hBox.getChildren().addAll(taskName, taskDescription, edit, delete); + hBox.getChildren().addAll(taskName, taskDescription, puffer, edit, delete); return hBox; } @@ -229,12 +236,15 @@ public class CropDetailController { label.setStyle("-fx-font-weight: bold"); HBox hBox = new HBox(); hBox.fillHeightProperty(); - Label label1 = new Label(pest.description()); - label1.setAlignment(Pos.TOP_LEFT); - label1.setWrapText(true); - label1.setMaxWidth(600); + Label description = new Label(pest.description()); + description.setAlignment(Pos.TOP_LEFT); + description.setWrapText(true); + description.setMaxWidth(600); + Pane puffer = new Pane(); + HBox.setHgrow(puffer, Priority.ALWAYS); Button button = new Button("Get Counter Measures"); - hBox.getChildren().addAll(label, label1, button); + HBox.setHgrow(button, Priority.NEVER); + hBox.getChildren().addAll(label, description, puffer, button); return hBox; } @@ -255,7 +265,7 @@ public class CropDetailController { return (event) -> { try { createTaskDialog(false, task); - } catch (IOException e) { + } catch (IOException | HardinessZoneNotSetException e) { e.printStackTrace(); } }; @@ -267,7 +277,7 @@ public class CropDetailController { }; } - private void createTaskDialog(boolean newTask, Task givenTask) throws IOException { + private void createTaskDialog(boolean newTask, Task givenTask) throws IOException, HardinessZoneNotSetException { Dialog dialog = new Dialog<>(); dialog.setTitle("Set Task"); dialog.setHeaderText("Add/Edit Task:"); @@ -289,7 +299,7 @@ public class CropDetailController { if (!newTask) { controller.setTaskValue(givenTask); } - dialog.setResultConverter(button -> button.equals(saveTask) ? controller.returnResult() : null); + dialog.setResultConverter(button -> button.equals(saveTask) ? controller.returnResult(this.crop) : null); dialog.showAndWait() .ifPresent(task -> { @@ -334,8 +344,11 @@ public class CropDetailController { //ToDo method to set location location_label.setText(string); } else { - System.out.println(string); - //ToDo method to set area of crop in garden + try { + garden.updateCrop(this.crop.withArea(Double.parseDouble(string))); + } catch (IOException e) { + e.printStackTrace(); + } area_label.setText(string); } }); diff --git a/src/main/java/ch/zhaw/gartenverwaltung/MyGardenController.java b/src/main/java/ch/zhaw/gartenverwaltung/MyGardenController.java index b6270ca..34cf1a7 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/MyGardenController.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/MyGardenController.java @@ -51,7 +51,6 @@ public class MyGardenController { @AfterInject @SuppressWarnings("unused") public void init() { - System.out.println("once"); setIconToButton(addPlant_button, "addIcon.png"); myGarden_listView.itemsProperty().bind(garden.getPlantedCrops()); setCellFactory(); diff --git a/src/main/java/ch/zhaw/gartenverwaltung/MyScheduleController.java b/src/main/java/ch/zhaw/gartenverwaltung/MyScheduleController.java index e895480..f73feb2 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/MyScheduleController.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/MyScheduleController.java @@ -9,11 +9,14 @@ 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.collections.FXCollections; import javafx.fxml.FXML; -import javafx.scene.control.Label; -import javafx.scene.control.ListCell; -import javafx.scene.control.ListView; +import javafx.scene.control.*; +import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import java.io.IOException; @@ -24,6 +27,7 @@ import java.util.logging.Logger; public class MyScheduleController { private static final Logger LOG = Logger.getLogger(MyScheduleController.class.getName()); + private final ListProperty> taskListProperty = new SimpleListProperty<>(FXCollections.observableArrayList()); private Crop selectedCrop = null; @@ -35,46 +39,7 @@ public class MyScheduleController { private PlantList plantList; @FXML - private Label day1_label; - - @FXML - private Pane day1_pane; - - @FXML - private Label day2_label; - - @FXML - private Pane day2_pane; - - @FXML - private Label day3_label; - - @FXML - private Pane day3_pane; - - @FXML - private Label day4_label; - - @FXML - private Pane day4_pane; - - @FXML - private Label day5_label; - - @FXML - private Pane day5_pane; - - @FXML - private Label day6_label; - - @FXML - private Pane day6_pane; - - @FXML - private Label day7_label; - - @FXML - private Pane day7_pane; + private ListView> week_listView; @FXML private Label information_label; @@ -85,10 +50,11 @@ public class MyScheduleController { @AfterInject @SuppressWarnings("unused") public void init() { - setCellFactoryListView(); + setCellFactoryCropListView(); + setCellFactoryTaskListView(); scheduledPlants_listview.itemsProperty().bind(garden.getPlantedCrops()); + week_listView.itemsProperty().bind(taskListProperty); lookForSelectedListEntries(); - setDayLabels(); information_label.setText(""); try { loadTaskList(); @@ -108,18 +74,7 @@ public class MyScheduleController { }); } - private void setDayLabels() { - LocalDate today = LocalDate.now(); - day1_label.setText(today.getDayOfWeek().toString()); - day2_label.setText(today.plusDays(1).getDayOfWeek().toString()); - day3_label.setText(today.plusDays(2).getDayOfWeek().toString()); - day4_label.setText(today.plusDays(3).getDayOfWeek().toString()); - day5_label.setText(today.plusDays(4).getDayOfWeek().toString()); - day6_label.setText(today.plusDays(5).getDayOfWeek().toString()); - day7_label.setText(today.plusDays(6).getDayOfWeek().toString()); - } - - private void setCellFactoryListView() { + private void setCellFactoryCropListView() { scheduledPlants_listview.setCellFactory(param -> new ListCell<>() { @Override protected void updateItem(Crop crop, boolean empty) { @@ -141,6 +96,23 @@ public class MyScheduleController { }); } + private void setCellFactoryTaskListView() { + week_listView.setCellFactory(param -> new ListCell<>() { + @Override + protected void updateItem(List taskList, boolean empty) { + super.updateItem(taskList, empty); + + if (empty || taskList == null) { + setGraphic(null); + setText(null); + } else { + setText(""); + setGraphic(weekTaskVBox(taskList, this.getIndex())); + } + } + }); + } + private void loadTaskList() throws IOException { List> taskLists; if (selectedCrop != null) { @@ -148,25 +120,66 @@ public class MyScheduleController { } else { taskLists = gardenSchedule.getTasksUpcomingWeek(); } - if (!taskLists.isEmpty()) { - viewTaskListOfDay(day1_pane, taskLists.get(0)); - viewTaskListOfDay(day2_pane, taskLists.get(1)); - viewTaskListOfDay(day3_pane, taskLists.get(2)); - viewTaskListOfDay(day4_pane, taskLists.get(3)); - viewTaskListOfDay(day5_pane, taskLists.get(4)); - viewTaskListOfDay(day6_pane, taskLists.get(5)); - viewTaskListOfDay(day7_pane, taskLists.get(6)); - } + taskListProperty.clear(); + taskListProperty.addAll(taskLists); } - private void viewTaskListOfDay(Pane pane, List tasks) { - //ToDo update pane with task list - VBox vBox = new VBox(); + private VBox weekTaskVBox(List tasks, int dayIndex) { + VBox vBox = new VBox(10); + LocalDate today = LocalDate.now(); + Label weekDay = new Label(today.plusDays(dayIndex).getDayOfWeek().toString()); + weekDay.setStyle("-fx-font-weight: bold; -fx-underline: true"); + vBox.getChildren().add(weekDay); for (Task task : tasks) { - Label label = new Label(task.getDescription()); - vBox.getChildren().add(label); + HBox hBox = new HBox(10); + Label taskName = new Label(task.getName() + ":"); + taskName.setStyle("-fx-font-weight: bold"); + taskName.setMinWidth(100); + taskName.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); + hBox.getChildren().addAll(taskName); + + HBox hBoxDescription = new HBox(); + Label taskDescription = new Label(task.getDescription()); + taskDescription.setWrapText(true); + taskDescription.setMaxSize(600, Double.MAX_VALUE); + Pane puffer = new Pane(); + HBox.setHgrow(puffer, Priority.ALWAYS); + CheckBox checkBox = new CheckBox("Task completed?"); + checkBox.selectedProperty().addListener((observable, oldValue, newValue) -> { + if (newValue) { + showConfirmation(task, checkBox); + } + }); + HBox.setHgrow(checkBox, Priority.NEVER); + hBoxDescription.getChildren().addAll(taskDescription, puffer, checkBox); + vBox.getChildren().addAll(hBox, hBoxDescription); } - pane.getChildren().add(vBox); + return vBox; + } + + /** + * Alert to confirm that task has been completed. + * @param task {@link Task} which is selected + */ + private void showConfirmation(Task task, CheckBox checkBox) { + Alert alert = new Alert(Alert.AlertType.CONFIRMATION); + alert.setTitle("Task Completed?"); + alert.setHeaderText("Are you sure you have completed this task?"); + alert.setContentText("Confirming that you have completed the task will remove it from the schedule."); + + alert.showAndWait() + .ifPresent(buttonType -> { + if (buttonType == ButtonType.OK) { + task.done(); + try { + loadTaskList(); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + checkBox.setSelected(false); + } + }); } diff --git a/src/main/java/ch/zhaw/gartenverwaltung/TaskFormularController.java b/src/main/java/ch/zhaw/gartenverwaltung/TaskFormularController.java index 936bf09..b4bb93b 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/TaskFormularController.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/TaskFormularController.java @@ -1,23 +1,35 @@ package ch.zhaw.gartenverwaltung; +import ch.zhaw.gartenverwaltung.bootstrap.AfterInject; +import ch.zhaw.gartenverwaltung.bootstrap.Inject; +import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException; +import ch.zhaw.gartenverwaltung.io.PlantList; +import ch.zhaw.gartenverwaltung.models.Garden; +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.binding.Binding; -import javafx.beans.binding.Bindings; -import javafx.beans.binding.BooleanBinding; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.*; import javafx.util.Callback; +import java.io.IOException; import java.net.URL; import java.time.LocalDate; import java.util.ResourceBundle; public class TaskFormularController implements Initializable { private Crop crop; + private Plant plant; + private Task task = null; + + @Inject + private GardenSchedule gardenSchedule; + @Inject + private Garden garden; + @Inject + private PlantList plantList; @FXML private TextArea description_area; @@ -34,19 +46,28 @@ public class TaskFormularController implements Initializable { @FXML private TextField taskName_field; + @AfterInject + @SuppressWarnings("unused") - public Task returnResult() { + public Task returnResult(Crop crop) { + int interval = 0; + if (!(interval_field.getText().isEmpty() || interval_field.getText().equals(""))) { + interval = Integer.parseInt(interval_field.getText()); + } Task task = new Task(taskName_field.getText(), description_area.getText(), start_datePicker.getValue(), end_datePicker.getValue(), - Integer.parseInt(interval_field.getText()), crop.getCropId().get()); + interval, crop.getCropId().get()); + if (this.task != null) return this.task.updateTask(task); return task; } - public void setCorp(Crop crop) { + public void setCorp(Crop crop) throws HardinessZoneNotSetException, IOException { this.crop = crop; + this.plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()).get(); } public void setTaskValue(Task task) { + this.task = task; taskName_field.setText(task.getName()); description_area.setText(task.getDescription()); start_datePicker.setValue(task.getStartDate()); @@ -69,7 +90,7 @@ public class TaskFormularController implements Initializable { setDisable(true); setStyle("-fx-background-color: #ffc0cb;"); - if (item.compareTo(today) > 0 && item.compareTo(crop.getStartDate()) > 0) { + if (item.compareTo(today) > 0 && item.compareTo(crop.getStartDate()) > 0 && item.compareTo(crop.getStartDate().plusDays(plant.timeToHarvest(0))) < 0) { setDisable(false); setStyle("-fx-background-color: #32CD32;"); } @@ -93,7 +114,7 @@ public class TaskFormularController implements Initializable { setDisable(true); setStyle("-fx-background-color: #ffc0cb;"); - if (item.compareTo(today) > 0 && item.compareTo(crop.getStartDate()) > 0) { + if (item.compareTo(today) > 0 && item.compareTo(crop.getStartDate()) > 0 && item.compareTo(crop.getStartDate().plusDays(plant.timeToHarvest(0))) < 0) { setDisable(false); setStyle("-fx-background-color: #32CD32;"); } @@ -114,12 +135,8 @@ public class TaskFormularController implements Initializable { }); button.disableProperty().bind(start_datePicker.valueProperty().isNull() - .or(end_datePicker.valueProperty().isNull()) .or(taskName_field.textProperty().isEmpty()) - .or(description_area.textProperty().isEmpty()) - .or(interval_field.textProperty().isEmpty())); - - + .or(description_area.textProperty().isEmpty())); } @Override diff --git a/src/main/java/ch/zhaw/gartenverwaltung/TextFieldFormularController.java b/src/main/java/ch/zhaw/gartenverwaltung/TextFieldFormularController.java index a53c240..97742d9 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/TextFieldFormularController.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/TextFieldFormularController.java @@ -27,6 +27,15 @@ public class TextFieldFormularController { } public void initSaveButton(Button button) { + text_area.textProperty().addListener((observable, oldValue, newValue) -> { + if (newValue.matches("\\d*\\.?\\d*")) { + text_area.setText(newValue); + } else { + text_area.setText(oldValue); + } + }); + button.disableProperty().bind(text_area.textProperty().isEmpty()); } + } diff --git a/src/main/java/ch/zhaw/gartenverwaltung/models/Garden.java b/src/main/java/ch/zhaw/gartenverwaltung/models/Garden.java index fd25b2a..617f03c 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/models/Garden.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/models/Garden.java @@ -70,6 +70,19 @@ public class Garden { plantedCrops.clear(); plantedCrops.addAll(cropList.getCrops()); } + + /** + * Updates the {@link Crop} from the file and the cache + * + * @param crop The crop which is being updated + * @throws IOException If the database cannot be accessed + */ + public void updateCrop(Crop crop) throws IOException { + cropList.saveCrop(crop); + plantedCrops.clear(); + plantedCrops.addAll(cropList.getCrops()); + } + /** * Returns a list of {@link Crop}s which are currently in the gardenplan. * diff --git a/src/main/java/ch/zhaw/gartenverwaltung/models/GardenSchedule.java b/src/main/java/ch/zhaw/gartenverwaltung/models/GardenSchedule.java index c3292f6..a3eccfa 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/models/GardenSchedule.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/models/GardenSchedule.java @@ -152,7 +152,7 @@ public class GardenSchedule { dayTaskList.get(finalI).add(task); } checkDate = checkDate.plusDays(task.getInterval().orElse(0)); - } while (task.getInterval().isPresent() && checkDate.isBefore(LocalDate.now().plusDays(listLength))); + } while (!(task.getInterval().orElse(0) == 0) && checkDate.isBefore(LocalDate.now().plusDays(listLength))); }); } return dayTaskList; diff --git a/src/main/java/ch/zhaw/gartenverwaltung/types/Task.java b/src/main/java/ch/zhaw/gartenverwaltung/types/Task.java index 9501861..4158057 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/types/Task.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/types/Task.java @@ -10,14 +10,15 @@ import java.util.Optional; */ public class Task { private Long id; - private final String name; - private final String description; - private final LocalDate startDate; + private String name; + private String description; + private LocalDate startDate; private Integer interval; private LocalDate endDate; private LocalDate nextExecution; private LocalDate nextNotification; private long cropId; + private boolean done; /** * default constructor @@ -69,7 +70,7 @@ public class Task { } public void done(){ - if(interval != null && !nextExecution.plusDays(interval).isAfter(endDate)){ + if(interval != null && interval != 0 && !nextExecution.plusDays(interval).isAfter(endDate)){ nextExecution = nextExecution.plusDays(interval); } else { nextExecution = null; @@ -103,4 +104,14 @@ public class Task { public Optional getEndDate() { return Optional.ofNullable(endDate); } + + public Task updateTask(Task task) { + this.name = task.getName(); + this.description = task.getDescription(); + this.startDate = task.getStartDate(); + this.endDate = task.getEndDate().orElse(null); + this.interval = task.getInterval().orElse(0); + this.cropId = task.getCropId(); + return this; + } } diff --git a/src/main/java/ch/zhaw/gartenverwaltung/types/TaskTemplate.java b/src/main/java/ch/zhaw/gartenverwaltung/types/TaskTemplate.java index b2cb06f..39e349f 100644 --- a/src/main/java/ch/zhaw/gartenverwaltung/types/TaskTemplate.java +++ b/src/main/java/ch/zhaw/gartenverwaltung/types/TaskTemplate.java @@ -42,7 +42,7 @@ public class TaskTemplate { } public Task generateTask(LocalDate realStartDate, long cropId) { - LocalDate endDate = relativeEndDate != null ? realStartDate.plusDays(relativeEndDate) : null; + LocalDate endDate = relativeEndDate != null ? realStartDate.plusDays(relativeEndDate) : realStartDate; if (interval == null) { this.interval = 0; diff --git a/src/main/resources/ch/zhaw/gartenverwaltung/CropDetail.fxml b/src/main/resources/ch/zhaw/gartenverwaltung/CropDetail.fxml index c0f0a7c..1ee27fb 100644 --- a/src/main/resources/ch/zhaw/gartenverwaltung/CropDetail.fxml +++ b/src/main/resources/ch/zhaw/gartenverwaltung/CropDetail.fxml @@ -107,7 +107,7 @@ -