diff --git a/app/src/main/java/org/cutem/cutecalendar/model/TodoItemUtil.java b/app/src/main/java/org/cutem/cutecalendar/model/TodoItemUtil.java index d9c1c65..9b7b450 100644 --- a/app/src/main/java/org/cutem/cutecalendar/model/TodoItemUtil.java +++ b/app/src/main/java/org/cutem/cutecalendar/model/TodoItemUtil.java @@ -3,6 +3,7 @@ package org.cutem.cutecalendar.model; import org.cutem.cutecalendar.util.CalendarUtil; import org.cutem.cutecalendar.util.GenericPair; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.*; @@ -37,7 +38,10 @@ public class TodoItemUtil { Calendar c2 = item.getEnd(); for (int i = 0; i < repeat; i++) { - result.add(GenericPair.makePair(c1, c2)); + result.add(GenericPair.makePair( + CalendarUtil.roundToMinute(c1), // calendar is mutable + CalendarUtil.roundToMinute(c2) + )); c1.add(Calendar.DAY_OF_MONTH, 7); c2.add(Calendar.DAY_OF_MONTH, 7); } @@ -243,10 +247,12 @@ public class TodoItemUtil { int pType = parent.getType(); int cType = child.getType(); - return pType != cType + + boolean typeConflict = pType != cType && arrayContains(PARENT_CHILDREN_CONFLICT, pType) - && arrayContains(PARENT_CHILDREN_CONFLICT, cType) - && isIn(parent, child); + && arrayContains(PARENT_CHILDREN_CONFLICT, cType); + + return !typeConflict && isIn(parent, child); } // endregion conflict check part @@ -256,7 +262,7 @@ public class TodoItemUtil { public static int getRepeatWeeks(@NotNull TodoItem item) { String repeat = item.getStringProperty(REPEAT_WEEKS); - return repeat == null ? 1 : Integer.parseInt(repeat); + return (repeat == null || repeat.trim().isEmpty()) ? 1 : Integer.parseInt(repeat); } // endregion REPEAT_WEEKS part @@ -379,6 +385,7 @@ public class TodoItemUtil { return factory.wholeDay(Calendar.getInstance()) .stringProperties(TITLE, title) .stringProperties(FINISH, "finish") + .stringProperties(ALARM_METHOD, "none") .build(); } @@ -387,7 +394,11 @@ public class TodoItemUtil { // region alarm part - public static boolean isValidAlarmIntString(@NotNull String interval) { + public static boolean isValidAlarmIntString(@Nullable String interval) { + if (interval == null) { + return false; + } + String[] strSlices = interval.split("[;,]"); for (String s : strSlices) { if (!s.matches("\\d+")) { @@ -397,7 +408,7 @@ public class TodoItemUtil { return true; } - public static int[] parseAlarmInterval(@NotNull String interval) { + private static int[] parseAlarmInterval(@NotNull String interval) { String[] slices = interval.split("[;,]"); int[] fields = new int[slices.length]; for (int i = 0; i < fields.length; i++) { @@ -406,7 +417,7 @@ public class TodoItemUtil { return fields; } - public static Calendar getNextCalendar(@NotNull Calendar old, @NotNull String interval) { + private static Calendar getNextCalendar(@NotNull Calendar old, @NotNull String interval) { Calendar now = Calendar.getInstance(); if (!isValidAlarmIntString(interval)) { throw new IllegalArgumentException("interval is bad formatted"); @@ -423,6 +434,20 @@ public class TodoItemUtil { return newTime; } + public static Calendar calculateNextCalendar(@NotNull TodoItem item, @NotNull Calendar last) { + String interval = item.getStringProperty(TodoItem.ALARM_INTERVAL); + if (!isValidAlarmIntString(interval)) { + return item.getBgn(); + } else { + return TodoItemUtil.getNextCalendar(last, interval); + } + } + + public static Calendar calculateNextCalendar(@NotNull TodoItem item) { + Calendar nxt = TodoItemUtil.getAlarmStartCalendar(item); + return calculateNextCalendar(item, nxt); + } + public static Calendar getAlarmStartCalendar(@NotNull TodoItem item) { String alarmStart = item.getStringProperty(ALARM_START); if (alarmStart != null && CalendarUtil.isValidCalendarString(alarmStart)) { @@ -433,13 +458,16 @@ public class TodoItemUtil { } public static boolean isNeedAlarm(@NotNull TodoItem item) { - String alarmMethod = item.getStringProperty(ALARM_METHOD); + Calendar start = getAlarmStartCalendar(item); + return isNeedNextAlarm(item, start); + } - if (Objects.equals("none", alarmMethod)) { - return false; + public static boolean isNeedNextAlarm(@NotNull TodoItem item, @NotNull Calendar nextAlarm) { + String alarmMethod = item.getStringProperty(ALARM_METHOD); + if (Objects.equals("dialog", alarmMethod) || Objects.equals("area", alarmMethod)) { + return !nextAlarm.after(item.getBgn()); } else { - Calendar start = getAlarmStartCalendar(item); - return !start.after(item.getBgn()); + return false; } } diff --git a/app/src/main/java/org/cutem/cutecalendar/presenter/ListTodoItemsStrategy.java b/app/src/main/java/org/cutem/cutecalendar/presenter/ListTodoItemsStrategy.java index 3e244f0..c13bfff 100644 --- a/app/src/main/java/org/cutem/cutecalendar/presenter/ListTodoItemsStrategy.java +++ b/app/src/main/java/org/cutem/cutecalendar/presenter/ListTodoItemsStrategy.java @@ -6,10 +6,12 @@ import javafx.scene.control.Button; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; import org.cutem.cutecalendar.model.TodoItem; +import org.cutem.cutecalendar.model.TodoItemManager; import org.cutem.cutecalendar.util.CalendarUtil; import org.jetbrains.annotations.NotNull; import java.io.IOException; +import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Objects; @@ -24,6 +26,9 @@ public class ListTodoItemsStrategy extends VBox { private Presenter mPresenter; + private Collection mTodoList = new ArrayList<>(); + private Collection mAlarmList = new ArrayList<>(); + @FXML private VBox timelessList; @FXML @@ -108,9 +113,32 @@ public class ListTodoItemsStrategy extends VBox { mPresenter = presenter; } + + private static Collection refreshList(Collection old) { + ArrayList newListTodoItems = new ArrayList<>(); + + TodoItemManager manager = TodoItemManager.getInstance(); + for (TodoItem i : old) { + TodoItem ni = manager.get(i.getId()); + if (ni != null) { + newListTodoItems.add(ni); + } + } + return newListTodoItems; + } + + public void refreshList() { + Collection newTodoList = refreshList(mTodoList); + listTodoItems(newTodoList); + Collection newAlarm = refreshList(mAlarmList); + listAlarmTodoItems(newAlarm); + } + public void listTodoItems(@NotNull Collection items) { + mTodoList.clear(); searchList.getChildren().clear(); for (TodoItem item : items) { + mTodoList.add(item); String info = pickTodoItem(item); Button btn = new Button(info); btn.setOnAction(e -> onClickTodoItem(item)); @@ -128,6 +156,7 @@ public class ListTodoItemsStrategy extends VBox { } public void listAlarmTodoItems(@NotNull Collection items) { + mAlarmList.clear(); alarmList.getChildren().clear(); for (TodoItem item : items) { String info = item.getTypeName() + ": " + item.getStringProperty(TodoItem.TITLE) @@ -136,7 +165,8 @@ public class ListTodoItemsStrategy extends VBox { String method = item.getStringProperty(TodoItem.ALARM_METHOD); if (Objects.equals(method, "dialog")) { mPresenter.showAlert(0, info); - } else { + } else if (Objects.equals(method, "area")) { + mAlarmList.add(item); Button btn = new Button(info); btn.setOnAction(e -> onClickTodoItem(item)); alarmList.getChildren().add(btn); diff --git a/app/src/main/java/org/cutem/cutecalendar/presenter/Presenter.java b/app/src/main/java/org/cutem/cutecalendar/presenter/Presenter.java index b6e2401..322b414 100644 --- a/app/src/main/java/org/cutem/cutecalendar/presenter/Presenter.java +++ b/app/src/main/java/org/cutem/cutecalendar/presenter/Presenter.java @@ -22,6 +22,7 @@ public abstract class Presenter { private final HolidayManager holidayManager = HolidayManager.getInstance(); + private HashMap mAlarmSet = new HashMap<>(); private Timer mTimer = new Timer(false); @@ -34,17 +35,11 @@ public abstract class Presenter { }; - private static boolean isNeedNextAlarm(@NotNull TodoItem item, @NotNull Calendar nextAlarm) { - return !nextAlarm.after(item.getBgn()); - } private void addAlarm(@NotNull TodoItem item) { if (TodoItemUtil.isNeedAlarm(item)) { - Calendar nxt = TodoItemUtil.getAlarmStartCalendar(item); - String interval = item.getStringProperty(TodoItem.ALARM_INTERVAL); - nxt = TodoItemUtil.getNextCalendar(nxt, interval); - - if (isNeedNextAlarm(item, nxt)) { + Calendar nxt = TodoItemUtil.calculateNextCalendar(item); + if (TodoItemUtil.isNeedNextAlarm(item, nxt)) { mAlarmSet.put(item, nxt); } } @@ -64,10 +59,8 @@ public abstract class Presenter { if (!now.before(old)) { alarms.add(item); - String interval = item.getStringProperty(TodoItem.ALARM_INTERVAL); - Calendar nxt = TodoItemUtil.getNextCalendar(old, interval); - - if (isNeedNextAlarm(item, nxt)) { + Calendar nxt = TodoItemUtil.calculateNextCalendar(item, old); + if (TodoItemUtil.isNeedNextAlarm(item, nxt)) { mAlarmSet.put(item, nxt); } else { removeAlarm(item); @@ -78,6 +71,7 @@ public abstract class Presenter { } + public final void goWork() { manager.load(); for (TodoItem v : manager.getItems()) { @@ -96,6 +90,7 @@ public abstract class Presenter { mTimer.cancel(); } + // region detail part protected void showTodoItemDetail(@NotNull TodoItem item) { @@ -115,6 +110,10 @@ public abstract class Presenter { throw new UnsupportedOperationException("not supported"); } + protected void refreshListTodoItemItems() { + throw new UnsupportedOperationException("not supported"); + } + protected final void listTodoItemDuring(@NotNull Calendar from, @NotNull Calendar to) { listTodoItems(manager.queryTodoItemsDuring(from, to)); } @@ -184,13 +183,15 @@ public abstract class Presenter { paintCalendar(date, days); } - protected final void repaint() { + private void repaint() { paintCalendar(getCalendarShowingDate()); } // endregion calendar part + // region general interfaces + protected final void save() { Thread thread = new Thread(() -> { synchronized (LOCK) { @@ -201,6 +202,11 @@ public abstract class Presenter { thread.start(); } + protected final void refreshAll() { + repaint(); + refreshListTodoItemItems(); + } + protected final void addTodoItem(@NotNull TodoItem... items) { for (TodoItem item : items) { @@ -208,14 +214,14 @@ public abstract class Presenter { addAlarm(item); } save(); - repaint(); + refreshAll(); } protected final void removeTodoItem(@NotNull TodoItem item) { manager.remove(item); removeAlarm(item); save(); - repaint(); + refreshAll(); } protected final void finishTodoItem(@NotNull TodoItem item) { @@ -238,6 +244,7 @@ public abstract class Presenter { protected final void finishTimelessItem(@NotNull String title) { manager.removeTimelessItem(title); + listTimelessItems(manager.getTimelessItems()); TodoItem item = TodoItemUtil.finishTimelessItem(title); addTodoItem(item); } @@ -249,4 +256,6 @@ public abstract class Presenter { alert.show(); } + // endregion general interfaces + } diff --git a/app/src/main/java/org/cutem/cutecalendar/presenter/newitems/NewItemBuilder.java b/app/src/main/java/org/cutem/cutecalendar/presenter/newitems/NewItemBuilder.java index 4e34367..26d845f 100644 --- a/app/src/main/java/org/cutem/cutecalendar/presenter/newitems/NewItemBuilder.java +++ b/app/src/main/java/org/cutem/cutecalendar/presenter/newitems/NewItemBuilder.java @@ -81,6 +81,7 @@ public abstract class NewItemBuilder extends VBox { protected final void showAlert(@NotNull String text) { Alert alert = new Alert(Alert.AlertType.WARNING); alert.setContentText(text); + alert.show(); } protected void loadLayout(@NotNull String location) { diff --git a/app/src/main/java/org/cutem/cutecalendar/presenter/newitems/TimelessTypeBuilder.java b/app/src/main/java/org/cutem/cutecalendar/presenter/newitems/TimelessTypeBuilder.java index baa9310..61f5a2e 100644 --- a/app/src/main/java/org/cutem/cutecalendar/presenter/newitems/TimelessTypeBuilder.java +++ b/app/src/main/java/org/cutem/cutecalendar/presenter/newitems/TimelessTypeBuilder.java @@ -43,7 +43,7 @@ public class TimelessTypeBuilder extends NewItemBuilder { @Override public @Nullable Object[] buildItem() { - String title = titleText.getText(); + String title = titleText.getText().trim(); if (title.isEmpty()) { showAlert("描述还没有填"); diff --git a/app/src/test/java/org/cutem/MainTest.java b/app/src/test/java/org/cutem/MainTest.java index 859d72e..3c25a0b 100644 --- a/app/src/test/java/org/cutem/MainTest.java +++ b/app/src/test/java/org/cutem/MainTest.java @@ -106,6 +106,11 @@ public class MainTest extends Application { listStrategy.listTodoItems(items); } + @Override + protected void refreshListTodoItemItems() { + listStrategy.refreshList(); + } + @Override protected void listTimelessItems(@NotNull Collection items) { listStrategy.listTimelessItems(items);