package oving0.todolist.fxui; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javafx.beans.property.StringProperty; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ListView; import javafx.scene.control.TextField; import javafx.scene.text.Text; import javafx.stage.FileChooser; import javafx.stage.Window; import oving0.todolist.model.TodoEntry; import oving0.todolist.model.TodoList; public class TodoController { private final TodoSettings todoSettings = new TodoSettings(); public TodoSettings getTodoSettings() { return todoSettings; } private TodoList todoList; public void setTodoList(final TodoList todoList) { this.todoList = todoList; updateTodoListView(); } private final ITodoFileReading fileSupport = new TodoFileSupport(); @FXML private String sampleTodoListResource; @FXML private Text todoListNameView; @FXML private ListView todoListEntriesView; @FXML private TextField todoEntryTextField; @FXML private TextField fileLocationNameField; @FXML private Button todoEntryButton; @FXML private Text statusText; private String defaultStatusText; @SuppressWarnings("unused") @FXML public void initialize() { final var todoList = new TodoList(); todoList.setName("todo list"); setTodoList(todoList); todoListEntriesView.getSelectionModel().selectedItemProperty() .addListener((prop, oldValue, newValue) -> { handleTodoListEntriesViewSelectedItemChanged(); }); handleTodoListEntriesViewSelectedItemChanged(); defaultStatusText = statusText.getText(); } private void updateTodoListView() { todoListNameView.setText(todoList.getName()); todoListEntriesView.getItems().setAll(getOrderedTodoListItems()); } protected List getOrderedTodoListItems() { final List listItems = new ArrayList<>(); for (final var entry : todoList) { listItems.add(entry.getText()); } switch (todoSettings.getTodoListOrder()) { case ADD_ORDER_REVERSED: { Collections.reverse(listItems); break; } case LEXICOGRAPHIC_ORDER: { Collections.sort(listItems); break; } default: } return listItems; } private void handleTodoListEntriesViewSelectedItemChanged() { todoEntryTextField.setText(todoListEntriesView.getSelectionModel().getSelectedItem()); } @FXML private void handleTodoEntryTextFieldChange(final StringProperty prop, final String oldValue, final String newValue) { if (todoList.hasEntry(newValue)) { todoEntryButton.setText("Remove"); } else { todoEntryButton.setText("Add"); } todoEntryButton.setDisable(newValue == null || newValue.isBlank()); } private FileChooser fileChooser; private String getFileLocationName(final boolean isSave) { if (fileChooser == null) { fileChooser = new FileChooser(); } final Window window = fileLocationNameField.getScene().getWindow(); File file = null; if (isSave) { file = fileChooser.showSaveDialog(window); } else { file = fileChooser.showOpenDialog(window); } if (file != null) { String name = file.getName(); final int pos = name.lastIndexOf('.'); if (pos >= 0) { name = name.substring(0, pos); } if (!name.isBlank()) { return file.getParent() + File.separator + name; } } return null; } @FXML private void handleBrowseButtonAction() { final String name = getFileLocationName(false); if (name != null) { fileLocationNameField.setText(name); } } private String ensureFileLocation(final boolean isSave) { String name = fileLocationNameField.getText(); if (name.isBlank()) { name = getFileLocationName(false); if (name != null) { fileLocationNameField.setText(name); } } return name; } @FXML private void handleLoadButtonAction() { final String name = ensureFileLocation(false); if (!name.isBlank()) { try { setTodoList(fileSupport.readTodoList(name)); statusText.setText(defaultStatusText); } catch (final IOException e) { statusText.setText(e.getMessage()); } } } @FXML private void handleSaveButtonAction() { final String name = ensureFileLocation(true); if (!name.isBlank()) { try { todoList.setName(name); fileSupport.writeTodoList(todoList); todoListNameView.setText(todoList.getName()); statusText.setText(defaultStatusText); } catch (final IOException e) { statusText.setText(e.getMessage()); } } } @FXML private void handleTodoEntryButtonAction() { final var text = todoEntryTextField.getText(); final var entry = todoList.findEntry(text); if (entry != null) { todoList.removeEntry(entry); } else { todoList.addEntry(new TodoEntry(text)); } todoEntryTextField.clear(); updateTodoListView(); } private TodoSettingsController settingsController; private Scene scene; private Parent oldSceneRoot, settingsSceneRoot; @FXML private void handleSettingsAction() { // check if we need to load settings ui from fxml if (settingsController == null) { final FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("TodoSettings.fxml")); try { // load settings ui settingsSceneRoot = fxmlLoader.load(); // remember old ui scene = todoListEntriesView.getScene(); oldSceneRoot = scene.getRoot(); // get the settings controller, so we can set its todoSettings property settingsController = fxmlLoader.getController(); settingsController.setTodoController(this); } catch (final IOException e) { } } if (settingsController != null) { todoListEntriesView.getScene().setRoot(settingsSceneRoot); settingsController.setTodoSettings(todoSettings); } } public void applyTodoSettings(final TodoSettings settings) { if (settings != null) { settings.copyInto(this.todoSettings); } scene.setRoot(oldSceneRoot); if (settings != null) { updateTodoListView(); } } }