package ch.zhaw.gartenverwaltung; import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException; import ch.zhaw.gartenverwaltung.plantList.PlantListModel; 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.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; 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.util.List; import java.util.Objects; import java.util.ResourceBundle; public class PlantsController implements Initializable { private final PlantListModel plantListModel = new PlantListModel(); 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 private VBox seasons; @FXML private VBox climate_zones; @FXML private Label description_plant; @FXML private ImageView img_plant; @FXML private ListView list_plants; @FXML private Button saveToMyPlant_button; @FXML private TextField search_plants; /** * saves the current selected plant in new JSON database * @param event event */ @FXML void saveToMyPlant(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); Stage stage = new Stage(); stage.setScene(new Scene(root)); stage.initModality(Modality.APPLICATION_MODAL); stage.setResizable(false); stage.showAndWait(); } /** * fill list view with current hardiness zone * set default values * create filter of season and hardiness zone * create event listener for selected list entry and search by query * {@inheritDoc} */ @Override public void initialize(URL url, ResourceBundle resourceBundle) { setListCellFactory(); fillPlantListWithHardinessZone(); list_plants.itemsProperty().bind(plantListProperty); description_plant.setText(""); saveToMyPlant_button.setDisable(true); createFilterSeasons(); createFilterHardinessZone(); lookForSelectedListEntry(); try { viewFilteredListBySearch(); } catch (HardinessZoneNotSetException | IOException e) { e.printStackTrace(); } } /** * set text of list view to plant name */ private void setListCellFactory() { list_plants.setCellFactory(param -> new ListCell() { @Override protected void updateItem(Plant plant, boolean empty) { super.updateItem(plant, empty); if (empty || plant == null || plant.name() == null) { setText(null); } else { setText(plant.name()); } } }); } /** * 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 */ private void viewFilteredListBySeason(Seasons season) throws HardinessZoneNotSetException, IOException { clearListView(); plantListProperty.addAll(plantListModel.getFilteredPlantListBySaisonWithoutGrowthPhase(plantListModel.getCurrentZone(), season.getStartDate(), season.getEndDate())); } /** * 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 */ private void viewFilteredListBySearch() throws HardinessZoneNotSetException, IOException { search_plants.textProperty().addListener((observable, oldValue, newValue) -> { if (newValue.isEmpty()) { fillPlantListWithHardinessZone(); }else { try { List filteredPlants = plantListModel.getFilteredPlantListByString(DEFAULT_HARDINESS_ZONE, newValue); clearListView(); plantListProperty.addAll(filteredPlants); } catch (HardinessZoneNotSetException | IOException e) { e.printStackTrace(); } } }); } /** * get plant list of current hardiness zone * fill list view with plant list */ private void fillPlantListWithHardinessZone() { try { clearListView(); plantListProperty.addAll(plantListModel.getPlantList(plantListModel.getCurrentZone())); } catch (HardinessZoneNotSetException | IOException e) { e.printStackTrace(); } } /** * creates radio buttons for the hardiness zones defined in enum HardinessZone * defines default value as selected * when selected filter viewList according to hardiness zone */ private void createFilterHardinessZone() { ToggleGroup hardinessGroup = new ToggleGroup(); for (HardinessZone zone : HardinessZone.values()) { RadioButton radioButton = new RadioButton(zone.name()); radioButton.setToggleGroup(hardinessGroup); radioButton.setPadding(new Insets(0,0,10,0)); if (zone.equals(DEFAULT_HARDINESS_ZONE)) { radioButton.setSelected(true); } radioButton.selectedProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { plantListModel.setCurrentZone(zone); fillPlantListWithHardinessZone(); } }); climate_zones.getChildren().add(radioButton); } } /** * creates radio buttons for the seasons defined in enum Seasons * defines default value as selected * when selected filter viewList according to seasons */ private void createFilterSeasons() { ToggleGroup seasonGroup = new ToggleGroup(); for (Seasons season : Seasons.values()) { RadioButton radioButton = new RadioButton(season.name()); radioButton.setToggleGroup(seasonGroup); radioButton.setPadding(new Insets(0,0,10,0)); if (season.equals(Seasons.AllSEASONS)) { radioButton.setSelected(true); } radioButton.selectedProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { if (season.equals(Seasons.AllSEASONS)) { fillPlantListWithHardinessZone(); } else { try { viewFilteredListBySeason(season); } catch (HardinessZoneNotSetException | IOException e) { e.printStackTrace(); } } } }); seasons.getChildren().add(radioButton); } } /** * observes changes in the selectedProperty of ListView and updates: * the description label * image of the plant */ private void lookForSelectedListEntry() { list_plants.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Plant oldValue, Plant newValue) { if(newValue != null) { selectedPlant = newValue; description_plant.setText(selectedPlant.description()); saveToMyPlant_button.setDisable(false); Image img; if(selectedPlant.image() != null) { img = selectedPlant.image(); } else { img = new Image(String.valueOf(PlantsController.class.getResource("placeholder.png"))); } img_plant.setImage(img); } else { selectedPlant = null; description_plant.setText(""); saveToMyPlant_button.setDisable(true); Image img = new Image(String.valueOf(PlantsController.class.getResource("placeholder.png"))); img_plant.setImage(img); } } }); } /** * clears the ListView of entries */ private void clearListView() { plantListProperty.clear(); } }