diff --git a/todolist/core/src/main/java/todolist/core/TodoModel.java b/todolist/core/src/main/java/todolist/core/TodoModel.java index f95c5c589662a74da617584685a0bcfd88013ded..03dc70ba9eb29b1ed0429825424daef7c768a962 100644 --- a/todolist/core/src/main/java/todolist/core/TodoModel.java +++ b/todolist/core/src/main/java/todolist/core/TodoModel.java @@ -125,6 +125,6 @@ public class TodoModel implements Iterable<AbstractTodoList> { * @return a function that gets the todo items of a todo list in the corresponding sort order */ public Function<TodoList, Collection<TodoItem>> getSortedTodoItemsProvider() { - return getSortedTodoItemsProvider(getSettings().getTodoItemSortOrder()); + return getSortedTodoItemsProvider(getSettings().getTodoItemsSortOrder()); } } diff --git a/todolist/core/src/main/java/todolist/core/TodoSettings.java b/todolist/core/src/main/java/todolist/core/TodoSettings.java index bac61bc0724b8182f5bc719fc9f0bac0aeaba8d7..4c8c75143f3f7782137d9b11dffa86d25b332ef5 100644 --- a/todolist/core/src/main/java/todolist/core/TodoSettings.java +++ b/todolist/core/src/main/java/todolist/core/TodoSettings.java @@ -1,7 +1,6 @@ package todolist.core; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -9,6 +8,11 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; +/** + * A class for managing settings, + * i.e. properties that control behavior of other classes. + * Changes to settings can be listened to and vetoed by throwing an exception. + */ public class TodoSettings { private Collection<TodoSettingsListener> todoSettingsListeners = new ArrayList<>(); @@ -23,7 +27,7 @@ public class TodoSettings { private Map<String, Object> oldValues = null; - private void fireSettingChanged(String property, Object oldValue, Object newValue) { + private void handleSettingChanged(String property, Object oldValue, Object newValue) { if (Objects.equals(oldValue, newValue)) { return; } @@ -48,21 +52,28 @@ public class TodoSettings { } } + /** + * Call to indicate that new values will be used, and + * old values can be forgotten. + */ public void applyChanges() { oldValues = null; } private void cancelChange(String property) { - Object oldValue = oldValues.get(property); + var oldValue = oldValues.get(property); + var setterName = "set" + Character.toUpperCase(property.charAt(0)) + property.substring(1); try { - Method setter = getClass().getMethod("set" + Character.toUpperCase(property.charAt(0)) + property.substring(1), - oldValue.getClass()); + var setter = getClass().getMethod(setterName, oldValue.getClass()); setter.invoke(this, oldValue); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { // ignore } } + /** + * Call to rollback changes to old values. + */ public void cancelChanges() { try { for (String property : oldValues.keySet()) { @@ -75,21 +86,30 @@ public class TodoSettings { // + /** + * Enum for possible values of sort order for items. + */ public enum TodoItemsSortOrder { NONE, UNCHECKED_CHECKED, CHECKED_UNCHECKED } - private TodoItemsSortOrder todoItemSortOrder = TodoItemsSortOrder.UNCHECKED_CHECKED; + private TodoItemsSortOrder todoItemsSortOrder = TodoItemsSortOrder.NONE; - public TodoItemsSortOrder getTodoItemSortOrder() { - return todoItemSortOrder; + public TodoItemsSortOrder getTodoItemsSortOrder() { + return todoItemsSortOrder; } - public final static String TODO_ITEM_SORT_ORDER_SETTING = "todoItemSortOrder"; - - public void setTodoItemSortOrder(TodoItemsSortOrder todoItemSortOrder) { - Object oldValue = this.todoItemSortOrder; - this.todoItemSortOrder = todoItemSortOrder; - fireSettingChanged(TODO_ITEM_SORT_ORDER_SETTING, oldValue, todoItemSortOrder); + // settings name must correspond to setter name! + public static final String TODO_ITEM_SORT_ORDER_SETTING = "todoItemsSortOrder"; + + /** + * Sets the todoItemsSortOrder property, and notifies listeners. + * + * @param todoItemSortOrder the new todoItemSortOrder value + */ + public void setTodoItemsSortOrder(TodoItemsSortOrder todoItemSortOrder) { + Object oldValue = this.todoItemsSortOrder; + this.todoItemsSortOrder = todoItemSortOrder; + handleSettingChanged(TODO_ITEM_SORT_ORDER_SETTING, oldValue, todoItemSortOrder); } } diff --git a/todolist/core/src/main/java/todolist/core/TodoSettingsListener.java b/todolist/core/src/main/java/todolist/core/TodoSettingsListener.java index 3178b49e46bcff5d4c5ddae9d64504a0d1c2183f..28698c4394f484a6508d1419082f4d6f3c76aa1e 100644 --- a/todolist/core/src/main/java/todolist/core/TodoSettingsListener.java +++ b/todolist/core/src/main/java/todolist/core/TodoSettingsListener.java @@ -2,6 +2,17 @@ package todolist.core; import java.util.Collection; +/** + * Listener for changes to TodoSettings. + */ public interface TodoSettingsListener { + + /** + * Called when settings are changed. + * Changes may be vetoed by throwing an exception. + * + * @param settings the TodoSettings that changed + * @param changedProperties the properties (names) that changed + */ public void todoSettingsChanged(TodoSettings settings, Collection<String> changedProperties); } \ No newline at end of file diff --git a/todolist/core/src/main/java/todolist/json/internal/TodoSettingsDeserializer.java b/todolist/core/src/main/java/todolist/json/internal/TodoSettingsDeserializer.java index d05316cf6b1124e6586da534cfad6ecf05475c1c..f6aee4d415a3243fb3fc28a6ccc1516f95c2187f 100644 --- a/todolist/core/src/main/java/todolist/json/internal/TodoSettingsDeserializer.java +++ b/todolist/core/src/main/java/todolist/json/internal/TodoSettingsDeserializer.java @@ -29,7 +29,7 @@ class TodoSettingsDeserializer extends JsonDeserializer<TodoSettings> { if (todoItemsSortOrderNode instanceof TextNode) { try { TodoItemsSortOrder sortOrder = TodoItemsSortOrder.valueOf(todoItemsSortOrderNode.asText()); - settings.setTodoItemSortOrder(sortOrder); + settings.setTodoItemsSortOrder(sortOrder); } catch (IllegalArgumentException iae) { // ignore unknown sort order constant } diff --git a/todolist/core/src/main/java/todolist/json/internal/TodoSettingsSerializer.java b/todolist/core/src/main/java/todolist/json/internal/TodoSettingsSerializer.java index b79dfeb1e917f2d167cb4b9ceb8842b82310f0ed..31bf770b4dd683de8d08f20b73760abf76b21cf9 100644 --- a/todolist/core/src/main/java/todolist/json/internal/TodoSettingsSerializer.java +++ b/todolist/core/src/main/java/todolist/json/internal/TodoSettingsSerializer.java @@ -9,7 +9,7 @@ import todolist.core.TodoSettings; class TodoSettingsSerializer extends JsonSerializer<TodoSettings> { /* - * format: { "todoItemSortOrder": "..." } + * format: { "todoItemsSortOrder": "..." } */ @Override @@ -17,7 +17,7 @@ class TodoSettingsSerializer extends JsonSerializer<TodoSettings> { SerializerProvider serializerProvider) throws IOException { jsonGen.writeStartObject(); - jsonGen.writeStringField(TodoSettings.TODO_ITEM_SORT_ORDER_SETTING, settings.getTodoItemSortOrder().name()); + jsonGen.writeStringField(TodoSettings.TODO_ITEM_SORT_ORDER_SETTING, settings.getTodoItemsSortOrder().name()); jsonGen.writeEndObject(); } } diff --git a/todolist/core/src/test/java/todolist/core/TodoModelTest.java b/todolist/core/src/test/java/todolist/core/TodoModelTest.java index 1bf7c693ca90f13e2440be8109c67c6e463ba3d6..e3fc9acd5714f07e3b166e0847793d71338c2a88 100644 --- a/todolist/core/src/test/java/todolist/core/TodoModelTest.java +++ b/todolist/core/src/test/java/todolist/core/TodoModelTest.java @@ -78,7 +78,7 @@ public class TodoModelTest { List<TodoItem> allAddedItems = new ArrayList<>(todoList.getTodoItems()); Collection<TodoItem> expectedOrder = Stream.of(sortedTodoItemIndices).map(allAddedItems::get).collect(Collectors.toList()); TodoListTest.checkItems(TodoModel.getSortedTodoItemsProvider(sortOrder).apply(todoList), expectedOrder.toArray(new TodoItem[expectedOrder.size()])); - todoModel.getSettings().setTodoItemSortOrder(sortOrder); + todoModel.getSettings().setTodoItemsSortOrder(sortOrder); TodoListTest.checkItems(todoModel.getSortedTodoItemsProvider().apply(todoList), expectedOrder.toArray(new TodoItem[expectedOrder.size()])); } diff --git a/todolist/core/src/test/java/todolist/core/TodoSettingsTest.java b/todolist/core/src/test/java/todolist/core/TodoSettingsTest.java index 0924caef0ad5daa74e7ebd10f0b51d50048ee29f..37822c0be81a206b71050dd293038dfebb4e9869 100644 --- a/todolist/core/src/test/java/todolist/core/TodoSettingsTest.java +++ b/todolist/core/src/test/java/todolist/core/TodoSettingsTest.java @@ -19,32 +19,32 @@ public class TodoSettingsTest { @BeforeEach public void setup() { todoSettings = new TodoSettings(); - todoSettings.setTodoItemSortOrder(TodoItemsSortOrder.NONE); + todoSettings.setTodoItemsSortOrder(TodoItemsSortOrder.NONE); todoSettings.applyChanges(); } @Test public void testSetTodoItemsSortOrder_changesProperty() { - todoSettings.setTodoItemSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); - assertEquals(TodoItemsSortOrder.CHECKED_UNCHECKED, todoSettings.getTodoItemSortOrder()); + todoSettings.setTodoItemsSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); + assertEquals(TodoItemsSortOrder.CHECKED_UNCHECKED, todoSettings.getTodoItemsSortOrder()); } - private static Collection<String> TODO_ITEMS_SORT_ORDER_SINGLETON_COLLECTION = Collections.singleton("todoItemSortOrder"); + private static Collection<String> TODO_ITEMS_SORT_ORDER_SINGLETON_COLLECTION = Collections.singleton(TodoSettings.TODO_ITEM_SORT_ORDER_SETTING); @Test public void testSetTodoItemsSortOrder_todoSettingsChangedCalledWhenPropertyChanged() { TodoSettingsListener todoSettingsListener = mock(TodoSettingsListener.class); todoSettings.addTodoSettingsListener(todoSettingsListener); - todoSettings.setTodoItemSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); - assertEquals(TodoItemsSortOrder.CHECKED_UNCHECKED, todoSettings.getTodoItemSortOrder()); + todoSettings.setTodoItemsSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); + assertEquals(TodoItemsSortOrder.CHECKED_UNCHECKED, todoSettings.getTodoItemsSortOrder()); // listener called when property changed verify(todoSettingsListener, times(1)).todoSettingsChanged(todoSettings, TODO_ITEMS_SORT_ORDER_SINGLETON_COLLECTION); - todoSettings.setTodoItemSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); - assertEquals(TodoItemsSortOrder.CHECKED_UNCHECKED, todoSettings.getTodoItemSortOrder()); + todoSettings.setTodoItemsSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); + assertEquals(TodoItemsSortOrder.CHECKED_UNCHECKED, todoSettings.getTodoItemsSortOrder()); // listener not called when property didn't change verify(todoSettingsListener, times(1)).todoSettingsChanged(todoSettings, TODO_ITEMS_SORT_ORDER_SINGLETON_COLLECTION); - todoSettings.setTodoItemSortOrder(TodoItemsSortOrder.UNCHECKED_CHECKED); - assertEquals(TodoItemsSortOrder.UNCHECKED_CHECKED, todoSettings.getTodoItemSortOrder()); + todoSettings.setTodoItemsSortOrder(TodoItemsSortOrder.UNCHECKED_CHECKED); + assertEquals(TodoItemsSortOrder.UNCHECKED_CHECKED, todoSettings.getTodoItemsSortOrder()); // listener called another time when property changed verify(todoSettingsListener, times(2)).todoSettingsChanged(todoSettings, TODO_ITEMS_SORT_ORDER_SINGLETON_COLLECTION); } @@ -53,7 +53,7 @@ public class TodoSettingsTest { public void testSetTodoItemsSortOrder_todoSettingsChangedNotCalledWhenPropertyNotChanged() { TodoSettingsListener todoSettingsListener = mock(TodoSettingsListener.class); todoSettings.addTodoSettingsListener(todoSettingsListener); - todoSettings.setTodoItemSortOrder(TodoItemsSortOrder.NONE); + todoSettings.setTodoItemsSortOrder(TodoItemsSortOrder.NONE); verifyNoInteractions(todoSettingsListener); } @@ -61,22 +61,22 @@ public class TodoSettingsTest { public void testSetTodoItemsSortOrder_applyChanges() { TodoSettingsListener todoSettingsListener = mock(TodoSettingsListener.class); todoSettings.addTodoSettingsListener(todoSettingsListener); - todoSettings.setTodoItemSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); + todoSettings.setTodoItemsSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); // listener called when property changed verify(todoSettingsListener, times(1)).todoSettingsChanged(todoSettings, TODO_ITEMS_SORT_ORDER_SINGLETON_COLLECTION); todoSettings.applyChanges(); // apply changes not canceled - assertEquals(TodoItemsSortOrder.CHECKED_UNCHECKED, todoSettings.getTodoItemSortOrder()); + assertEquals(TodoItemsSortOrder.CHECKED_UNCHECKED, todoSettings.getTodoItemsSortOrder()); } @Test public void testSetTodoItemsSortOrder_cancelChanges() { TodoSettingsListener todoSettingsListener = mock(TodoSettingsListener.class); todoSettings.addTodoSettingsListener(todoSettingsListener); - todoSettings.setTodoItemSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); + todoSettings.setTodoItemsSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); todoSettings.cancelChanges(); // property change(s) rolled back - assertEquals(TodoItemsSortOrder.NONE, todoSettings.getTodoItemSortOrder()); + assertEquals(TodoItemsSortOrder.NONE, todoSettings.getTodoItemsSortOrder()); } @Test @@ -84,9 +84,9 @@ public class TodoSettingsTest { TodoSettingsListener todoSettingsListener = mock(TodoSettingsListener.class); doThrow(IllegalStateException.class).when(todoSettingsListener).todoSettingsChanged(todoSettings, TODO_ITEMS_SORT_ORDER_SINGLETON_COLLECTION); todoSettings.addTodoSettingsListener(todoSettingsListener); - todoSettings.setTodoItemSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); + todoSettings.setTodoItemsSortOrder(TodoItemsSortOrder.CHECKED_UNCHECKED); // property change rolled back - assertEquals(TodoItemsSortOrder.NONE, todoSettings.getTodoItemSortOrder()); + assertEquals(TodoItemsSortOrder.NONE, todoSettings.getTodoItemsSortOrder()); verify(todoSettingsListener, times(2)).todoSettingsChanged(todoSettings, TODO_ITEMS_SORT_ORDER_SINGLETON_COLLECTION); } } diff --git a/todolist/core/src/test/java/todolist/json/TodoModuleTest.java b/todolist/core/src/test/java/todolist/json/TodoModuleTest.java index 2d67b2e85edf1db7ef63301111a5ba1075c63562..ab70ce624da7dfdcf60f7cd17ab29652484c2730 100644 --- a/todolist/core/src/test/java/todolist/json/TodoModuleTest.java +++ b/todolist/core/src/test/java/todolist/json/TodoModuleTest.java @@ -132,12 +132,12 @@ public class TodoModuleTest { @Test public void testTodoSettings() { TodoSettings settings = new TodoSettings(); - settings.setTodoItemSortOrder(TodoItemsSortOrder.UNCHECKED_CHECKED); + settings.setTodoItemsSortOrder(TodoItemsSortOrder.UNCHECKED_CHECKED); try { String json = mapper.writeValueAsString(settings); assertEquals(defaultTodoSettings.replaceAll("\\s+", ""), mapper.writeValueAsString(settings)); TodoSettings settings2 = mapper.readValue(json, TodoSettings.class); - assertEquals(settings.getTodoItemSortOrder(), settings2.getTodoItemSortOrder()); + assertEquals(settings.getTodoItemsSortOrder(), settings2.getTodoItemsSortOrder()); } catch (JsonProcessingException e) { fail(e.getMessage()); } diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoItemListCellDragHandler.java b/todolist/fxui/src/main/java/todolist/ui/TodoItemListCellDragHandler.java index 1db693735636d187ef8babeb94bf9679cdd548f6..5f6a425e309f89b76d7e48b56fb8b2e56d0c4db2 100644 --- a/todolist/fxui/src/main/java/todolist/ui/TodoItemListCellDragHandler.java +++ b/todolist/fxui/src/main/java/todolist/ui/TodoItemListCellDragHandler.java @@ -8,6 +8,9 @@ import javafx.scene.input.TransferMode; import todolist.core.TodoItem; import todolist.core.TodoList; +/** + * Handles dragging of ListCells in a ListView of TodoItems in a TodoList. + */ public class TodoItemListCellDragHandler { private TodoList todoList; diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoModelController.java b/todolist/fxui/src/main/java/todolist/ui/TodoModelController.java index 980f8934cbb2070b1032093fb661ac524c121183..87b5658683ca951109eab97a0e55d7016f4d83a4 100644 --- a/todolist/fxui/src/main/java/todolist/ui/TodoModelController.java +++ b/todolist/fxui/src/main/java/todolist/ui/TodoModelController.java @@ -15,8 +15,8 @@ import todolist.core.AbstractTodoList; import todolist.core.TodoList; import todolist.core.TodoModel; import todolist.core.TodoSettings; -import todolist.core.TodoSettingsListener; import todolist.core.TodoSettings.TodoItemsSortOrder; +import todolist.core.TodoSettingsListener; import todolist.ui.util.SceneTarget; /** @@ -40,6 +40,12 @@ public class TodoModelController implements TodoSettingsListener { @FXML TodoListController todoListViewController; + /** + * Sets the TodoModelAccess for this controller, + * so data can come from different sources. + * + * @param todoModelAccess the new TodoModelAccess to use + */ public void setTodoModelAccess(TodoModelAccess todoModelAccess) { this.todoModelAccess = todoModelAccess; updateTodoItemsProvider(); @@ -47,6 +53,7 @@ public class TodoModelController implements TodoSettingsListener { todoModelAccess.getTodoSettings().addTodoSettingsListener(this); } + @Override public void todoSettingsChanged(TodoSettings settings, Collection<String> changedProperties) { if (changedProperties.contains(TodoSettings.TODO_ITEM_SORT_ORDER_SETTING)) { updateTodoItemsProvider(); @@ -54,7 +61,7 @@ public class TodoModelController implements TodoSettingsListener { } private void updateTodoItemsProvider() { - TodoItemsSortOrder sortOrder = this.todoModelAccess.getTodoSettings().getTodoItemSortOrder(); + TodoItemsSortOrder sortOrder = this.todoModelAccess.getTodoSettings().getTodoItemsSortOrder(); todoListViewController.setTodoItemsProvider(TodoModel.getSortedTodoItemsProvider(sortOrder)); } diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoSettingsController.java b/todolist/fxui/src/main/java/todolist/ui/TodoSettingsController.java index 6a2cf1abbf6e67a7f3e4a2c67acf440e2915ba82..71452ee23acefc139b04f63b4cbb9e81eb8a48ee 100644 --- a/todolist/fxui/src/main/java/todolist/ui/TodoSettingsController.java +++ b/todolist/fxui/src/main/java/todolist/ui/TodoSettingsController.java @@ -7,6 +7,9 @@ import todolist.core.TodoSettings; import todolist.core.TodoSettings.TodoItemsSortOrder; import todolist.ui.util.SceneTarget; +/** + * Controller for editing TodoSettings. + */ public class TodoSettingsController { private TodoSettings todoSettings = new TodoSettings(); @@ -30,7 +33,7 @@ public class TodoSettingsController { void initialize() { todoItemsSortOrderSelector.setOnAction(actionEvent -> { int ordinal = todoItemsSortOrderSelector.getSelectionModel().getSelectedIndex(); - getTodoSettings().setTodoItemSortOrder(TodoItemsSortOrder.values()[ordinal]); + getTodoSettings().setTodoItemsSortOrder(TodoItemsSortOrder.values()[ordinal]); }); updateView(); } @@ -40,7 +43,7 @@ public class TodoSettingsController { } private void updateView() { - TodoItemsSortOrder sortOrder = getTodoSettings().getTodoItemSortOrder(); + TodoItemsSortOrder sortOrder = getTodoSettings().getTodoItemsSortOrder(); todoItemsSortOrderSelector.getSelectionModel().select(sortOrder.ordinal()); } } \ No newline at end of file diff --git a/todolist/fxui/src/main/java/todolist/ui/util/SceneTarget.java b/todolist/fxui/src/main/java/todolist/ui/util/SceneTarget.java index 15087ae7670268e8e4aba94244fc1074aff03290..2388ae07e84eafa8912052123a2253d9972002fc 100644 --- a/todolist/fxui/src/main/java/todolist/ui/util/SceneTarget.java +++ b/todolist/fxui/src/main/java/todolist/ui/util/SceneTarget.java @@ -6,6 +6,9 @@ import javafx.scene.Scene; import javafx.scene.control.Control; import javafx.stage.Stage; +/** + * Helper class for buttons that transition to a specific scene. + */ public class SceneTarget { private Scene scene; diff --git a/todolist/rest/src/main/java/todolist/restapi/TodoSettingsResource.java b/todolist/rest/src/main/java/todolist/restapi/TodoSettingsResource.java index 19e785b249236c8b1efbe2bae6d982b9182e35d3..b8b02a9d2e65df08cff42c8a33f4c5d30d99b063 100644 --- a/todolist/rest/src/main/java/todolist/restapi/TodoSettingsResource.java +++ b/todolist/rest/src/main/java/todolist/restapi/TodoSettingsResource.java @@ -44,8 +44,7 @@ public class TodoSettingsResource { /** * Replaces the TodoSettings. * - * @param todoSettings the todoSettings to set - * @return true if it was added, false if it replaced + * @param todoSettings the new TodoSettings to use */ @PUT @Consumes(MediaType.APPLICATION_JSON)