Compare commits

..

No commits in common. "e9fbbf2f9ffc78ebfdd2efd80e39b2f6cf13f775" and "129a26e1a96acfa2ffb7ef7e741a7f223836cbe1" have entirely different histories.

19 changed files with 68 additions and 131 deletions

View File

@ -0,0 +1,14 @@
package ch.zhaw.gartenverwaltung;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class HelloController {
@FXML
private Label welcomeText;
@FXML
protected void onHelloButtonClick() {
welcomeText.setText("Welcome to JavaFX Application!");
}
}

View File

@ -6,7 +6,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* Annotates a method to be executed after all dependencies annotated with {@link Inject} * Annotates a method to be executed after all dependencies annotates with {@link Inject}
* have been injected. * have been injected.
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)

View File

@ -23,10 +23,6 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
/**
* Class responsible for bootstrapping the application wide dependencies
* and injecting them into JavaFX Controllers.
*/
public class AppLoader { public class AppLoader {
/** /**
* Caching the panes * Caching the panes
@ -36,25 +32,18 @@ public class AppLoader {
/** /**
* Application-wide dependencies * Application-wide dependencies
*/ */
private final Map<String, Object> dependencies = new HashMap<>(); 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 { public AppLoader() throws IOException {
PlantList plantList = new JsonPlantList();
CropList cropList = new JsonCropList();
TaskList taskList = new JsonTaskList();
GardenSchedule gardenSchedule = new GardenSchedule(taskList, plantList);
dependencies.put(PlantList.class.getSimpleName(), plantList);
dependencies.put(CropList.class.getSimpleName(), cropList);
dependencies.put(TaskList.class.getSimpleName(), taskList);
dependencies.put(PlantListModel.class.getSimpleName(), new PlantListModel(plantList));
dependencies.put(GardenSchedule.class.getSimpleName(), gardenSchedule);
dependencies.put(Garden.class.getSimpleName(), new Garden(gardenSchedule, cropList));
dependencies.put(AppLoader.class.getSimpleName(), this);
} }
/** /**
* Loads and returns a {@link Pane} (cached). * Loads and returns a {@link Pane} (cached).
* *
@ -146,18 +135,26 @@ public class AppLoader {
}); });
Arrays.stream(controller.getClass().getMethods()) Arrays.stream(controller.getClass().getMethods())
.filter(method -> method.isAnnotationPresent(AfterInject.class) && method.getParameterCount() == 0) .filter(method -> method.isAnnotationPresent(AfterInject.class))
.forEach(afterInjectMethod -> { .forEach(afterInjectMethod -> {
if (afterInjectMethod.getParameterCount() == 0) {
try { try {
afterInjectMethod.invoke(controller); afterInjectMethod.invoke(controller);
} catch (IllegalAccessException | InvocationTargetException e) { } catch (IllegalAccessException | InvocationTargetException e) {
// TODO: Log
e.printStackTrace(); e.printStackTrace();
} }
}
}); });
} }
private Object getAppDependency(Class<?> type) { private Object getAppDependency(Class<?> type) {
return dependencies.get(type.getSimpleName()); return switch (type.getSimpleName()) {
case "Garden" -> garden;
case "PlantList" -> plantList;
case "PlantListModel" -> new PlantListModel(plantList);
case "GardenSchedule" -> gardenSchedule;
case "AppLoader" -> this;
default -> null;
};
} }
} }

View File

@ -3,20 +3,11 @@ package ch.zhaw.gartenverwaltung.bootstrap;
import javafx.event.Event; import javafx.event.Event;
import javafx.event.EventType; import javafx.event.EventType;
/**
* Represents an event that should lead to a view being changed.
*/
public class ChangeViewEvent extends Event { public class ChangeViewEvent extends Event {
private final String view; private final String view;
public static final EventType<ChangeViewEvent> CHANGE_MAIN_VIEW = new EventType<>("CHANGE_MAIN_VIEW"); public static final EventType<ChangeViewEvent> CHANGE_MAIN_VIEW = new EventType<>("CHANGE_MAIN_VIEW");
/**
* Creates an Event that should lead to the main view being changed.
*
* @param eventType The {@link EventType<ChangeViewEvent>} specifying which view should be changed.
* @param view The filename of the View to be changed to
*/
public ChangeViewEvent(EventType<? extends Event> eventType, String view) { public ChangeViewEvent(EventType<? extends Event> eventType, String view) {
super(eventType); super(eventType);
this.view = view; this.view = view;

View File

@ -6,7 +6,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* Annotates a Field to be injected from the application-dependencies. * Annotates a Field to be injected from the application-dependencies
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) @Target(ElementType.FIELD)

View File

@ -6,10 +6,6 @@ import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
/**
* Represents a List of {@link Crop}s.
* The interface specifies the operations to add/update and remove entries.
*/
public interface CropList { public interface CropList {
/** /**
* Yields a list of all {@link Crop}s in the database. * Yields a list of all {@link Crop}s in the database.

View File

@ -1,18 +1,10 @@
package ch.zhaw.gartenverwaltung.io; package ch.zhaw.gartenverwaltung.io;
/**
* Provides an sequential ID starting from the given initial Value.
*/
public class IdProvider { public class IdProvider {
private long currentId; private long currentId;
public IdProvider(long initialValue) { public IdProvider(long initialValue) {
currentId = initialValue; currentId = initialValue;
} }
/**
* Yields the next ID in the sequence.
* @return The next ID
*/
public long incrementAndGet() { public long incrementAndGet() {
return ++currentId; return ++currentId;
} }

View File

@ -19,11 +19,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
/**
* Implements the {@link CropList} interface for reading and writing {@link Crop} objects
* from and to a local JSON file.
* The reads are cached to minimize file-io operations.
*/
public class JsonCropList implements CropList { public class JsonCropList implements CropList {
private final URL dataSource; private final URL dataSource;
@ -45,7 +40,7 @@ public class JsonCropList implements CropList {
} }
/** /**
* Default constructor. Uses a file from the app resources. * Default constructor
*/ */
public JsonCropList() { public JsonCropList() {
this.dataSource = getClass().getResource("user-crops.json"); this.dataSource = getClass().getResource("user-crops.json");

View File

@ -20,8 +20,8 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
/** /**
* Implements the {@link PlantList} interface for reading {@link Plant} objects * Implements the {@link PlantList} interface for loading {@link Plant} objects
* from a local JSON file. * from a JSON file.
* The reads are cached to minimize file-io operations. * The reads are cached to minimize file-io operations.
*/ */
public class JsonPlantList implements PlantList { public class JsonPlantList implements PlantList {
@ -44,17 +44,9 @@ public class JsonPlantList implements PlantList {
imageModule.addDeserializer(Image.class, new PlantImageDeserializer()); imageModule.addDeserializer(Image.class, new PlantImageDeserializer());
} }
/**
* Default constructor. Uses a file from the app resources.
*/
public JsonPlantList() { public JsonPlantList() {
this.dataSource = getClass().getResource("plantdb.json"); this.dataSource = getClass().getResource("plantdb.json");
} }
/**
* Constructor to use a specified {@link URL} as a {@link #dataSource}
* @param dataSource A {@link URL} to the file to be used as a data source
*/
public JsonPlantList(URL dataSource) { public JsonPlantList(URL dataSource) {
this.dataSource = dataSource; this.dataSource = dataSource;
} }
@ -75,7 +67,7 @@ public class JsonPlantList implements PlantList {
} }
/** /**
* @see PlantList#getPlantById(HardinessZone, long) * @see PlantList#getPlantById(long)
*/ */
@Override @Override
public Optional<Plant> getPlantById(HardinessZone zone, long id) throws HardinessZoneNotSetException, IOException { public Optional<Plant> getPlantById(HardinessZone zone, long id) throws HardinessZoneNotSetException, IOException {

View File

@ -20,8 +20,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* Implements the {@link TaskList} interface for reading and writing {@link Task} objects * Implements the {@link TaskList} interface for loading and writing {@link Task} objects
* from and to a local JSON file. * from and to a JSON file.
* The reads are cached to minimize file-io operations. * The reads are cached to minimize file-io operations.
*/ */
public class JsonTaskList implements TaskList { public class JsonTaskList implements TaskList {
@ -45,17 +45,9 @@ public class JsonTaskList implements TaskList {
timeModule.addSerializer(LocalDate.class, dateSerializer); timeModule.addSerializer(LocalDate.class, dateSerializer);
} }
/**
* Default constructor. Uses a file from the app resources.
*/
public JsonTaskList() { public JsonTaskList() {
this.dataSource = getClass().getResource("taskdb.json"); this.dataSource = getClass().getResource("taskdb.json");
} }
/**
* Constructor to use a specified {@link URL} as a {@link #dataSource}
* @param dataSource A {@link URL} to the file to be used as a data source
*/
public JsonTaskList(URL dataSource) { public JsonTaskList(URL dataSource) {
this.dataSource = dataSource; this.dataSource = dataSource;
} }

View File

@ -8,7 +8,7 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
/** /**
* A List of {@link Plant}s. * A database of {@link Plant}s.
* The interface specifies the minimal required operations. * The interface specifies the minimal required operations.
*/ */
public interface PlantList { public interface PlantList {

View File

@ -7,8 +7,8 @@ import java.time.LocalDate;
import java.util.List; import java.util.List;
/** /**
* Represents a List of {@link Task}s. * A database of {@link Task}s.
* The interface specifies the operations to add/update and remove entries. * The interface specifies the minimal required operations.
*/ */
public interface TaskList { public interface TaskList {
/** /**

View File

@ -7,9 +7,6 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException; import java.io.IOException;
/**
* Used by the Jackson Library to deserialize a String to a {@link GrowthPhaseType}
*/
public class GrowthPhaseTypeDeserializer extends StdDeserializer<GrowthPhaseType> { public class GrowthPhaseTypeDeserializer extends StdDeserializer<GrowthPhaseType> {
public GrowthPhaseTypeDeserializer(Class<?> vc) { public GrowthPhaseTypeDeserializer(Class<?> vc) {
super(vc); super(vc);

View File

@ -7,9 +7,6 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException; import java.io.IOException;
/**
* Used by the Jackson Library to deserialize a String to a {@link HardinessZone}
*/
public class HardinessZoneDeserializer extends StdDeserializer<HardinessZone> { public class HardinessZoneDeserializer extends StdDeserializer<HardinessZone> {
public HardinessZoneDeserializer(Class<?> vc) { public HardinessZoneDeserializer(Class<?> vc) {
super(vc); super(vc);

View File

@ -13,9 +13,6 @@ import java.io.InputStream;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
/**
* Used by the Jackson Library to deserialize a String to a {@link Image}
*/
public class PlantImageDeserializer extends JsonDeserializer<Image> { public class PlantImageDeserializer extends JsonDeserializer<Image> {
@Override @Override

View File

@ -146,18 +146,14 @@ public class GardenSchedule {
dayTaskList.add(new ArrayList<>()); dayTaskList.add(new ArrayList<>());
final int finalI = i; final int finalI = i;
weekTasks.forEach(task -> { weekTasks.forEach(task -> {
if (task.getNextExecution() == null) {
task.isDone();
} else {
LocalDate checkDate = task.getNextExecution(); LocalDate checkDate = task.getNextExecution();
do { do {
if (date.equals(checkDate) && !date.isAfter(task.getEndDate().orElse(LocalDate.MIN))) { if (date.equals(checkDate) && !date.isAfter(task.getEndDate().orElse(LocalDate.MIN))) {
dayTaskList.get(finalI).add(task); dayTaskList.get(finalI).add(task);
} }
if (task.getInterval().orElse(0) == 0) break;
checkDate = checkDate.plusDays(task.getInterval().orElse(0)); checkDate = checkDate.plusDays(task.getInterval().orElse(0));
} while (!(task.getInterval().orElse(0) == 0) && checkDate.isBefore(LocalDate.now().plusDays(listLength))); } while (task.getInterval().isPresent() && checkDate.isBefore(LocalDate.now().plusDays(listLength)));
}
}); });
} }
return dayTaskList; return dayTaskList;
@ -192,6 +188,6 @@ public class GardenSchedule {
* @return a sorted coppy of the given Tasklist * @return a sorted coppy of the given Tasklist
*/ */
private List<Task> getSortedTaskList(List<Task> taskList, Comparator<Task> comparator) { private List<Task> getSortedTaskList(List<Task> taskList, Comparator<Task> comparator) {
return taskList.stream().filter(task -> task.getNextExecution() != null).sorted(comparator).collect(Collectors.toList()); return taskList.stream().sorted(comparator).collect(Collectors.toList());
} }
} }

View File

@ -42,7 +42,7 @@ public class TaskTemplate {
} }
public Task generateTask(LocalDate realStartDate, long cropId) { public Task generateTask(LocalDate realStartDate, long cropId) {
LocalDate endDate = relativeEndDate != null ? realStartDate.plusDays(relativeEndDate) : realStartDate; LocalDate endDate = relativeEndDate != null ? realStartDate.plusDays(relativeEndDate) : realStartDate.plusDays(0);
if (interval == null) { if (interval == null) {
this.interval = 0; this.interval = 0;

View File

@ -7,14 +7,14 @@
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="938.0" prefWidth="1110.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.gartenverwaltung.MainFXMLController"> <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="938.0" prefWidth="1110.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.gartenverwaltung.MainFXMLController">
<children> <children>
<HBox fx:id="menubar" maxWidth="35.0" minHeight="40.0" prefHeight="38.0" prefWidth="1110.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <HBox maxWidth="35.0" minHeight="35.0" prefHeight="38.0" prefWidth="1110.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children> <children>
<Button fx:id="home_button" mnemonicParsing="false" onAction="#goToHome" prefHeight="38.0" prefWidth="38.0" HBox.hgrow="NEVER" /> <Button fx:id="home_button" mnemonicParsing="false" onAction="#goToHome" prefHeight="38.0" prefWidth="40.0" HBox.hgrow="NEVER" />
<Button fx:id="myGarden_button" layoutX="10.0" layoutY="10.0" mnemonicParsing="false" onAction="#goToMyPlants" prefHeight="38.0" prefWidth="121.0" text="My Garden" /> <Button fx:id="myGarden_button" layoutX="10.0" layoutY="10.0" mnemonicParsing="false" onAction="#goToMyPlants" prefHeight="38.0" prefWidth="121.0" text="My Garden" />
<Button fx:id="mySchedule_button" layoutX="10.0" layoutY="10.0" mnemonicParsing="false" onAction="#goToMySchedule" prefHeight="38.0" prefWidth="121.0" text="My Schedule" /> <Button fx:id="mySchedule_button" layoutX="10.0" layoutY="10.0" mnemonicParsing="false" onAction="#goToMySchedule" prefHeight="38.0" prefWidth="121.0" text="My Schedule" />
<Button fx:id="tutorial_button" layoutX="10.0" layoutY="10.0" mnemonicParsing="false" onAction="#showTutorial" prefHeight="38.0" prefWidth="121.0" text="Tutorial" /> <Button fx:id="tutorial_button" layoutX="10.0" layoutY="10.0" mnemonicParsing="false" onAction="#showTutorial" prefHeight="38.0" prefWidth="121.0" text="Tutorial" />
<Pane fx:id="menu_pane" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS" /> <Pane maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" HBox.hgrow="ALWAYS" />
<Button fx:id="settings_button" mnemonicParsing="false" onAction="#openSettings" prefHeight="38.0" prefWidth="38.0" HBox.hgrow="NEVER" /> <Button fx:id="settings_button" maxHeight="1.7976931348623157E308" mnemonicParsing="false" onAction="#openSettings" prefHeight="38.0" prefWidth="40.0" HBox.hgrow="NEVER" />
</children> </children>
</HBox> </HBox>
<AnchorPane fx:id="mainPane" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="35.0" /> <AnchorPane fx:id="mainPane" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="35.0" />

View File

@ -1,25 +1,6 @@
/* .button{
-fx-text-fill: rgb(49, 89, 23);
#home_button, #myGarden_button, -fx-border-color: rgb(49, 89, 23);
#mySchedule_button, #settings_button, -fx-border-radius: 5;
#tutorial_button, #menu_pane { -fx-padding: 3 6 6 6;
-fx-text-fill: white;
-fx-background-color: rgb(0,128,0);
} }
#menubar {
-fx-background-color: rgb(0,128,0);
}
#home_button:hover, #myGarden_button:hover,
#mySchedule_button:hover, #settings_button:hover,
#tutorial_button:hover,
#home_button:focused, #myGarden_button:focused,
#mySchedule_button:focused, #settings_button:focused,
#tutorial_button:focused{
-fx-background-color: darkgreen;
}
.root, .split-pane {
-fx-background-color: linear-gradient(green 0%, lawngreen 33%, lightgreen 66%, #eee 100%);
}./