Jtimer-commits
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
March 2012
- 2 participants
- 47 discussions
r2842 - in branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer: . data entities io ui ui/alert ui/report ui/tasks ui/treetable ui/widget
by echatellier@users.chorem.org 27 Mar '12
by echatellier@users.chorem.org 27 Mar '12
27 Mar '12
Author: echatellier
Date: 2012-03-27 11:35:07 +0200 (Tue, 27 Mar 2012)
New Revision: 2842
Url: http://chorem.org/repositories/revision/jtimer/2842
Log:
Move internal task storage from seconds to milli-seconds for new time tracking algorithm
Modified:
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/JTimer.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/data/TimerDataManager.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/entities/TimerAlert.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/entities/TimerTask.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/StatusBar.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/alert/AlertTableModel.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report/ReportUtils.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/widget/DurationEditor.java
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/JTimer.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/JTimer.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/JTimer.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -937,7 +937,7 @@
*/
@Action(enabledProperty = "selectedSingleTask")
public void increment5Task() {
- incrementTaskTime(5 * 60);
+ incrementTaskTime(5 * 60000);
}
/**
@@ -945,7 +945,7 @@
*/
@Action(enabledProperty = "selectedSingleTask")
public void increment30Task() {
- incrementTaskTime(30 * 60);
+ incrementTaskTime(30 * 60000);
}
/**
@@ -953,7 +953,7 @@
*/
@Action(enabledProperty = "selectedSingleTask")
public void decrement1Task() {
- incrementTaskTime(-60);
+ incrementTaskTime(-60000);
}
/**
@@ -961,7 +961,7 @@
*/
@Action(enabledProperty = "selectedSingleTask")
public void decrement5Task() {
- incrementTaskTime(-5 * 60);
+ incrementTaskTime(-5 * 60000);
}
/**
@@ -969,7 +969,7 @@
*/
@Action(enabledProperty = "selectedSingleTask")
public void decrement30Task() {
- incrementTaskTime(-30 * 60);
+ incrementTaskTime(-30 * 60000);
}
/**
@@ -977,7 +977,7 @@
*/
@Action(enabledProperty = "selectedSingleTask")
public void increment1Task() {
- incrementTaskTime(60);
+ incrementTaskTime(60000);
}
/**
@@ -985,37 +985,29 @@
*
* To decrement, set negative increment:)
*
- * @param increment increment in seconds
+ * @param increment increment in ms
*/
protected void incrementTaskTime(long increment) {
TimerTask selectedTask = projectsAndTasksTable.getSelectedTasks()
.get(0);
- // check if task is running
- RunTaskJob job = getJobForRunningTask(selectedTask);
- if (job != null) {
- // task is running
- // increment is in seconds !!!
- job.incrementTaskTime(increment * 1000);
- } else {
- // task is not running
- Date now = new Date();
- long todayTime = selectedTask.getTime(now);
+ // task is not running
+ Date now = new Date();
+ long todayTime = selectedTask.getTime(now);
- long newTodayTime = todayTime + increment;
+ long newTodayTime = todayTime + increment;
- try {
- // check if + negative increment still positive
- if (newTodayTime > 0) {
- core.getData().changeTaskTime(selectedTask, now,
- newTodayTime);
- } else {
- // force to 0
- core.getData().changeTaskTime(selectedTask, now, 0L);
- }
- } catch (DataViolationException e) {
- displayErrorMessage(e.getExceptionKey());
+ try {
+ // check if + negative increment still positive
+ if (newTodayTime > 0) {
+ core.getData().changeTaskTime(selectedTask, now,
+ newTodayTime);
+ } else {
+ // force to 0
+ core.getData().changeTaskTime(selectedTask, now, 0L);
}
+ } catch (DataViolationException e) {
+ displayErrorMessage(e.getExceptionKey());
}
}
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/data/TimerDataManager.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/data/TimerDataManager.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/data/TimerDataManager.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -189,7 +189,7 @@
*
* @param task the task to change time
* @param date date to change time
- * @param value new time in seconds
+ * @param value new time in ms
*/
public synchronized void changeTaskTime(TimerTask task, Date date,
long value) {
@@ -429,18 +429,18 @@
while (itDataEventListener.hasNext()) {
itDataEventListener.next().preMergeTasks(destinationTask, otherTasks);
}
-
+
for (TimerTask otherTask : otherTasks) {
mergeTwoTasks(destinationTask, otherTask);
}
-
+
// send post notification
itDataEventListener = dataEventListeners.iterator();
while (itDataEventListener.hasNext()) {
itDataEventListener.next().postMergeTasks(destinationTask, otherTasks);
}
}
-
+
/**
* Merge two task together.
*
@@ -454,7 +454,7 @@
}
// task is modified during merge, deep clone it
-
+
// make sub task list copy (concurrency)
Collection<TimerTask> otherTaskSubTasks = new ArrayList<TimerTask>(otherTask.getSubTasks());
for (TimerTask otherTaskSubTask : otherTaskSubTasks) {
@@ -467,7 +467,7 @@
sameTaskNameTask = destSubTask;
}
}
-
+
// no similar task found
if (sameTaskNameTask == null) {
if (log.isDebugEnabled()) {
@@ -488,14 +488,14 @@
// TODO possible bug here, task times may not be saved
}
}
-
+
// copy otherTask times to current task
for (Entry<Date, Long> times : otherTask.getAllDaysAndTimes().entrySet()) {
Long currentDuration = destinationTask.getTime(times.getKey());
currentDuration += times.getValue();
destinationTask.setTime(times.getKey(), currentDuration);
}
-
+
// copy annotations
for (Entry<Date, String> note : otherTask.getAllDaysAnnotations().entrySet()) {
Date noteKey = note.getKey();
@@ -513,17 +513,17 @@
}
destinationTask.addAnnotation(noteKey, note.getValue());
}
-
+
// copy alerts
for (TimerAlert alert : otherTask.getAlerts()) {
destinationTask.addAlert(alert);
}
-
+
// finally otherTask still exist
// empty, but still exist
deleteTask(otherTask);
}
-
+
/**
* Add annotation on task for specified calendar, and send event.
*
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/entities/TimerAlert.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/entities/TimerAlert.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/entities/TimerAlert.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -52,7 +52,7 @@
/** Alert type. */
protected Type type;
- /** Alert duration. (in seconds) */
+ /** Alert duration. (in ms) */
protected long duration;
/**
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/entities/TimerTask.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/entities/TimerTask.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/entities/TimerTask.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -72,7 +72,7 @@
protected TimerTask parent;
/**
- * Map calendar of day -> time. (ordered on keys)
+ * Map calendar of day -> time (ms). (ordered on keys)
*/
protected SortedMap<Date, Long> allDaysTimes;
@@ -240,20 +240,18 @@
/**
* Add time.
*
- * Calendar will be forced to 0h00:00.000
- *
* @param date date
- * @param seconds seconds
+ * @param time time in ms
*/
- public void setTime(Date date, Long seconds) {
- allDaysTimes.put(date, seconds);
+ public void setTime(Date date, Long time) {
+ allDaysTimes.put(date, time);
}
/**
* Get time at date.
*
* @param date date
- * @return time at specified date
+ * @return time at specified date in ms
*/
public long getTime(Date date) {
long result = 0;
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -512,7 +512,7 @@
try {
Date keyDate = GTimerTimeUtil.yyyyMMdd2Date(sKey);
String timeString = (String) prop.get(sKey);
- t.setTime(keyDate, Long.valueOf(timeString));
+ t.setTime(keyDate, Long.valueOf(timeString) * 1000);
} catch (NumberFormatException e) {
if (log.isErrorEnabled()) {
log.error("Can't convert " + prop.get(sKey)
@@ -642,12 +642,12 @@
try {
if ("reachtotaltime".equals(alertType)) {
- Long duration = Long.parseLong(alertDuration);
+ Long duration = Long.parseLong(alertDuration) * 1000;
TimerAlert alert = new TimerAlert(
TimerAlert.Type.REACH_TOTAL_TIME, duration);
task.addAlert(alert);
} else if ("reachdailytime".equals(alertType)) {
- Long duration = Long.parseLong(alertDuration);
+ Long duration = Long.parseLong(alertDuration) * 1000;
TimerAlert alert = new TimerAlert(
TimerAlert.Type.REACH_DAILY_TIME, duration);
task.addAlert(alert);
@@ -1004,9 +1004,9 @@
for (Entry<Date, Long> entry : task.getAllDaysAndTimes().entrySet()) {
Date date = entry.getKey();
+ long value = entry.getValue() / 1000;
String gtimerDate = GTimerTimeUtil.date2yyyyMMdd(date);
-
- out.write(gtimerDate + " " + entry.getValue() + "\n");
+ out.write(gtimerDate + " " + value + "\n");
}
out.close();
@@ -1104,7 +1104,7 @@
for (TimerAlert alert : task.getAlerts()) {
Type type = alert.getType();
- long duration = alert.getDuration();
+ long duration = alert.getDuration() / 1000;
switch (type) {
case REACH_DAILY_TIME:
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/StatusBar.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/StatusBar.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/StatusBar.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -118,7 +118,7 @@
}
lblTime.setText(resourceMap
.getString("todayTotalMessage", DurationFormatUtils
- .formatDuration(duration * 1000, "HH:mm:ss")));
+ .formatDuration(duration, "HH:mm:ss")));
}
/*
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -574,7 +574,7 @@
long time = cloneTask.getTime(date);
Calendar cal = Calendar.getInstance();
// FIXME me, not use a calendar here !
- cal.setTimeInMillis(time * 1000 - cal.get(Calendar.ZONE_OFFSET));
+ cal.setTimeInMillis(time - cal.get(Calendar.ZONE_OFFSET));
spinnerH.setValue(cal.get(Calendar.HOUR_OF_DAY));
spinnerM.setValue(cal.get(Calendar.MINUTE));
@@ -629,7 +629,7 @@
long seconds = ((Integer) spinnerH.getValue() * 60 * 60)
+ ((Integer) spinnerM.getValue() * 60)
+ ((Integer) spinnerS.getValue());
- cloneTask.setTime(getSelectedDay().getTime(), seconds);
+ cloneTask.setTime(getSelectedDay().getTime(), seconds * 1000);
// annotation
if (isAnnotationChanged) {
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/alert/AlertTableModel.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/alert/AlertTableModel.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/alert/AlertTableModel.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -105,7 +105,7 @@
break;
case 1:
- result = alert.getDuration();
+ result = alert.getDuration() / 1000;
break;
default:
@@ -130,7 +130,7 @@
case 1:
long duration = ((Long)value).longValue();
- alert.setDuration(duration);
+ alert.setDuration(duration * 1000);
break;
default:
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report/ReportUtils.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report/ReportUtils.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report/ReportUtils.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -402,8 +402,7 @@
* @return formated duration
*/
public String formatDuration(long duration) {
- String result = DurationFormatUtils.formatDuration(duration * 1000,
- "HH:mm:ss");
+ String result = DurationFormatUtils.formatDuration(duration, "HH:mm:ss");
return result;
}
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -338,8 +338,7 @@
currentDuration = 0;
}
- dataManager.changeTaskTime(managedTask, new Date(),
- currentDuration / 1000);
+ dataManager.changeTaskTime(managedTask, new Date(), currentDuration);
checkTaskAlerts(managedTask);
}
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/treetable/ProjectsAndTasksModel.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -155,11 +155,11 @@
break;
case 1:
value = DurationFormatUtils.formatDuration(TimerTaskHelper
- .getTotalTime(task, new Date()) * 1000, "HH:mm:ss");
+ .getTotalTime(task, new Date()), "HH:mm:ss");
break;
case 2:
value = DurationFormatUtils.formatDuration(TimerTaskHelper
- .getAllTotalTime(task) * 1000, "HH:mm:ss");
+ .getAllTotalTime(task), "HH:mm:ss");
break;
}
} else {
Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/widget/DurationEditor.java
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/widget/DurationEditor.java 2012-03-26 13:00:47 UTC (rev 2841)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/widget/DurationEditor.java 2012-03-27 09:35:07 UTC (rev 2842)
@@ -68,7 +68,7 @@
/** Second spinner model. */
protected SpinnerNumberModel secondSpinnerModel;
- /** Duration. */
+ /** Duration (in ms). */
protected long duration;
/**
1
0
Author: fdesbois
Date: 2012-03-26 15:00:47 +0200 (Mon, 26 Mar 2012)
New Revision: 2841
Url: http://chorem.org/repositories/revision/jtimer/2841
Log:
Use last mavenpom version 3.2
Modified:
trunk/pom.xml
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2012-03-25 21:15:46 UTC (rev 2840)
+++ trunk/pom.xml 2012-03-26 13:00:47 UTC (rev 2841)
@@ -5,7 +5,7 @@
<parent>
<groupId>org.nuiton</groupId>
<artifactId>mavenpom4redmine</artifactId>
- <version>3.1</version>
+ <version>3.2</version>
</parent>
<groupId>org.chorem</groupId>
1
0
r2840 - in branches: . 1.4.0-ttalgo/src/main/java/org/chorem/jtimer 1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report 1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks
by echatellier@users.chorem.org 25 Mar '12
by echatellier@users.chorem.org 25 Mar '12
25 Mar '12
Author: echatellier
Date: 2012-03-25 23:15:46 +0200 (Sun, 25 Mar 2012)
New Revision: 2840
Url: http://chorem.org/repositories/revision/jtimer/2840
Log:
Add branche for new time tracking algorithm.
refs #13, #282, #492
Added:
branches/1.4.0-ttalgo/
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/JTimer.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report/ReportView.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java
Removed:
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/JTimer.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report/ReportView.java
branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java
Deleted: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/JTimer.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/JTimer.java 2012-03-23 15:11:54 UTC (rev 2836)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/JTimer.java 2012-03-25 21:15:46 UTC (rev 2840)
@@ -1,1458 +0,0 @@
-/*
- * #%L
- * jTimer
- *
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2007 - 2012 CodeLutin, Chatellier Eric
- * %%
- * This program 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.
- *
- * This program 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 this program. If not, see
- * <http://www.gnu.org/licenses/gpl-3.0.html>.
- * #L%
- */
-
-package org.chorem.jtimer;
-
-import java.awt.BorderLayout;
-import java.awt.Dimension;
-import java.awt.event.ActionEvent;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.io.File;
-import java.io.IOException;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-import java.util.Timer;
-
-import javax.swing.ButtonGroup;
-import javax.swing.InputMap;
-import javax.swing.JButton;
-import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JComponent;
-import javax.swing.JFrame;
-import javax.swing.JMenu;
-import javax.swing.JMenuBar;
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JPopupMenu;
-import javax.swing.JRadioButtonMenuItem;
-import javax.swing.JScrollPane;
-import javax.swing.JSeparator;
-import javax.swing.JToolBar;
-import javax.swing.KeyStroke;
-import javax.swing.ListSelectionModel;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.TreePath;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.chorem.jtimer.data.DataViolationException;
-import org.chorem.jtimer.data.TimerCore;
-import org.chorem.jtimer.entities.TimerProject;
-import org.chorem.jtimer.entities.TimerTask;
-import org.chorem.jtimer.ui.HelpFrame;
-import org.chorem.jtimer.ui.StatusBar;
-import org.chorem.jtimer.ui.TimerTaskEditor;
-import org.chorem.jtimer.ui.alert.AlertEditor;
-import org.chorem.jtimer.ui.report.ReportView;
-import org.chorem.jtimer.ui.systray.SystrayManager;
-import org.chorem.jtimer.ui.tasks.IdleDialog;
-import org.chorem.jtimer.ui.tasks.RefreshTreeTask;
-import org.chorem.jtimer.ui.tasks.RunTaskJob;
-import org.chorem.jtimer.ui.treetable.ProjectsAndTasksTable;
-import org.chorem.jtimer.ui.widget.WindowProperty2;
-import org.chorem.jtimer.ui.ws.SwingConnectionInformationHandler;
-import org.chorem.jtimer.ws.ConnectionDataHandler;
-import org.chorem.jtimer.ws.ProjectManagement;
-import org.jdesktop.application.Action;
-import org.jdesktop.application.Application;
-import org.jdesktop.application.ApplicationContext;
-import org.jdesktop.application.ResourceMap;
-import org.jdesktop.application.SingleFrameApplication;
-import org.jdesktop.application.Task;
-import org.jdesktop.application.TaskMonitor;
-
-/**
- * Main jTimer application window.
- *
- * Respect JSR-296
- *
- * @author chatellier
- * @version $Revision$
- *
- * Last update : $Date$
- * By : $Author$
- */
-public class JTimer extends SingleFrameApplication implements
- TreeSelectionListener, MouseListener {
-
- /** log. */
- private static Log log = LogFactory.getLog(JTimer.class);
-
- /** Timer core controller. */
- protected TimerCore core;
-
- /** Tree structure. */
- protected ProjectsAndTasksTable projectsAndTasksTable;
-
- /** Systray manager. */
- protected SystrayManager systrayManager;
-
- /** I18n resources map. */
- protected ResourceMap resourceMap;
-
- /** Jtimer application config. */
- public static JTimerConfig config;
-
- /** Single project selection property. */
- protected boolean selectedSingleProject;
-
- /** Single task selection property. */
- protected boolean selectedSingleTask;
-
- /** Single task or project selection. */
- protected boolean selectedSingleElement;
-
- /** Single running task selection. */
- protected boolean selectedSingleRunningTask;
-
- /** Single non running task selection. */
- protected boolean selectedSingleStoppedTask;
-
- /** Multiples projects selection. */
- protected boolean selectedMultiplesProjects;
-
- /** Multiples tasks selection. */
- protected boolean selectedMultiplesTasks;
-
- /** Multiples elements selection. */
- protected boolean selectedMultiplesElements;
-
- /**
- * Main. launch UI
- *
- * @param args args
- */
- public static void main(String[] args) {
-
- if (log.isInfoEnabled()) {
- log.info("Starting " + JTimer.class.getSimpleName() + " at "
- + new Date());
- }
- launch(JTimer.class, args);
- }
-
- /**
- * Initialize application. Called before UI build.
- *
- * @param args args
- * @see Application#initialize(String[])
- */
- @Override
- protected void initialize(String[] args) {
-
- // super, but does nothing
- super.initialize(args);
-
- // load configuration
- loadConfiguration(args);
-
- // init resources map
- ApplicationContext ctxt = getContext();
- resourceMap = ctxt.getResourceMap();
-
- // fix start in iconified mode
- ctxt.getSessionStorage().putProperty(JFrame.class, new WindowProperty2());
-
- // init timercore
- core = new TimerCore();
-
- // handler
- ConnectionDataHandler handler = new SwingConnectionInformationHandler(
- this);
- ProjectManagement managementService = JTimerFactory
- .getProjectManagementService();
- if (managementService != null) {
- managementService.setConnectionDataHandler(handler);
- }
-
- // Systray mgr
- systrayManager = new SystrayManager(this);
- core.getData().addDataEventListener(systrayManager);
-
- IdleDialog.init(this);
- }
-
- /**
- * Load configuration.
- *
- * @param args args to parse command line options
- */
- protected void loadConfiguration(String[] args) {
-
- config = new JTimerConfig();
-
- // add file migration for configuration file created before version 1.4
- File homeDir = new File(System.getProperty("user.home"), ".jtimer");
- File oldFile = new File(homeDir, "JTimer.properties");
- File newFile = new File(config.appConfig.getUserConfigDirectory(), config.appConfig.getConfigFileName());
- if (oldFile.isFile() && !newFile.isFile()) {
- if (log.isInfoEnabled()) {
- log.info("Migration configuration file location");
- }
- try {
- FileUtils.copyFile(oldFile, newFile);
- } catch (IOException ex) {
- if (log.isErrorEnabled()) {
- log.error("Can't copy config file to new location", ex);
- }
- }
- }
-
- // parse after file migration
- config.parse(args);
- }
-
- /**
- * startup.
- *
- * Create frame menu bar. Create main component.
- *
- * @see Application#startup()
- */
- @Override
- protected void startup() {
-
- // set Menu Bar
- getMainFrame().setJMenuBar(createMenuBar());
-
- // show main panel components
- show(createMainComponent());
-
- }
-
- /**
- * Create main component.
- *
- * Toolbar on top. Tree middle. Status bar on bottom.
- *
- * @return The component
- */
- protected JComponent createMainComponent() {
-
- // panel = main component
- JPanel panel = new JPanel(new BorderLayout());
-
- // toolbar on top (north)
- panel.add(createToolBar(), BorderLayout.NORTH);
-
- // tree middle (center-top)
- ProjectsAndTasksTable projectTreeTable = createTreeTable();
- JScrollPane scrollPaneProjectTreeTable = new JScrollPane(
- projectTreeTable);
- panel.add(scrollPaneProjectTreeTable, BorderLayout.CENTER);
-
- // status bar bottom
- StatusBar sb = new StatusBar(this, core.getData());
- // status bar ui will be notified from events
- core.getData().addDataEventListener(sb);
- panel.add(sb, BorderLayout.SOUTH);
-
- // taille par defaut au premier lancement de l'application
- // sera ecrasee par la restauration de la session
- panel.setPreferredSize(new Dimension(640, 480));
-
- return panel;
- }
-
- /**
- * Create complex tree table.
- *
- * @return ProjectsAndTaskTable instance
- */
- protected ProjectsAndTasksTable createTreeTable() {
-
- projectsAndTasksTable = new ProjectsAndTasksTable(this, core);
-
- // name used in properties files
- projectsAndTasksTable.setName("projectslist");
- projectsAndTasksTable.addTreeSelectionListener(this);
- projectsAndTasksTable.addMouseListener(this);
- projectsAndTasksTable.setShowClosed(config.isShowClosed());
-
- // since merge option, selection can be multiple
- projectsAndTasksTable
- .setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
-
- // remove F2 KeyStroke from table
- KeyStroke keyToRemove = KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0);
- InputMap imap = projectsAndTasksTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
- while (imap != null) {
- imap.remove(keyToRemove);
- imap = imap.getParent();
- }
-
- return projectsAndTasksTable;
- }
-
- /**
- * Create toolbar.
- *
- * @return tool bar builded
- */
- protected JComponent createToolBar() {
- String[] toolbarActionNames = { "startTask", "stopTask", "newProject",
- "newTask", "---", "addAnnotation", "editAlert" };
- JToolBar toolBar = new JToolBar();
- toolBar.setFloatable(false);
- for (String actionName : toolbarActionNames) {
-
- if (actionName.equals("---")) {
- toolBar.add(new JToolBar.Separator());
- } else {
- JButton button = new JButton();
- button.setAction(getAction(actionName));
-
- // hide text
- // button.setVerticalTextPosition(JButton.BOTTOM);
- // button.setHorizontalTextPosition(JButton.CENTER);
- button.setHideActionText(true);
-
- button.setFocusable(false);
- toolBar.add(button);
- }
- }
- return toolBar;
- }
-
- /**
- * Create application menu bar.
- *
- * @return menu bar
- */
- protected JMenuBar createMenuBar() {
-
- JMenuBar menuBar = new JMenuBar();
- String[] fileMenuActionNames = { "quit" };
- menuBar.add(createMenu("fileMenu", fileMenuActionNames));
-
- String[] projectMenuActionNames = { "newProject", "editProject",
- "closeProject", "deleteProject" };
- menuBar.add(createMenu("projectMenu", projectMenuActionNames));
-
- String[] taskMenuActionNames = { "newTask", "editTask", "closeTask",
- "deleteTask", "---", "startTask", "stopTask", "---",
- "addAnnotation", "editAlert", "increment1Task",
- "increment5Task", "increment30Task", "decrement1Task",
- "decrement5Task", "decrement30Task", "setToZero", "mergeTasks" };
- menuBar.add(createMenu("taskMenu", taskMenuActionNames));
-
- String[] reportMenuActionNames = { "makeReport" };
- menuBar.add(createMenu("reportMenu", reportMenuActionNames));
-
- JMenu optionmMenu = createOptionMenu();
- menuBar.add(optionmMenu);
-
- String[] helpMenuActionNames = { "about" };
- menuBar.add(createMenu("helpMenu", helpMenuActionNames));
-
- return menuBar;
- }
-
- /**
- * Create option dynamic menu.
- *
- * @return option menu
- */
- protected JMenu createOptionMenu() {
- JMenu menu = new JMenu();
- menu.setName("optionMenu");
-
- // show closed
- JMenuItem showClosedItem = new JCheckBoxMenuItem();
- showClosedItem.setAction(getAction("isShowClosed"));
- showClosedItem.setSelected(config.isShowClosed());
- showClosedItem.setIcon(null);
- menu.add(showClosedItem);
-
- // close to systray
- JMenuItem closeToSysItem = new JCheckBoxMenuItem();
- closeToSysItem.setAction(getAction("isCloseToSystray"));
- closeToSysItem.setSelected(config.isCloseToSystray());
- closeToSysItem.setIcon(null);
- menu.add(closeToSysItem);
-
- // report first day of week
- JMenu reportFDoW = new JMenu();
- reportFDoW.setName("optionReportFirstDayMenu");
- Calendar calendar = Calendar.getInstance();
- ButtonGroup bg = new ButtonGroup();
- // affiche la liste des jours dans l'ordre de la locale utilisateur
- for (int day = calendar.getFirstDayOfWeek() ; day < calendar.getFirstDayOfWeek() + 7 ; day++) {
- int realDay = (day - 1) % 7 + 1;
- JRadioButtonMenuItem fdowItem = new JRadioButtonMenuItem();
- fdowItem.setAction(getAction("isReportFirstDayOfWeek" + realDay));
- fdowItem.setSelected(realDay == JTimer.config.getReportFirstDayOfWeek());
- fdowItem.setIcon(null);
- reportFDoW.add(fdowItem);
- bg.add(fdowItem);
- }
- menu.add(reportFDoW);
-
- return menu;
- }
-
- /**
- * Create single menu.
- *
- * @param menuName menu name
- * @param actionNames associated actions
- * @return menu
- */
- protected JMenu createMenu(String menuName, String[] actionNames) {
- JMenu menu = new JMenu();
- menu.setName(menuName);
- addActionToMenu(menu, actionNames);
- return menu;
- }
-
- /**
- * Add saf action to an existing menu.
- *
- * Menu have to be a JMenu or JPopupMenu.
- *
- * @param menu parent menu
- * @param actionNames action names
- */
- protected void addActionToMenu(JComponent menu, String[] actionNames) {
- for (String actionName : actionNames) {
- if (actionName.equals("---")) {
- menu.add(new JSeparator());
- } else if (actionName.startsWith("is")) {
- // if action name start by is
- // display it as CheckBox
- JMenuItem menuItem = new JCheckBoxMenuItem();
- // link to an @Action
- menuItem.setAction(getAction(actionName));
- menuItem.setIcon(null);
- menu.add(menuItem);
- } else {
- JMenuItem menuItem = new JMenuItem();
- // link to an @Action
- menuItem.setAction(getAction(actionName));
- menuItem.setIcon(null);
- menu.add(menuItem);
- }
- }
- }
-
- /**
- * Ready. Called when UI is ready and displayed.
- *
- * @see Application#ready()
- */
- @Override
- protected void ready() {
-
- // init core, load list, synchronization, etc...
- boolean init = core.init();
-
- if (init) {
- // schedule tree refresh at midnight
- scheduleTreeRefresh();
-
- // install icon (do it at last action)
- systrayManager.install();
- } else {
- String failTitle = resourceMap.getString("startFail.title");
- String failMessage = resourceMap.getString("startFail.message");
- JOptionPane.showMessageDialog(getMainFrame(), failMessage,
- failTitle, JOptionPane.ERROR_MESSAGE);
- exit();
- }
- }
-
- /**
- * Called on application shutdown.
- *
- * Save context.
- *
- * @see SingleFrameApplication#shutdown()
- */
- @Override
- protected void shutdown() {
- log.debug("Shutdown called");
- core.exit();
-
- // save context
- // super, sauve le context des fenetres, etc...
- super.shutdown();
- }
-
- /**
- * Refresh tree at midnight.
- */
- protected void scheduleTreeRefresh() {
-
- // task used to refresh tree
- java.util.TimerTask refreshTreeTask = new RefreshTreeTask(core);
-
- Timer timer = new Timer();
-
- Calendar date = Calendar.getInstance();
- date.setTimeInMillis(System.currentTimeMillis());
- date.set(Calendar.HOUR_OF_DAY, 0);
- date.set(Calendar.MINUTE, 0);
- date.set(Calendar.SECOND, 0);
- date.set(Calendar.MILLISECOND, 0);
- date.add(Calendar.DAY_OF_YEAR, 1); // run only next day
-
- // Schedule to run every day in midnight
- // task,firstTime,period
- timer.schedule(refreshTreeTask, date.getTime(), // at date
- 1000 * 60 * 60 * 24 // every day
- );
- }
-
- /**
- * Display a popup error message.
- *
- * @param errorMessageKey saf error message key
- */
- protected void displayErrorMessage(String errorMessageKey) {
- String title = resourceMap.getString("action.invalidActionTitle");
- String message = resourceMap.getString(errorMessageKey);
-
- // check untranslated string
- if (StringUtils.isEmpty(message)) {
- message = resourceMap.getString("action.missingErrorMessage",
- errorMessageKey);
- }
-
- JOptionPane.showMessageDialog(getMainFrame(), message, title,
- JOptionPane.ERROR_MESSAGE);
- }
-
- /**
- * New project action.
- *
- * Ask user for project name
- */
- @Action
- public void newProject() {
-
- String projectName = JOptionPane.showInputDialog(getMainFrame(),
- resourceMap.getString("input.newProjectMessage"), resourceMap
- .getString("input.newProjectTitle"),
- JOptionPane.QUESTION_MESSAGE);
-
- if (projectName != null) {
-
- // remove unneeded spaces
- projectName = projectName.trim();
-
- TimerProject p = new TimerProject(projectName);
-
- // add creation date
- p.setCreationDate(new Date());
-
- try {
- core.getData().addProject(p);
- } catch (DataViolationException e) {
- displayErrorMessage(e.getExceptionKey());
- }
- }
- }
-
- /**
- * Edit project
- *
- * Enabled when a project is selected
- */
- @Action(enabledProperty = "selectedSingleProject")
- public void editProject() {
- TimerProject project = projectsAndTasksTable.getSelectedProjects().get(
- 0);
-
- String newProjectName = (String) JOptionPane.showInputDialog(getMainFrame(), resourceMap
- .getString("input.editProjectMessage"), resourceMap
- .getString("input.editProjectTitle"),
- JOptionPane.INFORMATION_MESSAGE, null, null, project.getName());
-
- if (newProjectName != null) {
-
- // remove unneeded spaces
- newProjectName = newProjectName.trim();
-
- try {
- core.getData().editProject(project, newProjectName);
- } catch (DataViolationException e) {
- displayErrorMessage(e.getExceptionKey());
- }
- }
- }
-
- /**
- * Create new task action.
- *
- * Enabled when a project or a task is selected
- */
- @Action(enabledProperty = "selectedSingleElement")
- public void newTask() {
-
- // select task to add new task
- TimerTask selectedTask = projectsAndTasksTable.getSelectedElements()
- .get(0);
-
- String taskName = JOptionPane.showInputDialog(getMainFrame(),
- resourceMap.getString("input.newTaskMessage", selectedTask
- .getName()), resourceMap
- .getString("input.newTaskTitle"),
- JOptionPane.QUESTION_MESSAGE);
-
- if (taskName != null) {
-
- // remove unneeded spaces
- taskName = taskName.trim();
-
- TimerTask t = new TimerTask(taskName);
-
- // Fix creation date
- t.setCreationDate(new Date());
-
- try {
- core.getData().addTask(selectedTask, t);
- } catch (DataViolationException e) {
- displayErrorMessage(e.getExceptionKey());
- }
- }
-
- }
-
- /**
- * Edit task.
- *
- * Enabled when a task is selected
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void editTask() {
-
- TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
-
- TimerTaskEditor editor = new TimerTaskEditor(this, task, core);
- editor.setLocationByPlatform(true);
- editor.setVisible(true);
- }
-
- /**
- * Start selected task in tree.
- *
- * If it not already been running
- *
- * @return TimerTask scheduled for start
- * @see Task
- */
- @Action(enabledProperty = "selectedSingleStoppedTask")
- public Task<?, ?> startTask() {
-
- // search for selected task in tree
- // can't be null
- TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
-
- RunTaskJob jobToRun = new RunTaskJob(this, task, core.getData());
- core.getData().startTask(task);
-
- return jobToRun;
- }
-
- /**
- * Called by task job manager when task as been started.
- *
- * @param task started task
- */
- public void startedTask(TimerTask task) {
- setSelectedSingleRunningTask(true);
- setSelectedSingleStoppedTask(false);
- }
-
- /**
- * Return job that manage running task.
- *
- * @param task timer task to get job
- * @return job or null
- */
- protected RunTaskJob getJobForRunningTask(TimerTask task) {
- RunTaskJob job = null;
-
- TaskMonitor tm = getContext().getTaskMonitor();
- for (Task<Void, Long> t : tm.getTasks()) {
- TimerTask localtask = ((RunTaskJob) t).getTask();
- if (task.equals(localtask)) {
- job = (RunTaskJob) t;
- }
- }
-
- return job;
- }
-
- /**
- * Stop selected task in tree.
- *
- * Verify if it has been started
- */
- @Action(enabledProperty = "selectedSingleRunningTask")
- public void stopTask() {
-
- // task can't be null
- TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
- stopTask(task);
-
- }
-
- /**
- * Stop a task.
- *
- * Delegate method. Called by idle detect ?
- * Called by delete method too.
- *
- * @param task task to stop
- */
- public void stopTask(TimerTask task) {
-
- RunTaskJob rtt = getJobForRunningTask(task);
- // test if task is already running
- if (rtt != null) {
- rtt.wantToStop();
- core.getData().stopTask(task);
-
- // re-enable/disable buttons
- setSelectedSingleRunningTask(false);
- setSelectedSingleStoppedTask(true);
- }
- }
-
- /**
- * Stop all running tasks.
- */
- public void stopAllTasks() {
-
- TaskMonitor tm = getContext().getTaskMonitor();
- for (Task<Void, Long> t : tm.getTasks()) {
- // task
- TimerTask ttask = ((RunTaskJob) t).getTask();
- stopTask(ttask);
- }
- }
-
- /**
- * Close project.
- */
- @Action(enabledProperty = "selectedSingleProject")
- public void closeProject() {
- TimerProject project = projectsAndTasksTable.getSelectedProjects().get(0);
-
- core.getData().changeProjectCloseState(project);
- }
-
- /**
- * Close task.
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void closeTask() {
- TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
-
- core.getData().changeTaskCloseState(task);
- }
-
- /**
- * Delete project.
- */
- @Action(enabledProperty = "selectedSingleProject")
- public void deleteProject() {
-
- TimerProject project = projectsAndTasksTable.getSelectedProjects().get(
- 0);
-
- if (project != null) {
- int confirm = JOptionPane.showConfirmDialog(getMainFrame(),
- resourceMap.getString("input.deleteProjectMessage", project
- .getName()), resourceMap
- .getString("input.deleteProjectTitle"),
- JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
-
- if (confirm == JOptionPane.YES_OPTION) { // approved
- try {
- core.getData().deleteProject(project);
- } catch (DataViolationException e) {
- displayErrorMessage(e.getExceptionKey());
- }
- }
-
- }
-
- }
-
- /**
- * Delete task.
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void deleteTask() {
-
- TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
-
- if (task != null) {
- int confirm = JOptionPane.showConfirmDialog(getMainFrame(),
- resourceMap.getString("input.deleteTaskMessage", task
- .getName()), resourceMap
- .getString("input.deleteTaskTitle"),
- JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
-
- if (confirm == JOptionPane.YES_OPTION) { // approved
- try {
- stopTask(task);
- core.getData().deleteTask(task);
- } catch (DataViolationException e) {
- displayErrorMessage(e.getExceptionKey());
- }
- }
- }
- }
-
- /**
- * Change show closed option.
- *
- * @param event action event
- */
- @Action
- public void isShowClosed(ActionEvent event) {
- JCheckBoxMenuItem source = (JCheckBoxMenuItem) event.getSource();
- boolean showClosed = source.isSelected();
- projectsAndTasksTable.setShowClosed(showClosed);
- config.setShowClosed(showClosed);
- }
-
- /**
- * Change close to systray option.
- *
- * @param event action event
- */
- @Action
- public void isCloseToSystray(ActionEvent event) {
- JCheckBoxMenuItem source = (JCheckBoxMenuItem) event.getSource();
- boolean closeToSystray = source.isSelected();
- config.setCloseToSystray(closeToSystray);
- }
-
- /**
- * Change report first day of week.
- */
- @Action
- public void isReportFirstDayOfWeek1() {
- config.setReportFirstDayOfWeek(1);
- }
-
- /**
- * Change report first day of week.
- */
- @Action
- public void isReportFirstDayOfWeek2() {
- config.setReportFirstDayOfWeek(2);
- }
-
- /**
- * Change report first day of week.
- */
- @Action
- public void isReportFirstDayOfWeek3() {
- config.setReportFirstDayOfWeek(3);
- }
-
- /**
- * Change report first day of week.
- */
- @Action
- public void isReportFirstDayOfWeek4() {
- config.setReportFirstDayOfWeek(4);
- }
-
- /**
- * Change report first day of week.
- */
- @Action
- public void isReportFirstDayOfWeek5() {
- config.setReportFirstDayOfWeek(5);
- }
-
- /**
- * Change report first day of week.
- */
- @Action
- public void isReportFirstDayOfWeek6() {
- config.setReportFirstDayOfWeek(6);
- }
-
- /**
- * Change report first day of week.
- */
- @Action
- public void isReportFirstDayOfWeek7() {
- config.setReportFirstDayOfWeek(7);
- }
-
- /**
- * Increment task time.
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void increment5Task() {
- incrementTaskTime(5 * 60);
- }
-
- /**
- * Increment task time.
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void increment30Task() {
- incrementTaskTime(30 * 60);
- }
-
- /**
- * Decrement task time.
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void decrement1Task() {
- incrementTaskTime(-60);
- }
-
- /**
- * Decrement task time.
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void decrement5Task() {
- incrementTaskTime(-5 * 60);
- }
-
- /**
- * Decrement task time.
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void decrement30Task() {
- incrementTaskTime(-30 * 60);
- }
-
- /**
- * Increment task time.
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void increment1Task() {
- incrementTaskTime(60);
- }
-
- /**
- * Increment task time.
- *
- * To decrement, set negative increment:)
- *
- * @param increment increment in seconds
- */
- protected void incrementTaskTime(long increment) {
- TimerTask selectedTask = projectsAndTasksTable.getSelectedTasks()
- .get(0);
-
- // check if task is running
- RunTaskJob job = getJobForRunningTask(selectedTask);
- if (job != null) {
- // task is running
- // increment is in seconds !!!
- job.incrementTaskTime(increment * 1000);
- } else {
- // task is not running
- Date now = new Date();
- long todayTime = selectedTask.getTime(now);
-
- long newTodayTime = todayTime + increment;
-
- try {
- // check if + negative increment still positive
- if (newTodayTime > 0) {
- core.getData().changeTaskTime(selectedTask, now,
- newTodayTime);
- } else {
- // force to 0
- core.getData().changeTaskTime(selectedTask, now, 0L);
- }
- } catch (DataViolationException e) {
- displayErrorMessage(e.getExceptionKey());
- }
- }
- }
-
- /**
- * Reset task time to zero.
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void setToZero() {
- TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
- incrementTaskTime(-task.getTime(new Date()));
- }
-
- /**
- * Merge multiples tasks action.
- */
- @Action(enabledProperty = "selectedMultiplesTasks")
- public void mergeTasks() {
- List<TimerTask> tasks = projectsAndTasksTable.getSelectedTasks();
-
- TimerTask destinationTask = tasks.get(0);
- List<TimerTask> otherTasks = tasks.subList(1, tasks.size());
- int confirm = JOptionPane.showConfirmDialog(getMainFrame(),
- resourceMap.getString("input.mergeTaskMessage", tasks.size(),
- destinationTask.getName()), resourceMap
- .getString("input.mergeTaskTitle"),
- JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
- if (confirm == JOptionPane.YES_OPTION) {
-
- try {
- core.getData().mergeTasks(destinationTask, otherTasks);
- } catch (DataViolationException e) {
- displayErrorMessage(e.getExceptionKey());
- }
- }
- }
-
- /**
- * Add annotation action.
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void addAnnotation() {
- // select task to add new annotation
- TimerTask selectedTask = projectsAndTasksTable.getSelectedTasks()
- .get(0);
-
- String annotation = JOptionPane.showInputDialog(getMainFrame(),
- resourceMap.getString("input.addAnnotationMessage",
- selectedTask.getName()), resourceMap
- .getString("input.addAnnotationTitle"),
- JOptionPane.QUESTION_MESSAGE);
-
- if (annotation != null) {
- // remove useless spaces
- annotation = annotation.trim();
-
- try {
- core.getData().addAnnotation(selectedTask, new Date(),
- annotation);
- } catch (DataViolationException e) {
- displayErrorMessage(e.getExceptionKey());
- }
- }
- }
-
- /**
- * Edit alert action.
- */
- @Action(enabledProperty = "selectedSingleTask")
- public void editAlert() {
- // select task to edit alert
- TimerTask selectedTask = projectsAndTasksTable.getSelectedTasks()
- .get(0);
-
- AlertEditor alertEditor = new AlertEditor(this, core.getData(),
- selectedTask);
- show(alertEditor);
- }
-
- /**
- * Create report.
- */
- @Action
- public void makeReport() {
- ReportView view = new ReportView(this, core);
- show(view);
- }
-
- /**
- * Show about frame.
- */
- @Action
- public void about() {
- HelpFrame aboutFrame = new HelpFrame(this);
- show(aboutFrame);
- }
-
- /**
- * Is selected project.
- *
- * @return selected project property
- */
- public boolean isSelectedSingleProject() {
- return selectedSingleProject;
- }
-
- /**
- * Change selected project property.
- *
- * @param selectedSingleProject selected project property
- */
- public void setSelectedSingleProject(boolean selectedSingleProject) {
- boolean oldValue = this.selectedSingleProject;
- this.selectedSingleProject = selectedSingleProject;
- firePropertyChange("selectedSingleProject", oldValue,
- selectedSingleProject);
- }
-
- /**
- * Is selected task.
- *
- * @return selected task property
- */
- public boolean isSelectedSingleTask() {
- return selectedSingleTask;
- }
-
- /**
- * Change selected task property.
- *
- * @param selectedSingleTask selected task property
- */
- public void setSelectedSingleTask(boolean selectedSingleTask) {
- boolean oldValue = this.selectedSingleTask;
- this.selectedSingleTask = selectedSingleTask;
- firePropertyChange("selectedSingleTask", oldValue, selectedSingleTask);
- }
-
- /**
- * Is selected task or project.
- *
- * @return selected task or project property
- */
- public boolean isSelectedSingleElement() {
- return selectedSingleElement;
- }
-
- /**
- * Change selected task or project property.
- *
- * @param selectedSingleElement selected task or project property
- */
- public void setSelectedSingleElement(boolean selectedSingleElement) {
- boolean oldValue = this.selectedSingleElement;
- this.selectedSingleElement = selectedSingleElement;
- firePropertyChange("selectedSingleElement", oldValue,
- selectedSingleElement);
- }
-
- /**
- * Is selected running task.
- *
- * @return the selectedSingleRunningTask
- */
- public boolean isSelectedSingleRunningTask() {
- return selectedSingleRunningTask;
- }
-
- /**
- * Change selected running task property.
- *
- * @param selectedSingleRunningTask selected running task property
- */
- public void setSelectedSingleRunningTask(boolean selectedSingleRunningTask) {
- boolean oldValue = this.selectedSingleRunningTask;
- this.selectedSingleRunningTask = selectedSingleRunningTask;
- firePropertyChange("selectedSingleRunningTask", oldValue,
- selectedSingleRunningTask);
- }
-
- /**
- * Is selected non running task.
- *
- * @return selected non running task
- */
- public boolean isSelectedSingleStoppedTask() {
- return selectedSingleStoppedTask;
- }
-
- /**
- * Change selected non running task property.
- *
- * @param selectedSingleStoppedTask selected non running task
- */
- public void setSelectedSingleStoppedTask(boolean selectedSingleStoppedTask) {
- boolean oldValue = this.selectedSingleStoppedTask;
- this.selectedSingleStoppedTask = selectedSingleStoppedTask;
- firePropertyChange("selectedSingleStoppedTask", oldValue,
- selectedSingleStoppedTask);
- }
-
- /**
- * Is selected multiples projects.
- *
- * @return selected multiples projects
- */
- public boolean isSelectedMultiplesProjects() {
- return selectedMultiplesProjects;
- }
-
- /**
- * Change selected multiples projects property.
- *
- * @param selectedMultiplesProjects selected multiples projects
- */
- public void setSelectedMultiplesProjects(boolean selectedMultiplesProjects) {
- boolean oldValue = this.selectedMultiplesProjects;
- this.selectedMultiplesProjects = selectedMultiplesProjects;
- firePropertyChange("selectedMultiplesProjects", oldValue,
- selectedMultiplesProjects);
- }
-
- /**
- * Is selected multiples tasks.
- *
- * @return selected multiples tasks
- */
- public boolean isSelectedMultiplesTasks() {
- return selectedMultiplesTasks;
- }
-
- /**
- * Change selected multiples tasks property.
- *
- * @param selectedMultiplesTasks selected multiples tasks
- */
- public void setSelectedMultiplesTasks(boolean selectedMultiplesTasks) {
- boolean oldValue = this.selectedMultiplesTasks;
- this.selectedMultiplesTasks = selectedMultiplesTasks;
- firePropertyChange("selectedMultiplesTasks", oldValue,
- selectedMultiplesTasks);
- }
-
- /**
- * Is selected multiples elements.
- *
- * @return selected multiples elements
- */
- public boolean isSelectedMultiplesElements() {
- return selectedMultiplesElements;
- }
-
- /**
- * Change selected multiples elements property.
- *
- * @param selectedMultiplesElements selected multiples elements
- */
- public void setSelectedMultiplesElements(boolean selectedMultiplesElements) {
- boolean oldValue = this.selectedMultiplesElements;
- this.selectedMultiplesElements = selectedMultiplesElements;
- firePropertyChange("selectedMultiplesElements", oldValue,
- selectedMultiplesElements);
- }
-
- /*
- * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
- */
- @Override
- public void valueChanged(TreeSelectionEvent e) {
- // get selected elements
- List<TimerTask> elements = projectsAndTasksTable.getSelectedElements();
- List<TimerProject> projects = projectsAndTasksTable
- .getSelectedProjects();
- List<TimerTask> tasks = projectsAndTasksTable.getSelectedTasks();
-
- // notify application that tree selection has changed
- if (tasks.size() == 1 && projects.size() == 0) {
- TimerTask task = tasks.get(0);
- setSelectedSingleTask(true);
-
- // ask for SAF job manager if task is running
- RunTaskJob job = getJobForRunningTask(task);
- if (job == null || job.isStopping()) {
- setSelectedSingleStoppedTask(true);
- setSelectedSingleRunningTask(false);
- } else {
- setSelectedSingleStoppedTask(false);
- setSelectedSingleRunningTask(true);
- }
- setSelectedMultiplesTasks(false);
- setSelectedSingleProject(false);
- setSelectedMultiplesProjects(false);
- } else {
- setSelectedSingleTask(false);
- setSelectedSingleStoppedTask(false);
- setSelectedSingleRunningTask(false);
-
- if (tasks.size() > 1) {
- setSelectedMultiplesTasks(projects.size() == 0);
- } else {
- setSelectedSingleProject(tasks.size() == 0
- && projects.size() == 1);
- setSelectedMultiplesProjects(tasks.size() == 0
- && projects.size() > 1);
- }
- }
- setSelectedSingleElement(elements.size() == 1);
- setSelectedMultiplesElements(elements.size() > 1);
- }
-
- /**
- * Get action for named component.
- *
- * Util method.
- *
- * @param actionName action name
- * @return swing action
- */
- protected javax.swing.Action getAction(String actionName) {
- return getContext().getActionMap().get(actionName);
- }
-
- /**
- * Show window
- */
- @Action
- public void show() {
- // TODO better code ? that use SAF methods ?
- getMainFrame().setVisible(true);
- getMainFrame().toFront();
- }
-
- /**
- * Show window
- */
- @Action
- public void hide() {
- // TODO better code ? that use SAF methods ?
- getMainFrame().setVisible(false);
- }
-
- /**
- * Notified by job on pre idle detect.
- */
- public void preIdleDetect() {
- systrayManager.preIdleDetect();
- }
-
- /**
- * Notified by job on post idle detect.
- */
- public void postIdleDetect() {
- systrayManager.postIdleDetect();
- }
-
- /*
- * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
- */
- public void mouseClicked(MouseEvent e) {
-
- if (log.isDebugEnabled()) {
- log.debug("Mouse clicked (" + e.getClickCount()
- + " clics), source = "
- + e.getSource().getClass().getName());
- }
-
- switch (e.getButton()) {
-
- // clic gauche
- case MouseEvent.BUTTON1:
- // clic sur l'arbre des projets
- if (e.getSource() == projectsAndTasksTable) {
- // demarre la tache lors d'un double clic dessus
- if (e.getClickCount() == 2) {
-
- if (isSelectedSingleStoppedTask()) { // can only launch non running tasks
- Task<?, ?> appTask = startTask();
- if (appTask != null) {
-
- // first, on dlb click stop all running tasks
- stopAllTasks();
-
- getContext().getTaskService().execute(appTask);
- }
- /* TODO EC-20100416 temp disable, called twice, can display
- -1 task running :(
- } else if (isSelectedSingleRunningTask()) {
- TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
- stopTask(task); */
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Non selected non running task to launch");
- }
- }
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Single clic on tree, do nothing");
- }
- }
- }
- break;
-
- // gestion du clic droit
- case MouseEvent.BUTTON3:
-
- // force task selection on rigth clic
- TreePath path = projectsAndTasksTable.getPathForLocation(e.getX(),
- e.getY());
- int selectedRow = projectsAndTasksTable.getRowForPath(path);
- projectsAndTasksTable.getSelectionModel().setSelectionInterval(
- selectedRow, selectedRow);
-
- // fix item selection
- JPopupMenu menu = new JPopupMenu();
-
- String[] actionNames = null;
-
- // construct menu in function of selection
- if (isSelectedSingleProject()) {
- actionNames = new String[] { "newTask", "---", "newProject",
- "editProject", "closeProject", "deleteProject" };
- }
-
- if (isSelectedSingleTask()) {
- actionNames = new String[] { "startTask", "stopTask", "---",
- "newTask", "editTask", "closeTask", "deleteTask",
- "---", "addAnnotation", "editAlert", "increment1Task",
- "increment5Task", "increment30Task", "decrement1Task",
- "decrement5Task", "decrement30Task", "setToZero" };
- }
-
- if (isSelectedMultiplesTasks()) {
- actionNames = new String[] { "mergeTasks" };
- }
-
- // case, right clic, but nothing selected
- if (actionNames != null) {
- addActionToMenu(menu, actionNames);
-
- menu.show(e.getComponent(), e.getX(), e.getY());
- }
- }
- }
-
- public void mouseEntered(MouseEvent e) {
- }
-
- public void mouseExited(MouseEvent e) {
- }
-
- public void mousePressed(MouseEvent e) {
- }
-
- public void mouseReleased(MouseEvent e) {
- }
-}
Copied: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/JTimer.java (from rev 2837, trunk/src/main/java/org/chorem/jtimer/JTimer.java)
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/JTimer.java (rev 0)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/JTimer.java 2012-03-25 21:15:46 UTC (rev 2840)
@@ -0,0 +1,1473 @@
+/*
+ * #%L
+ * jTimer
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2007 - 2012 CodeLutin, Chatellier Eric
+ * %%
+ * This program 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.
+ *
+ * This program 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 this program. If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+package org.chorem.jtimer;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.io.File;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Timer;
+
+import javax.swing.ButtonGroup;
+import javax.swing.InputMap;
+import javax.swing.JButton;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JRadioButtonMenuItem;
+import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
+import javax.swing.JToolBar;
+import javax.swing.KeyStroke;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.TreePath;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.chorem.jtimer.data.DataViolationException;
+import org.chorem.jtimer.data.TimerCore;
+import org.chorem.jtimer.entities.TimerProject;
+import org.chorem.jtimer.entities.TimerTask;
+import org.chorem.jtimer.ui.HelpFrame;
+import org.chorem.jtimer.ui.StatusBar;
+import org.chorem.jtimer.ui.TimerTaskEditor;
+import org.chorem.jtimer.ui.alert.AlertEditor;
+import org.chorem.jtimer.ui.report.ReportView;
+import org.chorem.jtimer.ui.systray.SystrayManager;
+import org.chorem.jtimer.ui.tasks.IdleDialog;
+import org.chorem.jtimer.ui.tasks.RefreshTreeTask;
+import org.chorem.jtimer.ui.tasks.RunTaskJob;
+import org.chorem.jtimer.ui.treetable.ProjectsAndTasksTable;
+import org.chorem.jtimer.ui.widget.WindowProperty2;
+import org.chorem.jtimer.ui.ws.SwingConnectionInformationHandler;
+import org.chorem.jtimer.ws.ConnectionDataHandler;
+import org.chorem.jtimer.ws.ProjectManagement;
+import org.jdesktop.application.Action;
+import org.jdesktop.application.Application;
+import org.jdesktop.application.ApplicationContext;
+import org.jdesktop.application.ResourceMap;
+import org.jdesktop.application.SingleFrameApplication;
+import org.jdesktop.application.Task;
+import org.jdesktop.application.TaskMonitor;
+
+/**
+ * Main jTimer application window.
+ *
+ * Respect JSR-296
+ *
+ * @author chatellier
+ * @version $Revision$
+ *
+ * Last update : $Date$
+ * By : $Author$
+ */
+public class JTimer extends SingleFrameApplication implements
+ TreeSelectionListener, MouseListener {
+
+ /** log. */
+ private static Log log = LogFactory.getLog(JTimer.class);
+
+ /** Timer core controller. */
+ protected TimerCore core;
+
+ /** Tree structure. */
+ protected ProjectsAndTasksTable projectsAndTasksTable;
+
+ /** Systray manager. */
+ protected SystrayManager systrayManager;
+
+ /** I18n resources map. */
+ protected ResourceMap resourceMap;
+
+ /** Jtimer application config. */
+ public static JTimerConfig config;
+
+ /** Single project selection property. */
+ protected boolean selectedSingleProject;
+
+ /** Single task selection property. */
+ protected boolean selectedSingleTask;
+
+ /** Single task or project selection. */
+ protected boolean selectedSingleElement;
+
+ /** Single running task selection. */
+ protected boolean selectedSingleRunningTask;
+
+ /** Single non running task selection. */
+ protected boolean selectedSingleStoppedTask;
+
+ /** Multiples projects selection. */
+ protected boolean selectedMultiplesProjects;
+
+ /** Multiples tasks selection. */
+ protected boolean selectedMultiplesTasks;
+
+ /** Multiples elements selection. */
+ protected boolean selectedMultiplesElements;
+
+ /**
+ * Main. launch UI
+ *
+ * @param args args
+ */
+ public static void main(String[] args) {
+
+ if (log.isInfoEnabled()) {
+ log.info("Starting " + JTimer.class.getSimpleName() + " at "
+ + new Date());
+ }
+ launch(JTimer.class, args);
+ }
+
+ /**
+ * Initialize application. Called before UI build.
+ *
+ * @param args args
+ * @see Application#initialize(String[])
+ */
+ @Override
+ protected void initialize(String[] args) {
+
+ // super, but does nothing
+ super.initialize(args);
+
+ // load configuration
+ loadConfiguration(args);
+
+ // init resources map
+ ApplicationContext ctxt = getContext();
+ resourceMap = ctxt.getResourceMap();
+
+ // fixme awt application name. Can be seen only with gnome-shell
+ // tray icon is displayed with name "org-chorem-jtimer-JTimer" instead of
+ // only "jTimer" with following fix :
+ try {
+ Toolkit xToolkit = Toolkit.getDefaultToolkit();
+ java.lang.reflect.Field awtAppClassNameField = xToolkit.getClass().getDeclaredField("awtAppClassName");
+ awtAppClassNameField.setAccessible(true);
+ awtAppClassNameField.set(xToolkit, resourceMap.getString("Application.title"));
+ } catch (Exception ex) {
+ if (log.isWarnEnabled()) {
+ log.warn("Can change awt application name", ex);
+ }
+ }
+
+ // fix start in iconified mode
+ ctxt.getSessionStorage().putProperty(JFrame.class, new WindowProperty2());
+
+ // init timercore
+ core = new TimerCore();
+
+ // handler
+ ConnectionDataHandler handler = new SwingConnectionInformationHandler(
+ this);
+ ProjectManagement managementService = JTimerFactory
+ .getProjectManagementService();
+ if (managementService != null) {
+ managementService.setConnectionDataHandler(handler);
+ }
+
+ // Systray mgr
+ systrayManager = new SystrayManager(this);
+ core.getData().addDataEventListener(systrayManager);
+
+ IdleDialog.init(this);
+ }
+
+ /**
+ * Load configuration.
+ *
+ * @param args args to parse command line options
+ */
+ protected void loadConfiguration(String[] args) {
+
+ config = new JTimerConfig();
+
+ // add file migration for configuration file created before version 1.4
+ File homeDir = new File(System.getProperty("user.home"), ".jtimer");
+ File oldFile = new File(homeDir, "JTimer.properties");
+ File newFile = new File(config.appConfig.getUserConfigDirectory(), config.appConfig.getConfigFileName());
+ if (oldFile.isFile() && !newFile.isFile()) {
+ if (log.isInfoEnabled()) {
+ log.info("Migration configuration file location");
+ }
+ try {
+ FileUtils.copyFile(oldFile, newFile);
+ } catch (IOException ex) {
+ if (log.isErrorEnabled()) {
+ log.error("Can't copy config file to new location", ex);
+ }
+ }
+ }
+
+ // parse after file migration
+ config.parse(args);
+ }
+
+ /**
+ * startup.
+ *
+ * Create frame menu bar. Create main component.
+ *
+ * @see Application#startup()
+ */
+ @Override
+ protected void startup() {
+
+ // set Menu Bar
+ getMainFrame().setJMenuBar(createMenuBar());
+
+ // show main panel components
+ show(createMainComponent());
+
+ }
+
+ /**
+ * Create main component.
+ *
+ * Toolbar on top. Tree middle. Status bar on bottom.
+ *
+ * @return The component
+ */
+ protected JComponent createMainComponent() {
+
+ // panel = main component
+ JPanel panel = new JPanel(new BorderLayout());
+
+ // toolbar on top (north)
+ panel.add(createToolBar(), BorderLayout.NORTH);
+
+ // tree middle (center-top)
+ ProjectsAndTasksTable projectTreeTable = createTreeTable();
+ JScrollPane scrollPaneProjectTreeTable = new JScrollPane(
+ projectTreeTable);
+ panel.add(scrollPaneProjectTreeTable, BorderLayout.CENTER);
+
+ // status bar bottom
+ StatusBar sb = new StatusBar(this, core.getData());
+ // status bar ui will be notified from events
+ core.getData().addDataEventListener(sb);
+ panel.add(sb, BorderLayout.SOUTH);
+
+ // taille par defaut au premier lancement de l'application
+ // sera ecrasee par la restauration de la session
+ panel.setPreferredSize(new Dimension(640, 480));
+
+ return panel;
+ }
+
+ /**
+ * Create complex tree table.
+ *
+ * @return ProjectsAndTaskTable instance
+ */
+ protected ProjectsAndTasksTable createTreeTable() {
+
+ projectsAndTasksTable = new ProjectsAndTasksTable(this, core);
+
+ // name used in properties files
+ projectsAndTasksTable.setName("projectslist");
+ projectsAndTasksTable.addTreeSelectionListener(this);
+ projectsAndTasksTable.addMouseListener(this);
+ projectsAndTasksTable.setShowClosed(config.isShowClosed());
+
+ // since merge option, selection can be multiple
+ projectsAndTasksTable
+ .setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+
+ // remove F2 KeyStroke from table
+ KeyStroke keyToRemove = KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0);
+ InputMap imap = projectsAndTasksTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
+ while (imap != null) {
+ imap.remove(keyToRemove);
+ imap = imap.getParent();
+ }
+
+ return projectsAndTasksTable;
+ }
+
+ /**
+ * Create toolbar.
+ *
+ * @return tool bar builded
+ */
+ protected JComponent createToolBar() {
+ String[] toolbarActionNames = { "startTask", "stopTask", "newProject",
+ "newTask", "---", "addAnnotation", "editAlert" };
+ JToolBar toolBar = new JToolBar();
+ toolBar.setFloatable(false);
+ for (String actionName : toolbarActionNames) {
+
+ if (actionName.equals("---")) {
+ toolBar.add(new JToolBar.Separator());
+ } else {
+ JButton button = new JButton();
+ button.setAction(getAction(actionName));
+
+ // hide text
+ // button.setVerticalTextPosition(JButton.BOTTOM);
+ // button.setHorizontalTextPosition(JButton.CENTER);
+ button.setHideActionText(true);
+
+ button.setFocusable(false);
+ toolBar.add(button);
+ }
+ }
+ return toolBar;
+ }
+
+ /**
+ * Create application menu bar.
+ *
+ * @return menu bar
+ */
+ protected JMenuBar createMenuBar() {
+
+ JMenuBar menuBar = new JMenuBar();
+ String[] fileMenuActionNames = { "quit" };
+ menuBar.add(createMenu("fileMenu", fileMenuActionNames));
+
+ String[] projectMenuActionNames = { "newProject", "editProject",
+ "closeProject", "deleteProject" };
+ menuBar.add(createMenu("projectMenu", projectMenuActionNames));
+
+ String[] taskMenuActionNames = { "newTask", "editTask", "closeTask",
+ "deleteTask", "---", "startTask", "stopTask", "---",
+ "addAnnotation", "editAlert", "increment1Task",
+ "increment5Task", "increment30Task", "decrement1Task",
+ "decrement5Task", "decrement30Task", "setToZero", "mergeTasks" };
+ menuBar.add(createMenu("taskMenu", taskMenuActionNames));
+
+ String[] reportMenuActionNames = { "makeReport" };
+ menuBar.add(createMenu("reportMenu", reportMenuActionNames));
+
+ JMenu optionmMenu = createOptionMenu();
+ menuBar.add(optionmMenu);
+
+ String[] helpMenuActionNames = { "about" };
+ menuBar.add(createMenu("helpMenu", helpMenuActionNames));
+
+ return menuBar;
+ }
+
+ /**
+ * Create option dynamic menu.
+ *
+ * @return option menu
+ */
+ protected JMenu createOptionMenu() {
+ JMenu menu = new JMenu();
+ menu.setName("optionMenu");
+
+ // show closed
+ JMenuItem showClosedItem = new JCheckBoxMenuItem();
+ showClosedItem.setAction(getAction("isShowClosed"));
+ showClosedItem.setSelected(config.isShowClosed());
+ showClosedItem.setIcon(null);
+ menu.add(showClosedItem);
+
+ // close to systray
+ JMenuItem closeToSysItem = new JCheckBoxMenuItem();
+ closeToSysItem.setAction(getAction("isCloseToSystray"));
+ closeToSysItem.setSelected(config.isCloseToSystray());
+ closeToSysItem.setIcon(null);
+ menu.add(closeToSysItem);
+
+ // report first day of week
+ JMenu reportFDoW = new JMenu();
+ reportFDoW.setName("optionReportFirstDayMenu");
+ Calendar calendar = Calendar.getInstance();
+ ButtonGroup bg = new ButtonGroup();
+ // affiche la liste des jours dans l'ordre de la locale utilisateur
+ for (int day = calendar.getFirstDayOfWeek() ; day < calendar.getFirstDayOfWeek() + 7 ; day++) {
+ int realDay = (day - 1) % 7 + 1;
+ JRadioButtonMenuItem fdowItem = new JRadioButtonMenuItem();
+ fdowItem.setAction(getAction("isReportFirstDayOfWeek" + realDay));
+ fdowItem.setSelected(realDay == JTimer.config.getReportFirstDayOfWeek());
+ fdowItem.setIcon(null);
+ reportFDoW.add(fdowItem);
+ bg.add(fdowItem);
+ }
+ menu.add(reportFDoW);
+
+ return menu;
+ }
+
+ /**
+ * Create single menu.
+ *
+ * @param menuName menu name
+ * @param actionNames associated actions
+ * @return menu
+ */
+ protected JMenu createMenu(String menuName, String[] actionNames) {
+ JMenu menu = new JMenu();
+ menu.setName(menuName);
+ addActionToMenu(menu, actionNames);
+ return menu;
+ }
+
+ /**
+ * Add saf action to an existing menu.
+ *
+ * Menu have to be a JMenu or JPopupMenu.
+ *
+ * @param menu parent menu
+ * @param actionNames action names
+ */
+ protected void addActionToMenu(JComponent menu, String[] actionNames) {
+ for (String actionName : actionNames) {
+ if (actionName.equals("---")) {
+ menu.add(new JSeparator());
+ } else if (actionName.startsWith("is")) {
+ // if action name start by is
+ // display it as CheckBox
+ JMenuItem menuItem = new JCheckBoxMenuItem();
+ // link to an @Action
+ menuItem.setAction(getAction(actionName));
+ menuItem.setIcon(null);
+ menu.add(menuItem);
+ } else {
+ JMenuItem menuItem = new JMenuItem();
+ // link to an @Action
+ menuItem.setAction(getAction(actionName));
+ menuItem.setIcon(null);
+ menu.add(menuItem);
+ }
+ }
+ }
+
+ /**
+ * Ready. Called when UI is ready and displayed.
+ *
+ * @see Application#ready()
+ */
+ @Override
+ protected void ready() {
+
+ // init core, load list, synchronization, etc...
+ boolean init = core.init();
+
+ if (init) {
+ // schedule tree refresh at midnight
+ scheduleTreeRefresh();
+
+ // install icon (do it at last action)
+ systrayManager.install();
+ } else {
+ String failTitle = resourceMap.getString("startFail.title");
+ String failMessage = resourceMap.getString("startFail.message");
+ JOptionPane.showMessageDialog(getMainFrame(), failMessage,
+ failTitle, JOptionPane.ERROR_MESSAGE);
+ exit();
+ }
+ }
+
+ /**
+ * Called on application shutdown.
+ *
+ * Save context.
+ *
+ * @see SingleFrameApplication#shutdown()
+ */
+ @Override
+ protected void shutdown() {
+ log.debug("Shutdown called");
+ core.exit();
+
+ // save context
+ // super, sauve le context des fenetres, etc...
+ super.shutdown();
+ }
+
+ /**
+ * Refresh tree at midnight.
+ */
+ protected void scheduleTreeRefresh() {
+
+ // task used to refresh tree
+ java.util.TimerTask refreshTreeTask = new RefreshTreeTask(core);
+
+ Timer timer = new Timer();
+
+ Calendar date = Calendar.getInstance();
+ date.setTimeInMillis(System.currentTimeMillis());
+ date.set(Calendar.HOUR_OF_DAY, 0);
+ date.set(Calendar.MINUTE, 0);
+ date.set(Calendar.SECOND, 0);
+ date.set(Calendar.MILLISECOND, 0);
+ date.add(Calendar.DAY_OF_YEAR, 1); // run only next day
+
+ // Schedule to run every day in midnight
+ // task,firstTime,period
+ timer.schedule(refreshTreeTask, date.getTime(), // at date
+ 1000 * 60 * 60 * 24 // every day
+ );
+ }
+
+ /**
+ * Display a popup error message.
+ *
+ * @param errorMessageKey saf error message key
+ */
+ protected void displayErrorMessage(String errorMessageKey) {
+ String title = resourceMap.getString("action.invalidActionTitle");
+ String message = resourceMap.getString(errorMessageKey);
+
+ // check untranslated string
+ if (StringUtils.isEmpty(message)) {
+ message = resourceMap.getString("action.missingErrorMessage",
+ errorMessageKey);
+ }
+
+ JOptionPane.showMessageDialog(getMainFrame(), message, title,
+ JOptionPane.ERROR_MESSAGE);
+ }
+
+ /**
+ * New project action.
+ *
+ * Ask user for project name
+ */
+ @Action
+ public void newProject() {
+
+ String projectName = JOptionPane.showInputDialog(getMainFrame(),
+ resourceMap.getString("input.newProjectMessage"), resourceMap
+ .getString("input.newProjectTitle"),
+ JOptionPane.QUESTION_MESSAGE);
+
+ if (projectName != null) {
+
+ // remove unneeded spaces
+ projectName = projectName.trim();
+
+ TimerProject p = new TimerProject(projectName);
+
+ // add creation date
+ p.setCreationDate(new Date());
+
+ try {
+ core.getData().addProject(p);
+ } catch (DataViolationException e) {
+ displayErrorMessage(e.getExceptionKey());
+ }
+ }
+ }
+
+ /**
+ * Edit project
+ *
+ * Enabled when a project is selected
+ */
+ @Action(enabledProperty = "selectedSingleProject")
+ public void editProject() {
+ TimerProject project = projectsAndTasksTable.getSelectedProjects().get(
+ 0);
+
+ String newProjectName = (String) JOptionPane.showInputDialog(getMainFrame(), resourceMap
+ .getString("input.editProjectMessage"), resourceMap
+ .getString("input.editProjectTitle"),
+ JOptionPane.INFORMATION_MESSAGE, null, null, project.getName());
+
+ if (newProjectName != null) {
+
+ // remove unneeded spaces
+ newProjectName = newProjectName.trim();
+
+ try {
+ core.getData().editProject(project, newProjectName);
+ } catch (DataViolationException e) {
+ displayErrorMessage(e.getExceptionKey());
+ }
+ }
+ }
+
+ /**
+ * Create new task action.
+ *
+ * Enabled when a project or a task is selected
+ */
+ @Action(enabledProperty = "selectedSingleElement")
+ public void newTask() {
+
+ // select task to add new task
+ TimerTask selectedTask = projectsAndTasksTable.getSelectedElements()
+ .get(0);
+
+ String taskName = JOptionPane.showInputDialog(getMainFrame(),
+ resourceMap.getString("input.newTaskMessage", selectedTask
+ .getName()), resourceMap
+ .getString("input.newTaskTitle"),
+ JOptionPane.QUESTION_MESSAGE);
+
+ if (taskName != null) {
+
+ // remove unneeded spaces
+ taskName = taskName.trim();
+
+ TimerTask t = new TimerTask(taskName);
+
+ // Fix creation date
+ t.setCreationDate(new Date());
+
+ try {
+ core.getData().addTask(selectedTask, t);
+ } catch (DataViolationException e) {
+ displayErrorMessage(e.getExceptionKey());
+ }
+ }
+
+ }
+
+ /**
+ * Edit task.
+ *
+ * Enabled when a task is selected
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void editTask() {
+
+ TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
+
+ TimerTaskEditor editor = new TimerTaskEditor(this, task, core);
+ editor.setLocationByPlatform(true);
+ editor.setVisible(true);
+ }
+
+ /**
+ * Start selected task in tree.
+ *
+ * If it not already been running
+ *
+ * @return TimerTask scheduled for start
+ * @see Task
+ */
+ @Action(enabledProperty = "selectedSingleStoppedTask")
+ public Task<?, ?> startTask() {
+
+ // search for selected task in tree
+ // can't be null
+ TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
+
+ RunTaskJob jobToRun = new RunTaskJob(this, task, core.getData());
+ core.getData().startTask(task);
+
+ return jobToRun;
+ }
+
+ /**
+ * Called by task job manager when task as been started.
+ *
+ * @param task started task
+ */
+ public void startedTask(TimerTask task) {
+ setSelectedSingleRunningTask(true);
+ setSelectedSingleStoppedTask(false);
+ }
+
+ /**
+ * Return job that manage running task.
+ *
+ * @param task timer task to get job
+ * @return job or null
+ */
+ protected RunTaskJob getJobForRunningTask(TimerTask task) {
+ RunTaskJob job = null;
+
+ TaskMonitor tm = getContext().getTaskMonitor();
+ for (Task t : tm.getTasks()) {
+ TimerTask localtask = ((RunTaskJob) t).getTask();
+ if (task.equals(localtask)) {
+ job = (RunTaskJob) t;
+ }
+ }
+
+ return job;
+ }
+
+ /**
+ * Stop selected task in tree.
+ *
+ * Verify if it has been started
+ */
+ @Action(enabledProperty = "selectedSingleRunningTask")
+ public void stopTask() {
+
+ // task can't be null
+ TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
+ stopTask(task);
+
+ }
+
+ /**
+ * Stop a task.
+ *
+ * Delegate method. Called by idle detect ?
+ * Called by delete method too.
+ *
+ * @param task task to stop
+ */
+ public void stopTask(TimerTask task) {
+
+ RunTaskJob rtt = getJobForRunningTask(task);
+ // test if task is already running
+ if (rtt != null) {
+ rtt.wantToStop();
+ core.getData().stopTask(task);
+
+ // re-enable/disable buttons
+ setSelectedSingleRunningTask(false);
+ setSelectedSingleStoppedTask(true);
+ }
+ }
+
+ /**
+ * Stop all running tasks.
+ */
+ public void stopAllTasks() {
+
+ TaskMonitor tm = getContext().getTaskMonitor();
+ for (Task t : tm.getTasks()) {
+ // task
+ TimerTask ttask = ((RunTaskJob) t).getTask();
+ stopTask(ttask);
+ }
+ }
+
+ /**
+ * Close project.
+ */
+ @Action(enabledProperty = "selectedSingleProject")
+ public void closeProject() {
+ TimerProject project = projectsAndTasksTable.getSelectedProjects().get(0);
+
+ core.getData().changeProjectCloseState(project);
+ }
+
+ /**
+ * Close task.
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void closeTask() {
+ TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
+
+ core.getData().changeTaskCloseState(task);
+ }
+
+ /**
+ * Delete project.
+ */
+ @Action(enabledProperty = "selectedSingleProject")
+ public void deleteProject() {
+
+ TimerProject project = projectsAndTasksTable.getSelectedProjects().get(
+ 0);
+
+ if (project != null) {
+ int confirm = JOptionPane.showConfirmDialog(getMainFrame(),
+ resourceMap.getString("input.deleteProjectMessage", project
+ .getName()), resourceMap
+ .getString("input.deleteProjectTitle"),
+ JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
+
+ if (confirm == JOptionPane.YES_OPTION) { // approved
+ try {
+ core.getData().deleteProject(project);
+ } catch (DataViolationException e) {
+ displayErrorMessage(e.getExceptionKey());
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * Delete task.
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void deleteTask() {
+
+ TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
+
+ if (task != null) {
+ int confirm = JOptionPane.showConfirmDialog(getMainFrame(),
+ resourceMap.getString("input.deleteTaskMessage", task
+ .getName()), resourceMap
+ .getString("input.deleteTaskTitle"),
+ JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
+
+ if (confirm == JOptionPane.YES_OPTION) { // approved
+ try {
+ stopTask(task);
+ core.getData().deleteTask(task);
+ } catch (DataViolationException e) {
+ displayErrorMessage(e.getExceptionKey());
+ }
+ }
+ }
+ }
+
+ /**
+ * Change show closed option.
+ *
+ * @param event action event
+ */
+ @Action
+ public void isShowClosed(ActionEvent event) {
+ JCheckBoxMenuItem source = (JCheckBoxMenuItem) event.getSource();
+ boolean showClosed = source.isSelected();
+ projectsAndTasksTable.setShowClosed(showClosed);
+ config.setShowClosed(showClosed);
+ }
+
+ /**
+ * Change close to systray option.
+ *
+ * @param event action event
+ */
+ @Action
+ public void isCloseToSystray(ActionEvent event) {
+ JCheckBoxMenuItem source = (JCheckBoxMenuItem) event.getSource();
+ boolean closeToSystray = source.isSelected();
+ config.setCloseToSystray(closeToSystray);
+ }
+
+ /**
+ * Change report first day of week.
+ */
+ @Action
+ public void isReportFirstDayOfWeek1() {
+ config.setReportFirstDayOfWeek(1);
+ }
+
+ /**
+ * Change report first day of week.
+ */
+ @Action
+ public void isReportFirstDayOfWeek2() {
+ config.setReportFirstDayOfWeek(2);
+ }
+
+ /**
+ * Change report first day of week.
+ */
+ @Action
+ public void isReportFirstDayOfWeek3() {
+ config.setReportFirstDayOfWeek(3);
+ }
+
+ /**
+ * Change report first day of week.
+ */
+ @Action
+ public void isReportFirstDayOfWeek4() {
+ config.setReportFirstDayOfWeek(4);
+ }
+
+ /**
+ * Change report first day of week.
+ */
+ @Action
+ public void isReportFirstDayOfWeek5() {
+ config.setReportFirstDayOfWeek(5);
+ }
+
+ /**
+ * Change report first day of week.
+ */
+ @Action
+ public void isReportFirstDayOfWeek6() {
+ config.setReportFirstDayOfWeek(6);
+ }
+
+ /**
+ * Change report first day of week.
+ */
+ @Action
+ public void isReportFirstDayOfWeek7() {
+ config.setReportFirstDayOfWeek(7);
+ }
+
+ /**
+ * Increment task time.
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void increment5Task() {
+ incrementTaskTime(5 * 60);
+ }
+
+ /**
+ * Increment task time.
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void increment30Task() {
+ incrementTaskTime(30 * 60);
+ }
+
+ /**
+ * Decrement task time.
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void decrement1Task() {
+ incrementTaskTime(-60);
+ }
+
+ /**
+ * Decrement task time.
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void decrement5Task() {
+ incrementTaskTime(-5 * 60);
+ }
+
+ /**
+ * Decrement task time.
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void decrement30Task() {
+ incrementTaskTime(-30 * 60);
+ }
+
+ /**
+ * Increment task time.
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void increment1Task() {
+ incrementTaskTime(60);
+ }
+
+ /**
+ * Increment task time.
+ *
+ * To decrement, set negative increment:)
+ *
+ * @param increment increment in seconds
+ */
+ protected void incrementTaskTime(long increment) {
+ TimerTask selectedTask = projectsAndTasksTable.getSelectedTasks()
+ .get(0);
+
+ // check if task is running
+ RunTaskJob job = getJobForRunningTask(selectedTask);
+ if (job != null) {
+ // task is running
+ // increment is in seconds !!!
+ job.incrementTaskTime(increment * 1000);
+ } else {
+ // task is not running
+ Date now = new Date();
+ long todayTime = selectedTask.getTime(now);
+
+ long newTodayTime = todayTime + increment;
+
+ try {
+ // check if + negative increment still positive
+ if (newTodayTime > 0) {
+ core.getData().changeTaskTime(selectedTask, now,
+ newTodayTime);
+ } else {
+ // force to 0
+ core.getData().changeTaskTime(selectedTask, now, 0L);
+ }
+ } catch (DataViolationException e) {
+ displayErrorMessage(e.getExceptionKey());
+ }
+ }
+ }
+
+ /**
+ * Reset task time to zero.
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void setToZero() {
+ TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
+ incrementTaskTime(-task.getTime(new Date()));
+ }
+
+ /**
+ * Merge multiples tasks action.
+ */
+ @Action(enabledProperty = "selectedMultiplesTasks")
+ public void mergeTasks() {
+ List<TimerTask> tasks = projectsAndTasksTable.getSelectedTasks();
+
+ TimerTask destinationTask = tasks.get(0);
+ List<TimerTask> otherTasks = tasks.subList(1, tasks.size());
+ int confirm = JOptionPane.showConfirmDialog(getMainFrame(),
+ resourceMap.getString("input.mergeTaskMessage", tasks.size(),
+ destinationTask.getName()), resourceMap
+ .getString("input.mergeTaskTitle"),
+ JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
+ if (confirm == JOptionPane.YES_OPTION) {
+
+ try {
+ core.getData().mergeTasks(destinationTask, otherTasks);
+ } catch (DataViolationException e) {
+ displayErrorMessage(e.getExceptionKey());
+ }
+ }
+ }
+
+ /**
+ * Add annotation action.
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void addAnnotation() {
+ // select task to add new annotation
+ TimerTask selectedTask = projectsAndTasksTable.getSelectedTasks()
+ .get(0);
+
+ String annotation = JOptionPane.showInputDialog(getMainFrame(),
+ resourceMap.getString("input.addAnnotationMessage",
+ selectedTask.getName()), resourceMap
+ .getString("input.addAnnotationTitle"),
+ JOptionPane.QUESTION_MESSAGE);
+
+ if (annotation != null) {
+ // remove useless spaces
+ annotation = annotation.trim();
+
+ try {
+ core.getData().addAnnotation(selectedTask, new Date(),
+ annotation);
+ } catch (DataViolationException e) {
+ displayErrorMessage(e.getExceptionKey());
+ }
+ }
+ }
+
+ /**
+ * Edit alert action.
+ */
+ @Action(enabledProperty = "selectedSingleTask")
+ public void editAlert() {
+ // select task to edit alert
+ TimerTask selectedTask = projectsAndTasksTable.getSelectedTasks()
+ .get(0);
+
+ AlertEditor alertEditor = new AlertEditor(this, core.getData(),
+ selectedTask);
+ show(alertEditor);
+ }
+
+ /**
+ * Create report.
+ */
+ @Action
+ public void makeReport() {
+ ReportView view = new ReportView(this, core);
+ show(view);
+ }
+
+ /**
+ * Show about frame.
+ */
+ @Action
+ public void about() {
+ HelpFrame aboutFrame = new HelpFrame(this);
+ show(aboutFrame);
+ }
+
+ /**
+ * Is selected project.
+ *
+ * @return selected project property
+ */
+ public boolean isSelectedSingleProject() {
+ return selectedSingleProject;
+ }
+
+ /**
+ * Change selected project property.
+ *
+ * @param selectedSingleProject selected project property
+ */
+ public void setSelectedSingleProject(boolean selectedSingleProject) {
+ boolean oldValue = this.selectedSingleProject;
+ this.selectedSingleProject = selectedSingleProject;
+ firePropertyChange("selectedSingleProject", oldValue,
+ selectedSingleProject);
+ }
+
+ /**
+ * Is selected task.
+ *
+ * @return selected task property
+ */
+ public boolean isSelectedSingleTask() {
+ return selectedSingleTask;
+ }
+
+ /**
+ * Change selected task property.
+ *
+ * @param selectedSingleTask selected task property
+ */
+ public void setSelectedSingleTask(boolean selectedSingleTask) {
+ boolean oldValue = this.selectedSingleTask;
+ this.selectedSingleTask = selectedSingleTask;
+ firePropertyChange("selectedSingleTask", oldValue, selectedSingleTask);
+ }
+
+ /**
+ * Is selected task or project.
+ *
+ * @return selected task or project property
+ */
+ public boolean isSelectedSingleElement() {
+ return selectedSingleElement;
+ }
+
+ /**
+ * Change selected task or project property.
+ *
+ * @param selectedSingleElement selected task or project property
+ */
+ public void setSelectedSingleElement(boolean selectedSingleElement) {
+ boolean oldValue = this.selectedSingleElement;
+ this.selectedSingleElement = selectedSingleElement;
+ firePropertyChange("selectedSingleElement", oldValue,
+ selectedSingleElement);
+ }
+
+ /**
+ * Is selected running task.
+ *
+ * @return the selectedSingleRunningTask
+ */
+ public boolean isSelectedSingleRunningTask() {
+ return selectedSingleRunningTask;
+ }
+
+ /**
+ * Change selected running task property.
+ *
+ * @param selectedSingleRunningTask selected running task property
+ */
+ public void setSelectedSingleRunningTask(boolean selectedSingleRunningTask) {
+ boolean oldValue = this.selectedSingleRunningTask;
+ this.selectedSingleRunningTask = selectedSingleRunningTask;
+ firePropertyChange("selectedSingleRunningTask", oldValue,
+ selectedSingleRunningTask);
+ }
+
+ /**
+ * Is selected non running task.
+ *
+ * @return selected non running task
+ */
+ public boolean isSelectedSingleStoppedTask() {
+ return selectedSingleStoppedTask;
+ }
+
+ /**
+ * Change selected non running task property.
+ *
+ * @param selectedSingleStoppedTask selected non running task
+ */
+ public void setSelectedSingleStoppedTask(boolean selectedSingleStoppedTask) {
+ boolean oldValue = this.selectedSingleStoppedTask;
+ this.selectedSingleStoppedTask = selectedSingleStoppedTask;
+ firePropertyChange("selectedSingleStoppedTask", oldValue,
+ selectedSingleStoppedTask);
+ }
+
+ /**
+ * Is selected multiples projects.
+ *
+ * @return selected multiples projects
+ */
+ public boolean isSelectedMultiplesProjects() {
+ return selectedMultiplesProjects;
+ }
+
+ /**
+ * Change selected multiples projects property.
+ *
+ * @param selectedMultiplesProjects selected multiples projects
+ */
+ public void setSelectedMultiplesProjects(boolean selectedMultiplesProjects) {
+ boolean oldValue = this.selectedMultiplesProjects;
+ this.selectedMultiplesProjects = selectedMultiplesProjects;
+ firePropertyChange("selectedMultiplesProjects", oldValue,
+ selectedMultiplesProjects);
+ }
+
+ /**
+ * Is selected multiples tasks.
+ *
+ * @return selected multiples tasks
+ */
+ public boolean isSelectedMultiplesTasks() {
+ return selectedMultiplesTasks;
+ }
+
+ /**
+ * Change selected multiples tasks property.
+ *
+ * @param selectedMultiplesTasks selected multiples tasks
+ */
+ public void setSelectedMultiplesTasks(boolean selectedMultiplesTasks) {
+ boolean oldValue = this.selectedMultiplesTasks;
+ this.selectedMultiplesTasks = selectedMultiplesTasks;
+ firePropertyChange("selectedMultiplesTasks", oldValue,
+ selectedMultiplesTasks);
+ }
+
+ /**
+ * Is selected multiples elements.
+ *
+ * @return selected multiples elements
+ */
+ public boolean isSelectedMultiplesElements() {
+ return selectedMultiplesElements;
+ }
+
+ /**
+ * Change selected multiples elements property.
+ *
+ * @param selectedMultiplesElements selected multiples elements
+ */
+ public void setSelectedMultiplesElements(boolean selectedMultiplesElements) {
+ boolean oldValue = this.selectedMultiplesElements;
+ this.selectedMultiplesElements = selectedMultiplesElements;
+ firePropertyChange("selectedMultiplesElements", oldValue,
+ selectedMultiplesElements);
+ }
+
+ /*
+ * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
+ */
+ @Override
+ public void valueChanged(TreeSelectionEvent e) {
+ // get selected elements
+ List<TimerTask> elements = projectsAndTasksTable.getSelectedElements();
+ List<TimerProject> projects = projectsAndTasksTable
+ .getSelectedProjects();
+ List<TimerTask> tasks = projectsAndTasksTable.getSelectedTasks();
+
+ // notify application that tree selection has changed
+ if (tasks.size() == 1 && projects.size() == 0) {
+ TimerTask task = tasks.get(0);
+ setSelectedSingleTask(true);
+
+ // ask for SAF job manager if task is running
+ RunTaskJob job = getJobForRunningTask(task);
+ if (job == null || job.isStopping()) {
+ setSelectedSingleStoppedTask(true);
+ setSelectedSingleRunningTask(false);
+ } else {
+ setSelectedSingleStoppedTask(false);
+ setSelectedSingleRunningTask(true);
+ }
+ setSelectedMultiplesTasks(false);
+ setSelectedSingleProject(false);
+ setSelectedMultiplesProjects(false);
+ } else {
+ setSelectedSingleTask(false);
+ setSelectedSingleStoppedTask(false);
+ setSelectedSingleRunningTask(false);
+
+ if (tasks.size() > 1) {
+ setSelectedMultiplesTasks(projects.size() == 0);
+ } else {
+ setSelectedSingleProject(tasks.size() == 0
+ && projects.size() == 1);
+ setSelectedMultiplesProjects(tasks.size() == 0
+ && projects.size() > 1);
+ }
+ }
+ setSelectedSingleElement(elements.size() == 1);
+ setSelectedMultiplesElements(elements.size() > 1);
+ }
+
+ /**
+ * Get action for named component.
+ *
+ * Util method.
+ *
+ * @param actionName action name
+ * @return swing action
+ */
+ protected javax.swing.Action getAction(String actionName) {
+ return getContext().getActionMap().get(actionName);
+ }
+
+ /**
+ * Show window
+ */
+ @Action
+ public void show() {
+ // TODO better code ? that use SAF methods ?
+ getMainFrame().setVisible(true);
+ getMainFrame().toFront();
+ }
+
+ /**
+ * Show window
+ */
+ @Action
+ public void hide() {
+ // TODO better code ? that use SAF methods ?
+ getMainFrame().setVisible(false);
+ }
+
+ /**
+ * Notified by job on pre idle detect.
+ */
+ public void preIdleDetect() {
+ systrayManager.preIdleDetect();
+ }
+
+ /**
+ * Notified by job on post idle detect.
+ */
+ public void postIdleDetect() {
+ systrayManager.postIdleDetect();
+ }
+
+ /*
+ * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
+ */
+ public void mouseClicked(MouseEvent e) {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Mouse clicked (" + e.getClickCount()
+ + " clics), source = "
+ + e.getSource().getClass().getName());
+ }
+
+ switch (e.getButton()) {
+
+ // clic gauche
+ case MouseEvent.BUTTON1:
+ // clic sur l'arbre des projets
+ if (e.getSource() == projectsAndTasksTable) {
+ // demarre la tache lors d'un double clic dessus
+ if (e.getClickCount() == 2) {
+
+ if (isSelectedSingleStoppedTask()) { // can only launch non running tasks
+ Task<?, ?> appTask = startTask();
+ if (appTask != null) {
+
+ // first, on dlb click stop all running tasks
+ stopAllTasks();
+
+ getContext().getTaskService().execute(appTask);
+ }
+ /* TODO EC-20100416 temp disable, called twice, can display
+ -1 task running :(
+ } else if (isSelectedSingleRunningTask()) {
+ TimerTask task = projectsAndTasksTable.getSelectedTasks().get(0);
+ stopTask(task); */
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("Non selected non running task to launch");
+ }
+ }
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("Single clic on tree, do nothing");
+ }
+ }
+ }
+ break;
+
+ // gestion du clic droit
+ case MouseEvent.BUTTON3:
+
+ // force task selection on rigth clic
+ TreePath path = projectsAndTasksTable.getPathForLocation(e.getX(),
+ e.getY());
+ int selectedRow = projectsAndTasksTable.getRowForPath(path);
+ projectsAndTasksTable.getSelectionModel().setSelectionInterval(
+ selectedRow, selectedRow);
+
+ // fix item selection
+ JPopupMenu menu = new JPopupMenu();
+
+ String[] actionNames = null;
+
+ // construct menu in function of selection
+ if (isSelectedSingleProject()) {
+ actionNames = new String[] { "newTask", "---", "newProject",
+ "editProject", "closeProject", "deleteProject" };
+ }
+
+ if (isSelectedSingleTask()) {
+ actionNames = new String[] { "startTask", "stopTask", "---",
+ "newTask", "editTask", "closeTask", "deleteTask",
+ "---", "addAnnotation", "editAlert", "increment1Task",
+ "increment5Task", "increment30Task", "decrement1Task",
+ "decrement5Task", "decrement30Task", "setToZero" };
+ }
+
+ if (isSelectedMultiplesTasks()) {
+ actionNames = new String[] { "mergeTasks" };
+ }
+
+ // case, right clic, but nothing selected
+ if (actionNames != null) {
+ addActionToMenu(menu, actionNames);
+
+ menu.show(e.getComponent(), e.getX(), e.getY());
+ }
+ }
+ }
+
+ public void mouseEntered(MouseEvent e) {
+ }
+
+ public void mouseExited(MouseEvent e) {
+ }
+
+ public void mousePressed(MouseEvent e) {
+ }
+
+ public void mouseReleased(MouseEvent e) {
+ }
+}
Deleted: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report/ReportView.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/ui/report/ReportView.java 2012-03-23 15:11:54 UTC (rev 2836)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report/ReportView.java 2012-03-25 21:15:46 UTC (rev 2840)
@@ -1,594 +0,0 @@
-/*
- * #%L
- * jTimer
- *
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2008 - 2012 CodeLutin, Chatellier Eric
- * %%
- * This program 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.
- *
- * This program 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 this program. If not, see
- * <http://www.gnu.org/licenses/gpl-3.0.html>.
- * #L%
- */
-
-package org.chorem.jtimer.ui.report;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Desktop;
-import java.awt.Font;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URLEncoder;
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.swing.BorderFactory;
-import javax.swing.ButtonGroup;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JComponent;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JRadioButton;
-import javax.swing.JScrollPane;
-import javax.swing.JSplitPane;
-import javax.swing.JTextArea;
-import javax.swing.JTree;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.chorem.jtimer.JTimer;
-import org.chorem.jtimer.data.TimerCore;
-import org.chorem.jtimer.entities.TimerProject;
-import org.chorem.jtimer.entities.TimerTask;
-import org.chorem.jtimer.ui.report.ReportGenerator.Type;
-import org.chorem.jtimer.ui.report.tree.CheckBoxTreeCellEditor;
-import org.chorem.jtimer.ui.report.tree.CheckBoxTreeCellRenderer;
-import org.chorem.jtimer.ui.report.tree.CheckBoxTreeModel;
-import org.jdesktop.application.Action;
-import org.jdesktop.application.Application;
-import org.jdesktop.application.FrameView;
-import org.jdesktop.swingx.JXDatePicker;
-
-/**
- * Reports UI.
- *
- * @author chatellier
- * @version $Revision$
- *
- * Last update : $Date$
- * By : $Author$
- */
-public class ReportView extends FrameView implements DocumentListener {
-
- /** Class logger */
- protected static Log log = LogFactory.getLog(ReportView.class);
-
- /** Timer core. */
- protected TimerCore core;
-
- /** Unselected task set. */
- protected Set<TimerTask> uncheckedTaskSet;
-
- /** Report sorting : day */
- protected JRadioButton radioByDay;
- /** Report sorting : month */
- protected JRadioButton radioByMonth;
- /** Report sorting : week */
- protected JRadioButton radioByWeek;
- /** Report sorting : year */
- protected JRadioButton radioByYear;
- /** Report sorting : project */
- protected JRadioButton radioByProject;
-
- /** Include annotations on reports */
- protected JCheckBox checkIncludesAnnotations;
- /** Include annotations time on reports */
- protected JCheckBox checkIncludesAnnotationsTime;
-
- /** Date pickers, from... to */
- protected JXDatePicker datePickerFrom, datePickerTo;
-
- /** Project tree (with checkbox) */
- protected JTree projectsTree;
-
- /** Show hidden project box. */
- protected JCheckBox showHiddenProjectBox;
-
- /** Report process generator */
- protected ReportGenerator reportGenerator;
-
- /** Report output */
- protected JTextArea reportArea;
-
- /** Can send mail property. */
- protected boolean canSendMail;
-
- /**
- * Reposts constructor.
- *
- * @param application parent reference
- * @param core core reference
- */
- public ReportView(Application application, TimerCore core) {
-
- super(application);
-
- // modify frame name
- // otherwise, get parent frame dimention
- getFrame().setName("reportFrame");
-
- this.core = core;
- this.uncheckedTaskSet = new HashSet<TimerTask>();
-
- // set title
- //setTitle(resourceMap.getString("reportTitle"));
-
- setComponent(getMainComponent());
-
- reportGenerator = new ReportGenerator();
-
- // reset selection
- //uncheckedTaskSet.clear();
- }
-
- /**
- * Get main view component.
- *
- * TODO use less complicated UI (no gbl)
- * @return main component
- */
- protected JComponent getMainComponent() {
-
- JPanel configComponent = new JPanel(new GridBagLayout());
-
- // panel for options
- JPanel panelOption = new JPanel(new GridBagLayout());
- panelOption.setBorder(BorderFactory.createTitledBorder(getResourceMap()
- .getString("reportOptions")));
-
- // first date picker
- JLabel labelFrom = new JLabel(getResourceMap().getString("reportFrom"));
- panelOption.add(labelFrom, new GridBagConstraints(0, 0, 1, 1, 0, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
- datePickerFrom = new JXDatePicker();
- datePickerFrom.getMonthView().setDayForeground(Calendar.SUNDAY, Color.RED);
- datePickerFrom.setFormats(DateFormat.getDateInstance(DateFormat.FULL));
- panelOption.add(datePickerFrom, new GridBagConstraints(1, 0, 2, 1, 1,
- 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
-
- // second date picker
- JLabel labelTo = new JLabel(getResourceMap().getString("reportTo"));
- panelOption.add(labelTo, new GridBagConstraints(0, 1, 1, 1, 0, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
- datePickerTo = new JXDatePicker();
- datePickerTo.getMonthView().setDayForeground(Calendar.SUNDAY, Color.RED);
- datePickerTo.setFormats(DateFormat.getDateInstance(DateFormat.FULL));
- panelOption.add(datePickerTo, new GridBagConstraints(1, 1, 2, 1, 0, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
-
- // set current week by default
- currentWeek();
-
- // action button to show current or previous week
- JButton currentWeekButton = new JButton();
- currentWeekButton.setAction(getContext().getActionMap(this).get(
- "currentWeek"));
- panelOption.add(currentWeekButton, new GridBagConstraints(3, 0, 1, 1, 0,
- 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
- JButton previousWeekButton = new JButton();
- previousWeekButton.setAction(getContext().getActionMap(this).get(
- "previousWeek"));
- panelOption.add(previousWeekButton, new GridBagConstraints(3, 1, 1, 1, 0,
- 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
-
- // Option for period grouping
- radioByDay = new JRadioButton(
- getResourceMap().getString("reportDaily"), true);
- radioByMonth = new JRadioButton(getResourceMap().getString(
- "reportMonthly"));
- radioByWeek = new JRadioButton(getResourceMap().getString(
- "reportWeekly"));
- radioByYear = new JRadioButton(getResourceMap().getString(
- "reportYearly"));
- radioByProject = new JRadioButton(getResourceMap().getString(
- "reportByProject"));
-
- ButtonGroup group = new ButtonGroup();
- group.add(radioByDay);
- group.add(radioByMonth);
- group.add(radioByWeek);
- group.add(radioByYear);
- group.add(radioByProject);
-
- panelOption.add(radioByDay, new GridBagConstraints(0, 2, 2, 1, 1, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
- panelOption.add(radioByMonth, new GridBagConstraints(2, 2, 2, 1, 1, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
- panelOption.add(radioByWeek, new GridBagConstraints(0, 3, 2, 1, 0, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
- panelOption.add(radioByYear, new GridBagConstraints(2, 3, 2, 1, 0, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
- panelOption.add(radioByProject, new GridBagConstraints(0, 4, 4, 1, 0,
- 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
-
- // miscellaneous
- checkIncludesAnnotations = new JCheckBox();
- checkIncludesAnnotations.setAction(getContext().getActionMap(this).get(
- "reportAnnotations"));
- panelOption.add(checkIncludesAnnotations, new GridBagConstraints(0, 5,
- 2, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
- checkIncludesAnnotationsTime = new JCheckBox(getResourceMap().getString(
- "reportAnnotationsTime"));
- checkIncludesAnnotationsTime.setEnabled(false);
- panelOption.add(checkIncludesAnnotationsTime, new GridBagConstraints(2, 5,
- 2, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
-
- // panel form projects
- JPanel panelProjects = new JPanel(new BorderLayout());
- panelProjects.setBorder(BorderFactory
- .createTitledBorder(getResourceMap()
- .getString("reportProjects")));
-
- // show hidden box
- showHiddenProjectBox = new JCheckBox(getContext().getActionMap(this)
- .get("showHiddenProjects"));
- panelProjects.add(showHiddenProjectBox, BorderLayout.NORTH);
-
- projectsTree = new JTree();
- projectsTree.setRootVisible(true);
- projectsTree.setEditable(true);
- projectsTree.setModel(new CheckBoxTreeModel(core, getResourceMap().getString("reportProjectsList") + " :"));
- projectsTree.setCellEditor(new CheckBoxTreeCellEditor(core, projectsTree,
- uncheckedTaskSet));
- projectsTree.setCellRenderer(new CheckBoxTreeCellRenderer(core, projectsTree,
- uncheckedTaskSet));
-
- JScrollPane jspTable = new JScrollPane(projectsTree);
- panelProjects.add(jspTable, BorderLayout.CENTER);
-
- configComponent.add(panelOption, new GridBagConstraints(0, 0, 1, 1, 0, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
-
- configComponent.add(panelProjects, new GridBagConstraints(0, 1, 1, 1, 1,
- 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
- new Insets(1, 1, 1, 1), 0, 0));
-
- // panel for report text
- JPanel panelReports = new JPanel(new GridBagLayout());
- panelReports.setBorder(BorderFactory.createTitledBorder(getResourceMap()
- .getString("reportContent")));
-
- reportArea = new JTextArea();
- reportArea.setFont(new Font("Courier", Font.PLAIN, 12));
- reportArea.getDocument().addDocumentListener(this);
- JScrollPane jspReport = new JScrollPane(reportArea);
- panelReports.add(jspReport, new GridBagConstraints(0, 0, 3, 1, 1, 1,
- GridBagConstraints.CENTER, GridBagConstraints.BOTH,
- new Insets(1, 1, 1, 1), 0, 0));
-
- // buttons
- JButton generateButton = new JButton();
- generateButton.setAction(getContext().getActionMap(this).get(
- "generateReport"));
- panelReports.add(generateButton, new GridBagConstraints(0, 1, 1, 1, 1,
- 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
-
- JButton sendMailButton = new JButton();
- sendMailButton.setAction(getContext().getActionMap(this)
- .get("sendMail"));
- panelReports.add(sendMailButton, new GridBagConstraints(1, 1, 1, 1, 1,
- 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
-
- JButton closeButton = new JButton();
- closeButton.setAction(getContext().getActionMap(this).get("closeView"));
- panelReports.add(closeButton, new GridBagConstraints(2, 1, 1, 1, 1, 0,
- GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- new Insets(1, 1, 1, 1), 0, 0));
-
- JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, configComponent, panelReports);
- splitPane.setOneTouchExpandable(true);
- return splitPane;
- }
-
- /**
- * Select current week in date pickers.
- */
- @Action
- public void currentWeek() {
- fillPickerDates(0);
- }
-
- /**
- * Display previous week in date pickers.
- */
- @Action
- public void previousWeek() {
- fillPickerDates(-1);
- }
-
- /**
- * Fill picker date with predefined week selection (from current)
- * and apply a delay (-1 = previous week).
- *
- * @param delay delay to add to current week
- */
- protected void fillPickerDates(int delay) {
- // init dates
- Calendar calendarBegin = Calendar.getInstance();
- int firstDayOfWeek = JTimer.config.getReportFirstDayOfWeek();
- if (firstDayOfWeek <= 0 || firstDayOfWeek > 7) {
- firstDayOfWeek = calendarBegin.getFirstDayOfWeek();
- }
- calendarBegin.set(Calendar.DAY_OF_WEEK, firstDayOfWeek);
- calendarBegin.set(Calendar.HOUR, 0);
- calendarBegin.set(Calendar.MINUTE, 0);
- calendarBegin.set(Calendar.SECOND, 0);
- calendarBegin.set(Calendar.MILLISECOND, 0);
-
- // calendar must be in current week by default
- if (calendarBegin.getTime().after(new Date())) {
- calendarBegin.add(Calendar.WEEK_OF_YEAR, -1);
- }
-
- // get end of week
- // take calendarBegin and add a week time
- Calendar calendarEnd = (Calendar) calendarBegin.clone();
- calendarEnd.add(Calendar.WEEK_OF_YEAR, 1);
- calendarEnd.add(Calendar.DAY_OF_YEAR, -1); // take the day before
-
- // apply delai
- calendarBegin.add(Calendar.WEEK_OF_YEAR, delay);
- calendarEnd.add(Calendar.WEEK_OF_YEAR, delay);
-
- datePickerFrom.setDate(calendarBegin.getTime());
- datePickerTo.setDate(calendarEnd.getTime());
- }
-
- /**
- * Close action.
- */
- @Action
- public void closeView() {
- getApplication().hide(this);
- }
-
- /**
- * Show annotation checkbox checked.
- */
- @Action
- public void reportAnnotations() {
- checkIncludesAnnotationsTime.setEnabled(checkIncludesAnnotations.isSelected());
- }
-
- /**
- * Make report.
- *
- * Set content in {@link #reportArea} text area.
- */
- @Action
- public void generateReport() {
-
- // Choose selected project type
- Type reportType = null;
- if (radioByDay.isSelected()) {
- reportType = Type.BY_DAY_REPORT;
- } else if (radioByMonth.isSelected()) {
- reportType = Type.BY_MONTH_REPORT;
- } else if (radioByWeek.isSelected()) {
- reportType = Type.BY_WEEK_REPORT;
- } else if (radioByYear.isSelected()) {
- reportType = Type.BY_YEAR_REPORT;
- } else {
- reportType = Type.BY_PROJECT_REPORT;
- }
-
- // get filtred project list
- // without non selected projet and tasks
- List<TimerProject> selectedProjects = getSelectedProjects(core
- .getData().getProjectsList(), uncheckedTaskSet);
-
- // make report
- String report = reportGenerator.getReportText(reportType,
- selectedProjects, datePickerFrom.getDate(), datePickerTo
- .getDate(), checkIncludesAnnotations.isSelected(),
- checkIncludesAnnotationsTime.isSelected());
-
- if (report != null && !report.isEmpty()) {
- reportArea.setText(report);
- } else {
- reportArea.setText("");
- }
- }
-
- /**
- * Get project list without project and task unselected in tree.
- *
- * @param projects original project list
- * @param uncheckedTaskList unselected task list
- * @return selected project list
- */
- protected List<TimerProject> getSelectedProjects(
- List<TimerProject> projects, Collection<TimerTask> uncheckedTaskList) {
-
- List<TimerProject> currentProjects = new ArrayList<TimerProject>();
- for (TimerProject project : projects) {
- if (!uncheckedTaskList.contains(project)) {
- TimerProject clonedProject = project.clone();
- clonedProject.getSubTasks().clear();
- clonedProject.getSubTasks().addAll(
- getSelectedTasks(project.getSubTasks(),
- uncheckedTaskList));
- currentProjects.add(clonedProject);
- }
- }
-
- return currentProjects;
- }
-
- /**
- * Get tasks list without tasks unselected in tree.
- *
- * @param tasks original project list
- * @param uncheckedTaskList unselected task list
- * @return selected project list
- */
- protected List<TimerTask> getSelectedTasks(List<? extends TimerTask> tasks,
- Collection<TimerTask> uncheckedTaskList) {
-
- List<TimerTask> currentTask = new ArrayList<TimerTask>();
- for (TimerTask task : tasks) {
- if (!uncheckedTaskList.contains(task)) {
- TimerTask clonedTask = task.clone();
- clonedTask.getSubTasks().clear();
- clonedTask.getSubTasks()
- .addAll(
- getSelectedTasks(task.getSubTasks(),
- uncheckedTaskList));
- currentTask.add(clonedTask);
- }
- }
-
- return currentTask;
- }
-
- /**
- * Update tree, showing hidden projects or not.
- */
- @Action
- public void showHiddenProjects() {
- CheckBoxTreeModel model = (CheckBoxTreeModel)projectsTree.getModel();
- model.setShowClosed(showHiddenProjectBox.isSelected());
- }
-
- /**
- * Send report by mail.
- */
- @Action(enabledProperty = "sendMailEnabled")
- public void sendMail() {
-
- String report = reportArea.getText();
-
- try {
- String encodedReport = URLEncoder.encode(report, "UTF-8");
-
- // bugfix for spaces
- encodedReport = encodedReport.replaceAll("\\+", "%20");
-
- URI mailtoURI = new URI("mailto:?body=" + encodedReport);
- Desktop.getDesktop().mail(mailtoURI);
- } catch (IOException e) {
- if (log.isWarnEnabled()) {
- log.warn("Cannot open link (maybe defaut browser in not configured ?)");
- }
- if (log.isDebugEnabled()) {
- log.debug("Error while opening link", e);
- }
- } catch (URISyntaxException e) {
- if (log.isErrorEnabled()) {
- log.error("Error while opening link", e);
- }
- } catch (UnsupportedOperationException e) {
- if (log.isWarnEnabled()) {
- log.warn("Cannot open link (maybe defaut browser in not configured ?)");
- }
- if (log.isDebugEnabled()) {
- log.debug("Error while opening link", e);
- }
- }
- }
-
- /**
- * Can send mail ?
- *
- * @return true if can send mail
- */
- public boolean isSendMailEnabled() {
- return canSendMail;
- }
-
- /**
- * Change can send mail property.
- *
- * @param enabled can send mail
- */
- public void setSendMailEnabled(boolean enabled) {
- boolean oldValue = canSendMail;
- canSendMail = enabled;
- firePropertyChange("sendMailEnabled", oldValue, canSendMail);
- }
-
- /*
- * @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
- */
- @Override
- public void changedUpdate(DocumentEvent e) {
- documentChanged();
- }
-
- /*
- * @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.DocumentEvent)
- */
- @Override
- public void insertUpdate(DocumentEvent e) {
- documentChanged();
- }
-
- /*
- * @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.DocumentEvent)
- */
- @Override
- public void removeUpdate(DocumentEvent e) {
- documentChanged();
- }
-
- /**
- * Document content changed.
- *
- * Update can send mail property.
- */
- protected void documentChanged() {
- setSendMailEnabled(reportArea.getText().trim().length() > 0);
- }
-}
Copied: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report/ReportView.java (from rev 2838, trunk/src/main/java/org/chorem/jtimer/ui/report/ReportView.java)
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report/ReportView.java (rev 0)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/report/ReportView.java 2012-03-25 21:15:46 UTC (rev 2840)
@@ -0,0 +1,613 @@
+/*
+ * #%L
+ * jTimer
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2008 - 2012 CodeLutin, Chatellier Eric
+ * %%
+ * This program 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.
+ *
+ * This program 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 this program. If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+package org.chorem.jtimer.ui.report;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Desktop;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTextArea;
+import javax.swing.JTree;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.chorem.jtimer.JTimer;
+import org.chorem.jtimer.data.TimerCore;
+import org.chorem.jtimer.entities.TimerProject;
+import org.chorem.jtimer.entities.TimerTask;
+import org.chorem.jtimer.ui.report.ReportGenerator.Type;
+import org.chorem.jtimer.ui.report.tree.CheckBoxTreeCellEditor;
+import org.chorem.jtimer.ui.report.tree.CheckBoxTreeCellRenderer;
+import org.chorem.jtimer.ui.report.tree.CheckBoxTreeModel;
+import org.jdesktop.application.Action;
+import org.jdesktop.application.Application;
+import org.jdesktop.application.FrameView;
+import org.jdesktop.swingx.JXDatePicker;
+
+/**
+ * Reports UI.
+ *
+ * @author chatellier
+ * @version $Revision$
+ *
+ * Last update : $Date$
+ * By : $Author$
+ */
+public class ReportView extends FrameView implements DocumentListener {
+
+ /** Class logger */
+ protected static Log log = LogFactory.getLog(ReportView.class);
+
+ /** Timer core. */
+ protected TimerCore core;
+
+ /** Unselected task set. */
+ protected Set<TimerTask> uncheckedTaskSet;
+
+ /** Report sorting : day */
+ protected JRadioButton radioByDay;
+ /** Report sorting : month */
+ protected JRadioButton radioByMonth;
+ /** Report sorting : week */
+ protected JRadioButton radioByWeek;
+ /** Report sorting : year */
+ protected JRadioButton radioByYear;
+ /** Report sorting : project */
+ protected JRadioButton radioByProject;
+
+ /** Include annotations on reports */
+ protected JCheckBox checkIncludesAnnotations;
+ /** Include annotations time on reports */
+ protected JCheckBox checkIncludesAnnotationsTime;
+
+ /** Date pickers, from... to */
+ protected JXDatePicker datePickerFrom, datePickerTo;
+
+ /** Project tree (with checkbox) */
+ protected JTree projectsTree;
+
+ /** Show hidden project box. */
+ protected JCheckBox showHiddenProjectBox;
+
+ /** Report process generator */
+ protected ReportGenerator reportGenerator;
+
+ /** Report output */
+ protected JTextArea reportArea;
+
+ /** Can send mail property. */
+ protected boolean canSendMail;
+
+ /**
+ * Reposts constructor.
+ *
+ * @param application parent reference
+ * @param core core reference
+ */
+ public ReportView(Application application, TimerCore core) {
+
+ super(application);
+
+ // modify frame name
+ // otherwise, get parent frame dimention
+ getFrame().setName("reportFrame");
+
+ this.core = core;
+ this.uncheckedTaskSet = new HashSet<TimerTask>();
+
+ // set title
+ //setTitle(resourceMap.getString("reportTitle"));
+
+ setComponent(getMainComponent());
+
+ reportGenerator = new ReportGenerator();
+
+ // reset selection
+ //uncheckedTaskSet.clear();
+ }
+
+ /**
+ * Get main view component.
+ *
+ * TODO use less complicated UI (no gbl)
+ * @return main component
+ */
+ protected JComponent getMainComponent() {
+
+ JPanel configComponent = new JPanel(new GridBagLayout());
+
+ // panel for options
+ JPanel panelOption = new JPanel(new GridBagLayout());
+ panelOption.setBorder(BorderFactory.createTitledBorder(getResourceMap()
+ .getString("reportOptions")));
+
+ // first date picker
+ JLabel labelFrom = new JLabel(getResourceMap().getString("reportFrom"));
+ panelOption.add(labelFrom, new GridBagConstraints(0, 0, 1, 1, 0, 0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+ datePickerFrom = new JXDatePicker();
+ datePickerFrom.getMonthView().setDayForeground(Calendar.SUNDAY, Color.RED);
+ datePickerFrom.setFormats(DateFormat.getDateInstance(DateFormat.FULL));
+ panelOption.add(datePickerFrom, new GridBagConstraints(1, 0, 2, 1, 1,
+ 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+
+ // second date picker
+ JLabel labelTo = new JLabel(getResourceMap().getString("reportTo"));
+ panelOption.add(labelTo, new GridBagConstraints(0, 1, 1, 1, 0, 0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+ datePickerTo = new JXDatePicker();
+ datePickerTo.getMonthView().setDayForeground(Calendar.SUNDAY, Color.RED);
+ datePickerTo.setFormats(DateFormat.getDateInstance(DateFormat.FULL));
+ panelOption.add(datePickerTo, new GridBagConstraints(1, 1, 2, 1, 0, 0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+
+ // set current week by default
+ currentWeek();
+
+ // action button to show current or previous week
+ JButton currentWeekButton = new JButton();
+ currentWeekButton.setAction(getContext().getActionMap(this).get(
+ "currentWeek"));
+ panelOption.add(currentWeekButton, new GridBagConstraints(3, 0, 1, 1, 0,
+ 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+ JButton previousWeekButton = new JButton();
+ previousWeekButton.setAction(getContext().getActionMap(this).get(
+ "previousWeek"));
+ panelOption.add(previousWeekButton, new GridBagConstraints(3, 1, 1, 1, 0,
+ 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+
+ // Option for period grouping
+ radioByDay = new JRadioButton(
+ getResourceMap().getString("reportDaily"), true);
+ radioByMonth = new JRadioButton(getResourceMap().getString(
+ "reportMonthly"));
+ radioByWeek = new JRadioButton(getResourceMap().getString(
+ "reportWeekly"));
+ radioByYear = new JRadioButton(getResourceMap().getString(
+ "reportYearly"));
+ radioByProject = new JRadioButton(getResourceMap().getString(
+ "reportByProject"));
+
+ ButtonGroup group = new ButtonGroup();
+ group.add(radioByDay);
+ group.add(radioByMonth);
+ group.add(radioByWeek);
+ group.add(radioByYear);
+ group.add(radioByProject);
+
+ panelOption.add(radioByDay, new GridBagConstraints(0, 2, 2, 1, 1, 0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+ panelOption.add(radioByMonth, new GridBagConstraints(2, 2, 2, 1, 1, 0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+ panelOption.add(radioByWeek, new GridBagConstraints(0, 3, 2, 1, 0, 0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+ panelOption.add(radioByYear, new GridBagConstraints(2, 3, 2, 1, 0, 0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+ panelOption.add(radioByProject, new GridBagConstraints(0, 4, 4, 1, 0,
+ 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+
+ // miscellaneous
+ checkIncludesAnnotations = new JCheckBox();
+ checkIncludesAnnotations.setAction(getContext().getActionMap(this).get(
+ "reportAnnotations"));
+ panelOption.add(checkIncludesAnnotations, new GridBagConstraints(0, 5,
+ 2, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+ checkIncludesAnnotationsTime = new JCheckBox(getResourceMap().getString(
+ "reportAnnotationsTime"));
+ checkIncludesAnnotationsTime.setEnabled(false);
+ panelOption.add(checkIncludesAnnotationsTime, new GridBagConstraints(2, 5,
+ 2, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+
+ // panel form projects
+ JPanel panelProjects = new JPanel(new BorderLayout());
+ panelProjects.setBorder(BorderFactory
+ .createTitledBorder(getResourceMap()
+ .getString("reportProjects")));
+
+ // show hidden box
+ showHiddenProjectBox = new JCheckBox(getContext().getActionMap(this)
+ .get("showHiddenProjects"));
+ panelProjects.add(showHiddenProjectBox, BorderLayout.NORTH);
+
+ projectsTree = new JTree();
+ projectsTree.setRootVisible(true);
+ projectsTree.setEditable(true);
+ projectsTree.setModel(new CheckBoxTreeModel(core, getResourceMap().getString("reportProjectsList") + " :"));
+ projectsTree.setCellEditor(new CheckBoxTreeCellEditor(core, projectsTree,
+ uncheckedTaskSet));
+ projectsTree.setCellRenderer(new CheckBoxTreeCellRenderer(core, projectsTree,
+ uncheckedTaskSet));
+
+ JScrollPane jspTable = new JScrollPane(projectsTree);
+ panelProjects.add(jspTable, BorderLayout.CENTER);
+
+ configComponent.add(panelOption, new GridBagConstraints(0, 0, 1, 1, 0, 0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+
+ configComponent.add(panelProjects, new GridBagConstraints(0, 1, 1, 1, 1,
+ 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+ new Insets(1, 1, 1, 1), 0, 0));
+
+ // panel for report text
+ JPanel panelReports = new JPanel(new GridBagLayout());
+ panelReports.setBorder(BorderFactory.createTitledBorder(getResourceMap()
+ .getString("reportContent")));
+
+ reportArea = new JTextArea();
+ reportArea.setFont(new Font("Courier", Font.PLAIN, 12));
+ reportArea.getDocument().addDocumentListener(this);
+ JScrollPane jspReport = new JScrollPane(reportArea);
+ panelReports.add(jspReport, new GridBagConstraints(0, 0, 3, 1, 1, 1,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH,
+ new Insets(1, 1, 1, 1), 0, 0));
+
+ // buttons
+ JButton generateButton = new JButton();
+ generateButton.setAction(getContext().getActionMap(this).get(
+ "generateReport"));
+ panelReports.add(generateButton, new GridBagConstraints(0, 1, 1, 1, 1,
+ 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+
+ JButton sendMailButton = new JButton();
+ sendMailButton.setAction(getContext().getActionMap(this)
+ .get("sendMail"));
+ panelReports.add(sendMailButton, new GridBagConstraints(1, 1, 1, 1, 1,
+ 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+
+ JButton closeButton = new JButton();
+ closeButton.setAction(getContext().getActionMap(this).get("closeView"));
+ panelReports.add(closeButton, new GridBagConstraints(2, 1, 1, 1, 1, 0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
+
+ JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, configComponent, panelReports);
+ splitPane.setOneTouchExpandable(true);
+ return splitPane;
+ }
+
+ /**
+ * Select current week in date pickers.
+ */
+ @Action
+ public void currentWeek() {
+ fillPickerDates(0);
+ }
+
+ /**
+ * Display previous week in date pickers.
+ */
+ @Action
+ public void previousWeek() {
+ fillPickerDates(-1);
+ }
+
+ /**
+ * Fill picker date with predefined week selection (from current)
+ * and apply a delay (-1 = previous week).
+ *
+ * @param delay delay to add to current week
+ */
+ protected void fillPickerDates(int delay) {
+ // init dates
+ Calendar calendarBegin = Calendar.getInstance();
+ int firstDayOfWeek = JTimer.config.getReportFirstDayOfWeek();
+ if (firstDayOfWeek <= 0 || firstDayOfWeek > 7) {
+ firstDayOfWeek = calendarBegin.getFirstDayOfWeek();
+ }
+ calendarBegin.set(Calendar.DAY_OF_WEEK, firstDayOfWeek);
+ calendarBegin.set(Calendar.HOUR, 0);
+ calendarBegin.set(Calendar.MINUTE, 0);
+ calendarBegin.set(Calendar.SECOND, 0);
+ calendarBegin.set(Calendar.MILLISECOND, 0);
+
+ // calendar must be in current week by default
+ if (calendarBegin.getTime().after(new Date())) {
+ calendarBegin.add(Calendar.WEEK_OF_YEAR, -1);
+ }
+
+ // get end of week
+ // take calendarBegin and add a week time
+ Calendar calendarEnd = (Calendar) calendarBegin.clone();
+ calendarEnd.add(Calendar.WEEK_OF_YEAR, 1);
+ calendarEnd.add(Calendar.DAY_OF_YEAR, -1); // take the day before
+
+ // apply delai
+ calendarBegin.add(Calendar.WEEK_OF_YEAR, delay);
+ calendarEnd.add(Calendar.WEEK_OF_YEAR, delay);
+
+ datePickerFrom.setDate(calendarBegin.getTime());
+ datePickerTo.setDate(calendarEnd.getTime());
+ }
+
+ /**
+ * Close action.
+ */
+ @Action
+ public void closeView() {
+ getApplication().hide(this);
+ }
+
+ /**
+ * Show annotation checkbox checked.
+ */
+ @Action
+ public void reportAnnotations() {
+ checkIncludesAnnotationsTime.setEnabled(checkIncludesAnnotations.isSelected());
+ }
+
+ /**
+ * Make report.
+ *
+ * Set content in {@link #reportArea} text area.
+ */
+ @Action
+ public void generateReport() {
+
+ // Choose selected project type
+ Type reportType = null;
+ if (radioByDay.isSelected()) {
+ reportType = Type.BY_DAY_REPORT;
+ } else if (radioByMonth.isSelected()) {
+ reportType = Type.BY_MONTH_REPORT;
+ } else if (radioByWeek.isSelected()) {
+ reportType = Type.BY_WEEK_REPORT;
+ } else if (radioByYear.isSelected()) {
+ reportType = Type.BY_YEAR_REPORT;
+ } else {
+ reportType = Type.BY_PROJECT_REPORT;
+ }
+
+ // get filtered project list
+ // without non selected project and tasks
+ List<TimerProject> selectedProjects = getSelectedProjects(core
+ .getData().getProjectsList(), uncheckedTaskSet);
+
+ // make report
+ String report = reportGenerator.getReportText(reportType,
+ selectedProjects, datePickerFrom.getDate(), datePickerTo
+ .getDate(), checkIncludesAnnotations.isSelected(),
+ checkIncludesAnnotationsTime.isSelected());
+
+ if (report != null && !report.isEmpty()) {
+ reportArea.setText(report);
+ } else {
+ reportArea.setText("");
+ }
+ }
+
+ /**
+ * Get project list without project and task unselected in tree.
+ *
+ * @param projects original project list
+ * @param uncheckedTaskList unselected task list
+ * @return selected project list
+ */
+ protected List<TimerProject> getSelectedProjects(
+ List<TimerProject> projects, Collection<TimerTask> uncheckedTaskList) {
+
+ List<TimerProject> currentProjects = new ArrayList<TimerProject>();
+ for (TimerProject project : projects) {
+
+ // take care of show closed option
+ if (!project.isClosed() || showHiddenProjectBox.isSelected()) {
+ List<TimerTask> subTasks = getSelectedTasks(project.getSubTasks(),
+ uncheckedTaskList);
+
+ // add current project only of at least one subtask is selected
+ // or current project is selected
+ if (!uncheckedTaskList.contains(project) || !subTasks.isEmpty()) {
+ TimerProject clonedProject = project.clone();
+ clonedProject.getSubTasks().clear();
+ clonedProject.getSubTasks().addAll(subTasks);
+ currentProjects.add(clonedProject);
+ }
+ }
+ }
+
+ return currentProjects;
+ }
+
+ /**
+ * Get tasks list without tasks unselected in tree.
+ *
+ * @param tasks original project list
+ * @param uncheckedTaskList unselected task list
+ * @return selected project list
+ */
+ protected List<TimerTask> getSelectedTasks(List<? extends TimerTask> tasks,
+ Collection<TimerTask> uncheckedTaskList) {
+
+ List<TimerTask> currentTask = new ArrayList<TimerTask>();
+ for (TimerTask task : tasks) {
+
+ // take care of show closed option
+ if (!task.isClosed() || showHiddenProjectBox.isSelected()) {
+ List<TimerTask> subTasks = getSelectedTasks(task.getSubTasks(),
+ uncheckedTaskList);
+
+ // add current task only of at least one subtask is selected
+ // or current task is selected
+ if (!uncheckedTaskList.contains(task) || !subTasks.isEmpty()) {
+ TimerTask clonedTask;
+ if (uncheckedTaskList.contains(task)) {
+ // to not show time of not selected task in report
+ clonedTask = new TimerTask(task.getName());
+ } else {
+ clonedTask = task.clone();
+ }
+ clonedTask.getSubTasks().clear();
+ clonedTask.getSubTasks().addAll(subTasks);
+ currentTask.add(clonedTask);
+ }
+ }
+ }
+
+ return currentTask;
+ }
+
+ /**
+ * Update tree, showing hidden projects or not.
+ */
+ @Action
+ public void showHiddenProjects() {
+ CheckBoxTreeModel model = (CheckBoxTreeModel)projectsTree.getModel();
+ model.setShowClosed(showHiddenProjectBox.isSelected());
+ }
+
+ /**
+ * Send report by mail.
+ */
+ @Action(enabledProperty = "sendMailEnabled")
+ public void sendMail() {
+
+ String report = reportArea.getText();
+
+ try {
+ String encodedReport = URLEncoder.encode(report, "UTF-8");
+
+ // bugfix for spaces
+ encodedReport = encodedReport.replaceAll("\\+", "%20");
+
+ URI mailtoURI = new URI("mailto:?body=" + encodedReport);
+ Desktop.getDesktop().mail(mailtoURI);
+ } catch (IOException e) {
+ if (log.isWarnEnabled()) {
+ log.warn("Cannot open link (maybe defaut browser in not configured ?)");
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Error while opening link", e);
+ }
+ } catch (URISyntaxException e) {
+ if (log.isErrorEnabled()) {
+ log.error("Error while opening link", e);
+ }
+ } catch (UnsupportedOperationException e) {
+ if (log.isWarnEnabled()) {
+ log.warn("Cannot open link (maybe defaut browser in not configured ?)");
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Error while opening link", e);
+ }
+ }
+ }
+
+ /**
+ * Can send mail ?
+ *
+ * @return true if can send mail
+ */
+ public boolean isSendMailEnabled() {
+ return canSendMail;
+ }
+
+ /**
+ * Change can send mail property.
+ *
+ * @param enabled can send mail
+ */
+ public void setSendMailEnabled(boolean enabled) {
+ boolean oldValue = canSendMail;
+ canSendMail = enabled;
+ firePropertyChange("sendMailEnabled", oldValue, canSendMail);
+ }
+
+ /*
+ * @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
+ */
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ documentChanged();
+ }
+
+ /*
+ * @see javax.swing.event.DocumentListener#insertUpdate(javax.swing.event.DocumentEvent)
+ */
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ documentChanged();
+ }
+
+ /*
+ * @see javax.swing.event.DocumentListener#removeUpdate(javax.swing.event.DocumentEvent)
+ */
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ documentChanged();
+ }
+
+ /**
+ * Document content changed.
+ *
+ * Update can send mail property.
+ */
+ protected void documentChanged() {
+ setSendMailEnabled(reportArea.getText().trim().length() > 0);
+ }
+}
Deleted: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java 2012-03-23 15:11:54 UTC (rev 2836)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java 2012-03-25 21:15:46 UTC (rev 2840)
@@ -1,449 +0,0 @@
-/*
- * #%L
- * jTimer
- *
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2007 - 2012 CodeLutin, Chatellier Eric
- * %%
- * This program 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.
- *
- * This program 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 this program. If not, see
- * <http://www.gnu.org/licenses/gpl-3.0.html>.
- * #L%
- */
-
-package org.chorem.jtimer.ui.tasks;
-
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-
-import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
-
-import org.apache.commons.lang3.time.DurationFormatUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.chorem.jtimer.JTimer;
-import org.chorem.jtimer.data.TimerDataManager;
-import org.chorem.jtimer.entities.TimerAlert;
-import org.chorem.jtimer.entities.TimerTask;
-import org.chorem.jtimer.entities.TimerTaskHelper;
-import org.chorem.jtimer.entities.TimerAlert.Type;
-import org.chorem.jtimer.ui.system.SystemInfo;
-import org.chorem.jtimer.ui.system.SystemInfoFactory;
-import org.chorem.jtimer.ui.system.UnsupportedSystemInfoException;
-import org.jdesktop.application.Task;
-
-/**
- * RunTaskJob.
- *
- * Notify every second the core controler.
- *
- * @author chatellier
- * @version $Revision$
- *
- * Last update : $Date$
- * By : $Author$
- */
-public class RunTaskJob extends Task<Void, Long> {
-
- /** Class logger. */
- private static Log log = LogFactory.getLog(RunTaskJob.class);
-
- /** Parent app reference. */
- protected JTimer parentApp;
-
- /** The task to manage. */
- protected TimerTask managedTask;
-
- /** Data manager. */
- protected TimerDataManager dataManager;
-
- /** System information (idle...). */
- protected SystemInfo systemInfo;
-
- /** Already thrown alert. */
- protected Collection<TimerAlert> alreadyTrownAlerts;
-
- /** The today total task time at start time. */
- protected long taskTimingBeforeStartInMs;
-
- /** Calendar instance when timing start. */
- protected Calendar taskStartCalendar;
-
- /**
- * Offset to adjust time for current day.
- * Include :
- * - Task idle time (task was running but time not counted)
- * - Manual user incremented time
- */
- protected long offsetTimeInMs;
-
- /** Last publish time to detect hibernate. */
- protected long lastPublishTimestamp;
-
- /** Want to stop flag. */
- protected Boolean bWantToStop;
-
- /**
- * Constructor.
- *
- * Take the task to manage
- *
- * @param parentApp parent application
- * @param managedTask task
- * @param dataManager data
- */
- public RunTaskJob(JTimer parentApp, TimerTask managedTask,
- TimerDataManager dataManager) {
- super(parentApp);
- this.parentApp = parentApp;
-
- // init with False
- bWantToStop = Boolean.FALSE;
-
- // save vars
- this.managedTask = managedTask;
- this.dataManager = dataManager;
-
- // must be init here, checkAlreadyThrownAlerts is called multiples times
- alreadyTrownAlerts = new HashSet<TimerAlert>();
- checkAlreadyThrownAlerts(managedTask);
-
- // init system info to get idleTime
- try {
- systemInfo = SystemInfoFactory.getSystemInfo();
- } catch (UnsupportedSystemInfoException e) {
- if (log.isErrorEnabled()) {
- log.error("Can't get system info", e);
- }
- systemInfo = null;
- }
- }
-
- /**
- * Check for already thrown alerts.
- *
- * Used to not fired again already fired alerts during previous
- * timing.
- *
- * @param task current task
- */
- protected void checkAlreadyThrownAlerts(TimerTask task) {
-
- 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()) {
- alreadyTrownAlerts.add(alert.clone());
- } else if (alert.getType().equals(Type.REACH_TOTAL_TIME)
- && TimerTaskHelper.getAllTotalTime(task) > alert.getDuration()) {
- alreadyTrownAlerts.add(alert.clone());
- }
- }
-
- // se souvient aussi de alerte deja lancées
- // pour les taches parentes
- if (task.getParent() != null) {
- checkAlreadyThrownAlerts(task.getParent());
- }
-
- }
-
- /**
- * Task getter.
- *
- * @return managed task
- */
- public TimerTask getTask() {
- return managedTask;
- }
-
- /**
- * Method to increment time while task is running (in ms).
- *
- * @param increment increment, can be negative
- */
- public void incrementTaskTime(long increment) {
-
- long nowTimestamp = Calendar.getInstance().getTimeInMillis();
-
- // new var, to not modify parameter
- long localIncrement = increment;
-
- // do go over 0
- if (taskTimingBeforeStartInMs + nowTimestamp
- - taskStartCalendar.getTimeInMillis() + offsetTimeInMs
- + increment < 0) {
- localIncrement = -(taskTimingBeforeStartInMs + nowTimestamp
- - taskStartCalendar.getTimeInMillis() + offsetTimeInMs);
- }
-
- offsetTimeInMs += localIncrement;
- }
-
- /**
- * Reset timing.
- *
- * For example if task goes over 0h00, need to reset...
- */
- public void resetTiming() {
-
- taskStartCalendar = Calendar.getInstance();
- lastPublishTimestamp = taskStartCalendar.getTimeInMillis();
- // need to be this for hibernate in same day
- taskTimingBeforeStartInMs = managedTask.getTime(new Date()) * 1000;
- offsetTimeInMs = 0;
- }
-
- /**
- * Check if task need to be reset.
- *
- * Test if today number if different of taskStartCalendar day number
- */
- protected void checkReset() {
-
- Calendar nowCalendar = Calendar.getInstance();
-
- // si les jours actuel et jours de debut de start ne sont
- // pas identiques : reset
- if (nowCalendar.get(Calendar.DAY_OF_YEAR) != taskStartCalendar
- .get(Calendar.DAY_OF_YEAR)) {
- if (log.isInfoEnabled()) {
- log.info("Day change detected, reset timing");
- }
- resetTiming();
- }
-
- }
-
- /*
- * @see org.jdesktop.swingworker.SwingWorker#doInBackground()
- */
- @Override
- protected Void doInBackground() throws Exception {
-
- // task effective start
- // notify ui
- parentApp.startedTask(managedTask);
-
- // reset on start just for init
- resetTiming();
-
- // get idle time
- long configIdleTime = JTimer.config.getIdleTime() * 1000;
-
- boolean dontWantToStop = true;
- while (dontWantToStop) {
- long currentTime = Calendar.getInstance().getTimeInMillis();
-
- // try to detect hibernate idle time
- if (currentTime - lastPublishTimestamp >= configIdleTime) {
- // hibernate detected
- // update time without idle time for specified day
- if (log.isInfoEnabled()) {
- log.info("Hibernate detected, reseting timing");
- }
- resetTiming();
- }
-
- lastPublishTimestamp = currentTime;
-
- // check user idle time
- long idleTime = 0;
- if (systemInfo != null) { // idle time available
- idleTime = systemInfo.getIdleTime();
-
- if (log.isDebugEnabled()) {
- log.debug("User is idle since " + (idleTime / 1000) + " s");
- }
- }
-
- // check reset before publish (day change)
- checkReset();
-
- // if long idleTime is unavailable, if is always false
- if (idleTime >= configIdleTime) {
-
- // to not display negative time near midnight
- long idleTimeOffset = Math.min(idleTime, currentTime - taskStartCalendar.getTimeInMillis());
-
- // idle detected
- // update time without idle time
- // math.min > for idle detected at 0:00
- offsetTimeInMs -= idleTimeOffset;
- publish(taskTimingBeforeStartInMs + currentTime - taskStartCalendar.getTimeInMillis() + offsetTimeInMs);
-
- // send idle detect event
- JTimer parentApplication = (JTimer)getApplication();
- parentApplication.preIdleDetect();
- // ask user what to do (long blocking call)
- int option = IdleDialog.showIdleDialog(currentTime - idleTime);
- // send idle detect event
- parentApplication.postIdleDetect();
-
- // day can have changed during idle
- checkReset();
-
- // get time after user idle
- long afterIdleTime = Calendar.getInstance().getTimeInMillis();
- lastPublishTimestamp = afterIdleTime;
-
- switch (option) {
-
- case IdleDialog.REVERT:
- // just stop the task
- ((JTimer) getApplication()).stopTask(managedTask);
- break;
-
- case IdleDialog.CONTINUE:
- // refresh time
- // remove idle time previously added
- offsetTimeInMs += idleTimeOffset;
- publish(taskTimingBeforeStartInMs + afterIdleTime
- - taskStartCalendar.getTimeInMillis()
- + offsetTimeInMs);
- break;
-
- default: // RESUME
-
- // resume = increment idle time
- offsetTimeInMs -= afterIdleTime - currentTime;
- // update time
- publish(taskTimingBeforeStartInMs + afterIdleTime
- - taskStartCalendar.getTimeInMillis()
- + offsetTimeInMs);
- break;
-
- }
- } else {
- // pas de idle, met a jour le temps
- publish(taskTimingBeforeStartInMs + currentTime
- - taskStartCalendar.getTimeInMillis() + offsetTimeInMs);
- }
-
- Thread.sleep(1000); // 1s
-
- // test if task want to stop
- synchronized (bWantToStop) {
- dontWantToStop = !bWantToStop.booleanValue();
- }
- }
-
- return null;
- }
-
- /*
- * @see application.Task#process(java.util.List)
- */
- @Override
- protected void process(List<Long> durations) {
-
- // take last notification
- // can be notified of many result
- // for example, if UI lag...
- long currentDuration = durations.get(durations.size() - 1);
-
- dataManager.changeTaskTime(managedTask, new Date(),
- currentDuration / 1000);
-
- checkTaskAlerts(managedTask);
- }
-
- /**
- * Check for alert to be fired.
- *
- * @param task
- */
- 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()) {
- 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()) {
- 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.
- if (task.getParent() != null) {
- checkTaskAlerts(task.getParent());
- }
- }
-
- /**
- * Display alert message without breaking UI.
- *
- * @param task task
- * @param alertType alert type
- * @param alertDuration alert duration
- */
- 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);
- } 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"));
- }
- });
- }
-
- /**
- * Notify that task want to stop
- */
- public void wantToStop() {
- synchronized (bWantToStop) {
- bWantToStop = Boolean.TRUE;
- }
- }
-
- /**
- * Tell if task is trying to stop.
- *
- * @return stopping flag
- */
- public boolean isStopping() {
- boolean stopping;
- synchronized (bWantToStop) {
- stopping = bWantToStop.booleanValue();
- }
- return stopping;
- }
-}
Copied: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java (from rev 2839, trunk/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java)
===================================================================
--- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java (rev 0)
+++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java 2012-03-25 21:15:46 UTC (rev 2840)
@@ -0,0 +1,435 @@
+/*
+ * #%L
+ * jTimer
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2007 - 2012 CodeLutin, Chatellier Eric
+ * %%
+ * This program 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.
+ *
+ * This program 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 this program. If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+package org.chorem.jtimer.ui.tasks;
+
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+
+import org.apache.commons.lang3.time.DateUtils;
+import org.apache.commons.lang3.time.DurationFormatUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.chorem.jtimer.JTimer;
+import org.chorem.jtimer.data.TimerDataManager;
+import org.chorem.jtimer.entities.TimerAlert;
+import org.chorem.jtimer.entities.TimerTask;
+import org.chorem.jtimer.entities.TimerTaskHelper;
+import org.chorem.jtimer.entities.TimerAlert.Type;
+import org.chorem.jtimer.ui.system.SystemInfo;
+import org.chorem.jtimer.ui.system.SystemInfoFactory;
+import org.chorem.jtimer.ui.system.UnsupportedSystemInfoException;
+import org.jdesktop.application.Task;
+
+/**
+ * RunTaskJob.
+ *
+ * Notify every second the core controler.
+ *
+ * @author chatellier
+ * @version $Revision$
+ *
+ * Last update : $Date$
+ * By : $Author$
+ */
+public class RunTaskJob extends Task<Void, Void> {
+
+ /** Class logger. */
+ private static Log log = LogFactory.getLog(RunTaskJob.class);
+
+ /** Parent app reference. */
+ protected JTimer parentApp;
+
+ /** The task to manage. */
+ protected TimerTask managedTask;
+
+ /** Data manager. */
+ protected TimerDataManager dataManager;
+
+ /** System information (idle...). */
+ protected SystemInfo systemInfo;
+
+ /** Already thrown alert. */
+ protected Collection<TimerAlert> alreadyTrownAlerts;
+
+ /** Timestamp when timing start. */
+ protected long taskStartTimestamp;
+
+ /** Last publish time to detect hibernate. */
+ protected long lastUserActivity;
+
+ /**
+ * Offset to adjust time for current day (last activity day).
+ * Include :
+ * - Task initial time
+ * - Task idle time (task was running but time not counted)
+ * - Manual user incremented time
+ */
+ protected long offsetTimeInMs;
+
+ /** Want to stop flag. */
+ protected Boolean bWantToStop;
+
+ /**
+ * Constructor.
+ *
+ * Take the task to manage
+ *
+ * @param parentApp parent application
+ * @param managedTask task
+ * @param dataManager data
+ */
+ public RunTaskJob(JTimer parentApp, TimerTask managedTask,
+ TimerDataManager dataManager) {
+ super(parentApp);
+ this.parentApp = parentApp;
+
+ // init with False
+ bWantToStop = Boolean.FALSE;
+
+ // save vars
+ this.managedTask = managedTask;
+ this.dataManager = dataManager;
+
+ // must be init here, checkAlreadyThrownAlerts is called multiples times
+ alreadyTrownAlerts = new HashSet<TimerAlert>();
+ checkAlreadyThrownAlerts(managedTask);
+
+ // init system info to get idleTime
+ try {
+ systemInfo = SystemInfoFactory.getSystemInfo();
+ } catch (UnsupportedSystemInfoException e) {
+ if (log.isErrorEnabled()) {
+ log.error("Can't get system info", e);
+ }
+ systemInfo = null;
+ }
+ }
+
+ /**
+ * Check for already thrown alerts.
+ *
+ * Used to not fired again already fired alerts during previous
+ * timing.
+ *
+ * @param task current task
+ */
+ protected void checkAlreadyThrownAlerts(TimerTask task) {
+
+ 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()) {
+ alreadyTrownAlerts.add(alert.clone());
+ } else if (alert.getType().equals(Type.REACH_TOTAL_TIME)
+ && TimerTaskHelper.getAllTotalTime(task) > alert
+ .getDuration()) {
+ alreadyTrownAlerts.add(alert.clone());
+ }
+ }
+
+ // se souvient aussi de alerte deja lancées
+ // pour les taches parentes
+ if (task.getParent() != null) {
+ checkAlreadyThrownAlerts(task.getParent());
+ }
+
+ }
+
+ /**
+ * Task getter.
+ *
+ * @return managed task
+ */
+ public TimerTask getTask() {
+ return managedTask;
+ }
+
+ /**
+ * Method to increment time while task is running (in ms).
+ *
+ * @param increment increment, can be negative
+ */
+ public void incrementTaskTime(long increment) {
+
+ long nowTimestamp = Calendar.getInstance().getTimeInMillis();
+
+ // new var, to not modify parameter
+ long localIncrement = increment;
+
+ // do go over 0
+ if (nowTimestamp - taskStartTimestamp + offsetTimeInMs + increment < 0) {
+ localIncrement = -(nowTimestamp - taskStartTimestamp + offsetTimeInMs);
+ }
+
+ offsetTimeInMs += localIncrement;
+ }
+
+ /**
+ * Reset timing.
+ *
+ * For example if task goes over 0h00, need to reset...
+ */
+ public void resetTiming() {
+ taskStartTimestamp = System.currentTimeMillis();
+ lastUserActivity = taskStartTimestamp;
+ offsetTimeInMs = managedTask.getTime(new Date()) * 1000;
+ }
+
+ /*
+ * @see org.jdesktop.swingworker.SwingWorker#doInBackground()
+ */
+ @Override
+ protected Void doInBackground() throws Exception {
+
+ // task effective start
+ // notify ui
+ parentApp.startedTask(managedTask);
+
+ // init timing
+ resetTiming();
+
+ // get idle time
+ long configIdleTime = JTimer.config.getIdleTime() * 1000;
+ long idleTime = 0;
+
+ boolean dontWantToStop = true;
+ while (dontWantToStop) {
+
+ long currentTime = System.currentTimeMillis();
+
+ // check user idle time
+ if (systemInfo != null) { // idle time available
+ idleTime = systemInfo.getIdleTime();
+
+ if (log.isDebugEnabled()) {
+ log.debug("User is idle since " + (idleTime / 1000) + " s");
+ }
+ }
+
+ // if long idleTime is unavailable, if is always false
+ if (idleTime >= configIdleTime) {
+ lastUserActivity -= idleTime;
+ }
+
+ // check for idleness with last user activity (real idle and hibernate)
+ if (currentTime - lastUserActivity >= configIdleTime) {
+
+ // update idle to publish time without counting idle
+ offsetTimeInMs -= currentTime - lastUserActivity;
+ publish();
+
+ // display idle detected (blocking call)
+ JTimer parentApplication = (JTimer) getApplication();
+ parentApplication.preIdleDetect();
+ int option = IdleDialog.showIdleDialog(currentTime - idleTime);
+ parentApplication.postIdleDetect();
+
+ // manage tracking resume after idle
+ currentTime = System.currentTimeMillis();
+ lastUserActivity = currentTime;
+
+ switch (option) {
+ case IdleDialog.REVERT:
+ // just stop the task
+ ((JTimer) getApplication()).stopTask(managedTask);
+ break;
+
+ case IdleDialog.CONTINUE:
+ // refresh time
+ // remove idle time previously added
+ //offsetTimeInMs += idleTimeOffset;
+ //publish(taskTimingBeforeStartInMs + afterIdleTime
+ // - taskStartCalendar.getTimeInMillis()
+ // + offsetTimeInMs);
+
+ break;
+
+ case IdleDialog.RESUME:
+ // resume = increment idle time
+ offsetTimeInMs += currentTime - lastUserActivity;
+
+ // check day change (after offset)
+ Calendar nowCalendar = Calendar.getInstance();
+ Calendar startCalendar = Calendar.getInstance();
+ startCalendar.setTimeInMillis(taskStartTimestamp);
+ if (!DateUtils.isSameDay(startCalendar, nowCalendar)) {
+ resetTiming();
+ }
+
+ // update time
+ publish();
+ break;
+ }
+
+ } else {
+
+ // no idle detected
+ lastUserActivity = currentTime;
+
+ // check day change
+ Calendar nowCalendar = Calendar.getInstance();
+ Calendar startCalendar = Calendar.getInstance();
+ startCalendar.setTimeInMillis(taskStartTimestamp);
+ if (!DateUtils.isSameDay(startCalendar, nowCalendar)) {
+ resetTiming();
+ }
+
+ // update new time
+ publish();
+ }
+
+ Thread.sleep(1000); // 1s
+
+ // test if task want to stop
+ synchronized (bWantToStop) {
+ dontWantToStop = !bWantToStop.booleanValue();
+ }
+ }
+
+ return null;
+ }
+
+ /*
+ * @see application.Task#process(java.util.List)
+ */
+ @Override
+ protected void process(List<Void> nothing) {
+
+ // take last notification
+ // can be notified of many result
+ // for example, if UI lag...
+ long currentTime = System.currentTimeMillis();
+ long currentDuration = currentTime - taskStartTimestamp + offsetTimeInMs;
+
+ // time can be negative due to adjust caused by idle or hibernate
+ // just publish 0 in this case
+ if (currentDuration < 0) {
+ currentDuration = 0;
+ }
+
+ dataManager.changeTaskTime(managedTask, new Date(),
+ currentDuration / 1000);
+
+ checkTaskAlerts(managedTask);
+ }
+
+ /**
+ * Check for alert to be fired.
+ *
+ * @param task
+ */
+ 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()) {
+ 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()) {
+ 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.
+ if (task.getParent() != null) {
+ checkTaskAlerts(task.getParent());
+ }
+ }
+
+ /**
+ * Display alert message without breaking UI.
+ *
+ * @param task task
+ * @param alertType alert type
+ * @param alertDuration alert duration
+ */
+ 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);
+ } 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"));
+ }
+ });
+ }
+
+ /**
+ * Notify that task want to stop
+ */
+ public void wantToStop() {
+ synchronized (bWantToStop) {
+ bWantToStop = Boolean.TRUE;
+ }
+ }
+
+ /**
+ * Tell if task is trying to stop.
+ *
+ * @return stopping flag
+ */
+ public boolean isStopping() {
+ boolean stopping;
+ synchronized (bWantToStop) {
+ stopping = bWantToStop.booleanValue();
+ }
+ return stopping;
+ }
+}
1
0
25 Mar '12
Author: echatellier
Date: 2012-03-25 21:28:19 +0200 (Sun, 25 Mar 2012)
New Revision: 2839
Url: http://chorem.org/repositories/revision/jtimer/2839
Log:
Simplify time tracking algorithm.
Init offset with task initial time.
Modified:
trunk/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java
Modified: trunk/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java 2012-03-25 13:18:14 UTC (rev 2838)
+++ trunk/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java 2012-03-25 19:28:19 UTC (rev 2839)
@@ -79,9 +79,6 @@
/** Already thrown alert. */
protected Collection<TimerAlert> alreadyTrownAlerts;
- /** The today total task time at start time. */
- protected long taskTimingBeforeStartInMs;
-
/** Calendar instance when timing start. */
protected Calendar taskStartCalendar;
@@ -187,11 +184,10 @@
long localIncrement = increment;
// do go over 0
- if (taskTimingBeforeStartInMs + nowTimestamp
- - taskStartCalendar.getTimeInMillis() + offsetTimeInMs
- + increment < 0) {
- localIncrement = -(taskTimingBeforeStartInMs + nowTimestamp
- - taskStartCalendar.getTimeInMillis() + offsetTimeInMs);
+ if (nowTimestamp - taskStartCalendar.getTimeInMillis()
+ + offsetTimeInMs + increment < 0) {
+ localIncrement = -(nowTimestamp - taskStartCalendar.getTimeInMillis()
+ + offsetTimeInMs);
}
offsetTimeInMs += localIncrement;
@@ -207,8 +203,7 @@
taskStartCalendar = Calendar.getInstance();
lastPublishTimestamp = taskStartCalendar.getTimeInMillis();
// need to be this for hibernate in same day
- taskTimingBeforeStartInMs = managedTask.getTime(new Date()) * 1000;
- offsetTimeInMs = 0;
+ offsetTimeInMs = managedTask.getTime(new Date()) * 1000;
}
/**
@@ -287,7 +282,7 @@
// update time without idle time
// math.min > for idle detected at 0:00
offsetTimeInMs -= idleTimeOffset;
- publish(taskTimingBeforeStartInMs + currentTime - taskStartCalendar.getTimeInMillis() + offsetTimeInMs);
+ publish(currentTime - taskStartCalendar.getTimeInMillis() + offsetTimeInMs);
// send idle detect event
JTimer parentApplication = (JTimer)getApplication();
@@ -315,8 +310,7 @@
// refresh time
// remove idle time previously added
offsetTimeInMs += idleTimeOffset;
- publish(taskTimingBeforeStartInMs + afterIdleTime
- - taskStartCalendar.getTimeInMillis()
+ publish(afterIdleTime - taskStartCalendar.getTimeInMillis()
+ offsetTimeInMs);
break;
@@ -325,16 +319,15 @@
// resume = increment idle time
offsetTimeInMs -= afterIdleTime - currentTime;
// update time
- publish(taskTimingBeforeStartInMs + afterIdleTime
- - taskStartCalendar.getTimeInMillis()
+ publish(afterIdleTime - taskStartCalendar.getTimeInMillis()
+ offsetTimeInMs);
break;
}
} else {
// pas de idle, met a jour le temps
- publish(taskTimingBeforeStartInMs + currentTime
- - taskStartCalendar.getTimeInMillis() + offsetTimeInMs);
+ publish(currentTime - taskStartCalendar.getTimeInMillis() +
+ offsetTimeInMs);
}
Thread.sleep(1000); // 1s
1
0
25 Mar '12
Author: echatellier
Date: 2012-03-25 15:18:14 +0200 (Sun, 25 Mar 2012)
New Revision: 2838
Url: http://chorem.org/repositories/revision/jtimer/2838
Log:
fixes #195 : Wrong project or task selection in report view
Modified:
trunk/src/main/java/org/chorem/jtimer/ui/report/ReportView.java
Modified: trunk/src/main/java/org/chorem/jtimer/ui/report/ReportView.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/ui/report/ReportView.java 2012-03-25 12:40:16 UTC (rev 2837)
+++ trunk/src/main/java/org/chorem/jtimer/ui/report/ReportView.java 2012-03-25 13:18:14 UTC (rev 2838)
@@ -424,8 +424,8 @@
reportType = Type.BY_PROJECT_REPORT;
}
- // get filtred project list
- // without non selected projet and tasks
+ // get filtered project list
+ // without non selected project and tasks
List<TimerProject> selectedProjects = getSelectedProjects(core
.getData().getProjectsList(), uncheckedTaskSet);
@@ -454,13 +454,20 @@
List<TimerProject> currentProjects = new ArrayList<TimerProject>();
for (TimerProject project : projects) {
- if (!uncheckedTaskList.contains(project)) {
- TimerProject clonedProject = project.clone();
- clonedProject.getSubTasks().clear();
- clonedProject.getSubTasks().addAll(
- getSelectedTasks(project.getSubTasks(),
- uncheckedTaskList));
- currentProjects.add(clonedProject);
+
+ // take care of show closed option
+ if (!project.isClosed() || showHiddenProjectBox.isSelected()) {
+ List<TimerTask> subTasks = getSelectedTasks(project.getSubTasks(),
+ uncheckedTaskList);
+
+ // add current project only of at least one subtask is selected
+ // or current project is selected
+ if (!uncheckedTaskList.contains(project) || !subTasks.isEmpty()) {
+ TimerProject clonedProject = project.clone();
+ clonedProject.getSubTasks().clear();
+ clonedProject.getSubTasks().addAll(subTasks);
+ currentProjects.add(clonedProject);
+ }
}
}
@@ -479,14 +486,26 @@
List<TimerTask> currentTask = new ArrayList<TimerTask>();
for (TimerTask task : tasks) {
- if (!uncheckedTaskList.contains(task)) {
- TimerTask clonedTask = task.clone();
- clonedTask.getSubTasks().clear();
- clonedTask.getSubTasks()
- .addAll(
- getSelectedTasks(task.getSubTasks(),
- uncheckedTaskList));
- currentTask.add(clonedTask);
+
+ // take care of show closed option
+ if (!task.isClosed() || showHiddenProjectBox.isSelected()) {
+ List<TimerTask> subTasks = getSelectedTasks(task.getSubTasks(),
+ uncheckedTaskList);
+
+ // add current task only of at least one subtask is selected
+ // or current task is selected
+ if (!uncheckedTaskList.contains(task) || !subTasks.isEmpty()) {
+ TimerTask clonedTask;
+ if (uncheckedTaskList.contains(task)) {
+ // to not show time of not selected task in report
+ clonedTask = new TimerTask(task.getName());
+ } else {
+ clonedTask = task.clone();
+ }
+ clonedTask.getSubTasks().clear();
+ clonedTask.getSubTasks().addAll(subTasks);
+ currentTask.add(clonedTask);
+ }
}
}
1
0
Author: echatellier
Date: 2012-03-25 14:40:16 +0200 (Sun, 25 Mar 2012)
New Revision: 2837
Url: http://chorem.org/repositories/revision/jtimer/2837
Log:
fixes 493 : Application name is not correct under gnome-shell
Modified:
trunk/src/main/java/org/chorem/jtimer/JTimer.java
Modified: trunk/src/main/java/org/chorem/jtimer/JTimer.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/JTimer.java 2012-03-23 15:11:54 UTC (rev 2836)
+++ trunk/src/main/java/org/chorem/jtimer/JTimer.java 2012-03-25 12:40:16 UTC (rev 2837)
@@ -27,6 +27,7 @@
import java.awt.BorderLayout;
import java.awt.Dimension;
+import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
@@ -179,6 +180,20 @@
ApplicationContext ctxt = getContext();
resourceMap = ctxt.getResourceMap();
+ // fixme awt application name. Can be seen only with gnome-shell
+ // tray icon is displayed with name "org-chorem-jtimer-JTimer" instead of
+ // only "jTimer" with following fix :
+ try {
+ Toolkit xToolkit = Toolkit.getDefaultToolkit();
+ java.lang.reflect.Field awtAppClassNameField = xToolkit.getClass().getDeclaredField("awtAppClassName");
+ awtAppClassNameField.setAccessible(true);
+ awtAppClassNameField.set(xToolkit, resourceMap.getString("Application.title"));
+ } catch (Exception ex) {
+ if (log.isWarnEnabled()) {
+ log.warn("Can change awt application name", ex);
+ }
+ }
+
// fix start in iconified mode
ctxt.getSessionStorage().putProperty(JFrame.class, new WindowProperty2());
1
0
23 Mar '12
Author: echatellier
Date: 2012-03-23 16:11:54 +0100 (Fri, 23 Mar 2012)
New Revision: 2836
Url: http://chorem.org/repositories/revision/jtimer/2836
Log:
Fix dialog positionning under openjdk
Modified:
trunk/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java
Modified: trunk/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java 2012-03-19 09:06:53 UTC (rev 2835)
+++ trunk/src/main/java/org/chorem/jtimer/ui/TimerTaskEditor.java 2012-03-23 15:11:54 UTC (rev 2836)
@@ -159,6 +159,12 @@
super(application.getMainFrame());
setModal(true);
+ // remove dialog name to this dialog, due to bug
+ // http://chorem.org/issues/484 and
+ // http://kenai.com/jira/browse/BSAF-107
+ // cause infinite loop under openjdk
+ setName(null); // force nameExplicitlySet to true
+
// set color on jxmonthview unselectable days
// UIManager.put("JXMonthView.unselectableDayForeground", Color.GRAY);
1
0
19 Mar '12
Author: echatellier
Date: 2012-03-19 10:06:53 +0100 (Mon, 19 Mar 2012)
New Revision: 2835
Url: http://chorem.org/repositories/revision/jtimer/2835
Log:
Fix header
Modified:
trunk/src/main/java/org/chorem/jtimer/ui/widget/WindowProperty2.java
Modified: trunk/src/main/java/org/chorem/jtimer/ui/widget/WindowProperty2.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/ui/widget/WindowProperty2.java 2012-03-18 16:44:26 UTC (rev 2834)
+++ trunk/src/main/java/org/chorem/jtimer/ui/widget/WindowProperty2.java 2012-03-19 09:06:53 UTC (rev 2835)
@@ -1,25 +1,23 @@
/*
* #%L
- *
- *
* $Id$
* $HeadURL$
* %%
* Copyright (C) 2012 Codelutin, Chatellier Eric
* %%
* This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
+ * 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.
*
* This program 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 Lesser Public License for more details.
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Lesser Public
+ * You should have received a copy of the GNU General Public
* License along with this program. If not, see
- * <http://www.gnu.org/licenses/lgpl-3.0.html>.
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
1
0
r2834 - in trunk/src: main/java/org/chorem/jtimer/ui/report main/resources/ftl main/resources/org/chorem/jtimer/ui/report/resources test/java/org/chorem/jtimer test/java/org/chorem/jtimer/ui/report test/resources/testdata
by echatellier@users.chorem.org 18 Mar '12
by echatellier@users.chorem.org 18 Mar '12
18 Mar '12
Author: echatellier
Date: 2012-03-18 17:44:26 +0100 (Sun, 18 Mar 2012)
New Revision: 2834
Url: http://chorem.org/repositories/revision/jtimer/2834
Log:
#185 : Display date (date and time) on annotations
Modified:
trunk/src/main/java/org/chorem/jtimer/ui/report/ReportGenerator.java
trunk/src/main/java/org/chorem/jtimer/ui/report/ReportUtils.java
trunk/src/main/java/org/chorem/jtimer/ui/report/ReportView.java
trunk/src/main/resources/ftl/reportByDay.ftl
trunk/src/main/resources/ftl/reportByDay_fr.ftl
trunk/src/main/resources/ftl/reportByMonth.ftl
trunk/src/main/resources/ftl/reportByMonth_fr.ftl
trunk/src/main/resources/ftl/reportByProject.ftl
trunk/src/main/resources/ftl/reportByProject_fr.ftl
trunk/src/main/resources/ftl/reportByWeek.ftl
trunk/src/main/resources/ftl/reportByWeek_fr.ftl
trunk/src/main/resources/ftl/reportByYear.ftl
trunk/src/main/resources/ftl/reportByYear_fr.ftl
trunk/src/main/resources/org/chorem/jtimer/ui/report/resources/ReportView.properties
trunk/src/main/resources/org/chorem/jtimer/ui/report/resources/ReportView_fr.properties
trunk/src/test/java/org/chorem/jtimer/AbstractJTimerTest.java
trunk/src/test/java/org/chorem/jtimer/ui/report/ReportGeneratorTest.java
trunk/src/test/resources/testdata/4.ann
trunk/src/test/resources/testdata/5.ann
Modified: trunk/src/main/java/org/chorem/jtimer/ui/report/ReportGenerator.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/ui/report/ReportGenerator.java 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/java/org/chorem/jtimer/ui/report/ReportGenerator.java 2012-03-18 16:44:26 UTC (rev 2834)
@@ -86,7 +86,6 @@
freemarkerConfiguration.setTemplateLoader(templateLoader);
freemarkerConfiguration.setObjectWrapper(new BeansWrapper());
-
}
/**
@@ -97,11 +96,12 @@
* @param begin begin date
* @param end end date
* @param includeAnnotate include annotations
+ * @param includeAnnotateTime include annotations time
*
* @return report text
*/
public String getReportText(Type reportType, List<TimerProject> projects,
- Date begin, Date end, boolean includeAnnotate) {
+ Date begin, Date end, boolean includeAnnotate, boolean includeAnnotateTime) {
Template template = null;
String content = null;
@@ -131,7 +131,7 @@
}
content = getReportContent(template, projects, begin, end,
- includeAnnotate);
+ includeAnnotate, includeAnnotateTime);
} catch (IOException e) {
if (log.isErrorEnabled()) {
log.error("Can't get freemarker template", e);
@@ -153,6 +153,7 @@
* @param end end date
* @param template freemarker template to use
* @param includeAnnotate include annotations
+ * @param includeAnnotateTime include annotations time
*
* @return string content
*
@@ -163,7 +164,7 @@
*/
protected String getReportContent(Template template,
List<TimerProject> projects, Date begin, Date end,
- boolean includeAnnotate) throws TemplateException, IOException {
+ boolean includeAnnotate, boolean includeAnnotateTime) throws TemplateException, IOException {
// Create the root hash
Map<String, Object> root = new HashMap<String, Object>();
@@ -172,6 +173,7 @@
root.put("begin", begin);
root.put("end", end);
root.put("annotations", includeAnnotate);
+ root.put("annotationsTime", includeAnnotateTime);
root.put("utils", new ReportUtils());
Writer out = new StringWriter();
Modified: trunk/src/main/java/org/chorem/jtimer/ui/report/ReportUtils.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/ui/report/ReportUtils.java 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/java/org/chorem/jtimer/ui/report/ReportUtils.java 2012-03-18 16:44:26 UTC (rev 2834)
@@ -28,7 +28,9 @@
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.apache.commons.lang3.time.DurationFormatUtils;
import org.chorem.jtimer.entities.TimerTask;
@@ -412,9 +414,9 @@
* @param day day
* @return annotations of the day
*/
- public List<String> getDailyTaskAnnotation(TimerTask task, Date day) {
+ public Map<Date, String> getDailyTaskAnnotation(TimerTask task, Date day) {
- List<String> result = TimerTaskHelper.getAnnotation(task, day);
+ Map<Date, String> result = TimerTaskHelper.getAnnotationMap(task, day);
return result;
}
@@ -430,10 +432,10 @@
* @param toDay to day (inclusive)
* @return annotations of the week
*/
- public List<String> getWeeklyTaskAnnotation(TimerTask task, Date week,
+ public Map<Date, String> getWeeklyTaskAnnotation(TimerTask task, Date week,
Date fromDay, Date toDay) {
- List<String> result = new ArrayList<String>();
+ Map<Date, String> result = new HashMap<Date, String>();
Calendar beginPeriodDate = Calendar.getInstance();
beginPeriodDate.setTime(week);
@@ -451,9 +453,9 @@
if ((fromDay == null || fromDay.compareTo(loopPeriodDate.getTime()) <= 0)
&& (toDay == null || toDay.compareTo(loopPeriodDate
.getTime()) >= 0)) {
- List<String> anns = TimerTaskHelper
- .getAnnotation(task, loopPeriodDate.getTime());
- result.addAll(anns);
+ Map<Date, String> anns = TimerTaskHelper
+ .getAnnotationMap(task, loopPeriodDate.getTime());
+ result.putAll(anns);
}
loopPeriodDate.add(Calendar.DAY_OF_YEAR, 1);
@@ -473,9 +475,9 @@
* @param toDay to day (inclusive)
* @return annotations of the month
*/
- public List<String> getMonthlyTaskAnnotation(TimerTask task, Date month,
+ public Map<Date, String> getMonthlyTaskAnnotation(TimerTask task, Date month,
Date fromDay, Date toDay) {
- List<String> result = new ArrayList<String>();
+ Map<Date, String> result = new HashMap<Date, String>();
Calendar beginPeriodDate = Calendar.getInstance();
beginPeriodDate.setTime(month);
@@ -492,9 +494,9 @@
if ((fromDay == null || fromDay.compareTo(loopPeriodDate.getTime()) <= 0)
&& (toDay == null || toDay.compareTo(loopPeriodDate
.getTime()) >= 0)) {
- List<String> anns = TimerTaskHelper
- .getAnnotation(task, loopPeriodDate.getTime());
- result.addAll(anns);
+ Map<Date, String> anns = TimerTaskHelper
+ .getAnnotationMap(task, loopPeriodDate.getTime());
+ result.putAll(anns);
}
loopPeriodDate.add(Calendar.DAY_OF_YEAR, 1);
@@ -514,10 +516,10 @@
* @param toDay to day (inclusive)
* @return annotations of the year
*/
- public List<String> getYearlyTaskAnnotation(TimerTask task, Date year,
+ public Map<Date, String> getYearlyTaskAnnotation(TimerTask task, Date year,
Date fromDay, Date toDay) {
- List<String> result = new ArrayList<String>();
+ Map<Date, String> result = new HashMap<Date, String>();
Calendar beginPeriodDate = Calendar.getInstance();
beginPeriodDate.setTime(year);
@@ -535,9 +537,9 @@
if ((fromDay == null || fromDay.compareTo(loopPeriodDate.getTime()) <= 0)
&& (toDay == null || toDay.compareTo(loopPeriodDate
.getTime()) >= 0)) {
- List<String> anns = TimerTaskHelper
- .getAnnotation(task, loopPeriodDate.getTime());
- result.addAll(anns);
+ Map<Date, String> anns = TimerTaskHelper
+ .getAnnotationMap(task, loopPeriodDate.getTime());
+ result.putAll(anns);
}
loopPeriodDate.add(Calendar.DAY_OF_YEAR, 1);
Modified: trunk/src/main/java/org/chorem/jtimer/ui/report/ReportView.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/ui/report/ReportView.java 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/java/org/chorem/jtimer/ui/report/ReportView.java 2012-03-18 16:44:26 UTC (rev 2834)
@@ -108,6 +108,8 @@
/** Include annotations on reports */
protected JCheckBox checkIncludesAnnotations;
+ /** Include annotations time on reports */
+ protected JCheckBox checkIncludesAnnotationsTime;
/** Date pickers, from... to */
protected JXDatePicker datePickerFrom, datePickerTo;
@@ -247,11 +249,18 @@
new Insets(1, 1, 1, 1), 0, 0));
// miscellaneous
- checkIncludesAnnotations = new JCheckBox(getResourceMap().getString(
+ checkIncludesAnnotations = new JCheckBox();
+ checkIncludesAnnotations.setAction(getContext().getActionMap(this).get(
"reportAnnotations"));
panelOption.add(checkIncludesAnnotations, new GridBagConstraints(0, 5,
- 4, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ 2, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
new Insets(1, 1, 1, 1), 0, 0));
+ checkIncludesAnnotationsTime = new JCheckBox(getResourceMap().getString(
+ "reportAnnotationsTime"));
+ checkIncludesAnnotationsTime.setEnabled(false);
+ panelOption.add(checkIncludesAnnotationsTime, new GridBagConstraints(2, 5,
+ 2, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(1, 1, 1, 1), 0, 0));
// panel form projects
JPanel panelProjects = new JPanel(new BorderLayout());
@@ -386,6 +395,14 @@
}
/**
+ * Show annotation checkbox checked.
+ */
+ @Action
+ public void reportAnnotations() {
+ checkIncludesAnnotationsTime.setEnabled(checkIncludesAnnotations.isSelected());
+ }
+
+ /**
* Make report.
*
* Set content in {@link #reportArea} text area.
@@ -415,7 +432,8 @@
// make report
String report = reportGenerator.getReportText(reportType,
selectedProjects, datePickerFrom.getDate(), datePickerTo
- .getDate(), checkIncludesAnnotations.isSelected());
+ .getDate(), checkIncludesAnnotations.isSelected(),
+ checkIncludesAnnotationsTime.isSelected());
if (report != null && !report.isEmpty()) {
reportArea.setText(report);
Modified: trunk/src/main/resources/ftl/reportByDay.ftl
===================================================================
--- trunk/src/main/resources/ftl/reportByDay.ftl 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/ftl/reportByDay.ftl 2012-03-18 16:44:26 UTC (rev 2834)
@@ -33,9 +33,9 @@
<#local taskTime=utils.getDailyTaskTime(subtask, periodTime?date)/>
<#list 1..ident as i> </#list>- ${subtask.name}<#if taskTime > 0> : ${utils.formatDuration(taskTime)}</#if>
<#if annotations>
- <#local taskAnnotations=utils.getDailyTaskAnnotation(subtask, periodTime?date)/>
- <#list taskAnnotations as taskAnnotation>
-<#list 1..ident as i> </#list> * ${taskAnnotation}
+ <#local taskAnnTimes=utils.getDailyTaskAnnotation(subtask, periodTime?date)/>
+ <#list taskAnnTimes.keySet() as taskAnnTime>
+<#list 1..ident as i> </#list> * <#if annotationsTime>${taskAnnTime?time?string.short} : </#if>${taskAnnTimes.get(taskAnnTime)}
</#list>
</#if>
<@displaySubtaskReport task=subtask periodTime=periodTime identation=ident/>
Modified: trunk/src/main/resources/ftl/reportByDay_fr.ftl
===================================================================
--- trunk/src/main/resources/ftl/reportByDay_fr.ftl 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/ftl/reportByDay_fr.ftl 2012-03-18 16:44:26 UTC (rev 2834)
@@ -33,9 +33,9 @@
<#local taskTime=utils.getDailyTaskTime(subtask, periodTime?date)/>
<#list 1..ident as i> </#list>- ${subtask.name}<#if taskTime > 0> : ${utils.formatDuration(taskTime)}</#if>
<#if annotations>
- <#local taskAnnotations=utils.getDailyTaskAnnotation(subtask, periodTime?date)/>
- <#list taskAnnotations as taskAnnotation>
-<#list 1..ident as i> </#list> * ${taskAnnotation}
+ <#local taskAnnTimes=utils.getDailyTaskAnnotation(subtask, periodTime?date)/>
+ <#list taskAnnTimes.keySet() as taskAnnTime>
+<#list 1..ident as i> </#list> * <#if annotationsTime>${taskAnnTime?time?string.short} : </#if>${taskAnnTimes.get(taskAnnTime)}
</#list>
</#if>
<@displaySubtaskReport task=subtask periodTime=periodTime identation=ident/>
Modified: trunk/src/main/resources/ftl/reportByMonth.ftl
===================================================================
--- trunk/src/main/resources/ftl/reportByMonth.ftl 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/ftl/reportByMonth.ftl 2012-03-18 16:44:26 UTC (rev 2834)
@@ -33,9 +33,9 @@
<#local taskTime=utils.getMonthlyTaskTime(subtask, periodTime?date, begin?date, end?date)/>
<#list 1..ident as i> </#list>- ${subtask.name}<#if taskTime > 0> : ${utils.formatDuration(taskTime)}</#if>
<#if annotations>
- <#local taskAnnotations=utils.getMonthlyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
- <#list taskAnnotations as taskAnnotation>
-<#list 1..ident as i> </#list> * ${taskAnnotation}
+ <#local taskAnnTimes=utils.getMonthlyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
+ <#list taskAnnTimes.keySet() as taskAnnTime>
+<#list 1..ident as i> </#list> * <#if annotationsTime>${taskAnnTime?datetime?string.short} : </#if>${taskAnnTimes.get(taskAnnTime)}
</#list>
</#if>
<@displaySubtaskReport task=subtask periodTime=periodTime identation=ident/>
Modified: trunk/src/main/resources/ftl/reportByMonth_fr.ftl
===================================================================
--- trunk/src/main/resources/ftl/reportByMonth_fr.ftl 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/ftl/reportByMonth_fr.ftl 2012-03-18 16:44:26 UTC (rev 2834)
@@ -33,9 +33,9 @@
<#local taskTime=utils.getMonthlyTaskTime(subtask, periodTime?date, begin?date, end?date)/>
<#list 1..ident as i> </#list>- ${subtask.name}<#if taskTime > 0> : ${utils.formatDuration(taskTime)}</#if>
<#if annotations>
- <#local taskAnnotations=utils.getMonthlyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
- <#list taskAnnotations as taskAnnotation>
-<#list 1..ident as i> </#list> * ${taskAnnotation}
+ <#local taskAnnTimes=utils.getMonthlyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
+ <#list taskAnnTimes.keySet() as taskAnnTime>
+<#list 1..ident as i> </#list> * <#if annotationsTime>${taskAnnTime?datetime?string.short} : </#if>${taskAnnTimes.get(taskAnnTime)}
</#list>
</#if>
<@displaySubtaskReport task=subtask periodTime=periodTime identation=ident/>
Modified: trunk/src/main/resources/ftl/reportByProject.ftl
===================================================================
--- trunk/src/main/resources/ftl/reportByProject.ftl 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/ftl/reportByProject.ftl 2012-03-18 16:44:26 UTC (rev 2834)
@@ -42,9 +42,9 @@
<#list 1..ident as i> </#list>- ${subtask.name}<#if taskTime > 0> : ${utils.formatDuration(taskTime)}</#if>
<#if annotations>
<#list periods as period>
- <#local taskAnnotations=utils.getDailyTaskAnnotation(subtask, period?date)/>
- <#list taskAnnotations as taskAnnotation>
-<#list 1..ident as i> </#list> * ${taskAnnotation}
+ <#local taskAnnTimes=utils.getDailyTaskAnnotation(subtask, period?date)/>
+ <#list taskAnnTimes.keySet() as taskAnnTime>
+<#list 1..ident as i> </#list> * <#if annotationsTime>${taskAnnTime?datetime?string.short} : </#if>${taskAnnTimes.get(taskAnnTime)}
</#list>
</#list>
</#if>
Modified: trunk/src/main/resources/ftl/reportByProject_fr.ftl
===================================================================
--- trunk/src/main/resources/ftl/reportByProject_fr.ftl 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/ftl/reportByProject_fr.ftl 2012-03-18 16:44:26 UTC (rev 2834)
@@ -42,9 +42,9 @@
<#list 1..ident as i> </#list>- ${subtask.name}<#if taskTime > 0> : ${utils.formatDuration(taskTime)}</#if>
<#if annotations>
<#list periods as period>
- <#local taskAnnotations=utils.getDailyTaskAnnotation(subtask, period?date)/>
- <#list taskAnnotations as taskAnnotation>
-<#list 1..ident as i> </#list> * ${taskAnnotation}
+ <#local taskAnnTimes=utils.getDailyTaskAnnotation(subtask, period?date)/>
+ <#list taskAnnTimes.keySet() as taskAnnTime>
+<#list 1..ident as i> </#list> * <#if annotationsTime>${taskAnnTime?datetime?string.short} : </#if>${taskAnnTimes.get(taskAnnTime)}
</#list>
</#list>
</#if>
Modified: trunk/src/main/resources/ftl/reportByWeek.ftl
===================================================================
--- trunk/src/main/resources/ftl/reportByWeek.ftl 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/ftl/reportByWeek.ftl 2012-03-18 16:44:26 UTC (rev 2834)
@@ -33,9 +33,9 @@
<#local taskTime=utils.getWeeklyTaskTime(subtask, periodTime?date, begin?date, end?date)/>
<#list 1..ident as i> </#list>- ${subtask.name}<#if taskTime > 0> : ${utils.formatDuration(taskTime)}</#if>
<#if annotations>
- <#local taskAnnotations=utils.getWeeklyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
- <#list taskAnnotations as taskAnnotation>
-<#list 1..ident as i> </#list> * ${taskAnnotation}
+ <#local taskAnnTimes=utils.getWeeklyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
+ <#list taskAnnTimes.keySet() as taskAnnTime>
+<#list 1..ident as i> </#list> * <#if annotationsTime>${taskAnnTime?datetime?string.short} : </#if>${taskAnnTimes.get(taskAnnTime)}
</#list>
</#if>
<@displaySubtaskReport task=subtask periodTime=periodTime identation=ident/>
Modified: trunk/src/main/resources/ftl/reportByWeek_fr.ftl
===================================================================
--- trunk/src/main/resources/ftl/reportByWeek_fr.ftl 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/ftl/reportByWeek_fr.ftl 2012-03-18 16:44:26 UTC (rev 2834)
@@ -33,9 +33,9 @@
<#local taskTime=utils.getWeeklyTaskTime(subtask, periodTime?date, begin?date, end?date)/>
<#list 1..ident as i> </#list>- ${subtask.name}<#if taskTime > 0> : ${utils.formatDuration(taskTime)}</#if>
<#if annotations>
- <#local taskAnnotations=utils.getWeeklyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
- <#list taskAnnotations as taskAnnotation>
-<#list 1..ident as i> </#list> * ${taskAnnotation}
+ <#local taskAnnTimes=utils.getWeeklyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
+ <#list taskAnnTimes.keySet() as taskAnnTime>
+<#list 1..ident as i> </#list> * <#if annotationsTime>${taskAnnTime?datetime?string.short} : </#if>${taskAnnTimes.get(taskAnnTime)}
</#list>
</#if>
<@displaySubtaskReport task=subtask periodTime=periodTime identation=ident/>
Modified: trunk/src/main/resources/ftl/reportByYear.ftl
===================================================================
--- trunk/src/main/resources/ftl/reportByYear.ftl 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/ftl/reportByYear.ftl 2012-03-18 16:44:26 UTC (rev 2834)
@@ -33,9 +33,9 @@
<#local taskTime=utils.getYearlyTaskTime(subtask, periodTime?date, begin?date, end?date)/>
<#list 1..ident as i> </#list>- ${subtask.name}<#if taskTime > 0> : ${utils.formatDuration(taskTime)}</#if>
<#if annotations>
- <#local taskAnnotations=utils.getYearlyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
- <#list taskAnnotations as taskAnnotation>
-<#list 1..ident as i> </#list> * ${taskAnnotation}
+ <#local taskAnnTimes=utils.getYearlyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
+ <#list taskAnnTimes.keySet() as taskAnnTime>
+<#list 1..ident as i> </#list> * <#if annotationsTime>${taskAnnTime?datetime?string.short} : </#if>${taskAnnTimes.get(taskAnnTime)}
</#list>
</#if>
<@displaySubtaskReport task=subtask periodTime=periodTime identation=ident/>
Modified: trunk/src/main/resources/ftl/reportByYear_fr.ftl
===================================================================
--- trunk/src/main/resources/ftl/reportByYear_fr.ftl 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/ftl/reportByYear_fr.ftl 2012-03-18 16:44:26 UTC (rev 2834)
@@ -33,9 +33,9 @@
<#local taskTime=utils.getYearlyTaskTime(subtask, periodTime?date, begin?date, end?date)/>
<#list 1..ident as i> </#list>- ${subtask.name}<#if taskTime > 0> : ${utils.formatDuration(taskTime)}</#if>
<#if annotations>
- <#local taskAnnotations=utils.getYearlyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
- <#list taskAnnotations as taskAnnotation>
-<#list 1..ident as i> </#list> * ${taskAnnotation}
+ <#local taskAnnTimes=utils.getYearlyTaskAnnotation(subtask, periodTime?date, begin?date, end?date)/>
+ <#list taskAnnTimes.keySet() as taskAnnTime>
+<#list 1..ident as i> </#list> * <#if annotationsTime>${taskAnnTime?datetime?string.short} : </#if>${taskAnnTimes.get(taskAnnTime)}
</#list>
</#if>
<@displaySubtaskReport task=subtask periodTime=periodTime identation=ident/>
Modified: trunk/src/main/resources/org/chorem/jtimer/ui/report/resources/ReportView.properties
===================================================================
--- trunk/src/main/resources/org/chorem/jtimer/ui/report/resources/ReportView.properties 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/org/chorem/jtimer/ui/report/resources/ReportView.properties 2012-03-18 16:44:26 UTC (rev 2834)
@@ -32,7 +32,7 @@
reportWeekly=Weekly
reportYearly=Yearly
reportByProject=By project
-reportAnnotations=Include annotations
+reportAnnotationsTime=with time
reportProjects=Projects
reportContent=Report
reportProjectsList=Projects list
@@ -43,6 +43,8 @@
previousWeek.Action.icon = date_previous.png
previousWeek.Action.shortDescription = Previous week
+reportAnnotations.Action.text = Include annotations
+
showHiddenProjects.Action.text = Show hidden projects
showHiddenProjects.Action.shortDescription = Show hidden projects
Modified: trunk/src/main/resources/org/chorem/jtimer/ui/report/resources/ReportView_fr.properties
===================================================================
--- trunk/src/main/resources/org/chorem/jtimer/ui/report/resources/ReportView_fr.properties 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/main/resources/org/chorem/jtimer/ui/report/resources/ReportView_fr.properties 2012-03-18 16:44:26 UTC (rev 2834)
@@ -32,7 +32,8 @@
reportWeekly=Par semaine
reportYearly=Par ann\u00E9e
reportByProject=Par projet
-reportAnnotations=Inclure les annotations
+
+reportAnnotationsTime=avec l'heure
reportProjects=Projets
reportContent=Rapport
reportProjectsList=Liste des projets
@@ -44,6 +45,8 @@
showHiddenProjects.Action.text = Afficher les cach\u00E9s
showHiddenProjects.Action.shortDescription = Afficher les cach\u00E9s
+reportAnnotations.Action.text = Inclure les annotations
+
generateReport.Action.text = G\u00E9n\u00E9rer
generateReport.Action.shortDescription = G\u00E9n\u00E9rer le report
Modified: trunk/src/test/java/org/chorem/jtimer/AbstractJTimerTest.java
===================================================================
--- trunk/src/test/java/org/chorem/jtimer/AbstractJTimerTest.java 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/test/java/org/chorem/jtimer/AbstractJTimerTest.java 2012-03-18 16:44:26 UTC (rev 2834)
@@ -29,6 +29,7 @@
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
+import java.util.Locale;
import java.util.Properties;
import org.apache.commons.io.FileUtils;
@@ -137,6 +138,10 @@
log.debug("Set up test");
}
+ // jtimer code use default system locale
+ // test are coded in en_US
+ Locale.setDefault(Locale.US);
+
initDataDirectory();
}
Modified: trunk/src/test/java/org/chorem/jtimer/ui/report/ReportGeneratorTest.java
===================================================================
--- trunk/src/test/java/org/chorem/jtimer/ui/report/ReportGeneratorTest.java 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/test/java/org/chorem/jtimer/ui/report/ReportGeneratorTest.java 2012-03-18 16:44:26 UTC (rev 2834)
@@ -57,6 +57,7 @@
/**
* Test report generation.
+ *
* @throws ParseException
*/
@Test
@@ -70,7 +71,8 @@
List<TimerProject> projects = new ArrayList<TimerProject>();
projects.addAll(testSaver.load());
ReportGenerator generator = new ReportGenerator();
- String content = generator.getReportText(ReportGenerator.Type.BY_DAY_REPORT, projects, d1, d2, false);
+ String content = generator.getReportText(ReportGenerator.Type.BY_DAY_REPORT,
+ projects, d1, d2, false, false);
if (log.isDebugEnabled()) {
log.debug("Daily report = " + content);
@@ -103,9 +105,48 @@
}
}*/
}
-
+
/**
+ * Test report generation with annotation time.
+ *
+ * @throws ParseException
+ */
+ @Test
+ public void getReportTextDailyAnnotationTime() throws ParseException {
+
+ /*try {
+ FIXME saver.lock();*/
+
+ Date d1 = df.parse("November 1, 2008");
+ Date d2 = df.parse("March 31, 2009");
+ List<TimerProject> projects = new ArrayList<TimerProject>();
+ projects.addAll(testSaver.load());
+ ReportGenerator generator = new ReportGenerator();
+ String content = generator.getReportText(ReportGenerator.Type.BY_DAY_REPORT,
+ projects, d1, d2, true, true);
+
+ if (log.isDebugEnabled()) {
+ log.debug("Daily report = " + content);
+ }
+
+ Assert.assertNotNull(content);
+
+ // with annotations and time (* is important in test)
+ Assert.assertTrue(content.indexOf("* 2:10 PM : Test task and subtask time") > 0);
+ Assert.assertTrue(content.indexOf("* 12:00 AM : Not easy work") > 0);
+
+ /*FIXME saver.unlock();
+ } catch (DataLockingException e) {
+ if(log.isErrorEnabled()) {
+ log.error("getProjectFromFileTest error", e);
+ Assert.fail();
+ }
+ }*/
+ }
+
+ /**
* Test report generation.
+ *
* @throws ParseException
*/
@Test
@@ -119,7 +160,8 @@
List<TimerProject> projects = new ArrayList<TimerProject>();
projects.addAll(testSaver.load());
ReportGenerator generator = new ReportGenerator();
- String content = generator.getReportText(ReportGenerator.Type.BY_WEEK_REPORT, projects, d1, d2, true);
+ String content = generator.getReportText(ReportGenerator.Type.BY_WEEK_REPORT,
+ projects, d1, d2, true, false);
if (log.isDebugEnabled()) {
log.debug("Weekly report = " + content);
@@ -136,9 +178,47 @@
Assert.assertTrue(content.indexOf("Add webservice") > 0);
Assert.assertTrue(content.indexOf("Add workspace support") > 0);
+ // with annotations
+ Assert.assertTrue(content.indexOf("* Test task and subtask time") > 0);
+ Assert.assertTrue(content.indexOf("* Not easy work") > 0);
+
+ /*FIXME saver.unlock();
+ } catch (DataLockingException e) {
+ if(log.isErrorEnabled()) {
+ log.error("getProjectFromFileTest error", e);
+ Assert.fail();
+ }
+ }*/
+ }
+
+ /**
+ * Test report generation with annotation time.
+ *
+ * @throws ParseException
+ */
+ @Test
+ public void getReportTextMonthlyAnnotationTime() throws ParseException {
+
+ /*try {
+ FIXME saver.lock();*/
+
+ Date d1 = df.parse("November 1, 2008");
+ Date d2 = df.parse("March 31, 2009");
+ List<TimerProject> projects = new ArrayList<TimerProject>();
+ projects.addAll(testSaver.load());
+ ReportGenerator generator = new ReportGenerator();
+ String content = generator.getReportText(ReportGenerator.Type.BY_MONTH_REPORT,
+ projects, d1, d2, true, true);
+
+ if (log.isDebugEnabled()) {
+ log.debug("Monthly report = " + content);
+ }
+
+ Assert.assertNotNull(content);
+
// no annotations
- Assert.assertTrue(content.indexOf("Test task and subtask time") > 0);
- Assert.assertTrue(content.indexOf("Not easy work") > 0);
+ Assert.assertTrue(content.indexOf("* 2/3/09 2:10 PM : Test task and subtask time") > 0);
+ Assert.assertTrue(content.indexOf("* 12/11/08 12:00 AM : Not easy work") > 0);
/*FIXME saver.unlock();
} catch (DataLockingException e) {
@@ -164,7 +244,8 @@
List<TimerProject> projects = new ArrayList<TimerProject>();
projects.addAll(testSaver.load());
ReportGenerator generator = new ReportGenerator();
- String content = generator.getReportText(ReportGenerator.Type.BY_MONTH_REPORT, projects, d1, d2, false);
+ String content = generator.getReportText(ReportGenerator.Type.BY_MONTH_REPORT,
+ projects, d1, d2, false, false);
if (log.isDebugEnabled()) {
log.debug("Monthly report = " + content);
@@ -209,7 +290,8 @@
List<TimerProject> projects = new ArrayList<TimerProject>();
projects.addAll(testSaver.load());
ReportGenerator generator = new ReportGenerator();
- String content = generator.getReportText(ReportGenerator.Type.BY_YEAR_REPORT, projects, d1, d2, false);
+ String content = generator.getReportText(ReportGenerator.Type.BY_YEAR_REPORT,
+ projects, d1, d2, false, false);
if (log.isDebugEnabled()) {
log.debug("Yearly report = " + content);
@@ -255,7 +337,8 @@
List<TimerProject> projects = new ArrayList<TimerProject>();
projects.addAll(testSaver.load());
ReportGenerator generator = new ReportGenerator();
- String content = generator.getReportText(ReportGenerator.Type.BY_PROJECT_REPORT, projects, d1, d2, true);
+ String content = generator.getReportText(ReportGenerator.Type.BY_PROJECT_REPORT,
+ projects, d1, d2, true, false);
if (log.isDebugEnabled()) {
log.debug("Project report = " + content);
@@ -273,9 +356,9 @@
Assert.assertTrue(content.indexOf("Add service layer") > 0);
Assert.assertTrue(content.indexOf("Calendar to date") > 0);
- // no annotations
+ // test annotations
Assert.assertFalse(content.indexOf("Test task and subtask time") > 0);
- Assert.assertTrue(content.indexOf("Not easy work") > 0);
+ Assert.assertTrue(content.indexOf("* Not easy work") > 0);
/*FIXME saver.unlock();
} catch (DataLockingException e) {
Modified: trunk/src/test/resources/testdata/4.ann
===================================================================
--- trunk/src/test/resources/testdata/4.ann 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/test/resources/testdata/4.ann 2012-03-18 16:44:26 UTC (rev 2834)
@@ -1 +1 @@
-1233615601 Test task and subtask time
\ No newline at end of file
+1233666601 Test task and subtask time
\ No newline at end of file
Modified: trunk/src/test/resources/testdata/5.ann
===================================================================
--- trunk/src/test/resources/testdata/5.ann 2012-03-17 10:47:17 UTC (rev 2833)
+++ trunk/src/test/resources/testdata/5.ann 2012-03-18 16:44:26 UTC (rev 2834)
@@ -1 +1 @@
-1233615601 Test subtask time
+1233621301 Test subtask time
1
0
r2833 - in trunk/src: main/java/org/chorem/jtimer/entities test/java/org/chorem/jtimer/entities
by echatellier@users.chorem.org 17 Mar '12
by echatellier@users.chorem.org 17 Mar '12
17 Mar '12
Author: echatellier
Date: 2012-03-17 11:47:17 +0100 (Sat, 17 Mar 2012)
New Revision: 2833
Url: http://chorem.org/repositories/revision/jtimer/2833
Log:
Modify clone implementation (just soft clone now)
Modified:
trunk/src/main/java/org/chorem/jtimer/entities/TimerTask.java
trunk/src/test/java/org/chorem/jtimer/entities/TimerTaskTest.java
Modified: trunk/src/main/java/org/chorem/jtimer/entities/TimerTask.java
===================================================================
--- trunk/src/main/java/org/chorem/jtimer/entities/TimerTask.java 2012-03-17 09:58:17 UTC (rev 2832)
+++ trunk/src/main/java/org/chorem/jtimer/entities/TimerTask.java 2012-03-17 10:47:17 UTC (rev 2833)
@@ -33,21 +33,16 @@
import java.util.TreeMap;
import java.util.UUID;
-import org.apache.commons.lang3.SerializationUtils;
import org.chorem.jtimer.utils.DailySortedMap;
/**
* Represents a task.
*
- * This task is cloneable using SerializationUtils (commons-lang).
- *
* @author chatellier
* @version $Revision$
*
* Last update : $Date$
* By : $Author$
- *
- * @see SerializationUtils
*/
public class TimerTask implements Cloneable,
Comparable<TimerTask>, Serializable {
@@ -369,27 +364,14 @@
try {
task = (TimerTask) super.clone();
- // clone collections using
- // commons-lang SerializationUtils
-
- // copy name
- task.name = name;
-
// copy date
task.creationDate = creationDate == null ? null
: (Date) creationDate.clone();
- // copy durations
- task.allDaysTimes = (DailySortedMap<Long>) SerializationUtils
- .clone((DailySortedMap<Long>) allDaysTimes);
-
- // copy notes
- task.allDaysAnnotations = (TreeMap<Date, String>) SerializationUtils
- .clone((TreeMap<Date, String>) allDaysAnnotations);
-
- // copy subtasks
- task.subTasks = (ArrayList<TimerTask>) SerializationUtils
- .clone((ArrayList<TimerTask>) subTasks);
+ // make new list instance
+ task.allDaysTimes = new DailySortedMap<Long>(allDaysTimes);
+ task.allDaysAnnotations = new TreeMap<Date, String>(allDaysAnnotations);
+ task.subTasks = new ArrayList<TimerTask>(subTasks);
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Can't clone", e);
}
Modified: trunk/src/test/java/org/chorem/jtimer/entities/TimerTaskTest.java
===================================================================
--- trunk/src/test/java/org/chorem/jtimer/entities/TimerTaskTest.java 2012-03-17 09:58:17 UTC (rev 2832)
+++ trunk/src/test/java/org/chorem/jtimer/entities/TimerTaskTest.java 2012-03-17 10:47:17 UTC (rev 2833)
@@ -5,7 +5,7 @@
* $Id$
* $HeadURL$
* %%
- * Copyright (C) 2008 - 2011 CodeLutin, Chatellier Eric
+ * Copyright (C) 2008 - 2012 CodeLutin, Chatellier Eric
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
@@ -25,7 +25,6 @@
package org.chorem.jtimer.entities;
-import java.util.Calendar;
import java.util.Date;
import org.chorem.jtimer.AbstractJTimerTest;
@@ -70,7 +69,7 @@
Assert.assertTrue(clonedTask.allDaysTimes instanceof DailySortedMap<?>, "Clone put invalid type for map");
Assert.assertFalse(clonedTask.allDaysAnnotations instanceof DailySortedMap<?>, "Clone put invalid type for map");
}
-
+
/**
* Test task subtasks.
*/
@@ -91,7 +90,6 @@
Assert.assertEquals(1, clonedTask.getSubTasks().size());
// subtask modification
- subtask.setName("bobo");
Assert.assertEquals("subtest", clonedTask.getSubTasks().get(0).getName());
// clone removal, not modify first
@@ -99,4 +97,26 @@
Assert.assertEquals(0, clonedTask.getSubTasks().size());
Assert.assertEquals(1, task.getSubTasks().size());
}
+
+ /**
+ * Test that clone is a soft clone (excepted for lists).
+ */
+ @Test
+ public void testCloneLists() {
+ TimerTask task = new TimerTask();
+ task.setName("test");
+
+ TimerTask clonedTask = task.clone();
+
+ task.setClosed(true);
+ task.addTask(new TimerTask());
+ task.setName("new name");
+
+ Assert.assertEquals(task.getName(), "new name");
+ Assert.assertEquals(clonedTask.getName(), "test");
+ Assert.assertTrue(task.isClosed());
+ Assert.assertFalse(clonedTask.isClosed());
+ Assert.assertEquals(task.getSubTasks().size(), 1);
+ Assert.assertEquals(clonedTask.getSubTasks().size(), 0);
+ }
}
1
0