[Planner Dev] Prop. for new feat. - first patch



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]