/**
* Copyright 2008 Mathias Doenitz, http://lis.to/
*
* This file is part of the lis.to java desktop client. The lis.to java desktop client is free software: you can
* redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* The lis.to java desktop client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with the lis.to java desktop client.
* If not, see http://www.gnu.org/licenses/
*/
package listo.client;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import listo.client.dialogs.BaseDialog;
import listo.client.dialogs.PopupDialog;
import listo.client.model.Task;
import listo.client.model.Tasks;
import listo.client.model.operations.UpdateTasksOp;
import listo.utils.logging.Log;
import listo.utils.types.Cal;
import listo.utils.types.DateTime;
import javax.swing.*;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
@Singleton
public class ReminderRunner implements Runnable, BaseDialog.OkCancelListener<PopupDialog.Model> {
private final ContextManager contextManager;
private final Provider<PopupDialog> popupDialogProvider;
private final AppConfig appConfig;
private final Preferences preferences;
private final Log log;
private final Provider<Formatter> formatterProvider;
private final int pauseDelay;
private final Object popupClosed = new Object();
private Tasks tasks;
private boolean pauseRequested;
@Inject
protected ReminderRunner(ContextManager contextManager, Provider<PopupDialog> popupDialogProvider,
AppConfig appConfig, Preferences preferences, Log log, Executors executors,
Provider<Formatter> formatterProvider) {
this.contextManager = contextManager;
this.popupDialogProvider = popupDialogProvider;
this.appConfig = appConfig;
this.preferences = preferences;
this.log = log;
this.formatterProvider = formatterProvider;
pauseDelay = appConfig.getOnCancelReminderPause() * 60 * 1000;
log.debug("Starting reminder runner");
int delay = appConfig.getReminderCheck();
executors.getReminderExecutor().scheduleWithFixedDelay(this, delay, delay, TimeUnit.SECONDS);
}
// run from the reminder thread
public void run() {
//log.trace("Running reminder check");
DateTime now = new DateTime();
tasks = new Tasks();
for (Task task : contextManager.getCurrentContext().getTasks()) {
if (task.isCompleted() || !task.hasFolders()) continue;
DateTime due = task.getDue();
if (due == null) continue;
Integer reminder = task.getReminder();
if (reminder == null) continue;
DateTime popupTime = new Cal(due).add(Calendar.MINUTE, reminder).getDateTime();
if (popupTime.before(now)) tasks.add(task);
}
if (tasks.isEmpty()) return;
log.debug("%s due tasks found, opening reminder popup");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
PopupDialog dialog = popupDialogProvider.get();
dialog.setOkListener(ReminderRunner.this);
dialog.run(new PopupDialog.Model(tasks, preferences.getDefaultSnoozeTime()));
}
});
// we don't return from this task until the popup dialog is closed or the
// application is shutting down, this way the reminder checking thread is
// "suspended" until the user has taken some action
try {
synchronized (popupClosed) {
popupClosed.wait();
}
// if the user cancelled the popup dialog we don't resume before the pause delay is up
if (pauseRequested) Thread.sleep(pauseDelay);
} catch (InterruptedException e) {
// just quit
}
}
// run from the EDT
public void onOk(PopupDialog.Model model) {
if (model.snoozeTime != null) {
Formatter formatter = formatterProvider.get();
// we need to set the snooze time on the open tasks
for (Task task : tasks) {
if (task.isCompleted() || !task.hasFolders()) continue;
// we use the setReminderString() logic to set the snooze time
task.setReminder(formatter.fromReminderString("++" + model.snoozeTime.toString(), task.getDue()));
UpdateTasksOp op = new UpdateTasksOp();
op.setTasks(task.getId());
op.addField("reminder", Integer.toString(task.getReminder()));
contextManager.addAndRun(op);
}
}
// reactive reminder-checking
pauseRequested = false;
synchronized (popupClosed) {
popupClosed.notify();
}
}
// run from the EDT
public void onCancel(PopupDialog.Model model) {
log.debug("Reminder popup cancelled, disabling reminders for %s minutes", appConfig.getOnCancelReminderPause());
// reactive reminder-checking requesting a pause
pauseRequested = true;
synchronized (popupClosed) {
popupClosed.notify();
}
}
}
|