[Planner Dev] Prop. for new feat. - first patch
- From: Matteo Nastasi <nastasi alternativeoutput it>
- To: planner-dev lists imendio com
- Subject: [Planner Dev] Prop. for new feat. - first patch
- Date: Sun, 15 Jan 2006 02:21:55 +0100
Hi guys.
I send you my first patch to your current version of planner.
I was started to work on debian sarge sources so I had work a little
to patch your current bazaar version (with little discardable modify
to compile under debian sarge in configure.in file).
This version not include our choise of toggle option in View menu
to hide/unhide new not standard work/not work days rappresentation.
Can you check it and tell me your opinion ?
If it is all ok, I proceed with the rest of modifies.
Regards, Matteo.
--
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 planner bazaar ubuntu com/planner--MAIN--0--patch-822 to compare with
* comparing to planner bazaar ubuntu com/planner--MAIN--0--patch-822
M libplanner/mrp-task.h
M libplanner/mrp-task.c
M src/planner-task-tree.c
M configure.in
M libplanner/mrp-task-manager.c
M libplanner/mrp-calendar.c
M libplanner/mrp-calendar.h
M src/planner-gantt-row.c
* modified files
--- orig/configure.in
+++ mod/configure.in
@@ -65,14 +65,14 @@
dnl If you add a version number here, you *must* add an AC_SUBST line for
dnl it too, or it will never make it into the spec file!
-GLIB_REQUIRED=2.6.0
-GTK_REQUIRED=2.6.0
-LIBGNOMECANVAS_REQUIRED=2.10.0
-LIBGNOMEUI_REQUIRED=2.10.0
-LIBGLADE_REQUIRED=2.3.0
-LIBGNOMEPRINTUI_REQUIRED=2.10.0
-GNOME_VFS_REQUIRED=2.10.0
-GCONF_REQUIRED=2.10.0
+GLIB_REQUIRED=2.0
+GTK_REQUIRED=2.0
+LIBGNOMECANVAS_REQUIRED=2.0
+LIBGNOMEUI_REQUIRED=2.0
+LIBGLADE_REQUIRED=2.0
+LIBGNOMEPRINTUI_REQUIRED=2.2
+GNOME_VFS_REQUIRED=2.0
+GCONF_REQUIRED=2.0
LIBXML_REQUIRED=2.6.0
LIBXSLT_REQUIRED=1.1.0
PYGTK_REQUIRED=2.6.0
--- 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
@@ -77,6 +77,10 @@
GParamSpec *spec,
MrpTaskManager *manager);
static void
+task_manager_task_priority_notify_cb (MrpTask *task,
+ GParamSpec *spec,
+ MrpTaskManager *manager);
+static void
task_manager_task_constraint_notify_cb (MrpTask *task,
GParamSpec *spec,
MrpTaskManager *manager);
@@ -261,6 +265,11 @@
"notify::duration",
G_CALLBACK (task_manager_task_duration_notify_cb),
manager);
+ /* Added to manage the transaction from normal to vampire. */
+ g_signal_connect (task,
+ "notify::priority",
+ G_CALLBACK (task_manager_task_priority_notify_cb),
+ manager);
g_signal_connect (task,
"notify::constraint",
G_CALLBACK (task_manager_task_constraint_notify_cb),
@@ -1222,15 +1231,8 @@
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: UnitsInterval moved in mrp-task.h to enable
+ other objects to use it. */
static gint
units_interval_sort_func (gconstpointer a, gconstpointer b)
{
@@ -1291,49 +1293,160 @@
MrpCalendar *calendar;
MrpDay *day;
GList *ivals, *l;
- MrpInterval *ival;
+ MrpInterval *ival, *ival_split;
UnitsInterval *unit_ival, *new_unit_ival;
+ UnitsInterval *unit_ival_start, *unit_ival_end;
+ UnitsInterval *unit_ival_start_cmp;
+ UnitsInterval *split_unit_ival;
GList *unit_ivals = NULL;
- MrpAssignment *assignment;
- MrpResource *resource;
- GList *assignments, *a;
- gint units;
+ MrpAssignment *assignment, *v_assignment;
+ MrpResource *resource, *v_resource;
+ GList *assignments, *v_assignments, *a, *v_a;
+ gint units, units_full, units_orig, v_units, priority;
+ GList *v_tasks, *v_l;
+
mrptime t;
mrptime poc;
- GPtrArray *array;
+ GPtrArray *array, *array_split;
guint len;
- gint i;
+ gint i, e, lastct;
+
+ mrptime diffe, i_start, i_end, v_start, v_end;
+ mrptime i_start_post, i_end_post, i_start_cmp, i_end_cmp;
+
+ gint res_n;
priv = manager->priv;
assignments = mrp_task_get_assignments (task);
array = g_ptr_array_new ();
+ priority = mrp_task_get_priority (task);
+
+ v_tasks = mrp_task_manager_get_all_tasks (manager);
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;
+
+ 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_vampire (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 vampire 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 vampire 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 vampire 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 vampire
+ */
+ 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 vampire
+ */
+ 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;
+ }
+ }
+ if (v_a != NULL)
+ break;
+ }
+
+
+ if (v_l == NULL) {
/* 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);
+ }
}
}
@@ -1351,20 +1464,79 @@
/* 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);
}
}
+ /* 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;
+ /* 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 +1548,27 @@
* 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 (UnitsInterval, 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;
}
}
@@ -1499,11 +1675,12 @@
gint work;
gint effort;
gint delta;
- GList *unit_ivals, *l;
+ GList *unit_ivals, *unit_ivals_tot = NULL, *l = NULL;
UnitsInterval *unit_ival;
MrpTaskType type;
MrpTaskSched sched;
+
priv = manager->priv;
if (task == priv->root) {
@@ -1547,6 +1724,7 @@
}
if (!unit_ivals) {
+ /* Holidays for all. */
t += 60*60*24;
continue;
}
@@ -1556,7 +1734,6 @@
t1 = t + unit_ival->start;
t2 = t + unit_ival->end;
-
/* Skip any intervals before the task starts. */
if (t2 < start) {
continue;
@@ -1577,6 +1754,7 @@
if (sched == MRP_TASK_SCHED_FIXED_WORK) {
delta = floor (0.5 + (double) unit_ival->units * (t2 - t1) / 100.0);
+ if (unit_ival->units_full > 0)
*duration += (t2 - t1);
if (effort + delta >= work) {
@@ -1584,8 +1762,14 @@
/* 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 +1786,6 @@
effort += delta;
}
-
t += 60*60*24;
}
@@ -1613,9 +1796,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;
}
@@ -1977,6 +2169,14 @@
}
static void
+task_manager_task_priority_notify_cb (MrpTask *task,
+ GParamSpec *spec,
+ MrpTaskManager *manager)
+{
+ mrp_task_manager_recalc (manager, TRUE);
+}
+
+static void
task_manager_task_constraint_notify_cb (MrpTask *task,
GParamSpec *spec,
MrpTaskManager *manager)
@@ -2254,6 +2454,80 @@
return work;
}
+static gint
+task_manager_get_work_for_calendar_ex (MrpTaskManager *manager,
+ MrpTask *task,
+ mrptime start,
+ mrptime finish)
+{
+ MrpTaskManagerPriv *priv;
+ mrptime t;
+ mrptime t1, t2;
+ gint work, delta;
+ GList *ivals, *l;
+ UnitsInterval *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 +2539,7 @@
{
MrpTaskManagerPriv *priv;
gint work = 0;
- MrpAssignment *assignment;
- MrpResource *resource;
- GList *assignments, *a;
+ GList *assignments;
MrpCalendar *calendar;
priv = manager->priv;
@@ -2293,24 +2565,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,
+ if (assignments) {
+ work = task_manager_get_work_for_calendar_ex (manager,
+ task,
start,
- finish) *
- mrp_assignment_get_units (assignment) / 100;
+ 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,86 @@
}
/**
+ * 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;
+}
+
+/**
+ * mrp_task_is_vampire:
+ * @task: an #MrpTask
+ *
+ * Retrieves if @task is a vampire task.
+ *
+ * Return value: if @task is a vampire task.
+ **/
+gboolean
+mrp_task_is_vampire (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_VAMPIRE_PRIORITY)
+ return (FALSE);
+
+ return (TRUE);
+}
+
+/**
+ * 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 +1599,27 @@
}
/**
+ * 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,29 @@
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;
+} UnitsInterval;
+
+#define UNIT_IVAL_GET_TIME(R) ((R->is_start?R->start:R->end))
+
+// value of the magic priority of a vampire task
+#define MRP_VAMPIRE_PRIORITY 9999
+
#include <libplanner/mrp-relation.h>
struct _MrpTask
@@ -95,7 +118,15 @@
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);
+gboolean mrp_task_is_vampire (MrpTask *task);
+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-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"
@@ -91,6 +92,8 @@
GdkGC *break_gc;
GdkGC *fill_gc;
GdkGC *frame_gc;
+ GdkGC *ttask_gc;
+
/* FIXME: Don't need those per gantt row. */
GdkColor color_normal;
@@ -219,6 +222,16 @@
static GList * gantt_row_get_selected_tasks (GtkTreeSelection *selection);
+static UnitsInterval *mop_get_next_ival(GList **cur, gint *is_a_gap, GList *start, UnitsInterval *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;
static guint signals[LAST_SIGNAL];
@@ -807,6 +820,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 +862,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 +886,219 @@
GDK_JOIN_MITER);
}
+
+static UnitsInterval *mop_get_next_ival(GList **cur, gint *is_a_gap, GList *start, UnitsInterval *buf)
+{
+ UnitsInterval *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);
+}
+
+
+/* x,y w,h sono relate al rettangolo visibile rispetto al canvas del widget
+ in oggetto */
static void
gantt_row_draw (GnomeCanvasItem *item,
GdkDrawable *drawable,
@@ -881,7 +1112,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;
@@ -891,31 +1122,78 @@
gint complete_x2, complete_width;
gboolean highlight_critical;
gboolean critical;
-
+ gboolean is_vampire;
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;
+ UnitsInterval *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 = -1, shadup_end = -1;
+ gint shaddo_start = -1, shaddo_end = -1;
+
+ gboolean workup_is_cached, workup_draw_it;
+ gboolean workdo_is_cached, workdo_draw_it;
+ gint workup_start = -1, workup_end = -1;
+ gint workdo_start = -1, workdo_end = -1;
+
+ gboolean wunits_is_first = FALSE, wunits_is_cached = FALSE, wunits_draw_it;
+ gint wunits_x_start = -1;
+
+ gint last_end;
+
+ gint topy, nres, finish;
+ gdouble delta = -1.0;
+ GList *assignments;
+
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);
level = planner_scale_clamp_zoom (priv->zoom);
+
+ /*
+ MOP 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;
+ dy1 = priv->y + 0.25 * priv->height;
dx2 = priv->x + priv->width;
- dy2 = priv->y + 0.70 * priv->height;
+ dy2 = priv->y + 0.75 * priv->height;
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 +1210,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 * 0.25 * priv->height + 0.5) - y;
/* "Clip" the expose area. */
rx1 = MAX (cx1, 0);
@@ -953,7 +1231,11 @@
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);
+ is_vampire = mrp_task_is_vampire(priv->task);
+
if (!summary) {
complete_width = floor ((cx2 - cx1) * (percent_complete / 100.0) + 0.5);
complete_x2 = MIN (cx1 + complete_width, rx2);
@@ -967,20 +1249,422 @@
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;
+ }
+ 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:
+ 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 );
+ }
+
+ /*
+ 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 +1675,27 @@
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);
+ for (i = 0 ; i < (is_vampire && !(!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 {
+ gdk_draw_line (drawable, priv->frame_gc, rx1, cy1, rx2, cy1);
+ gdk_draw_line (drawable, priv->frame_gc, rx1, cy2, rx2, cy2);
+ }
+ }
if (!highlight_critical || !critical) {
gdk_gc_set_foreground (priv->fill_gc, &priv->color_normal_light);
@@ -1037,25 +1740,30 @@
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);
+ for (i = 0 ; i < (is_vampire && !(!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);
+ }
+
+ 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);
+
+ 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);
+ }
}
}
else if (type == MRP_TASK_TYPE_MILESTONE && !summary && rx1 <= rx2) {
@@ -1361,10 +2069,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;
}
}
@@ -1494,11 +2204,11 @@
#define IN_DRAG_DURATION_SPOT(x,y,right,top,height) \
((abs(x - (right)) <= 3) && \
- (y > top + 0.15 * height) && (y < top + 0.70 * height))
+ (y > top + 0.25 * height) && (y < top + 0.75 * height))
#define IN_DRAG_RELATION_SPOT(x,y,right,top,height) \
((x <= right) && \
- (y > top + 0.15 * height) && (y < top + 0.70 * height))
+ (y > top + 0.25 * height) && (y < top + 0.75 * height))
static gboolean
gantt_row_event (GnomeCanvasItem *item, GdkEvent *event)
@@ -1592,9 +2302,9 @@
priv->state = STATE_DRAG_DURATION;
wx1 = priv->x;
- wy1 = priv->y + 0.15 * priv->height;
+ wy1 = priv->y + 0.25 * priv->height;
wx2 = event->button.x;
- wy2 = priv->y + 0.70 * priv->height;
+ wy2 = priv->y + 0.75 * priv->height;
gnome_canvas_item_i2w (item, &wx1, &wy1);
gnome_canvas_item_i2w (item, &wx2, &wy2);
@@ -1621,7 +2331,6 @@
priv->y,
priv->height)) {
priv->state = STATE_DRAG_LINK;
-
if (drag_points == NULL) {
drag_points = gnome_canvas_points_new (2);
}
@@ -1817,7 +2526,7 @@
project = mrp_object_get_project (MRP_OBJECT (priv->task));
wx2 = event->motion.x;
- wy2 = priv->y + 0.70 * priv->height;
+ wy2 = priv->y + 0.75 * priv->height;
gnome_canvas_item_i2w (item, &wx2, &wy2);
--- orig/src/planner-task-tree.c
+++ mod/src/planner-task-tree.c
@@ -2276,6 +2276,12 @@
switch (column) {
case COL_WBS:
cell = gtk_cell_renderer_text_new ();
+
+ /* NOTE: with ypad and yalign add space
+ to insert not working bands */
+ g_object_set (cell, "ypad", 6, NULL);
+ g_object_set (cell, "yalign", 0.5, NULL);
+
col = gtk_tree_view_column_new_with_attributes (title,
cell,
NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]