Re: [Planner Dev] "Nonstandard Days" and "Dominant tasks" - 5th patch - the end of the tunnel ? ; )
- From: Kurt Maute <kurt maute us>
- To: Planner Project Manager - Development List <planner-dev lists imendio com>
- Subject: Re: [Planner Dev] "Nonstandard Days" and "Dominant tasks" - 5th patch - the end of the tunnel ? ; )
- Date: Tue, 21 Mar 2006 22:35:53 -0500
On Tue, 2006-03-21 at 11:08 +0100, Matteo Nastasi wrote:
> Hi guys, attached the 5th revision of my patch.
>
> Your comments are wellcome.
I didn't want to torture you any longer with picky stylistic issues, so
I went ahead and made some adjustments in terms of spacing, and one
instance of omitted braces on a for statement. Patch attached.
I did notice something though, it appears when zooming out on a project
until the weekend nonworking time is no longer greyed out in the gantt
background. Looks like the gantt bars white out during the weekend time
creating a striped look. This is new behavior.
http://www.maute.us/planner/images/WeekendStriping.png
> ADDENDA: I think that I solve the vertical alignement problem of the
> text at right of the tasks in gantt view, can you verify it ?
Looks like they're vertically centered now. I don't see a bug report
for vertical alignment though - maybe I missed it.
--
Kurt Maute <kurt maute us>
? planner/{arch}
? planner/docs/user-guide/eu/Makefile
? planner/docs/user-guide/eu/Makefile.in
? planner/docs/user-guide/eu/omf_timestamp
? planner/docs/user-guide/eu/planner-eu.omf.out
Index: planner/autogen.sh
===================================================================
RCS file: /cvs/gnome/planner/autogen.sh,v
retrieving revision 1.7
diff -u -r1.7 autogen.sh
--- planner/autogen.sh 16 Apr 2005 16:30:25 -0000 1.7
+++ planner/autogen.sh 22 Mar 2006 03:22:59 -0000
@@ -163,7 +163,7 @@
fi
done
-conf_flags="--enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c
+conf_flags="--enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c #--enable-simple-priority-scheduling
cd "$ORIGDIR"
Index: planner/configure.in
===================================================================
RCS file: /cvs/gnome/planner/configure.in,v
retrieving revision 1.69
diff -u -r1.69 configure.in
--- planner/configure.in 24 Jan 2006 04:59:01 -0000 1.69
+++ planner/configure.in 22 Mar 2006 03:22:59 -0000
@@ -249,6 +249,18 @@
AM_CONDITIONAL(HAVE_EDS_PLUGIN, test x$use_eds = xyes)
dnl -----------------------------------------------------------
+dnl -----------------------------------
+dnl | Simple Priority Scheduling check |-----------------------------------------
+dnl -----------------------------------
+AC_ARG_ENABLE(simple_priority_scheduling, [ --enable-simple-priority-scheduling enable a simple priority scheduling in tasks management[default=no]], enable_simple_priority_scheduling="$enableval", enable_simple_priority_scheduling=no)
+if test "x$enable_simple_priority_scheduling" = "xyes" ; then
+ use_simple_priority_scheduling=yes
+ AC_DEFINE(WITH_SIMPLE_PRIORITY_SCHEDULING, 1, [Define to 1 to enable enable a simple priority scheduling in tasks management feature])
+else
+ use_simple_priority_scheduling=no
+fi
+AM_CONDITIONAL(HAVE_SIMPLE_PRIORITY_SCHEDULING, test x$use_simple_priority_scheduling = xyes)
+dnl -----------------------------------------------------------
dnl -------------------------------------
dnl | Evolution Data Server Backend check |--------------------------------------
@@ -326,10 +338,15 @@
echo "Python bindings : $have_python"
echo "Python plugin : $enable_python_plugin"
#echo "Dotnet bindings : $have_dotnet"
+echo "Simple priority scheduling : $use_simple_priority_scheduling"
echo "Database/GDA support : $use_gda"
echo "Evolution Data Server import : $use_eds"
echo "Evolution Data Server backend: $use_eds_backend"
echo
+
+if test "x$use_simple_priority_scheduling" = "xyes" ; then
+ echo "*** Note: The use simple priority tasks scheduling is experimental. Don't use it in production systems ***"
+fi
if test "x$enable_eds_backend" = "xyes" ; then
echo "*** Note: The Evolution backend is experimental. Don't use it in production systems ***"
Index: planner/data/planner.schemas.in
===================================================================
RCS file: /cvs/gnome/planner/data/planner.schemas.in,v
retrieving revision 1.1
diff -u -r1.1 planner.schemas.in
--- planner/data/planner.schemas.in 19 Feb 2005 16:22:05 -0000 1.1
+++ planner/data/planner.schemas.in 22 Mar 2006 03:23:00 -0000
@@ -14,6 +14,18 @@
</schema>
<schema>
+ <key>/schemas/apps/planner/views/gantt_view/display_nonstandard_days</key>
+ <applyto>/apps/planner/views/gantt_view/display_nonstandard_days</applyto>
+ <owner>planner</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Display nonstandard days in Gantt view</short>
+ <long>Whether to display nonstandard days in the Gantt view.</long>
+ </locale>
+ </schema>
+
+ <schema>
<key>/schemas/apps/planner/views/task_view/highlight_critical_path</key>
<applyto>/apps/planner/views/task_view/highlight_critical_path</applyto>
<owner>planner</owner>
Index: planner/data/ui/gantt-view.ui
===================================================================
RCS file: /cvs/gnome/planner/data/ui/gantt-view.ui,v
retrieving revision 1.10
diff -u -r1.10 gantt-view.ui
--- planner/data/ui/gantt-view.ui 19 Apr 2005 20:01:41 -0000 1.10
+++ planner/data/ui/gantt-view.ui 22 Mar 2006 03:23:00 -0000
@@ -14,6 +14,7 @@
<placeholder name="View specific placeholder bottom">
<menuitem action="EditColumns"/>
<menuitem action="HighlightCriticalTasks"/>
+ <menuitem action="NonstandardDays"/>
</placeholder>
</menu>
Index: planner/libplanner/mrp-calendar.c
===================================================================
RCS file: /cvs/gnome/planner/libplanner/mrp-calendar.c,v
retrieving revision 1.7
diff -u -r1.7 mrp-calendar.c
--- planner/libplanner/mrp-calendar.c 24 Feb 2005 22:31:41 -0000 1.7
+++ planner/libplanner/mrp-calendar.c 22 Mar 2006 03:23:00 -0000
@@ -1063,6 +1063,29 @@
}
}
+/**
+ * mrp_interval_set_absolute:
+ * @interval: an #MrpInterval
+ * @offset: the offset to subtract to start and end
+ * @start: value of start time
+ * @end: value of end time
+ *
+ * Set the start and end time of #interval, with an optional @offset.
+ *
+ **/
+void
+mrp_interval_set_absolute (MrpInterval *interval,
+ mrptime offset,
+ mrptime start,
+ mrptime end)
+{
+ g_return_if_fail (interval != NULL);
+
+ interval->start = start - offset;
+
+ interval->end = end - offset;
+}
+
static void
foreach_day_interval_add_to_list (MrpDay *day,
GList *intervals,
Index: planner/libplanner/mrp-calendar.h
===================================================================
RCS file: /cvs/gnome/planner/libplanner/mrp-calendar.h,v
retrieving revision 1.3
diff -u -r1.3 mrp-calendar.h
--- planner/libplanner/mrp-calendar.h 29 Jun 2004 09:06:44 -0000 1.3
+++ planner/libplanner/mrp-calendar.h 22 Mar 2006 03:23:00 -0000
@@ -127,6 +127,10 @@
mrptime offset,
mrptime *start,
mrptime *end);
+void mrp_interval_set_absolute (MrpInterval *interval,
+ mrptime offset,
+ mrptime start,
+ mrptime end);
#endif /* __MRP_CALENDAR_H__ */
Index: planner/libplanner/mrp-task-manager.c
===================================================================
RCS file: /cvs/gnome/planner/libplanner/mrp-task-manager.c,v
retrieving revision 1.18
diff -u -r1.18 mrp-task-manager.c
--- planner/libplanner/mrp-task-manager.c 25 Oct 2005 21:26:40 -0000 1.18
+++ planner/libplanner/mrp-task-manager.c 22 Mar 2006 03:23:01 -0000
@@ -76,6 +76,12 @@
task_manager_task_duration_notify_cb (MrpTask *task,
GParamSpec *spec,
MrpTaskManager *manager);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+static void
+task_manager_task_priority_notify_cb (MrpTask *task,
+ GParamSpec *spec,
+ MrpTaskManager *manager);
+#endif
static void
task_manager_task_constraint_notify_cb (MrpTask *task,
GParamSpec *spec,
@@ -261,6 +267,13 @@
"notify::duration",
G_CALLBACK (task_manager_task_duration_notify_cb),
manager);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ /* Added to manage the transaction from normal to dominant. */
+ g_signal_connect (task,
+ "notify::priority",
+ G_CALLBACK (task_manager_task_priority_notify_cb),
+ manager);
+#endif
g_signal_connect (task,
"notify::constraint",
G_CALLBACK (task_manager_task_constraint_notify_cb),
@@ -1222,20 +1235,13 @@
return start;
}
-typedef struct {
- gboolean is_start;
- mrptime start;
- mrptime end;
- gint units;
-} UnitsInterval;
-
-#define UNIT_IVAL_GET_TIME(R) ((R->is_start?R->start:R->end))
-
+/* NOTE: MrpUnitsInterval moved in mrp-task.h to enable
+ other objects to use it. */
static gint
units_interval_sort_func (gconstpointer a, gconstpointer b)
{
- UnitsInterval *ai = *(UnitsInterval **) a;
- UnitsInterval *bi = *(UnitsInterval **) b;
+ MrpUnitsInterval *ai = *(MrpUnitsInterval **) a;
+ MrpUnitsInterval *bi = *(MrpUnitsInterval **) b;
mrptime at, bt;
if (ai->is_start) {
@@ -1260,12 +1266,12 @@
}
}
-static UnitsInterval *
+static MrpUnitsInterval *
units_interval_new (MrpInterval *ival, gint units, gboolean is_start)
{
- UnitsInterval *unit_ival;
+ MrpUnitsInterval *unit_ival;
- unit_ival = g_new (UnitsInterval, 1);
+ unit_ival = g_new (MrpUnitsInterval, 1);
unit_ival->is_start = is_start;
unit_ival->units = units;
@@ -1292,50 +1298,184 @@
MrpDay *day;
GList *ivals, *l;
MrpInterval *ival;
- UnitsInterval *unit_ival, *new_unit_ival;
+
+ MrpUnitsInterval *unit_ival, *new_unit_ival;
+ MrpUnitsInterval *unit_ival_start, *unit_ival_end;
GList *unit_ivals = NULL;
MrpAssignment *assignment;
MrpResource *resource;
GList *assignments, *a;
- gint units;
+ gint units, units_full, units_orig, priority;
+ mrptime i_start, i_end;
+
mrptime t;
mrptime poc;
GPtrArray *array;
guint len;
gint i;
+ mrptime diffe;
+
+ gint res_n;
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ MrpInterval *ival_split;
+ MrpUnitsInterval *unit_ival_start_cmp;
+ MrpUnitsInterval *split_unit_ival;
+ MrpAssignment *v_assignment;
+ MrpResource *v_resource;
+ GList *v_assignments, *v_a;
+ gint v_units;
+ GList *v_tasks, *v_l;
+ GPtrArray *array_split;
+ gint e, lastct;
+ mrptime v_start, v_end;
+ mrptime i_start_post, i_end_post, i_start_cmp, i_end_cmp;
+#endif
+
priv = manager->priv;
assignments = mrp_task_get_assignments (task);
array = g_ptr_array_new ();
+ priority = mrp_task_get_priority (task);
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ v_tasks = mrp_task_manager_get_all_tasks (manager);
+#endif
for (a = assignments; a; a = a->next) {
assignment = a->data;
resource = mrp_assignment_get_resource (assignment);
- units = mrp_assignment_get_units (assignment);
+ units_orig = mrp_assignment_get_units (assignment);
calendar = mrp_resource_get_calendar (resource);
if (!calendar) {
calendar = mrp_project_get_calendar (priv->project);
}
-
day = mrp_calendar_get_day (calendar, date, TRUE);
ivals = mrp_calendar_day_get_intervals (calendar, day, TRUE);
for (l = ivals; l; l = l->next) {
ival = l->data;
+ mrp_interval_get_absolute (ival, date, &i_start, &i_end);
+ units = units_orig;
+ diffe = i_end - i_start;
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ for (v_l = v_tasks; v_l; v_l = v_l->next) {
+ MrpTask *v_task;
+
+ v_task = v_l->data;
+
+ if (v_task == task) {
+ continue;
+ }
+
+ if (mrp_task_is_dominant (v_task) == FALSE) {
+ continue;
+ }
+ /* If intervals not overlapped -> contine. */
+ v_start = mrp_task_get_work_start (v_task);
+ v_end = mrp_task_get_finish (v_task);
+
+ if (i_start > v_end || i_end < v_start) {
+ continue;
+ }
+
+ /* Compare resources task with resources of dominant task. */
+ v_assignments = mrp_task_get_assignments (v_task);
+
+ for (v_a = v_assignments; v_a; v_a = v_a->next) {
+ v_assignment = v_a->data;
+
+ v_resource = mrp_assignment_get_resource (v_assignment);
+ if (v_resource == resource) {
+ v_units = mrp_assignment_get_units (v_assignment);
+ /*
+ If the dominant cost is compatible with the task
+ request -> break.
+
+ FIXME - tasks that share the vampirised resource not work!
+ */
+ if (100 - v_units > units) {
+ break;
+ }
+
+ /* Trim the interval of the dominant task. */
+ v_start = (v_start < i_start ?
+ i_start : v_start);
+ v_end = (v_end > i_end ?
+ i_end : v_end);
+
+ if (i_start < v_start) {
+ /*
+ ----...
+ ------...
+ ival len from start to dominant
+ */
+ ival = mrp_interval_new (i_start-date, v_start-date);
+
+ unit_ival_start = units_interval_new (ival, units, TRUE);
+ unit_ival_start->units_full = units;
+ unit_ival_end = units_interval_new (ival, units, FALSE);
+ unit_ival_end->units_full = units;
+ g_ptr_array_add (array, unit_ival_start);
+ g_ptr_array_add (array, unit_ival_end);
+ }
+
+ ival = mrp_interval_new (v_start-date, v_end-date);
+
+ unit_ival_start = units_interval_new (ival, (100 - v_units), TRUE);
+ unit_ival_start->units_full = units;
+ unit_ival_end = units_interval_new (ival, (100 - v_units), FALSE);
+ unit_ival_end->units_full = units;
+ g_ptr_array_add (array, unit_ival_start);
+ g_ptr_array_add (array, unit_ival_end);
+
+ if (v_end < i_end) {
+ /*
+ ---- ...
+ ------...
+ ival len from end to dominant
+ */
+ ival = mrp_interval_new (v_end-date, i_end-date);
+
+ unit_ival_start = units_interval_new (ival, units, TRUE);
+ unit_ival_start->units_full = units;
+ unit_ival_end = units_interval_new (ival, units, FALSE);
+ unit_ival_end->units_full = units;
+ g_ptr_array_add (array, unit_ival_start);
+ g_ptr_array_add (array, unit_ival_end);
+ }
+ break;
+ }
+ } /* for (v_a = v_assignments; v_a; ... */
+ if (v_a != NULL) {
+ break;
+ }
+ } /* for (v_l = v_tasks; v_l; ... */
+
+
+ if (v_l == NULL) {
+#endif /* ifdef WITH_SIMPLE_PRIORITY_SCHEDULING */
/* Start of the interval. */
- unit_ival = units_interval_new (ival, units, TRUE);
- g_ptr_array_add (array, unit_ival);
+ unit_ival_start = units_interval_new (ival, units, TRUE);
+ unit_ival_start->units_full = units;
/* End of the interval. */
- unit_ival = units_interval_new (ival, units, FALSE);
- g_ptr_array_add (array, unit_ival);
- }
- }
+ unit_ival_end = units_interval_new (ival, units, FALSE);
+ unit_ival_end->units_full = units;
+
+ g_ptr_array_add (array, unit_ival_start);
+ g_ptr_array_add (array, unit_ival_end);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ }
+#endif
+ } /* for (l = ivals; l; ... */
+ } /* for (a = assignments; a; ... */
/* If the task is not allocated, we handle it as if we have one resource
* assigned to it, 100%, using the project calendar.
@@ -1351,20 +1491,82 @@
/* Start of the interval. */
unit_ival = units_interval_new (ival, 100, TRUE);
+ unit_ival->units_full = 100;
g_ptr_array_add (array, unit_ival);
/* End of the interval. */
unit_ival = units_interval_new (ival, 100, FALSE);
+ unit_ival->units_full = 100;
g_ptr_array_add (array, unit_ival);
}
}
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ /* Requantize the time intervals. */
+ array_split = g_ptr_array_new ();
+ len = array->len;
+ poc = -1;
+ units = 0;
+ /* += 2 because start and end are strictly joined. */
+ for (i = 0; i < len; i+= 2) {
+ unit_ival_start = g_ptr_array_index (array, i);
+
+ i_start = unit_ival_start->start;
+ i_end = unit_ival_start->end;
+
+ lastct = 1;
+ i_end_post = i_end;
+ for (i_start_post = i_start; i_start_post < i_end && lastct > 0;) {
+ lastct = 0;
+ i_end_post = i_end;
+ for (e = 0 ; e < len ; e+= 2) {
+ unit_ival_start_cmp = g_ptr_array_index (array, e);
+
+ i_start_cmp = unit_ival_start_cmp->start;
+ i_end_cmp = unit_ival_start_cmp->end;
+
+ /* If not overlapped intervals. */
+ if (i_start_post >= i_end_cmp || i_end_post <= i_start_cmp) {
+ continue;
+ }
+ if (i_start_post < i_start_cmp && i_start_cmp < i_end_post) {
+ i_end_post = i_start_cmp;
+ lastct++;
+ continue;
+ }
+ if (i_start_post < i_end_cmp && i_end_cmp < i_end_post) {
+ i_end_post = i_end_cmp;
+ lastct++;
+ continue;
+ }
+ }
+ ival_split = mrp_interval_new (i_start_post, i_end_post);
+ split_unit_ival = units_interval_new (ival_split, unit_ival_start->units, TRUE);
+ split_unit_ival->units_full = unit_ival_start->units_full;
+ g_ptr_array_add (array_split, split_unit_ival);
+ split_unit_ival = units_interval_new (ival_split, unit_ival_start->units, FALSE);
+ split_unit_ival->units_full = unit_ival_start->units_full;
+ g_ptr_array_add (array_split, split_unit_ival);
+ i_start_post = i_end_post;
+ }
+ }
+ for (i = 0; i < array->len; i++) {
+ g_free (array->pdata[i]);
+ }
+
+ g_ptr_array_free (array, TRUE);
+ array = array_split;
+#endif /* ifdef WITH_SIMPLE_PRIORITY_SCHEDULING */
+ /* Clean and reassign the split_array ptr to the array */
g_ptr_array_sort (array, units_interval_sort_func);
len = array->len;
+
poc = -1;
units = 0;
+ units_full = 0;
+ res_n = 0;
for (i = 0; i < len; i++) {
unit_ival = g_ptr_array_index (array, i);
@@ -1376,23 +1578,28 @@
* determined by now.
*/
if (poc != -1) {
- if (units > 0) {
- new_unit_ival = g_new (UnitsInterval, 1);
- new_unit_ival->units = units;
- new_unit_ival->start = poc;
- new_unit_ival->end = t;
-
- unit_ivals = g_list_prepend (unit_ivals, new_unit_ival);
- }
+ new_unit_ival = g_new (MrpUnitsInterval, 1);
+ new_unit_ival->units = units;
+ new_unit_ival->units_full = units_full;
+ new_unit_ival->start = poc;
+ new_unit_ival->end = t;
+ new_unit_ival->res_n = res_n;
+ res_n = 0;
+ unit_ivals = g_list_prepend (unit_ivals, new_unit_ival);
}
-
+
poc = t;
}
-
+
if (unit_ival->is_start) {
units += unit_ival->units;
+ units_full += unit_ival->units_full;
+ if (assignments) {
+ res_n++;
+ }
} else {
units -= unit_ival->units;
+ units_full -= unit_ival->units_full;
}
}
@@ -1416,7 +1623,7 @@
mrptime t1, t2;
mrptime work_start;
GList *unit_ivals, *l;
- UnitsInterval *unit_ival;
+ MrpUnitsInterval *unit_ival;
MrpTaskType type;
priv = manager->priv;
@@ -1499,11 +1706,12 @@
gint work;
gint effort;
gint delta;
- GList *unit_ivals, *l;
- UnitsInterval *unit_ival;
+ GList *unit_ivals, *unit_ivals_tot = NULL, *l = NULL;
+ MrpUnitsInterval *unit_ival;
MrpTaskType type;
MrpTaskSched sched;
+
priv = manager->priv;
if (task == priv->root) {
@@ -1547,6 +1755,7 @@
}
if (!unit_ivals) {
+ /* Holidays for all. */
t += 60*60*24;
continue;
}
@@ -1556,7 +1765,6 @@
t1 = t + unit_ival->start;
t2 = t + unit_ival->end;
-
/* Skip any intervals before the task starts. */
if (t2 < start) {
continue;
@@ -1577,15 +1785,23 @@
if (sched == MRP_TASK_SCHED_FIXED_WORK) {
delta = floor (0.5 + (double) unit_ival->units * (t2 - t1) / 100.0);
- *duration += (t2 - t1);
-
+ if (unit_ival->units_full > 0) {
+ *duration += (t2 - t1);
+ }
+
if (effort + delta >= work) {
finish = t1 + floor (0.5 + (work - effort) / unit_ival->units * 100.0);
/* Subtract the spill. */
*duration -= floor (0.5 + (effort + delta - work) / unit_ival->units * 100.0);
+ unit_ival->start = t1;
+ unit_ival->end = finish;
+ unit_ivals_tot = g_list_prepend (unit_ivals_tot, unit_ival);
goto done;
}
+ unit_ival->start = t1;
+ unit_ival->end = t2;
+ unit_ivals_tot = g_list_prepend (unit_ivals_tot, unit_ival);
}
else if (sched == MRP_TASK_SCHED_FIXED_DURATION) {
delta = t2 - t1;
@@ -1602,7 +1818,6 @@
effort += delta;
}
-
t += 60*60*24;
}
@@ -1613,9 +1828,18 @@
}
imrp_task_set_work_start (task, work_start);
- g_list_foreach (unit_ivals, (GFunc) g_free, NULL);
+ /* clean the tail of the list before exit of function. */
+ if (l) {
+ for (l = l->next ; l; l = l->next) {
+ unit_ival = l->data;
+ g_free (unit_ival);
+ }
+ }
g_list_free (unit_ivals);
+ unit_ivals_tot = g_list_reverse (unit_ivals_tot);
+ mrp_task_set_unit_ivals (task, unit_ivals_tot);
+
return finish;
}
@@ -1976,6 +2200,15 @@
mrp_task_manager_recalc (manager, TRUE);
}
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+static void
+task_manager_task_priority_notify_cb (MrpTask *task,
+ GParamSpec *spec,
+ MrpTaskManager *manager)
+{
+ mrp_task_manager_recalc (manager, TRUE);
+}
+#endif
static void
task_manager_task_constraint_notify_cb (MrpTask *task,
GParamSpec *spec,
@@ -2100,8 +2333,9 @@
node = imrp_task_get_graph_node (task);
for (l = node->next; l; l = l->next) {
- if (!check_predecessor_traverse (manager, l->data, end, length + 1))
+ if (!check_predecessor_traverse (manager, l->data, end, length + 1)) {
return FALSE;
+ }
}
return TRUE;
@@ -2254,6 +2488,80 @@
return work;
}
+static gint
+task_manager_get_work_for_task_with_assignments (MrpTaskManager *manager,
+ MrpTask *task,
+ mrptime start,
+ mrptime finish)
+{
+ MrpTaskManagerPriv *priv;
+ mrptime t;
+ mrptime t1, t2;
+ gint work, delta;
+ GList *ivals, *l;
+ MrpUnitsInterval *ival;
+
+ priv = manager->priv;
+
+ work = 0;
+
+ /* Loop through the intervals of the calendar and add up the work, until
+ * the finish time is hit.
+ */
+ t = mrp_time_align_day (start);
+
+
+ while (t < finish) {
+ ivals = task_manager_get_task_units_intervals (manager, task, t);
+
+ /* If we don't get anywhere in 100 days, then the calendar must
+ * be broken, so we abort the scheduling of this task. It's not
+ * the best solution but fixes the issue for now.
+ */
+ if (work == 0 && t - start > (60*60*24*100)) {
+ break;
+ }
+
+ if (!ivals) {
+ /* Holidays for all. */
+ t += 60*60*24;
+ continue;
+ }
+
+ for (l = ivals; l; l = l->next) {
+ ival = l->data;
+
+ t1 = t + ival->start;
+ t2 = t + ival->end;
+ /* Skip any intervals before the task starts. */
+ if (t2 < start) {
+ continue;
+ }
+
+ /* Don't add time before the start of the task. */
+ t1 = MAX (t1, start);
+ if (t1 == t2) {
+ continue;
+ }
+
+ /* Resize the too long interval */
+ t2 = MIN (t2, finish);
+ if (t1 >= t2) {
+ break;
+ }
+
+ delta = floor (0.5 + (double) ival->units * (t2 - t1) / 100.0);
+
+ work += delta;
+ }
+
+
+ t += 24*60*60;
+ }
+
+ return (work);
+}
+
/* Calculate the work needed to achieve the specified start and finish, with the
* allocated resources' calendars in consideration.
*/
@@ -2265,9 +2573,7 @@
{
MrpTaskManagerPriv *priv;
gint work = 0;
- MrpAssignment *assignment;
- MrpResource *resource;
- GList *assignments, *a;
+ GList *assignments;
MrpCalendar *calendar;
priv = manager->priv;
@@ -2293,24 +2599,13 @@
*/
assignments = mrp_task_get_assignments (task);
- for (a = assignments; a; a = a->next) {
- assignment = a->data;
-
- resource = mrp_assignment_get_resource (assignment);
-
- calendar = mrp_resource_get_calendar (resource);
- if (!calendar) {
- calendar = mrp_project_get_calendar (priv->project);
- }
-
- work += task_manager_get_work_for_calendar (manager,
- calendar,
- start,
- finish) *
- mrp_assignment_get_units (assignment) / 100;
+ if (assignments) {
+ work = task_manager_get_work_for_task_with_assignments (manager,
+ task,
+ start,
+ finish);
}
-
- if (!assignments) {
+ else {
calendar = mrp_project_get_calendar (priv->project);
work = task_manager_get_work_for_calendar (manager,
Index: planner/libplanner/mrp-task.c
===================================================================
RCS file: /cvs/gnome/planner/libplanner/mrp-task.c,v
retrieving revision 1.14
diff -u -r1.14 mrp-task.c
--- planner/libplanner/mrp-task.c 23 Nov 2005 03:41:43 -0000 1.14
+++ planner/libplanner/mrp-task.c 22 Mar 2006 03:23:01 -0000
@@ -125,6 +125,9 @@
/* List of assignments. */
GList *assignments;
+ /* Intervals to build graphical view of the task */
+ GList *unit_ivals;
+
gfloat cost;
gboolean cost_cached;
};
@@ -195,6 +198,7 @@
priv->cost = 0.0;
priv->cost_cached = FALSE;
+ priv->unit_ivals = NULL;
}
static void
@@ -1499,6 +1503,89 @@
}
/**
+ * mrp_task_get_priority:
+ * @task: an #MrpTask
+ *
+ * Retrieves the priority of @task.
+ *
+ * Return value: The priority of @task.
+ **/
+gint
+mrp_task_get_priority (MrpTask *task)
+{
+ g_return_val_if_fail (MRP_IS_TASK (task), 0);
+
+ return task->priv->priority;
+}
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+/**
+ * mrp_task_is_dominant:
+ * @task: an #MrpTask
+ *
+ * Retrieves if @task is a dominant task.
+ *
+ * Return value: if @task is a dominant task.
+ **/
+gboolean
+mrp_task_is_dominant (MrpTask *task)
+{
+ MrpConstraint constraint;
+
+ g_return_val_if_fail (MRP_IS_TASK (task), 0);
+
+ constraint = impr_task_get_constraint (task);
+ if (constraint.type != MRP_CONSTRAINT_MSO) {
+ return (FALSE);
+ }
+
+ if (task->priv->priority != MRP_DOMINANT_PRIORITY) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+#endif
+/**
+ * mrp_task_get_unit_ivals:
+ * @task: an #MrpTask
+ *
+ * Retrieves the list of intervals of @task.
+ *
+ * Return value: Intervals of @task.
+ **/
+GList *
+mrp_task_get_unit_ivals (MrpTask *task)
+{
+ g_return_val_if_fail (MRP_IS_TASK (task), 0);
+
+ return task->priv->unit_ivals;
+}
+
+/**
+ * mrp_task_set_unit_ivals:
+ * @task: an #MrpTask
+ *
+ * Set the list of intervals of @task.
+ *
+ * Return value: Intervals of @task.
+ **/
+GList *
+mrp_task_set_unit_ivals (MrpTask *task, GList *ivals)
+{
+ g_return_val_if_fail (MRP_IS_TASK (task), 0);
+
+ if (task->priv->unit_ivals) {
+ g_list_foreach (task->priv->unit_ivals, (GFunc) g_free, NULL);
+ g_list_free (task->priv->unit_ivals);
+ task->priv->unit_ivals = NULL;
+ }
+ task->priv->unit_ivals = ivals;
+
+ return task->priv->unit_ivals;
+}
+
+/**
* mrp_task_get_assignments:
* @task: an #MrpTask
*
@@ -1512,6 +1599,28 @@
g_return_val_if_fail (MRP_IS_TASK (task), NULL);
return task->priv->assignments;
+}
+
+/**
+ * mrp_task_get_nres:
+ * @task: an #MrpTask
+ *
+ * Calculate the number of resources assigned to task.
+ *
+ * Return value: the number of resources.
+ **/
+gint mrp_task_get_nres (MrpTask *task)
+{
+ GList *assignments, *a;
+ gint nres = 0;
+
+ assignments = mrp_task_get_assignments (task);
+
+ for (a = assignments; a; a = a->next) {
+ nres++;
+ }
+
+ return (nres);
}
/**
Index: planner/libplanner/mrp-task.h
===================================================================
RCS file: /cvs/gnome/planner/libplanner/mrp-task.h,v
retrieving revision 1.6
diff -u -r1.6 mrp-task.h
--- planner/libplanner/mrp-task.h 18 Feb 2005 17:27:56 -0000 1.6
+++ planner/libplanner/mrp-task.h 22 Mar 2006 03:23:01 -0000
@@ -42,6 +42,33 @@
typedef struct _MrpTaskClass MrpTaskClass;
typedef struct _MrpTaskPriv MrpTaskPriv;
+/*
+ NOTE: moved from libplanner/mrp-task-manager.c to use
+ the structure in the src/planner-gantt-row.c
+ new fields are:
+ units . worked units in the interval
+ units_full . expected worked units in the interval
+ all resources that are working in the
+ interval in the right percentage
+ res_n . number of expected resources working
+ at the task in the interval
+*/
+typedef struct {
+ gboolean is_start;
+ mrptime start;
+ mrptime end;
+ gint units;
+ gint units_full;
+ gint res_n;
+} MrpUnitsInterval;
+
+#define UNIT_IVAL_GET_TIME(R) ((R->is_start?R->start:R->end))
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+/* Value of the magic priority of a dominant task. */
+#define MRP_DOMINANT_PRIORITY 9999
+#endif
+
#include <libplanner/mrp-relation.h>
struct _MrpTask
@@ -95,7 +122,17 @@
mrptime mrp_task_get_latest_finish (MrpTask *task);
gint mrp_task_get_duration (MrpTask *task);
gint mrp_task_get_work (MrpTask *task);
+gint mrp_task_get_priority (MrpTask *task);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+gboolean mrp_task_is_dominant (MrpTask *task);
+#endif
+GList * mrp_task_get_unit_ivals (MrpTask *task);
+GList * mrp_task_set_unit_ivals (MrpTask *task,
+ GList *ivals);
GList *mrp_task_get_assignments (MrpTask *task);
+gint mrp_task_get_nres (MrpTask *task);
+
+gint mrp_task_get_fullwork (MrpTask *task);
MrpAssignment *mrp_task_get_assignment (MrpTask *task,
MrpResource *resource);
void mrp_task_reset_constraint (MrpTask *task);
Index: planner/src/planner-gantt-chart.c
===================================================================
RCS file: /cvs/gnome/planner/src/planner-gantt-chart.c,v
retrieving revision 1.19
diff -u -r1.19 planner-gantt-chart.c
--- planner/src/planner-gantt-chart.c 9 Oct 2004 14:36:14 -0000 1.19
+++ planner/src/planner-gantt-chart.c 22 Mar 2006 03:23:01 -0000
@@ -53,7 +53,8 @@
/* Font width factor. */
static gdouble f = 1.0;
-#define CRITICAL_PATH_KEY "/views/gantt_view/highlight_critical_path"
+#define CRITICAL_PATH_KEY "/views/gantt_view/highlight_critical_path"
+#define NOSTDDAYS_PATH_KEY "/views/gantt_view/display_nonstandard_days"
typedef struct _TreeNode TreeNode;
@@ -103,6 +104,9 @@
/* Critical path. */
gboolean highlight_critical;
+
+ /* Nonstandard days visualization */
+ gboolean nonstandard_days;
/* Keep a list of signal connection ids, so we can remove them
* easily.
@@ -384,6 +388,8 @@
priv->highlight_critical = planner_conf_get_bool (CRITICAL_PATH_KEY,
NULL);
+ priv->nonstandard_days = planner_conf_get_bool (NOSTDDAYS_PATH_KEY,
+ NULL);
}
static void
@@ -1916,4 +1922,33 @@
g_return_val_if_fail (PLANNER_IS_GANTT_CHART (chart), FALSE);
return chart->priv->highlight_critical;
+}
+
+void
+planner_gantt_chart_set_nonstandard_days (PlannerGanttChart *chart,
+ gboolean state)
+{
+ PlannerGanttChartPriv *priv;
+
+ g_return_if_fail (PLANNER_IS_GANTT_CHART (chart));
+
+ priv = chart->priv;
+
+ if (priv->nonstandard_days == state) {
+ return;
+ }
+
+ priv->nonstandard_days = state;
+
+ gtk_widget_queue_draw (GTK_WIDGET (priv->canvas));
+
+ planner_conf_set_bool (NOSTDDAYS_PATH_KEY, state, NULL);
+}
+
+gboolean
+planner_gantt_chart_get_nonstandard_days (PlannerGanttChart *chart)
+{
+ g_return_val_if_fail (PLANNER_IS_GANTT_CHART (chart), FALSE);
+
+ return chart->priv->nonstandard_days;
}
Index: planner/src/planner-gantt-chart.h
===================================================================
RCS file: /cvs/gnome/planner/src/planner-gantt-chart.h,v
retrieving revision 1.6
diff -u -r1.6 planner-gantt-chart.h
--- planner/src/planner-gantt-chart.h 4 Oct 2004 22:29:19 -0000 1.6
+++ planner/src/planner-gantt-chart.h 22 Mar 2006 03:23:01 -0000
@@ -90,5 +90,11 @@
gboolean
planner_gantt_chart_get_highlight_critical_tasks (PlannerGanttChart *chart);
+void
+planner_gantt_chart_set_nonstandard_days (PlannerGanttChart *chart,
+ gboolean state);
+gboolean
+planner_gantt_chart_get_nonstandard_days (PlannerGanttChart *chart);
+
#endif /* __PLANNER_GANTT_CHART_H__ */
Index: planner/src/planner-gantt-row.c
===================================================================
RCS file: /cvs/gnome/planner/src/planner-gantt-row.c,v
retrieving revision 1.27
diff -u -r1.27 planner-gantt-row.c
--- planner/src/planner-gantt-row.c 16 Oct 2005 14:36:11 -0000 1.27
+++ planner/src/planner-gantt-row.c 22 Mar 2006 03:23:02 -0000
@@ -28,6 +28,7 @@
#include <libplanner/mrp-project.h>
#include <libplanner/mrp-resource.h>
#include <libplanner/mrp-task.h>
+#include <libplanner/mrp-calendar.h>
#include <glib/gi18n.h>
#include <libgnomecanvas/gnome-canvas.h>
#include "planner-marshal.h"
@@ -57,6 +58,21 @@
/* Minimum width for a task to keep it visible. */
#define MIN_WIDTH 2
+/* Trim the value to short int work space. */
+#define TRSH(a) ((int)((a) < SHRT_MIN ? (short int)SHRT_MIN : ((a) > SHRT_MAX ? (short int)SHRT_MAX : (a))))
+
+/* Same gdk_draw_rectangle but with trimmed x,y,w,h args. */
+#define draw_cut_rectangle(a,b,c,d,e,f,g) \
+ gdk_draw_rectangle ((a), (b), (c), TRSH (d), TRSH (e), TRSH (f), TRSH (g))
+
+/* Same gdk_draw_rectangle but with trimmed x1,y1,x2,y2 args. */
+#define draw_cut_line(a,b,c,d,e,f) \
+ gdk_draw_line ((a), (b), TRSH (c), TRSH (d), TRSH (e), TRSH (f))
+
+/* Same gdk_draw_layout but with trimmed x,y args. */
+#define draw_cut_layout(a,b,c,d,e) \
+ gdk_draw_layout ((a), (b), TRSH (c), TRSH (d), (e))
+
enum {
PROP_0,
PROP_X,
@@ -91,6 +107,8 @@
GdkGC *break_gc;
GdkGC *fill_gc;
GdkGC *frame_gc;
+ GdkGC *ttask_gc;
+
/* FIXME: Don't need those per gantt row. */
GdkColor color_normal;
@@ -130,6 +148,8 @@
/* Cached values for the geometry of the bar. */
gdouble width;
gdouble height;
+ gdouble bar_top; /* Top y position of the bar. */
+ gdouble bar_bot; /* Bottom y position of the bar. */
gdouble text_width;
/* Cached positions of each assigned resource. */
@@ -211,13 +231,35 @@
gint *x1,
gint *x2);
-static PlannerCmd *task_cmd_edit_property (PlannerWindow *window,
- PlannerTaskTree *tree,
- MrpTask *task,
- const gchar *property,
- const GValue *value);
-
-static GList * gantt_row_get_selected_tasks (GtkTreeSelection *selection);
+static PlannerCmd *task_cmd_edit_property (PlannerWindow *window,
+ PlannerTaskTree *tree,
+ MrpTask *task,
+ const gchar *property,
+ const GValue *value);
+
+static GList * gantt_row_get_selected_tasks (GtkTreeSelection *selection);
+
+static MrpUnitsInterval * mop_get_next_ival (GList **cur,
+ gint *is_a_gap,
+ GList *start,
+ MrpUnitsInterval *buf);
+static MrpInterval * mop_get_next_mrp_ival (GList **cur,
+ gint *is_a_gap,
+ GList *start,
+ MrpInterval *buf);
+static gboolean gantt_draw_tasktime (GdkDrawable *drawable,
+ GdkGC *gc,
+ GnomeCanvas *canvas,
+ gdouble start_wx,
+ gdouble start_wy,
+ gdouble end_wx,
+ gdouble end_wy,
+ gint cy1,
+ gint cy2,
+ gint x,
+ gint y,
+ gboolean is_up,
+ gchar *colorname);
static GnomeCanvasItemClass *parent_class;
@@ -365,6 +407,8 @@
priv->y = 0.0;
priv->width = 0.0;
priv->height = 0.0;
+ priv->bar_top = 0.0;
+ priv->bar_bot = 0.0;
priv->scale = 1.0;
priv->visible = TRUE;
priv->highlight = FALSE;
@@ -529,7 +573,19 @@
case PROP_HEIGHT:
tmp_dbl = g_value_get_double (value);
if (tmp_dbl != priv->height) {
+ gboolean nonstd_days;
+ PlannerGanttChart *chart;
+ double htask;
+
+ chart = g_object_get_data (G_OBJECT (item->canvas), "chart");
+ nonstd_days = planner_gantt_chart_get_nonstandard_days (chart);
+
priv->height = tmp_dbl;
+
+ htask = priv->height / 2.0;
+ priv->bar_top = ((priv->height - htask) / 2.0);
+ priv->bar_bot = ((priv->height + htask) / 2.0);
+
changed = TRUE;
}
break;
@@ -807,6 +863,8 @@
priv->frame_gc = gdk_gc_new (item->canvas->layout.bin_window);
+ priv->ttask_gc = gdk_gc_new (item->canvas->layout.bin_window);
+
gnome_canvas_get_color (item->canvas,
"LightSkyBlue3",
&priv->color_normal);
@@ -847,6 +905,9 @@
gdk_gc_unref (row->priv->frame_gc);
row->priv->frame_gc = NULL;
+ gdk_gc_unref (row->priv->ttask_gc);
+ row->priv->ttask_gc = NULL;
+
if (break_stipple) {
g_object_unref (break_stipple);
}
@@ -868,6 +929,221 @@
GDK_JOIN_MITER);
}
+
+static MrpUnitsInterval *mop_get_next_ival(GList **cur, gint *is_a_gap, GList *start, MrpUnitsInterval *buf)
+{
+ MrpUnitsInterval *cur_ival;
+ gint last_end, md;
+
+ if (start) {
+ *cur = start;
+ cur_ival = start->data;
+ md = cur_ival->start % (24*60*60);
+ if (md > 0) {
+ buf->start = cur_ival->start - md;
+ buf->end = cur_ival->start;
+ buf->units = 0;
+ buf->units_full = 0;
+ buf->res_n = 0;
+
+ *is_a_gap = 1;
+
+ return (buf);
+ }
+ else {
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ }
+ if ((*cur) == NULL) {
+ return (NULL);
+ }
+
+ cur_ival = (*cur)->data;
+
+ if (*is_a_gap == 1) { /* last was a gap */
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ else {
+ if ((*cur)->next != NULL) {
+ last_end = cur_ival->end;
+ *cur = (*cur)->next;
+ cur_ival = (*cur)->data;
+
+ if (last_end < cur_ival->start) { /* another gap */
+ buf->start = last_end;
+ buf->end = cur_ival->start;
+ buf->units = 0;
+ buf->units_full = 0;
+ buf->res_n = 0;
+
+ *is_a_gap = 1;
+ return (buf);
+ }
+ else {
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ }
+ else {
+ md = cur_ival->end % (24*60*60);
+ if (md > 0) {
+ buf->start = cur_ival->end;
+ buf->end = cur_ival->end - md + (24*60*60);
+ buf->units = 0;
+ buf->units_full = 0;
+ buf->res_n = 0;
+
+ *is_a_gap = 1;
+ *cur = NULL;
+ return (buf);
+ }
+ else {
+ return (NULL);
+ }
+ }
+ }
+
+ return (NULL);
+}
+
+
+
+static MrpInterval *mop_get_next_mrp_ival(GList **cur, gint *is_a_gap, GList *start, MrpInterval *buf)
+{
+ MrpInterval *cur_ival;
+ gint last_end, md;
+ mrptime cur_start, cur_end;
+
+ if (start) {
+ *cur = start;
+ cur_ival = start->data;
+
+ mrp_interval_get_absolute (cur_ival, 0, &cur_start, &cur_end);
+ md = cur_start % (24*60*60);
+ if (md > 0) {
+ mrp_interval_set_absolute (buf, 0, 0, cur_start);
+ *is_a_gap = 1;
+
+ return (buf);
+ }
+ else {
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ }
+ if ((*cur) == NULL) {
+ return (NULL);
+ }
+
+ cur_ival = (*cur)->data;
+ mrp_interval_get_absolute (cur_ival, 0, &cur_start, &cur_end);
+
+ if (*is_a_gap == 1) { /* last was a gap */
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ else {
+ if ((*cur)->next != NULL) {
+ last_end = cur_end;
+ *cur = (*cur)->next;
+ cur_ival = (*cur)->data;
+ mrp_interval_get_absolute (cur_ival, 0, &cur_start, &cur_end);
+
+ if (last_end < cur_start) { /* another gap */
+ mrp_interval_set_absolute (buf, 0, last_end, cur_start);
+
+ *is_a_gap = 1;
+ return (buf);
+ }
+ else {
+ *is_a_gap = 0;
+ return (cur_ival);
+ }
+ }
+ else {
+ md = cur_end % (24*60*60);
+ if (md > 0) {
+ mrp_interval_set_absolute (buf, 0, cur_end, cur_end - md + (24*60*60));
+
+ *is_a_gap = 1;
+ *cur = NULL;
+ return (buf);
+ }
+ else {
+ return (NULL);
+ }
+ }
+ }
+
+ return (NULL);
+}
+
+
+static gboolean gantt_draw_tasktime(GdkDrawable *drawable,
+ GdkGC *gc,
+ GnomeCanvas *canvas,
+ gdouble start_wx, gdouble start_wy,
+ gdouble end_wx, gdouble end_wy,
+ gint cy1, gint cy2,
+ gint x, gint y,
+ gboolean is_up,
+ gchar *colorname)
+{
+ GdkColor color;
+ gint ttime_x1, ttime_y1, ttime_x2, ttime_y2;
+
+ gnome_canvas_w2c (canvas, start_wx, start_wy, &ttime_x1, &ttime_y1);
+ gnome_canvas_w2c (canvas, end_wx, end_wy, &ttime_x2, &ttime_y2);
+ ttime_x1 -= x; ttime_y1 -= y;
+ ttime_x2 -= x; ttime_y2 -= y;
+
+ if (ttime_x2 > ttime_x1) {
+ gnome_canvas_get_color (canvas, colorname, &color);
+ gdk_gc_set_foreground (gc, &color);
+
+ if (is_up) {
+ gdk_draw_rectangle (drawable,
+ gc,
+ TRUE,
+ ttime_x1,
+ ttime_y1,
+ ttime_x2 - ttime_x1,
+ cy1 - ttime_y1);
+
+ gnome_canvas_get_color (canvas, "gray40", &color);
+ gdk_gc_set_foreground (gc, &color);
+
+ gdk_draw_line (drawable, gc, ttime_x1, ttime_y1,
+ ttime_x2-1, ttime_y1);
+ gdk_draw_line (drawable, gc, ttime_x1, ttime_y1,
+ ttime_x1, cy1-1);
+ }
+ else {
+ gdk_draw_rectangle (drawable,
+ gc,
+ TRUE,
+ ttime_x1, cy2+1,
+ ttime_x2 - ttime_x1,
+ ttime_y2 - cy2 - 1);
+
+ gnome_canvas_get_color (canvas, "gray40", &color);
+ gdk_gc_set_foreground (gc, &color);
+
+ gdk_draw_line (drawable, gc, ttime_x1, ttime_y2,
+ ttime_x2-1, ttime_y2);
+ gdk_draw_line (drawable, gc, ttime_x1, cy2+1,
+ ttime_x1, ttime_y2);
+ }
+
+ return (TRUE);
+ }
+ else {
+ return (FALSE);
+ }
+}
+
static void
gantt_row_draw (GnomeCanvasItem *item,
GdkDrawable *drawable,
@@ -881,7 +1157,7 @@
PlannerGanttChart *chart;
gdouble i2w_dx;
gdouble i2w_dy;
- gdouble dx1, dy1, dx2, dy2;
+ gdouble dx1, dy1, dx2, dy2, dshay1, dshay2;
gint level;
MrpTaskType type;
gboolean summary;
@@ -890,32 +1166,98 @@
gint percent_complete;
gint complete_x2, complete_width;
gboolean highlight_critical;
+ gboolean display_nonstandard_days;
gboolean critical;
-
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ gboolean is_dominant;
+#endif
gint rx1, ry1;
gint rx2, ry2;
gint cx1, cy1, cx2, cy2;
-
+
+ GList *unit_ivals, *cal_ivals, *cur_unit, *cur_cal;
+ GdkColor color;
+ gint x_start, x_end, y_dumb, is_a_gap, is_a_subgap;
+ MrpUnitsInterval *unit_ival, ival_buf;
+ MrpInterval *ival_subbuf = NULL, *cal_ival;
+ gint i, day_cur, cur_start, cur_end;
+
+ MrpProject *project;
+ MrpDay *day;
+ MrpCalendar *calendar;
+ mrptime cal_start, cal_end;
+ gboolean is_before_work;
+ gboolean shadup_is_cached, shadup_draw_it;
+ gboolean shaddo_is_cached, shaddo_draw_it;
+ gint shadup_start, shadup_end;
+ gint shaddo_start, shaddo_end;
+
+ gboolean workup_is_cached, workup_draw_it;
+ gboolean workdo_is_cached, workdo_draw_it;
+ gint workup_start, workup_end;
+ gint workdo_start, workdo_end;
+
+ gboolean wunits_is_first, wunits_is_cached, wunits_draw_it;
+ gint wunits_x_start;
+
+ gint last_end;
+
+ gint topy, nres, finish;
+ gdouble delta;
+ GList *assignments;
+
+ shadup_start = -1;
+ shadup_end = -1;
+ shaddo_start = -1;
+ shaddo_end = -1;
+ workup_start = -1;
+ workup_end = -1;
+ workdo_start = -1;
+ workdo_end = -1;
+ wunits_is_first = FALSE;
+ wunits_is_cached = FALSE;
+ wunits_x_start = -1;
+ last_end = 0;
+ delta = -1.0;
+
row = PLANNER_GANTT_ROW (item);
priv = row->priv;
+ project = mrp_object_get_project (MRP_OBJECT (priv->task));
+ calendar = mrp_project_get_calendar (project);
+
chart = g_object_get_data (G_OBJECT (item->canvas), "chart");
highlight_critical = planner_gantt_chart_get_highlight_critical_tasks (chart);
-
+ display_nonstandard_days = planner_gantt_chart_get_nonstandard_days (chart);
level = planner_scale_clamp_zoom (priv->zoom);
+
+ /*
+ NOTES
+
+ w -> world
+ i -> item
+ c -> canvas
+
+ priv->x = t * scale
+ */
+
/* Get item area in canvas coordinates. */
i2w_dx = 0.0;
i2w_dy = 0.0;
+
gnome_canvas_item_i2w (item, &i2w_dx, &i2w_dy);
- dx1 = priv->x;
- dy1 = priv->y + 0.15 * priv->height;
+ dx1 = priv->x;
+
+ dy1 = priv->y + priv->bar_top;
dx2 = priv->x + priv->width;
- dy2 = priv->y + 0.70 * priv->height;
+ dy2 = priv->y + priv->bar_bot;
dx2 = MAX (dx2, dx1 + MIN_WIDTH);
+ dshay1 = priv->y + 0.08 * priv->height;
+ dshay2 = priv->y + 0.92 * priv->height;
gnome_canvas_w2c (item->canvas,
dx1 + i2w_dx,
dy1 + i2w_dy,
@@ -932,12 +1274,12 @@
cy1 -= y;
cx2 -= x;
cy2 -= y;
-
+
if (cy1 >= cy2 || cx1 >= cx2) {
return;
}
- summary_y = floor (priv->y + 2 * 0.15 * priv->height + 0.5) - y;
+ summary_y = floor (priv->y + 2 * priv->bar_top + 0.5) - y;
/* "Clip" the expose area. */
rx1 = MAX (cx1, 0);
@@ -953,7 +1295,12 @@
percent_complete = mrp_task_get_percent_complete (priv->task);
critical = mrp_task_get_critical (priv->task);
type = mrp_task_get_task_type (priv->task);
-
+ finish = mrp_task_get_finish (priv->task);
+ nres = mrp_task_get_nres (priv->task);
+ assignments = mrp_task_get_assignments (priv->task);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ is_dominant = mrp_task_is_dominant (priv->task);
+#endif
if (!summary) {
complete_width = floor ((cx2 - cx1) * (percent_complete / 100.0) + 0.5);
complete_x2 = MIN (cx1 + complete_width, rx2);
@@ -967,20 +1314,433 @@
priv->complete_gc);
}
+ if (assignments) {
+ /* #define DRAW_BACKGROUND_CHECK 1 */
+#ifdef DRAW_BACKGROUND_CHECK
+ gnome_canvas_get_color (item->canvas, "indian red", &color);
+ gdk_gc_set_foreground (priv->fill_gc, &color);
+ gdk_draw_rectangle (drawable,
+ priv->fill_gc,
+ TRUE,
+ rx1,
+ cy1,
+ rx2 - rx1,
+ cy2 - cy1);
+#endif
+
+ /* Start slices drawer */
+ unit_ivals = mrp_task_get_unit_ivals (priv->task);
+ ival_subbuf = mrp_interval_new (0,0);
+
+ is_before_work = TRUE;
+ shadup_is_cached = FALSE;
+ shaddo_is_cached = FALSE;
+ workup_is_cached = FALSE;
+ workdo_is_cached = FALSE;
+ for (i = 0, unit_ival = mop_get_next_ival (&cur_unit, &is_a_gap,
+ unit_ivals, &ival_buf)
+ ; unit_ival && (i == 0 || cur_start < finish) ; i++) {
+ if (i == 0) {
+ /* first iteration: read the day when start the task */
+ day_cur = mrp_time_align_day (unit_ival->start);
+
+ /* extract the intervals of the day */
+ day = mrp_calendar_get_day (calendar, day_cur, TRUE);
+ cal_ivals = mrp_calendar_day_get_intervals (calendar, day, TRUE);
+
+ if (cal_ivals == NULL) {
+ mrp_interval_set_absolute (ival_subbuf, 0, 0, (24*60*60));
+ is_a_subgap = 1;
+ cal_ival = ival_subbuf;
+ }
+ else {
+ for (cal_ival = mop_get_next_mrp_ival (&cur_cal, &is_a_subgap,
+ cal_ivals, ival_subbuf) ;
+ cal_ival ;
+ cal_ival = mop_get_next_mrp_ival (&cur_cal, &is_a_subgap,
+ NULL, ival_subbuf)) {
+ mrp_interval_get_absolute (cal_ival, day_cur, &cal_start, &cal_end);
+
+ if (cal_end > unit_ival->start) {
+ break;
+ }
+ }
+ }
+ cur_start = MAX (unit_ival->start, cal_start);
+ cur_end = MIN (unit_ival->end , cal_end );
+ wunits_is_first = TRUE;
+ }
+ g_assert (cal_ival != NULL);
+
+ gnome_canvas_w2c (item->canvas, (cur_start * priv->scale)
+ + i2w_dx, i2w_dy, &x_start, &y_dumb);
+ gnome_canvas_w2c (item->canvas, (cur_end * priv->scale)
+ + i2w_dx, i2w_dy, &x_end, &y_dumb);
+ x_start -= x;
+ x_end -= x;
+
+ if (is_before_work) {
+ if (unit_ival->units_full == 0) {
+ goto cont_shadowloop;
+ }
+ else {
+ is_before_work = FALSE;
+ }
+
+ }
+ if (display_nonstandard_days) {
+ shadup_draw_it = FALSE;
+ shaddo_draw_it = FALSE;
+ workup_draw_it = FALSE;
+ workdo_draw_it = FALSE;
+
+ if (unit_ival->res_n == 0 && (!is_a_subgap ||
+ (is_a_subgap && planner_scale_conf[level].nonworking_limit
+ > cal_end - cal_start))) {
+ if (shadup_is_cached == FALSE) {
+ shadup_start = cur_start;
+ shadup_is_cached = TRUE;
+ }
+ }
+ else {
+ if (shadup_is_cached == TRUE) {
+ if (planner_scale_conf[level].nonworking_limit <=
+ cur_start - shadup_start) {
+ shadup_end = cur_start;
+ shadup_draw_it = TRUE;
+ }
+ shadup_is_cached = FALSE;
+ }
+ }
+
+ if (unit_ival->res_n < nres && (!is_a_subgap ||
+ (is_a_subgap && planner_scale_conf[level].nonworking_limit
+ > cal_end - cal_start))) {
+
+ if (shaddo_is_cached == FALSE) {
+ shaddo_start = cur_start;
+ shaddo_is_cached = TRUE;
+ }
+ }
+ else {
+ if (shaddo_is_cached == TRUE) {
+ if (planner_scale_conf[level].nonworking_limit <=
+ cur_start - shaddo_start) {
+ shaddo_end = cur_start;
+ shaddo_draw_it = TRUE;
+ }
+ shaddo_is_cached = FALSE;
+ }
+ }
+
+ if ((unit_ival->res_n == nres && is_a_subgap) ||
+ (unit_ival->res_n == 0 &&
+ (cal_start % (24*60*60) == 0) && (cal_end % (24*60*60) == 0) &&
+ planner_scale_conf[level].nonworking_limit > cur_end - cur_start)) {
+ if (workup_is_cached == FALSE) {
+ workup_start = cur_start;
+ workup_is_cached = TRUE;
+ }
+ }
+ else {
+ if (workup_is_cached == TRUE) {
+ if (planner_scale_conf[level].nonworking_limit <=
+ cur_start - workup_start) {
+ workup_end = cur_start;
+ workup_draw_it = TRUE;
+ }
+ workup_is_cached = FALSE;
+ }
+ }
+
+ if ((unit_ival->res_n > 0 && is_a_subgap) ||
+ (unit_ival->res_n == 0 &&
+ (cal_start % (24*60*60) == 0) && (cal_end % (24*60*60) == 0) &&
+ planner_scale_conf[level].nonworking_limit > cur_end - cur_start)) {
+
+ if (workdo_is_cached == FALSE) {
+ workdo_start = cur_start;
+ workdo_is_cached = TRUE;
+ }
+ }
+ else {
+ if (workdo_is_cached == TRUE) {
+ if (planner_scale_conf[level].nonworking_limit <=
+ cur_start - workdo_start) {
+ workdo_end = cur_start;
+ workdo_draw_it = TRUE;
+ }
+ workdo_is_cached = FALSE;
+ }
+ }
+
+ /* Show shadow up. */
+ if (shadup_draw_it ||
+ (shadup_is_cached &&
+ ((cur_end % (24*60*60)) == 0))) {
+ if (!shadup_draw_it && ((cur_end % (24*60*60)) == 0)) {
+ shadup_end = cur_end;
+ }
+ if (planner_scale_conf[level].nonworking_limit <=
+ shadup_end - shadup_start) {
+
+ gantt_draw_tasktime (drawable, priv->ttask_gc, item->canvas,
+ (shadup_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (shadup_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, TRUE, "grey96");
+ }
+ shadup_draw_it = FALSE;
+ shadup_is_cached = FALSE;
+ }
+
+ /* Show shadow down. */
+ if (shaddo_draw_it ||
+ (shaddo_is_cached &&
+ ((cur_end % (24*60*60)) == 0))) {
+ if (!shaddo_draw_it && ((cur_end % (24*60*60)) == 0)) {
+ shaddo_end = cur_end;
+ }
+ if (planner_scale_conf[level].nonworking_limit <=
+ shaddo_end - shaddo_start) {
+
+ gantt_draw_tasktime (drawable, priv->ttask_gc, item->canvas,
+ (shaddo_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (shaddo_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, FALSE, "grey96");
+ }
+ shaddo_draw_it = FALSE;
+ shaddo_is_cached = FALSE;
+ }
+
+ /* Show work up. */
+ if (workup_draw_it ||
+ (workup_is_cached &&
+ ((cur_end % (24*60*60)) == 0))) {
+ if (!workup_draw_it && ((cur_end % (24*60*60)) == 0)) {
+ workup_end = cur_end;
+ }
+ if (planner_scale_conf[level].nonworking_limit <=
+ workup_end - workup_start) {
+
+ gantt_draw_tasktime (drawable, priv->ttask_gc, item->canvas,
+ (workup_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (workup_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, TRUE, "white");
+ }
+ workup_draw_it = FALSE;
+ workup_is_cached = FALSE;
+ }
+
+ /* Show work down. */
+ if (workdo_draw_it ||
+ (workdo_is_cached &&
+ ((cur_end % (24*60*60)) == 0))) {
+ if (!workdo_draw_it && ((cur_end % (24*60*60)) == 0)) {
+ workdo_end = cur_end;
+ }
+ if (planner_scale_conf[level].nonworking_limit <=
+ workdo_end - workdo_start) {
+
+ gantt_draw_tasktime (drawable, priv->ttask_gc, item->canvas,
+ (workdo_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (workdo_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, FALSE, "white");
+
+ workdo_draw_it = FALSE;
+ workdo_is_cached = FALSE;
+ }
+ }
+ }
+ /* Draw area. */
+ wunits_draw_it = TRUE;
+ if (unit_ival->res_n > 0 && unit_ival->units_full > 0) {
+ delta = (double)unit_ival->units / (double)unit_ival->units_full;
+ }
+ else {
+ if (planner_scale_conf[level].nonworking_limit <=
+ cur_end - cur_start) {
+ delta = 1.0;
+ }
+ else {
+ if (wunits_is_first == TRUE) {
+ wunits_is_cached = TRUE;
+ wunits_x_start = x_start;
+ wunits_draw_it = FALSE;
+ }
+ }
+ }
+
+ topy = floor ((cy1 + ((1.0 - (double)delta) * (double)(cy2 - cy1 - 3))) + 0.5);
+ if (!highlight_critical || !critical) {
+ gdk_gc_set_foreground (priv->fill_gc, &priv->color_normal);
+ } else {
+ gdk_gc_set_foreground (priv->fill_gc, &priv->color_critical);
+ }
+
+ if (wunits_draw_it) {
+ if (wunits_is_cached) {
+ wunits_is_cached = FALSE;
+ }
+ else {
+ wunits_x_start = x_start;
+ }
+
+ if ((cy2 - topy - 3) > 0) {
+ gdk_draw_rectangle (drawable,
+ priv->fill_gc,
+ TRUE,
+ wunits_x_start,
+ topy + 2,
+ x_end - wunits_x_start,
+ cy2 - topy - 3);
+ }
+ if (topy - cy1 > 0) {
+ gnome_canvas_get_color (item->canvas, "white", &color);
+ gdk_gc_set_foreground (priv->fill_gc, &color);
+ gdk_draw_rectangle (drawable,
+ priv->fill_gc,
+ TRUE,
+ wunits_x_start,
+ cy1+2,
+ x_end - wunits_x_start,
+ topy - cy1);
+ }
+ }
+
+ cont_shadowloop:
+ if (display_nonstandard_days) {
+ last_end = cur_end;
+ }
+ wunits_is_first = FALSE;
+
+ if (cur_end == unit_ival->end) {
+ if ((unit_ival = mop_get_next_ival (&cur_unit, &is_a_gap,
+ NULL, &ival_buf)) == NULL) {
+ break;
+ }
+ }
+ if (cur_end == cal_end) {
+ if ((cal_ival = mop_get_next_mrp_ival (&cur_cal, &is_a_subgap,
+ NULL, ival_subbuf)) == NULL) {
+ /* End of the day intervals, read next. */
+ day_cur += (24*60*60);
+ day = mrp_calendar_get_day (calendar, day_cur, TRUE);
+ cal_ivals = mrp_calendar_day_get_intervals (calendar, day, TRUE);
+ if (cal_ivals) {
+ /* Not empty day. */
+ cal_ival = mop_get_next_mrp_ival (&cur_cal, &is_a_subgap,
+ cal_ivals, ival_subbuf);
+ }
+ else {
+ /* Empty day. */
+ mrp_interval_set_absolute (ival_subbuf, 0, 0, (24*60*60));
+ is_a_subgap = 1;
+ cal_ival = ival_subbuf;
+ }
+ wunits_is_first = TRUE;
+ }
+ mrp_interval_get_absolute (cal_ival, day_cur, &cal_start, &cal_end);
+ }
+
+ cur_start = MAX (unit_ival->start, cal_start);
+ cur_end = MIN (unit_ival->end , cal_end );
+ }
+
+ if (display_nonstandard_days) {
+ /*
+ H O L Y D A Y S
+ */
+
+ /* Show shad up. */
+ if (shadup_is_cached) {
+ shadup_end = last_end;
+
+ gantt_draw_tasktime (drawable, priv->ttask_gc, item->canvas,
+ (shadup_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (shadup_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, TRUE, "grey96");
+ }
+
+ /* Show shad down. */
+ if (shaddo_is_cached) {
+ shaddo_end = last_end;
+
+ gantt_draw_tasktime (drawable, priv->ttask_gc, item->canvas,
+ (shaddo_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (shaddo_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, FALSE, "grey96");
+ }
+
+ /*
+ W O R K
+ */
+
+ /* Show work up. */
+ if (workup_is_cached) {
+ workup_end = last_end;
+
+ gantt_draw_tasktime (drawable, priv->ttask_gc, item->canvas,
+ (workup_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (workup_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, TRUE, "white");
+ }
+
+ /* Show work down. */
+ if (workdo_is_cached) {
+ workdo_end = last_end;
+
+ gantt_draw_tasktime (drawable, priv->ttask_gc, item->canvas,
+ (workdo_start * priv->scale) + i2w_dx,
+ dshay1 + i2w_dy,
+ (workdo_end * priv->scale) + i2w_dx,
+ dshay2 + i2w_dy,
+ cy1, cy2, x, y, FALSE, "white");
+ }
+ }
+ }
+ else { /* if (assignments) ... */
+ if (!highlight_critical || !critical) {
+ gdk_gc_set_foreground (priv->fill_gc, &priv->color_normal);
+ } else {
+ gdk_gc_set_foreground (priv->fill_gc, &priv->color_critical);
+ }
+ gdk_draw_rectangle (drawable,
+ priv->fill_gc,
+ TRUE,
+ rx1,
+ cy1,
+ rx2 - rx1,
+ cy2 - cy1);
+ }
+
+
+ gnome_canvas_get_color (item->canvas, "black", &color);
+ gdk_gc_set_foreground (priv->frame_gc, &color);
+
+ if (ival_subbuf) {
+ mrp_interval_unref (ival_subbuf);
+ }
+
if (!highlight_critical || !critical) {
gdk_gc_set_foreground (priv->fill_gc, &priv->color_normal);
} else {
gdk_gc_set_foreground (priv->fill_gc, &priv->color_critical);
}
-
- gdk_draw_rectangle (drawable,
- priv->fill_gc,
- TRUE,
- rx1,
- cy1 + 1,
- rx2 - rx1,
- cy2 - cy1 - 1);
-
+
if (rx1 <= complete_x2) {
gdk_draw_rectangle (drawable,
priv->complete_gc,
@@ -991,8 +1751,31 @@
cy2 - cy1 - 7);
}
- gdk_draw_line (drawable, priv->frame_gc, rx1, cy1, rx2, cy1);
- gdk_draw_line (drawable, priv->frame_gc, rx1, cy2, rx2, cy2);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ for (i = 0 ; i < (is_dominant && !(!summary && priv->highlight) ? 2 : 1) ; ++i) {
+ if (i == 1) {
+ gnome_canvas_get_color (item->canvas, "indian red", &color);
+ gdk_gc_set_foreground (priv->frame_gc, &color);
+
+ gdk_gc_set_line_attributes (priv->frame_gc,
+ 0,
+ GDK_LINE_ON_OFF_DASH,
+ GDK_CAP_BUTT,
+ GDK_JOIN_MITER);
+ gdk_draw_line (drawable, priv->frame_gc, cx1, cy1, cx2, cy1);
+ gdk_draw_line (drawable, priv->frame_gc, cx1, cy2, cx2, cy2);
+ gantt_row_setup_frame_gc (row, !summary && priv->highlight);
+ gnome_canvas_get_color (item->canvas, "black", &color);
+ gdk_gc_set_foreground (priv->frame_gc, &color);
+ }
+ else {
+#endif
+ gdk_draw_line (drawable, priv->frame_gc, rx1, cy1, rx2, cy1);
+ gdk_draw_line (drawable, priv->frame_gc, rx1, cy2, rx2, cy2);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ }
+ }
+#endif
if (!highlight_critical || !critical) {
gdk_gc_set_foreground (priv->fill_gc, &priv->color_normal_light);
@@ -1037,26 +1820,36 @@
rx2 - 1,
cy2 - 1);
}
-
- /* FIXME: Drawing of shadows on non-working time should go here. */
-
- if (cx1 == rx1) {
- gdk_draw_line (drawable,
- priv->frame_gc,
- rx1,
- cy1,
- rx1,
- cy2);
- }
-
- if (cx2 == rx2) {
- gdk_draw_line (drawable,
- priv->frame_gc,
- rx2,
- cy1,
- rx2,
- cy2);
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ for (i = 0 ; i < (is_dominant && !(!summary && priv->highlight) ? 2 : 1) ; ++i) {
+ if (i == 1) {
+ gnome_canvas_get_color (item->canvas, "red", &color);
+ gdk_gc_set_foreground (priv->frame_gc, &color);
+
+ gdk_gc_set_line_attributes (priv->frame_gc,
+ 0,
+ GDK_LINE_ON_OFF_DASH,
+ GDK_CAP_BUTT,
+ GDK_JOIN_MITER);
+ }
+#endif
+ if (cx1 == rx1) {
+ gdk_draw_line (drawable, priv->frame_gc,
+ cx1, cy1, cx1, cy2);
+ }
+ if (cx2 == rx2) {
+ gdk_draw_line (drawable, priv->frame_gc,
+ cx2, cy1, cx2, cy2);
+ }
+
+#ifdef WITH_SIMPLE_PRIORITY_SCHEDULING
+ if (i == 1) {
+ gantt_row_setup_frame_gc (row, !summary && priv->highlight);
+ gnome_canvas_get_color (item->canvas, "black", &color);
+ gdk_gc_set_foreground (priv->frame_gc, &color);
+ }
}
+#endif
}
else if (type == MRP_TASK_TYPE_MILESTONE && !summary && rx1 <= rx2) {
points[0].x = cx1;
@@ -1137,11 +1930,14 @@
rx2 = MIN (cx2 + TEXT_PADDING + priv->text_width, width);
if (priv->layout != NULL && rx1 < rx2) {
- /* FIXME: Center the text vertically? */
+ /* NOTE: cy1 - priv->bar_top: report to the top of the cell,
+ + 3: is an empirical value to realign with task-tree result of the
+ default gtkcellrenderertext ypad property (2) + 1 ??? ;). */
+
gdk_draw_layout (drawable,
GTK_WIDGET (item->canvas)->style->text_gc[GTK_STATE_NORMAL],
cx2 + TEXT_PADDING,
- cy1,
+ cy1 - priv->bar_top + 3,
priv->layout);
if (priv->mouse_over_index != -1) {
@@ -1250,7 +2046,8 @@
* it since it's a good optimization.
*/
else if (strcmp (pspec->name, "critical") != 0 &&
- strcmp (pspec->name, "percent-complete")) {
+ strcmp (pspec->name, "priority") != 0 &&
+ strcmp (pspec->name, "percent-complete")) {
return;
}
@@ -1361,10 +2158,12 @@
*x2 = priv->x + priv->width;
}
if (y1) {
- *y1 = priv->y + 0.15 * priv->height;
+ /* preMOP *y1 = priv->y + 0.15 * priv->height; */
+ *y1 = priv->y;
}
if (y2) {
- *y2 = priv->y + 0.70 * priv->height;
+ /* preMOP *y2 = priv->y + 0.70 * priv->height; */
+ *y2 = priv->y + priv->height;
}
}
@@ -1492,13 +2291,13 @@
return TRUE;
}
-#define IN_DRAG_DURATION_SPOT(x,y,right,top,height) \
- ((abs(x - (right)) <= 3) && \
- (y > top + 0.15 * height) && (y < top + 0.70 * height))
+#define IN_DRAG_DURATION_SPOT(x,y,right,top,ymin,ymax) \
+ ((abs (x - (right)) <= 3) && \
+ (y > top + ymin) && (y < top + ymax))
-#define IN_DRAG_RELATION_SPOT(x,y,right,top,height) \
+#define IN_DRAG_RELATION_SPOT(x,y,right,top,ymin,ymax) \
((x <= right) && \
- (y > top + 0.15 * height) && (y < top + 0.70 * height))
+ (y > top + ymin) && (y < top + ymax))
static gboolean
gantt_row_event (GnomeCanvasItem *item, GdkEvent *event)
@@ -1533,7 +2332,8 @@
switch (event->button.button) {
case 3:
if (IN_DRAG_RELATION_SPOT (event->button.x, event->button.y,
- priv->x + priv->width, priv->y, priv->height)) {
+ priv->x + priv->width, priv->y,
+ priv->bar_top, priv->bar_bot)) {
PlannerGanttChart *chart;
PlannerTaskTree *tree;
GtkTreePath *path;
@@ -1586,15 +2386,16 @@
event->button.y,
priv->x + priv->width,
priv->y,
- priv->height)) {
+ priv->bar_top,
+ priv->bar_bot)) {
guint rgba;
priv->state = STATE_DRAG_DURATION;
wx1 = priv->x;
- wy1 = priv->y + 0.15 * priv->height;
+ wy1 = priv->y + priv->bar_top;
wx2 = event->button.x;
- wy2 = priv->y + 0.70 * priv->height;
+ wy2 = priv->y + priv->bar_bot;
gnome_canvas_item_i2w (item, &wx1, &wy1);
gnome_canvas_item_i2w (item, &wx2, &wy2);
@@ -1619,9 +2420,9 @@
event->button.y,
priv->x + priv->width,
priv->y,
- priv->height)) {
+ priv->bar_top,
+ priv->bar_bot)) {
priv->state = STATE_DRAG_LINK;
-
if (drag_points == NULL) {
drag_points = gnome_canvas_points_new (2);
}
@@ -1721,7 +2522,8 @@
event->button.y,
priv->x + priv->width,
priv->y,
- priv->height)) {
+ priv->bar_top,
+ priv->bar_bot)) {
cursor = gdk_cursor_new (GDK_RIGHT_SIDE);
gdk_window_set_cursor (canvas_widget->window, cursor);
if (cursor) {
@@ -1817,7 +2619,7 @@
project = mrp_object_get_project (MRP_OBJECT (priv->task));
wx2 = event->motion.x;
- wy2 = priv->y + 0.70 * priv->height;
+ wy2 = priv->y + priv->bar_bot;
gnome_canvas_item_i2w (item, &wx2, &wy2);
@@ -2020,7 +2822,8 @@
case GDK_2BUTTON_PRESS:
if (event->button.button == 1) {
if (IN_DRAG_RELATION_SPOT (event->button.x, event->button.y,
- priv->x + priv->width, priv->y, priv->height)) {
+ priv->x + priv->width, priv->y,
+ priv->bar_top, priv->bar_bot)) {
PlannerTaskTree *tree;
GtkTreePath *path;
GtkTreeSelection *selection;
Index: planner/src/planner-gantt-view.c
===================================================================
RCS file: /cvs/gnome/planner/src/planner-gantt-view.c,v
retrieving revision 1.28
diff -u -r1.28 planner-gantt-view.c
--- planner/src/planner-gantt-view.c 23 Apr 2005 10:33:09 -0000 1.28
+++ planner/src/planner-gantt-view.c 22 Mar 2006 03:23:02 -0000
@@ -84,6 +84,8 @@
gpointer data);
static void gantt_view_highlight_critical_cb (GtkAction *action,
gpointer data);
+static void gantt_view_nonstandard_days_cb (GtkAction *action,
+ gpointer data);
static void gantt_view_edit_columns_cb (GtkAction *action,
gpointer data);
static void gantt_view_update_row_height (PlannerGanttView *view);
@@ -175,10 +177,14 @@
static const GtkToggleActionEntry toggle_entries[] = {
{ "HighlightCriticalTasks", NULL, N_("_Highlight Critical Tasks"),
NULL, NULL,
- G_CALLBACK (gantt_view_highlight_critical_cb), FALSE }
+ G_CALLBACK (gantt_view_highlight_critical_cb), FALSE },
+ { "NonstandardDays", NULL, N_("_Nonstandard Days"),
+ NULL, NULL,
+ G_CALLBACK (gantt_view_nonstandard_days_cb), FALSE }
};
+
G_DEFINE_TYPE (PlannerGanttView, planner_gantt_view, PLANNER_TYPE_VIEW);
@@ -213,7 +219,7 @@
gantt_view_activate (PlannerView *view)
{
PlannerGanttViewPriv *priv;
- gboolean show_critical;
+ gboolean show_critical, show_nostd_days;
gchar *filename;
priv = PLANNER_GANTT_VIEW (view)->priv;
@@ -242,13 +248,23 @@
show_critical = planner_gantt_chart_get_highlight_critical_tasks (
PLANNER_GANTT_CHART (priv->gantt));
+ show_nostd_days = planner_gantt_chart_get_nonstandard_days (
+ PLANNER_GANTT_CHART (priv->gantt));
+
planner_task_tree_set_highlight_critical (PLANNER_TASK_TREE (priv->tree),
show_critical);
+ planner_task_tree_set_nonstandard_days (PLANNER_TASK_TREE (priv->tree),
+ show_nostd_days);
+
gtk_toggle_action_set_active (
GTK_TOGGLE_ACTION (gtk_action_group_get_action (priv->actions, "HighlightCriticalTasks")),
show_critical);
+ gtk_toggle_action_set_active (
+ GTK_TOGGLE_ACTION (gtk_action_group_get_action (priv->actions, "NonstandardDays")),
+ show_nostd_days);
+
gantt_view_selection_changed_cb (PLANNER_TASK_TREE (priv->tree),
PLANNER_GANTT_VIEW (view));
gantt_view_update_zoom_sensitivity (PLANNER_GANTT_VIEW (view));
@@ -816,7 +832,7 @@
view = PLANNER_GANTT_VIEW (data);
priv = view->priv;
- state = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action));
+ state = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
planner_gantt_chart_set_highlight_critical_tasks (
PLANNER_GANTT_CHART (priv->gantt),
@@ -825,6 +841,29 @@
planner_task_tree_set_highlight_critical (
PLANNER_TASK_TREE (priv->tree),
state);
+}
+
+static void
+gantt_view_nonstandard_days_cb (GtkAction *action,
+ gpointer data)
+{
+ PlannerGanttView *view;
+ PlannerGanttViewPriv *priv;
+ gboolean state;
+
+ view = PLANNER_GANTT_VIEW (data);
+ priv = view->priv;
+
+ state = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+
+ planner_gantt_chart_set_nonstandard_days (
+ PLANNER_GANTT_CHART (priv->gantt),
+ state);
+ planner_task_tree_set_nonstandard_days (
+ PLANNER_TASK_TREE (priv->tree),
+ state);
+ gantt_view_update_row_height (view);
+
}
static void
Index: planner/src/planner-task-tree.c
===================================================================
RCS file: /cvs/gnome/planner/src/planner-task-tree.c,v
retrieving revision 1.61
diff -u -r1.61 planner-task-tree.c
--- planner/src/planner-task-tree.c 12 Apr 2005 22:20:47 -0000 1.61
+++ planner/src/planner-task-tree.c 22 Mar 2006 03:23:03 -0000
@@ -60,7 +60,10 @@
PlannerWindow *main_window;
gboolean highlight_critical;
-
+
+ /* Nonstandard days visualization */
+ gboolean nonstandard_days;
+
/* Keep the dialogs here so that we can just raise the dialog if it's
* opened twice for the same task.
*/
@@ -95,7 +98,7 @@
static void task_tree_setup_tree_view (GtkTreeView *tree,
MrpProject *project,
PlannerGanttModel *model);
-static void task_tree_add_column (GtkTreeView *tree,
+static void task_tree_add_column (PlannerTaskTree *tree,
gint column,
const gchar *title);
static void task_tree_name_data_func (GtkTreeViewColumn *tree_column,
@@ -515,7 +518,9 @@
child_parent = planner_gantt_model_get_indent_task_target (model, cmd->task);
- if (cmd->children != NULL) task_cmd_restore_children (cmd);
+ if (cmd->children != NULL) {
+ task_cmd_restore_children (cmd);
+ }
task_cmd_restore_relations (cmd);
task_cmd_restore_assignments (cmd);
@@ -1356,7 +1361,6 @@
iter,
COL_WBS, &str,
-1);
-
g_object_set (cell,
"text", str,
NULL);
@@ -2265,7 +2269,7 @@
}
static void
-task_tree_add_column (GtkTreeView *tree,
+task_tree_add_column (PlannerTaskTree *tree,
gint column,
const gchar *title)
{
@@ -2276,13 +2280,14 @@
switch (column) {
case COL_WBS:
cell = gtk_cell_renderer_text_new ();
+
col = gtk_tree_view_column_new_with_attributes (title,
cell,
NULL);
gtk_tree_view_column_set_cell_data_func (col,
cell,
task_tree_wbs_data_func,
- tree, NULL);
+ GTK_TREE_VIEW (tree), NULL);
g_object_set_data (G_OBJECT (col),
"data-func", task_tree_wbs_data_func);
g_object_set_data (G_OBJECT (col), "id", "wbs");
@@ -2297,7 +2302,7 @@
g_signal_connect (cell,
"edited",
G_CALLBACK (task_tree_name_edited),
- tree);
+ GTK_TREE_VIEW (tree));
col = gtk_tree_view_column_new_with_attributes (title,
cell,
@@ -2305,7 +2310,7 @@
gtk_tree_view_column_set_cell_data_func (col,
cell,
task_tree_name_data_func,
- tree, NULL);
+ GTK_TREE_VIEW (tree), NULL);
g_object_set_data (G_OBJECT (col),
"data-func", task_tree_name_data_func);
g_object_set_data (G_OBJECT (col), "id", "name");
@@ -2320,11 +2325,11 @@
g_signal_connect (cell,
"edited",
G_CALLBACK (task_tree_start_edited),
- tree);
+ GTK_TREE_VIEW (tree));
g_signal_connect (cell,
"show-popup",
G_CALLBACK (task_tree_start_show_popup),
- tree);
+ GTK_TREE_VIEW (tree));
col = gtk_tree_view_column_new_with_attributes (title,
cell,
@@ -2334,7 +2339,7 @@
gtk_tree_view_column_set_cell_data_func (col,
cell,
task_tree_start_data_func,
- tree, NULL);
+ GTK_TREE_VIEW (tree), NULL);
g_object_set_data (G_OBJECT (col),
"data-func", task_tree_start_data_func);
g_object_set_data (G_OBJECT (col), "id", "start");
@@ -2350,7 +2355,7 @@
gtk_tree_view_column_set_cell_data_func (col,
cell,
task_tree_duration_data_func,
- tree,
+ GTK_TREE_VIEW (tree),
NULL);
g_object_set_data (G_OBJECT (col),
"data-func", task_tree_duration_data_func);
@@ -2359,7 +2364,7 @@
g_signal_connect (cell,
"edited",
G_CALLBACK (task_tree_duration_edited),
- tree);
+ GTK_TREE_VIEW (tree));
break;
case COL_WORK:
@@ -2372,7 +2377,7 @@
gtk_tree_view_column_set_cell_data_func (col,
cell,
task_tree_work_data_func,
- tree,
+ GTK_TREE_VIEW (tree),
NULL);
g_object_set_data (G_OBJECT (col),
"data-func", task_tree_work_data_func);
@@ -2381,7 +2386,7 @@
g_signal_connect (cell,
"edited",
G_CALLBACK (task_tree_work_edited),
- tree);
+ GTK_TREE_VIEW (tree));
break;
case COL_SLACK:
@@ -2394,7 +2399,7 @@
gtk_tree_view_column_set_cell_data_func (col,
cell,
task_tree_slack_data_func,
- tree,
+ GTK_TREE_VIEW (tree),
NULL);
g_object_set_data (G_OBJECT (col),
"data-func", task_tree_slack_data_func);
@@ -2406,7 +2411,7 @@
g_signal_connect (cell,
"show-popup",
G_CALLBACK (task_tree_start_show_popup),
- tree);
+ GTK_TREE_VIEW (tree));
col = gtk_tree_view_column_new_with_attributes (title,
cell,
@@ -2416,7 +2421,7 @@
gtk_tree_view_column_set_cell_data_func (col,
cell,
task_tree_finish_data_func,
- tree, NULL);
+ GTK_TREE_VIEW (tree), NULL);
g_object_set_data (G_OBJECT (col),
"data-func", task_tree_finish_data_func);
g_object_set_data (G_OBJECT (col), "id", "finish");
@@ -2432,7 +2437,7 @@
gtk_tree_view_column_set_cell_data_func (col,
cell,
task_tree_cost_data_func,
- tree,
+ GTK_TREE_VIEW (tree),
NULL);
g_object_set_data (G_OBJECT (col),
"data-func", task_tree_cost_data_func);
@@ -2449,7 +2454,7 @@
gtk_tree_view_column_set_cell_data_func (col,
cell,
task_tree_assigned_to_data_func,
- tree,
+ GTK_TREE_VIEW (tree),
NULL);
g_object_set_data (G_OBJECT (col),
"data-func", task_tree_assigned_to_data_func);
@@ -2462,17 +2467,17 @@
gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
- g_object_set_data (G_OBJECT (col), "user-data", tree);
- gtk_tree_view_append_column (tree, col);
+ g_object_set_data (G_OBJECT (col), "user-data", GTK_TREE_VIEW (tree));
+ gtk_tree_view_append_column (GTK_TREE_VIEW (tree), col);
if (expander) {
- gtk_tree_view_set_expander_column (tree, col);
+ gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree), col);
}
g_signal_connect (col,
"notify::width",
G_CALLBACK (task_tree_column_notify_width_cb),
- tree);
+ GTK_TREE_VIEW (tree));
}
GtkWidget *
@@ -2511,10 +2516,10 @@
if (add_newline) {
tmp = g_strdup_printf ("\n%s", (gchar *) title);
- task_tree_add_column (GTK_TREE_VIEW (tree), col, tmp);
+ task_tree_add_column (tree, col, tmp);
g_free (tmp);
} else {
- task_tree_add_column (GTK_TREE_VIEW (tree), col, title);
+ task_tree_add_column (tree, col, title);
}
col = va_arg (args, gint);
@@ -3579,6 +3584,19 @@
gtk_widget_queue_draw (GTK_WIDGET (tree));
}
+void
+planner_task_tree_set_nonstandard_days (PlannerTaskTree *tree,
+ gboolean nonstandard_days)
+{
+ g_return_if_fail (PLANNER_IS_TASK_TREE (tree));
+
+ if (tree->priv->nonstandard_days == nonstandard_days) {
+ return;
+ }
+ tree->priv->nonstandard_days = nonstandard_days;
+ gtk_widget_queue_draw (GTK_WIDGET (tree));
+}
+
gboolean
planner_task_tree_get_highlight_critical (PlannerTaskTree *tree)
{
@@ -3586,6 +3604,15 @@
return tree->priv->highlight_critical;
}
+
+gboolean
+planner_task_tree_get_nonstandard_days (PlannerTaskTree *tree)
+{
+ g_return_val_if_fail (PLANNER_IS_TASK_TREE (tree), FALSE);
+
+ return tree->priv->nonstandard_days;
+}
+
void
planner_task_tree_set_anchor (PlannerTaskTree *tree, GtkTreePath *anchor)
Index: planner/src/planner-task-tree.h
===================================================================
RCS file: /cvs/gnome/planner/src/planner-task-tree.h,v
retrieving revision 1.11
diff -u -r1.11 planner-task-tree.h
--- planner/src/planner-task-tree.h 12 Apr 2005 22:20:47 -0000 1.11
+++ planner/src/planner-task-tree.h 22 Mar 2006 03:23:03 -0000
@@ -82,6 +82,9 @@
void planner_task_tree_set_highlight_critical (PlannerTaskTree *tree,
gboolean highlight);
gboolean planner_task_tree_get_highlight_critical (PlannerTaskTree *tree);
+void planner_task_tree_set_nonstandard_days (PlannerTaskTree *tree,
+ gboolean nonstandard_days);
+gboolean planner_task_tree_get_nonstandard_days (PlannerTaskTree *tree);
void planner_task_tree_set_anchor (PlannerTaskTree *tree,
GtkTreePath *anchor);
GtkTreePath* planner_task_tree_get_anchor (PlannerTaskTree *tree);
Index: planner/src/planner-task-view.c
===================================================================
RCS file: /cvs/gnome/planner/src/planner-task-view.c,v
retrieving revision 1.24
diff -u -r1.24 planner-task-view.c
--- planner/src/planner-task-view.c 23 Apr 2005 10:33:10 -0000 1.24
+++ planner/src/planner-task-view.c 22 Mar 2006 03:23:03 -0000
@@ -96,6 +96,8 @@
gpointer data);
static void task_view_highlight_critical_cb (GtkAction *action,
gpointer data);
+static void task_view_nonstandard_days_cb (GtkAction *action,
+ gpointer data);
static void task_view_edit_columns_cb (GtkAction *action,
gpointer data);
static void task_view_selection_changed_cb (PlannerTaskTree *tree,
@@ -156,10 +158,13 @@
static const GtkToggleActionEntry toggle_entries[] = {
{ "HighlightCriticalTasks", NULL, N_("_Highlight Critical Tasks"), NULL, NULL,
- G_CALLBACK (task_view_highlight_critical_cb), FALSE }
+ G_CALLBACK (task_view_highlight_critical_cb), FALSE },
+ { "NonstandardDays", NULL, N_("_Nonstandard Days"), NULL, NULL,
+ G_CALLBACK (task_view_nonstandard_days_cb), FALSE }
};
-#define CRITICAL_PATH_KEY "/views/task_view/highlight_critical_path"
+#define CRITICAL_PATH_KEY "/views/task_view/highlight_critical_path"
+#define NOSTDDAYS_PATH_KEY "/views/task_view/display_nonstandard_days"
G_DEFINE_TYPE (PlannerTaskView, planner_task_view, PLANNER_TYPE_VIEW);
@@ -196,7 +201,8 @@
{
PlannerTaskViewPriv *priv;
gboolean show_critical;
- gchar *filename;
+ gboolean show_nostd_days;
+ gchar *filename;
priv = PLANNER_TASK_VIEW (view)->priv;
@@ -219,14 +225,20 @@
gtk_ui_manager_ensure_update (priv->ui_manager);
/* Set the initial UI state. */
- show_critical = planner_conf_get_bool (CRITICAL_PATH_KEY, NULL);
-
+ show_critical = planner_conf_get_bool (CRITICAL_PATH_KEY, NULL);
+ show_nostd_days = planner_conf_get_bool (NOSTDDAYS_PATH_KEY, NULL);
planner_task_tree_set_highlight_critical (PLANNER_TASK_TREE (priv->tree),
show_critical);
+ planner_task_tree_set_nonstandard_days (PLANNER_TASK_TREE (priv->tree),
+ show_nostd_days);
gtk_toggle_action_set_active (
GTK_TOGGLE_ACTION (gtk_action_group_get_action (priv->actions, "HighlightCriticalTasks")),
show_critical);
+
+ gtk_toggle_action_set_active (
+ GTK_TOGGLE_ACTION (gtk_action_group_get_action (priv->actions, "NonstandardDays")),
+ show_nostd_days);
task_view_selection_changed_cb (PLANNER_TASK_TREE (priv->tree), view);
@@ -579,6 +591,25 @@
state);
planner_conf_set_bool (CRITICAL_PATH_KEY, state, NULL);
+}
+
+static void
+task_view_nonstandard_days_cb (GtkAction *action,
+ gpointer data)
+{
+ PlannerTaskViewPriv *priv;
+ gboolean state;
+
+ priv = PLANNER_TASK_VIEW (data)->priv;
+
+ state = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+
+ planner_task_tree_set_nonstandard_days (
+ PLANNER_TASK_TREE (priv->tree),
+ state);
+
+
+ planner_conf_set_bool (NOSTDDAYS_PATH_KEY, state, NULL);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]