Re: [Planner Dev] "Nonstandard Days" and "Dominant tasks" - 6th patch
- From: Matteo Nastasi <nastasi alternativeoutput it>
- To: planner-dev lists imendio com
- Subject: Re: [Planner Dev] "Nonstandard Days" and "Dominant tasks" - 6th patch
- Date: Sun, 9 Apr 2006 14:14:35 +0200
Hi guys,
The changelog from 5th to 6th patch is:
1) Integrated the Kurt's code style patch
2) Solved the bug of white stripes in wide range time Gantt view.
3) Used the overflow proof graphical functions (I had defined these
before but I have forgotten to use them).
Regards, Matteo.
On Sat, Mar 25, 2006 at 09:13:48AM -0500, Kurt Maute wrote:
> On Fri, 2006-03-24 at 18:32 +0100, Richard Hult wrote:
> > Hi,
> >
> > Thanks guys, this looks really nice :) Let's get it committed, maybe
> > after fixing the bug Kurt found?
>
> Agree. Once that bug is fixed we're ready to commit.
>
> --
> Kurt Maute <kurt maute us>
>
> _______________________________________________
> Planner-dev mailing list
> Planner-dev lists imendio com
> http://lists.imendio.com/mailman/listinfo/planner-dev
--
Matteo Nastasi - Milano - Italy | HomePage: www.alternativeoutput.it
Sostenere e supportare GNU/Linux ! | IRC: #linux-mi irc freenode net
Milano Linux | E-Mail: matteo nastasi milug org
Users Group www.milug.org | nastasi alternativeoutput it
* looking for nastasi alternativeoutput it--projects/planner--mop2--0--base-0 to compare with
* comparing to nastasi alternativeoutput it--projects/planner--mop2--0--base-0
A {arch}/planner/planner--mop2/planner--mop2--0/nastasi alternativeoutput it--projects/patch-log/patch-1
A {arch}/planner/planner--mop2/planner--mop2--0/nastasi alternativeoutput it--projects/patch-log/patch-2
M libplanner/mrp-task.h
M libplanner/mrp-task.c
M src/planner-task-tree.c
M configure.in
M src/planner-gantt-chart.c
M autogen.sh
M data/ui/gantt-view.ui
M libplanner/mrp-task-manager.c
M src/planner-task-tree.h
M src/planner-gantt-chart.h
M libplanner/mrp-calendar.c
M libplanner/mrp-calendar.h
M src/planner-gantt-view.c
M src/planner-task-view.c
M src/planner-gantt-row.c
M data/planner.schemas.in
* modified files
--- orig/autogen.sh
+++ mod/autogen.sh
@@ -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"
--- orig/configure.in
+++ mod/configure.in
@@ -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,11 +338,16 @@
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 ***"
fi
--- orig/data/planner.schemas.in
+++ mod/data/planner.schemas.in
@@ -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>
--- orig/data/ui/gantt-view.ui
+++ mod/data/ui/gantt-view.ui
@@ -14,6 +14,7 @@
<placeholder name="View specific placeholder bottom">
<menuitem action="EditColumns"/>
<menuitem action="HighlightCriticalTasks"/>
+ <menuitem action="NonstandardDays"/>
</placeholder>
</menu>
--- orig/libplanner/mrp-calendar.c
+++ mod/libplanner/mrp-calendar.c
@@ -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,
--- orig/libplanner/mrp-calendar.h
+++ mod/libplanner/mrp-calendar.h
@@ -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__ */
--- orig/libplanner/mrp-task-manager.c
+++ mod/libplanner/mrp-task-manager.c
@@ -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,
--- orig/libplanner/mrp-task.c
+++ mod/libplanner/mrp-task.c
@@ -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
*
@@ -1515,6 +1602,28 @@
}
/**
+ * 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);
+}
+
+/**
* mrp_task_get_assignment:
* @task: an #MrpTask
* @resource: an #MrpResource
--- orig/libplanner/mrp-task.h
+++ mod/libplanner/mrp-task.h
@@ -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);
--- orig/src/planner-gantt-chart.c
+++ mod/src/planner-gantt-chart.c
@@ -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
@@ -1917,3 +1923,32 @@
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;
+}
--- orig/src/planner-gantt-chart.h
+++ mod/src/planner-gantt-chart.h
@@ -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__ */
--- orig/src/planner-gantt-row.c
+++ mod/src/planner-gantt-row.c
@@ -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_line 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) {
+ draw_cut_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);
+
+ draw_cut_line (drawable, gc, ttime_x1, ttime_y1,
+ ttime_x2-1, ttime_y1);
+ draw_cut_line (drawable, gc, ttime_x1, ttime_y1,
+ ttime_x1, cy1-1);
+ }
+ else {
+ draw_cut_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);
+
+ draw_cut_line (drawable, gc, ttime_x1, ttime_y2,
+ ttime_x2-1, ttime_y2);
+ draw_cut_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,22 +1314,442 @@
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);
+ draw_cut_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 (unit_ival->res_n == 0) { /* It is a nonworking interval. */
+ if (planner_scale_conf[level].nonworking_limit <=
+ cur_end - cur_start) {
+ delta = 1.0;
+ } /* else it use the last selected value */
+ }
+ /* It isn't a nonworking interval. */
+ else if (planner_scale_conf[level].nonworking_limit <=
+ cur_end - cur_start) { /* Visible non working interval. */
+ delta = 1.0;
+ }
+ else { /* use the last selected value */
+ 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) {
+ draw_cut_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);
+ draw_cut_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);
+ }
+ draw_cut_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,
+ draw_cut_rectangle (drawable,
priv->complete_gc,
TRUE,
rx1,
@@ -991,8 +1758,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);
+ draw_cut_line (drawable, priv->frame_gc, cx1, cy1, cx2, cy1);
+ draw_cut_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
+ draw_cut_line (drawable, priv->frame_gc, rx1, cy1, rx2, cy1);
+ draw_cut_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);
@@ -1000,7 +1790,7 @@
gdk_gc_set_foreground (priv->fill_gc, &priv->color_critical_light);
}
- gdk_draw_line (drawable,
+ draw_cut_line (drawable,
priv->fill_gc,
rx1 + 0,
cy1 + 1,
@@ -1008,7 +1798,7 @@
cy1 + 1);
if (cx1 == rx1) {
- gdk_draw_line (drawable,
+ draw_cut_line (drawable,
priv->fill_gc,
rx1 + 1,
cy1 + 1,
@@ -1022,7 +1812,7 @@
gdk_gc_set_foreground (priv->fill_gc, &priv->color_critical_dark);
}
- gdk_draw_line (drawable,
+ draw_cut_line (drawable,
priv->fill_gc,
rx1 + 0,
cy2 - 1,
@@ -1030,33 +1820,43 @@
cy2 - 1);
if (cx2 == rx2) {
- gdk_draw_line (drawable,
+ draw_cut_line (drawable,
priv->fill_gc,
rx2 - 1,
cy1 + 1,
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) {
+ draw_cut_line (drawable, priv->frame_gc,
+ cx1, cy1, cx1, cy2);
+ }
+ if (cx2 == rx2) {
+ draw_cut_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;
@@ -1081,7 +1881,7 @@
/* FIXME: Maybe we should try and make the summary be thicker
* for larger heights and always centered vertically?
*/
- gdk_draw_rectangle (drawable,
+ draw_cut_rectangle (drawable,
priv->frame_gc,
TRUE,
rx1,
@@ -1137,11 +1937,14 @@
rx2 = MIN (cx2 + TEXT_PADDING + priv->text_width, width);
if (priv->layout != NULL && rx1 < rx2) {
- /* FIXME: Center the text vertically? */
- gdk_draw_layout (drawable,
+ /* 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 ??? ;). */
+
+ draw_cut_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) {
@@ -1157,7 +1960,7 @@
x1 += cx2 + TEXT_PADDING;
x2 += cx2 + TEXT_PADDING;
- gdk_draw_line (drawable,
+ draw_cut_line (drawable,
GTK_WIDGET (item->canvas)->style->text_gc[GTK_STATE_NORMAL],
x1,
cy2 + 2,
@@ -1250,7 +2053,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 +2165,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 +2298,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 +2339,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 +2393,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 +2427,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 +2529,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 +2626,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 +2829,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;
@@ -2255,7 +3065,7 @@
tx2 = MIN (tx2, rx2);
if (tx1 < tx2) {
- gdk_draw_rectangle (drawable,
+ draw_cut_rectangle (drawable,
priv->fill_gc,
TRUE,
tx1,
@@ -2265,14 +3075,14 @@
}
/*gdk_gc_set_foreground (priv->fill_gc, &color_high);
- gdk_draw_line (drawable,
+ draw_cut_line (drawable,
priv->fill_gc,
tx1,
cy1 + 1,
tx1,
cy2 - 1);
- gdk_draw_line (drawable,
+ draw_cut_line (drawable,
priv->fill_gc,
tx2 - 1,
cy1 + 1,
@@ -2312,7 +3122,7 @@
tx2 = MIN (tx2, rx2);
if (tx1 < tx2) {
- gdk_draw_rectangle (drawable,
+ draw_cut_rectangle (drawable,
priv->fill_gc,
TRUE,
tx1,
--- orig/src/planner-gantt-view.c
+++ mod/src/planner-gantt-view.c
@@ -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),
@@ -828,6 +844,29 @@
}
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
gantt_view_edit_columns_cb (GtkAction *action,
gpointer data)
{
--- orig/src/planner-task-tree.c
+++ mod/src/planner-task-tree.c
@@ -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)
{
@@ -3587,6 +3605,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)
{
--- orig/src/planner-task-tree.h
+++ mod/src/planner-task-tree.h
@@ -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);
--- orig/src/planner-task-view.c
+++ mod/src/planner-task-view.c
@@ -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);
@@ -582,6 +594,25 @@
}
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
task_view_edit_columns_cb (GtkAction *action,
gpointer data)
{
* added files
--- /dev/null
+++ mod/{arch}/planner/planner--mop2/planner--mop2--0/nastasi alternativeoutput it--projects/patch-log/patch-1
@@ -0,0 +1,19 @@
+Revision: planner--mop2--0--patch-1
+Archive: nastasi alternativeoutput it--projects
+Creator: Matteo Nastasi aka mop <nastasi alternativeoutput it>
+Date: dom apr 9 14:03:19 CEST 2006
+Standard-date: 2006-04-09 12:03:19 GMT
+Modified-files: autogen.sh configure.in
+ data/planner.schemas.in data/ui/gantt-view.ui
+ libplanner/mrp-calendar.c libplanner/mrp-calendar.h
+ libplanner/mrp-task-manager.c libplanner/mrp-task.c
+ libplanner/mrp-task.h src/planner-gantt-chart.c
+ src/planner-gantt-chart.h src/planner-gantt-row.c
+ src/planner-gantt-view.c src/planner-task-tree.c
+ src/planner-task-tree.h src/planner-task-view.c
+New-patches: nastasi alternativeoutput it--projects/planner--mop2--0--patch-1
+Summary: kurt refactoring of mop05 revision
+Keywords:
+
+kurt refactoring of mop05 revision
+
--- /dev/null
+++ mod/{arch}/planner/planner--mop2/planner--mop2--0/nastasi alternativeoutput it--projects/patch-log/patch-2
@@ -0,0 +1,12 @@
+Revision: planner--mop2--0--patch-2
+Archive: nastasi alternativeoutput it--projects
+Creator: Matteo Nastasi aka mop <nastasi alternativeoutput it>
+Date: dom apr 9 14:04:43 CEST 2006
+Standard-date: 2006-04-09 12:04:43 GMT
+Modified-files: src/planner-gantt-row.c
+New-patches: nastasi alternativeoutput it--projects/planner--mop2--0--patch-2
+Summary: changed the policy of color management and used trimmed graphical functions
+Keywords:
+
+changed the policy of color management and used trimmed graphical functions
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]