Author: echatellier
Date: 2009-11-16 10:21:54 +0100 (Mon, 16 Nov 2009)
New Revision: 2694
Added:
trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/appointment-new.png
Removed:
trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/alert.png
Modified:
trunk/src/main/java/org/chorem/jtimer/ui/tasks/IdleDialog.java
trunk/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java
trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog.properties
trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog_fr.properties
Log:
Affichage de la dur?\195?\169e d'inactivit?\195?\169
Modified: trunk/src/main/java/org/chorem/jtimer/ui/tasks/IdleDialog.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/ui/tasks/IdleDialog.java 2009-11-16 09:19:51 UTC (rev 2693)
+++ trunk/src/main/java/org/chorem/jtimer/ui/tasks/IdleDialog.java 2009-11-16 09:21:54 UTC (rev 2694)
@@ -22,15 +22,18 @@
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
+import java.util.Timer;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
-import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
+import javax.swing.SwingConstants;
+import javax.swing.WindowConstants;
+import org.apache.commons.lang.time.DurationFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.chorem.jtimer.JTimerFactory;
@@ -41,7 +44,7 @@
import org.jdesktop.application.SingleFrameApplication;
/**
- * Idle dialog showed to user when idle has been detected.
+ * Modal idle dialog showed to user when idle has been detected.
*
* Composed of an unique blocking show method.
*
@@ -66,23 +69,42 @@
/** log */
private static Log log = LogFactory.getLog(IdleDialog.class);
+ /** Mutex object (multiples running tasks are waiting on it) */
+ protected static Object mutex = new Object();
+
+ /** Singleton dialog instance. */
+ protected static IdleDialog idleDialog;
+
+ /** Resume option. */
+ protected static int lastResumeOption;
+
+ /** Parent application. */
protected SingleFrameApplication application;
+ /** I18N resource map. */
protected ResourceMap resourceMap;
-
- protected static IdleDialog mutex;
- protected static int lastResumeOption;
+ /** Timer (for idle duration scheduling). */
+ protected Timer timer;
+ /** Current Idle duration refresh task. */
+ protected UpdateIdleTime updateIdleTime;
+
+ /** Timestamp when idle starts. */
+ protected long idleStartTimestamp;
+
+ /** Duration label. */
protected JLabel idleDurationLabel;
- /** Option after idle detect */
+ /** Revert option after idle detect. */
public static final int REVERT = 0;
- /** Option after idle detect */
+
+ /** Continue option after idle detect. */
public static final int CONTINUE = 1;
- /** Option after idle detect */
+
+ /** Resume option after idle detect. */
public static final int RESUME = 2;
-
+
/**
* IdleDialog constructor.
*
@@ -91,23 +113,28 @@
* @param parent parent application
*/
protected IdleDialog(SingleFrameApplication application) {
- super(application.getMainFrame());
-
+ // don't make reference on other parent
+ // windows, cause idle to unlock some task
+ // if parent window is hidden by systray
+ super();
+
// init resources map
this.application = application;
ApplicationContext ctxt = application.getContext();
ResourceManager mgr = ctxt.getResourceManager();
resourceMap = mgr.getResourceMap(IdleDialog.class);
-
- //setName("idleFrame");
+
+ setName("idleFrame");
setTitle(resourceMap.getString("idleTitle"));
setResizable(false);
-
- // TODO : must be modal , but break mecanism
- //setModal(true);
-
- getRootPane().setLayout(new BorderLayout(1,1));
+ setModal(true);
+ setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+
+ getRootPane().setLayout(new BorderLayout(1, 1));
getRootPane().add(getMainComponent(), BorderLayout.CENTER);
+
+ // timer
+ timer = new Timer();
}
/**
@@ -121,103 +148,117 @@
// label
JLabel idleIcon = new JLabel(resourceMap.getIcon("idleIcon"));
mainComponent.add(idleIcon, new GridBagConstraints(0, 0, 1, 5, 0, 1,
- GridBagConstraints.NORTH, GridBagConstraints.NONE,
- new Insets(10, 10, 10, 10), 0, 0));
-
+ GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(
+ 10, 5, 10, 10), 0, 0));
+
// label
- JLabel idleLabel = new JLabel(resourceMap.getString("idleMessage",
- Long.valueOf(JTimerFactory.getIdleTime() / (60 * 1000))));
+ JLabel idleLabel = new JLabel(resourceMap.getString("idleMessage", Long
+ .valueOf(JTimerFactory.getIdleTime() / (60 * 1000))));
mainComponent.add(idleLabel, new GridBagConstraints(1, 0, 3, 1, 1, 0,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
new Insets(5, 0, 0, 3), 0, 0));
idleDurationLabel = new JLabel(" ");
- mainComponent.add(idleDurationLabel, new GridBagConstraints(1, 1, 3, 1, 1, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(5, 0, 5, 5), 0, 0));
-
+ mainComponent.add(idleDurationLabel, new GridBagConstraints(1, 1, 3, 1,
+ 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(5, 0, 3, 5), 0, 0));
+
// separator
- mainComponent.add(new JSeparator(), new GridBagConstraints(1, 2, 3, 1, 1, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ mainComponent.add(new JSeparator(), new GridBagConstraints(1, 2, 3, 1,
+ 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 5), 0, 0));
-
+
// label
JLabel idleRestart = new JLabel(resourceMap.getString("idleRestart"));
mainComponent.add(idleRestart, new GridBagConstraints(1, 3, 3, 1, 1, 0,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(5, 0, 0, 3), 0, 0));
-
+ new Insets(3, 0, 0, 5), 0, 0));
+
JButton revertButton = new JButton();
- revertButton.setHorizontalAlignment(JLabel.LEFT);
- revertButton.setAction(application.getContext().getActionMap(this).get("chooseRevertOption"));
- mainComponent.add(revertButton, new GridBagConstraints(1, 4, 1, 1, 1, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(5, 0, 5, 5), 0, 0));
+ revertButton.setHorizontalAlignment(SwingConstants.LEFT);
+ revertButton.setAction(application.getContext().getActionMap(this).get(
+ "chooseRevertOption"));
+ mainComponent.add(revertButton, new GridBagConstraints(1, 4, 1, 1, 1,
+ 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(3, 0, 5, 5), 0, 0));
JButton continueButton = new JButton();
- continueButton.setHorizontalAlignment(JLabel.LEFT);
- continueButton.setAction(application.getContext().getActionMap(this).get("chooseContinueOption"));
- mainComponent.add(continueButton, new GridBagConstraints(2, 4, 1, 1, 1, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(5, 0, 5, 5), 0, 0));
+ continueButton.setHorizontalAlignment(SwingConstants.LEFT);
+ continueButton.setAction(application.getContext().getActionMap(this)
+ .get("chooseContinueOption"));
+ mainComponent.add(continueButton, new GridBagConstraints(2, 4, 1, 1, 1,
+ 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(3, 0, 5, 5), 0, 0));
JButton resumeButton = new JButton();
- resumeButton.setHorizontalAlignment(JLabel.LEFT);
- resumeButton.setAction(application.getContext().getActionMap(this).get("chooseResumeOption"));
- mainComponent.add(resumeButton, new GridBagConstraints(3, 4, 1, 1, 1, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(5, 0, 5, 5), 0, 0));
+ resumeButton.setHorizontalAlignment(SwingConstants.LEFT);
+ resumeButton.setAction(application.getContext().getActionMap(this).get(
+ "chooseResumeOption"));
+ mainComponent.add(resumeButton, new GridBagConstraints(3, 4, 1, 1, 1,
+ 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(3, 0, 5, 5), 0, 0));
return mainComponent;
}
- public void run () {
- idleDurationLabel.setText(resourceMap.getString("idleDuration",
- Long.valueOf(JTimerFactory.getIdleTime() / (60 * 1000))));
- }
/**
- * Init dialog mutex instance.
+ * Init dialog idleDialog instance.
*
* @param parent parent reference
*/
public static void init(SingleFrameApplication parent) {
- mutex = new IdleDialog(parent);
+ idleDialog = new IdleDialog(parent);
}
+ /**
+ * Revert button action.
+ */
@Action
public void chooseRevertOption() {
lastResumeOption = REVERT;
idleEnded();
}
+ /**
+ * Continue button action.
+ */
@Action
public void chooseContinueOption() {
lastResumeOption = CONTINUE;
idleEnded();
}
-
+
+ /**
+ * Resume button action.
+ */
@Action
public void chooseResumeOption() {
lastResumeOption = RESUME;
idleEnded();
}
+ /**
+ * Unblock all waiting threads on {@link #mutex}.
+ */
protected void idleEnded() {
- synchronized(this) {
- notifyAll();
+ synchronized (mutex) {
+ mutex.notifyAll();
}
setVisible(false);
}
- protected synchronized void waitForIdleEnd() {
- try {
- wait();
- log.debug("Thread unwaiting");
- } catch (InterruptedException e) {
- if (log.isErrorEnabled()) {
- log.error("Thread inturrupted", e);
- }
+ @Override
+ public void setVisible(boolean b) {
+
+ if (b) {
+ updateIdleTime = new UpdateIdleTime();
+ timer.schedule(updateIdleTime, 0, 1000 * 60 /* every minutes */);
+ } else {
+ updateIdleTime.cancel();
+ timer.purge();
}
+
+ super.setVisible(b);
}
/**
@@ -226,19 +267,55 @@
* This function is thread safe and show only one dialog even if
* function is called multiples times.
*
- * @param lastActivityTimestamp
+ * @param idleStartTimestamp time stamp when idle start
* @return idle option
*/
- public static int showIdleDialog(long lastActivityTimestamp) {
- //synchronized(mutex) {
- if (!mutex.isVisible()) {
- mutex.application.show(mutex);
- mutex.run();
+ public static int showIdleDialog(long idleStartTimestamp) {
+
+ // only the first call must display dialog
+ // (can happen if multiples task are running)
+ boolean mustShow = false;
+ synchronized (idleDialog) {
+ mustShow = !idleDialog.isVisible();
+ }
+
+ // the first frame will be blocked by show modal
+ // blocking status...
+ if (mustShow) {
+ idleDialog.idleStartTimestamp = idleStartTimestamp;
+ idleDialog.application.show(idleDialog);
+ } else {
+ // ...the others by wait();
+ synchronized (mutex) {
+ try {
+ mutex.wait();
+ } catch (InterruptedException e) {
+ if (log.isErrorEnabled()) {
+ log.error("Thread inturrupted", e);
+ }
+ }
}
- //}
+ }
- mutex.waitForIdleEnd();
-
return lastResumeOption;
}
+
+ /**
+ * Task to update idle time duration while dialog is showed.
+ */
+ protected class UpdateIdleTime extends java.util.TimerTask {
+
+ /*
+ * @see java.util.TimerTask#run()
+ */
+ @Override
+ public void run() {
+ if (log.isDebugEnabled()) {
+ log.debug("Update idle duration");
+ }
+ String duration = DurationFormatUtils.formatDuration(
+ System.currentTimeMillis() - idleStartTimestamp, "HH:mm");
+ idleDurationLabel.setText(resourceMap.getString("idleDuration", duration));
+ }
+ }
}
Modified: trunk/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java 2009-11-16 09:19:51 UTC (rev 2693)
+++ trunk/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java 2009-11-16 09:21:54 UTC (rev 2694)
@@ -104,7 +104,7 @@
TimerDataManager dataManager) {
super(parentApp);
this.parentApp = parentApp;
-
+
// init with False
bWantToStop = Boolean.FALSE;
@@ -140,10 +140,11 @@
Date now = new Date();
// check alert to be fired
for (TimerAlert alert : task.getAlerts()) {
- if (alert.getType().equals(Type.REACH_DAILY_TIME) && TimerTaskHelper.getTotalTime(task, now) > alert.getDuration()) {
+ if (alert.getType().equals(Type.REACH_DAILY_TIME)
+ && TimerTaskHelper.getTotalTime(task, now) > alert.getDuration()) {
alreadyTrownAlerts.add(alert.clone());
- }
- else if (alert.getType().equals(Type.REACH_TOTAL_TIME) && TimerTaskHelper.getAllTotalTime(task) > alert.getDuration()) {
+ } else if (alert.getType().equals(Type.REACH_TOTAL_TIME)
+ && TimerTaskHelper.getAllTotalTime(task) > alert.getDuration()) {
alreadyTrownAlerts.add(alert.clone());
}
}
@@ -153,7 +154,7 @@
if (task.getParent() != null) {
checkAlreadyThrownAlerts(task.getParent());
}
-
+
}
/**
@@ -282,17 +283,15 @@
// idle detected
// update time without idle time
offsetTimeInMs -= configIdleTime;
- publish(taskTimingBeforeStartInMs + loopTimestamp
- - taskStartCalendar.getTimeInMillis() + offsetTimeInMs);
+ publish(taskTimingBeforeStartInMs + loopTimestamp - taskStartCalendar.getTimeInMillis() + offsetTimeInMs);
// parent application
JTimer parentApplication = (JTimer)getApplication();
-
+
// send idle detect event
parentApplication.preIdleDetect();
// ask user what to do
- //int option = ((JTimer) getApplication()).askIdleOption();
- int option = IdleDialog.showIdleDialog(lastPublishTimestamp);
+ int option = IdleDialog.showIdleDialog(loopTimestamp - idleTime);
// send idle detect event
parentApplication.postIdleDetect();
@@ -356,8 +355,9 @@
// for example, if UI lag...
long currentDuration = durations.get(durations.size() - 1);
- dataManager.changeTaskTime(managedTask, new Date(), currentDuration / 1000);
-
+ dataManager.changeTaskTime(managedTask, new Date(),
+ currentDuration / 1000);
+
checkTaskAlerts(managedTask);
}
@@ -368,25 +368,22 @@
*/
protected void checkTaskAlerts(TimerTask task) {
Date now = new Date();
-
+
// check alert to be fired
for (TimerAlert alert : task.getAlerts()) {
if (!alreadyTrownAlerts.contains(alert)) {
- if (alert.getType().equals(Type.REACH_DAILY_TIME) && TimerTaskHelper.getTotalTime(task, now) >= alert.getDuration()) {
- //String alertMessage = "Task '%s' has reached %s for current day !";
- //displayAlert(String.format(alertMessage, task.getName(), DurationFormatUtils.formatDuration(alert.getDuration() * 1000, "HH:mm:ss")));
+ if (alert.getType().equals(Type.REACH_DAILY_TIME)
+ && TimerTaskHelper.getTotalTime(task, now) >= alert.getDuration()) {
displayAlert(task, Type.REACH_DAILY_TIME, alert.getDuration());
alreadyTrownAlerts.add(alert.clone());
- }
- else if (alert.getType().equals(Type.REACH_TOTAL_TIME) && TimerTaskHelper.getAllTotalTime(task) >= alert.getDuration()) {
- //String alertMessage = "Task '%s' has reached %s !";
- //displayAlert(String.format(alertMessage, task.getName(), DurationFormatUtils.formatDuration(alert.getDuration() * 1000, "HH:mm:ss")));
+ } else if (alert.getType().equals(Type.REACH_TOTAL_TIME)
+ && TimerTaskHelper.getAllTotalTime(task) >= alert.getDuration()) {
displayAlert(task, Type.REACH_TOTAL_TIME, alert.getDuration());
alreadyTrownAlerts.add(alert.clone());
}
}
}
-
+
// lance aussi les alertes sur les taches parentes
// par exemple, si une tache passe en temps journaliers a 1h
// sont parent y passe aussi, donc les alertes doivent être levée.
@@ -400,21 +397,24 @@
*
* @param alertMessage alert message
*/
- protected void displayAlert(final TimerTask task, final Type alertType, final long alertDuration) {
+ protected void displayAlert(final TimerTask task, final Type alertType,
+ final long alertDuration) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
String alertMessage = null;
String formattedTime = DurationFormatUtils.formatDuration(alertDuration * 1000, "HH:mm:ss");
if (Type.REACH_DAILY_TIME.equals(alertType)) {
- alertMessage = getResourceMap().getString("alert.dailyAlertMessage", task.getName(), formattedTime);
+ alertMessage = getResourceMap().getString(
+ "alert.dailyAlertMessage", task.getName(), formattedTime);
+ } else if (Type.REACH_TOTAL_TIME.equals(alertType)) {
+ alertMessage = getResourceMap().getString(
+ "alert.totalAlertMessage", task.getName(), formattedTime);
}
- else if (Type.REACH_TOTAL_TIME.equals(alertType)) {
- alertMessage = getResourceMap().getString("alert.totalAlertMessage", task.getName(), formattedTime);
- }
-
+
JOptionPane.showMessageDialog(null, alertMessage,
- getResourceMap().getString("alert.title"), JOptionPane.INFORMATION_MESSAGE,
- getResourceMap().getIcon("alert.alertIcon"));
+ getResourceMap().getString("alert.title"),
+ JOptionPane.INFORMATION_MESSAGE, getResourceMap()
+ .getIcon("alert.alertIcon"));
}
});
}
Modified: trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog.properties
===================================================================
--- trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog.properties 2009-11-16 09:19:51 UTC (rev 2693)
+++ trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog.properties 2009-11-16 09:21:54 UTC (rev 2694)
@@ -1,9 +1,9 @@
# idle i18n
idleTitle = Idle detect
-idleIcon = alert.png
+idleIcon = appointment-new.png
idleMessage = You have been idle for %d minutes.
idleRestart = Choose restart option :
-idleDuration = Idle duration : %s
+idleDuration = Idle duration : %s.
chooseRevertOption.Action.text=Stop
chooseRevertOption.Action.shortDescription=Stop task without counting elapsed time
Modified: trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog_fr.properties
===================================================================
--- trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog_fr.properties 2009-11-16 09:19:51 UTC (rev 2693)
+++ trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/IdleDialog_fr.properties 2009-11-16 09:21:54 UTC (rev 2694)
@@ -2,7 +2,7 @@
idleTitle = Inactivit\u00E9 d\u00E9tect\u00E9e
idleMessage = Vous avez \u00E9t\u00E9 inactif pendant %d minutes.
idleRestart = Choisissez une option :
-idleDuration = Dur\u00E9e d'inactivit\u00E9 : %s
+idleDuration = Dur\u00E9e de l'inactivit\u00E9 : %s.
chooseRevertOption.Action.text=Stopper
chooseRevertOption.Action.shortDescription=Annuler le temps \u00E9coul\u00E9 et stopper la t\u00E2che
Deleted: trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/alert.png
===================================================================
(Binary files differ)
Added: trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/appointment-new.png
===================================================================
(Binary files differ)
Property changes on: trunk/src/main/resources/org/chorem/jtimer/ui/tasks/resources/appointment-new.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream