[planner: 10/32] Port to GTK3 and adapt to changes in imported libgnomecanvas




commit fd4e332f4101130e4048ecdda78542432be3882a
Author: Mart Raudsepp <leio gentoo org>
Date:   Sun Mar 21 11:18:52 2021 +0200

    Port to GTK3 and adapt to changes in imported libgnomecanvas
    
    Includes changes that need to be done at the time of the switch, including
    for compatibility with the imported GTK3 supporting libgnomecanvas.
    
    gantt-header, gantt-chart and usage-chart are ported to GtkScrollable
    interface and their widget packing adjusted and simplified. The scrolling
    sync between treeview and charts (and chart and its header) is simplified
    by making use of GtkAdjustment object sharing.

 meson.build                    |   8 +-
 src/dummy-canvas-item.c        |  81 ++++++++----------
 src/eel-canvas-rect.c          | 121 ++++++++++++---------------
 src/libgnomecanvas/meson.build |  27 ++++++
 src/meson.build                |   9 +-
 src/planner-canvas-line.c      |  22 +++--
 src/planner-gantt-background.c |  38 ++++-----
 src/planner-gantt-chart.c      | 181 ++++++++++++++++++++++++++---------------
 src/planner-gantt-header.c     | 165 +++++++++++++++++++++++--------------
 src/planner-gantt-row.c        |  78 ++++++------------
 src/planner-gantt-view.c       | 121 ++++++++-------------------
 src/planner-relation-arrow.c   |  44 +++++-----
 src/planner-resource-view.c    |  10 +--
 src/planner-task-view.c        |  22 ++---
 src/planner-usage-chart.c      | 178 ++++++++++++++++++++++++++--------------
 src/planner-usage-row.c        | 101 ++++++++---------------
 src/planner-usage-view.c       | 116 ++++++++------------------
 17 files changed, 644 insertions(+), 678 deletions(-)
---
diff --git a/meson.build b/meson.build
index b8eb2025..8c90e92e 100644
--- a/meson.build
+++ b/meson.build
@@ -41,14 +41,16 @@ libplanner_inc = include_directories('libplanner')
 
 glib_req_version = '2.50'
 glib_req = '>= @0@'.format(glib_req_version)
+gtk_req_version = '3.0'
+gtk_req = '>= @0@'.format(gtk_req_version)
 eds_req = '>= 3.6'
 
 glib_dep = dependency('glib-2.0', version: glib_req)
 gmodule_dep = dependency('gmodule-2.0')
 gobject_dep = dependency('gobject-2.0')
 gio_dep = dependency('gobject-2.0')
-gtk_dep = dependency('gtk+-2.0', version: '>= 2.24.0')
-gnomecanvas_dep = dependency('libgnomecanvas-2.0', version: '>=2.10.0')
+gtk_dep = dependency('gtk+-3.0', version: gtk_req)
+gail_dep = dependency('gail-3.0', version: gtk_req)
 libxml_dep = dependency('libxml-2.0', version: '>= 2.6.27')
 xslt_dep = dependency('libxslt', version: '>= 1.1.23')
 exslt_dep = dependency('libexslt')
@@ -58,7 +60,7 @@ gda_dep = dependency('libgda-5.0', version: '>= 1.0', required: get_option('data
 libeds_dep = dependency('libebook-1.2', version: eds_req, required: get_option('eds'))
 
 libplanner_deps = [glib_dep, gmodule_dep, gobject_dep, libxml_dep, m_dep]
-planner_deps = [glib_dep, gobject_dep, gmodule_dep, gio_dep, gtk_dep, gnomecanvas_dep]
+planner_deps = [glib_dep, gobject_dep, gmodule_dep, gio_dep, gtk_dep]
 
 glib_version_arr = glib_req_version.split('.')
 glib_major_version = glib_version_arr[0]
diff --git a/src/dummy-canvas-item.c b/src/dummy-canvas-item.c
index 78676920..9c7098bb 100644
--- a/src/dummy-canvas-item.c
+++ b/src/dummy-canvas-item.c
@@ -49,7 +49,7 @@ enum {
 
 static void gnome_canvas_dummy_class_init   (GnomeCanvasDummyClass *class);
 static void gnome_canvas_dummy_init         (GnomeCanvasDummy      *dummy);
-static void gnome_canvas_dummy_destroy      (GtkObject             *object);
+static void gnome_canvas_dummy_destroy      (GtkWidget             *widget);
 static void gnome_canvas_dummy_set_property (GObject               *object,
                                             guint                  param_id,
                                             const GValue          *value,
@@ -59,15 +59,14 @@ static void gnome_canvas_dummy_get_property (GObject               *object,
                                             GValue                *value,
                                             GParamSpec            *pspec);
 
-static void   gnome_canvas_dummy_update      (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int 
flags);
+static void   gnome_canvas_dummy_update      (GnomeCanvasItem *item, const cairo_matrix_t *i2c, int flags);
 static void   gnome_canvas_dummy_realize     (GnomeCanvasItem *item);
 static void   gnome_canvas_dummy_unrealize   (GnomeCanvasItem *item);
-static void   gnome_canvas_dummy_draw        (GnomeCanvasItem *item, GdkDrawable *drawable,
+static void   gnome_canvas_dummy_draw        (GnomeCanvasItem *item, cairo_t *cr,
                                             int x, int y, int width, int height);
-static double gnome_canvas_dummy_point       (GnomeCanvasItem *item, double x, double y,
-                                            int cx, int cy, GnomeCanvasItem **actual_item);
+static GnomeCanvasItem * gnome_canvas_dummy_point (GnomeCanvasItem *item, double x, double y,
+                                                  int cx, int cy);
 static void   gnome_canvas_dummy_bounds      (GnomeCanvasItem *item, double *x1, double *y1, double *x2, 
double *y2);
-static void   gnome_canvas_dummy_render      (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
 
 
 static GnomeCanvasItemClass *parent_class;
@@ -103,11 +102,11 @@ static void
 gnome_canvas_dummy_class_init (GnomeCanvasDummyClass *class)
 {
        GObjectClass *gobject_class;
-       GtkObjectClass *object_class;
+       GtkWidgetClass *widget_class;
        GnomeCanvasItemClass *item_class;
 
        gobject_class = (GObjectClass *) class;
-       object_class = (GtkObjectClass *) class;
+       widget_class = (GtkWidgetClass *) class;
        item_class = (GnomeCanvasItemClass *) class;
 
        parent_class = g_type_class_peek_parent (class);
@@ -140,7 +139,7 @@ gnome_canvas_dummy_class_init (GnomeCanvasDummyClass *class)
                                      -G_MAXDOUBLE, G_MAXDOUBLE, 0,
                                      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
 
-       object_class->destroy = gnome_canvas_dummy_destroy;
+       widget_class->destroy = gnome_canvas_dummy_destroy;
 
        item_class->update = gnome_canvas_dummy_update;
        item_class->realize = gnome_canvas_dummy_realize;
@@ -148,8 +147,6 @@ gnome_canvas_dummy_class_init (GnomeCanvasDummyClass *class)
        item_class->draw = gnome_canvas_dummy_draw;
        item_class->point = gnome_canvas_dummy_point;
        item_class->bounds = gnome_canvas_dummy_bounds;
-
-       item_class->render = gnome_canvas_dummy_render;
 }
 
 static void
@@ -162,15 +159,15 @@ gnome_canvas_dummy_init (GnomeCanvasDummy *dummy)
 }
 
 static void
-gnome_canvas_dummy_destroy (GtkObject *object)
+gnome_canvas_dummy_destroy (GtkWidget *widget)
 {
-       g_return_if_fail (object != NULL);
-       g_return_if_fail (GNOME_IS_CANVAS_DUMMY (object));
+       g_return_if_fail (widget != NULL);
+       g_return_if_fail (GNOME_IS_CANVAS_DUMMY (widget));
 
        /* remember, destroy can be run multiple times! */
 
-       if (GTK_OBJECT_CLASS (parent_class)->destroy)
-               (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+       if (GTK_WIDGET_CLASS (parent_class)->destroy)
+               (* GTK_WIDGET_CLASS (parent_class)->destroy) (widget);
 }
 
 /* Computes the bounding box of the dummy object.
@@ -203,19 +200,21 @@ get_bounds (GnomeCanvasDummy *dummy, double *bx1, double *by1, double *bx2, doub
 /* Computes the bounding box of the dummy, in canvas coordinates.
  */
 static void
-get_bounds_canvas (GnomeCanvasDummy *dummy, double *bx1, double *by1, double *bx2, double *by2, double 
affine[6])
+get_bounds_canvas (GnomeCanvasDummy *dummy, double *bx1, double *by1, double *bx2, double *by2)
 {
-       ArtDRect bbox_world;
-       ArtDRect bbox_canvas;
+       gdouble x1, x2, y1, y2;
+       cairo_matrix_t matrix;
 
-       get_bounds (dummy, &bbox_world.x0, &bbox_world.y0, &bbox_world.x1, &bbox_world.y1);
+       get_bounds (dummy, &x1, &y1, &x2, &y2);
+       gnome_canvas_item_i2w_matrix (GNOME_CANVAS_ITEM (dummy), &matrix);
+
+       gnome_canvas_matrix_transform_rect (&matrix, &x1, &y2, &x2, &y2);
 
-       art_drect_affine_transform (&bbox_canvas, &bbox_world, affine);
        /* include 1 pixel of fudge */
-       *bx1 = bbox_canvas.x0 - 1;
-       *by1 = bbox_canvas.y0 - 1;
-       *bx2 = bbox_canvas.x1 + 1;
-       *by2 = bbox_canvas.y1 + 1;
+       *bx1 = floor (x1) - 1;
+       *by1 = floor (y1) - 1;
+       *bx2 = ceil (x2) + 1;
+       *by2 = ceil (y2) + 1;
 }
 
 static void
@@ -297,13 +296,9 @@ gnome_canvas_dummy_get_property (GObject              *object,
 }
 
 static void
-gnome_canvas_dummy_render (GnomeCanvasItem *item,
-                            GnomeCanvasBuf *buf)
-{
-}
-
-static void
-gnome_canvas_dummy_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+gnome_canvas_dummy_update (GnomeCanvasItem      *item,
+                           const cairo_matrix_t *i2c,
+                           int                   flags)
 {
        GnomeCanvasDummy *dummy;
        double x1, y1, x2, y2;
@@ -311,14 +306,10 @@ gnome_canvas_dummy_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_p
        dummy = GNOME_CANVAS_DUMMY (item);
 
        if (parent_class->update)
-               (* parent_class->update) (item, affine, clip_path, flags);
+               (* parent_class->update) (item, i2c, flags);
 
-       if (item->canvas->aa) {
-               g_assert(FALSE);
-       } else {
-               get_bounds_canvas (dummy, &x1, &y1, &x2, &y2, affine);
-               gnome_canvas_update_bbox (item, x1, y1, x2, y2);
-       }
+       get_bounds_canvas (dummy, &x1, &y1, &x2, &y2);
+       gnome_canvas_update_bbox (item, x1, y1, x2, y2);
 }
 
 static void
@@ -336,19 +327,17 @@ gnome_canvas_dummy_unrealize (GnomeCanvasItem *item)
 }
 
 static void
-gnome_canvas_dummy_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
+gnome_canvas_dummy_draw (GnomeCanvasItem *item, cairo_t *cr,
                        int x, int y, int width, int height)
 {
 }
 
-static double
+static GnomeCanvasItem *
 gnome_canvas_dummy_point (GnomeCanvasItem *item, double x, double y,
-                        int cx, int cy, GnomeCanvasItem **actual_item)
+                        int cx, int cy)
 {
-       *actual_item = item;
-
-       /* Always return a distance > 0 so we don't receive events */
-       return 1.0;
+       /* Always return NULL, so we don't receive events */
+       return NULL;
 }
 
 static void
diff --git a/src/eel-canvas-rect.c b/src/eel-canvas-rect.c
index 41f8c4c4..1eda13a2 100644
--- a/src/eel-canvas-rect.c
+++ b/src/eel-canvas-rect.c
@@ -32,6 +32,18 @@
 #include <cairo.h>
 #include <libgnomecanvas/gnome-canvas-util.h>
 
+/* TODO: Old libart_lgpl remnants compat - refactor them out */
+typedef struct _EelDRect EelDRect;
+
+struct _EelDRect {
+       double x0, y0, x1, y1;
+};
+
+static int
+_eel_drect_empty (const EelDRect *src) {
+       return (src->x1 <= src->x0 || src->y1 <= src->y0);
+}
+
 /*
  * name                        type            read/write      description
  * ------------------------------------------------------------------------------------------
@@ -65,16 +77,16 @@ struct EelCanvasRectDetails {
        guint outline_color;
        guint width_pixels;
 
-       ArtDRect last_update_rect;
-       ArtDRect last_outline_update_rect;
+       EelDRect last_update_rect;
+       EelDRect last_outline_update_rect;
 };
 
 
 G_DEFINE_TYPE (EelCanvasRect, eel_canvas_rect, GNOME_TYPE_CANVAS_ITEM);
 
 
-static ArtDRect  make_drect (double x0, double y0, double x1, double y1);
-static void      diff_rects (ArtDRect r1, ArtDRect r2, int *count, ArtDRect result[4]);
+static EelDRect  make_drect (double x0, double y0, double x1, double y1);
+static void      diff_rects (EelDRect r1, EelDRect r2, int *count, EelDRect result[4]);
 
 
 static void
@@ -203,7 +215,7 @@ eel_canvas_rect_get_property (GObject     *object,
 
 static void
 request_redraw_borders (GnomeCanvas *canvas,
-                       ArtDRect    *update_rect,
+                       EelDRect    *update_rect,
                        double       width)
 {
        gnome_canvas_request_redraw (canvas,
@@ -221,16 +233,15 @@ request_redraw_borders (GnomeCanvas *canvas,
 }
 
 static void
-eel_canvas_rect_update (GnomeCanvasItem *item,
-                       double *affine,
-                       ArtSVP *clip_path,
-                       int flags)
+eel_canvas_rect_update (GnomeCanvasItem      *item,
+                        const cairo_matrix_t *i2c,
+                        int                   flags)
 {
        EelCanvasRect *rect;
        EelCanvasRectDetails *details;
        double x1, y1, x2, y2;
        int cx1, cy1, cx2, cy2;
-       ArtDRect update_rect, repaint_rects[4];
+       EelDRect update_rect, repaint_rects[4];
        int repaint_rects_count, i;
        double width_lt, width_rb;
 
@@ -238,12 +249,12 @@ eel_canvas_rect_update (GnomeCanvasItem *item,
        details = rect->details;
 
        if (GNOME_CANVAS_ITEM_CLASS (eel_canvas_rect_parent_class)->update) {
-               GNOME_CANVAS_ITEM_CLASS (eel_canvas_rect_parent_class)->update (item, affine, clip_path, 
flags);
+               GNOME_CANVAS_ITEM_CLASS (eel_canvas_rect_parent_class)->update (item, i2c, flags);
        }
 
        /* Update bounding box: */
-       width_lt = floor (details->width_pixels / 2.0) / item->canvas->pixels_per_unit;
-       width_rb = ceil (details->width_pixels / 2.0) / item->canvas->pixels_per_unit;
+       width_lt = floor (details->width_pixels / 2.0);
+       width_rb = ceil (details->width_pixels / 2.0);
 
        x1 = details->x1;
        y1 = details->y1;
@@ -274,9 +285,9 @@ eel_canvas_rect_update (GnomeCanvasItem *item,
 
        update_rect = make_drect (cx1, cy1, cx2, cy2);
        request_redraw_borders (item->canvas, &details->last_outline_update_rect,
-                               (width_lt + width_rb)*item->canvas->pixels_per_unit);
+                               (width_lt + width_rb));
        request_redraw_borders (item->canvas, &update_rect,
-                               (width_lt + width_rb)*item->canvas->pixels_per_unit);
+                               (width_lt + width_rb));
        details->last_outline_update_rect = update_rect;
 
        item->x1 = cx1;
@@ -285,31 +296,22 @@ eel_canvas_rect_update (GnomeCanvasItem *item,
        item->y2 = cy2;
 }
 
-static void
-eel_canvas_rect_render (GnomeCanvasItem *item,
-                       GnomeCanvasBuf  *buf)
-{
-       g_assert_not_reached ();
-}
-
-static double
+static GnomeCanvasItem *
 eel_canvas_rect_point (GnomeCanvasItem *item,
-                      double x, double y,
-                      int cx, int cy,
-                      GnomeCanvasItem **actual_item)
+                       double           x,
+                       double           y,
+                       int              cx,
+                       int              cy)
 {
        EelCanvasRect *rect;
        EelCanvasRectDetails *details;
        double x1, y1, x2, y2;
        double hwidth;
-       double dx, dy;
 
        rect = EEL_CANVAS_RECT (item);
        details = rect->details;
 
-       *actual_item = item;
-
-       hwidth = (details->width_pixels / item->canvas->pixels_per_unit) / 2.0;
+       hwidth = details->width_pixels / 2.0;
        x1 = details->x1 - hwidth;
        y1 = details->y1 - hwidth;
        x2 = details->x2 + hwidth;
@@ -317,30 +319,16 @@ eel_canvas_rect_point (GnomeCanvasItem *item,
 
 
        if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
-               return 0.0;
+               return item;
        }
 
        /* Point is outside rectangle */
-       if (x < x1)
-               dx = x1 - x;
-       else if (x > x2)
-               dx = x - x2;
-       else
-               dx = 0.0;
-
-       if (y < y1)
-               dy = y1 - y;
-       else if (y > y2)
-               dy = y - y2;
-       else
-               dy = 0.0;
-
-       return sqrt (dx * dx + dy * dy);
+       return NULL;
 }
 
 static void
 render_rect_alpha (EelCanvasRect *rect,
-                  GdkDrawable *drawable,
+                  cairo_t *cr,
                   int x, int y,
                   int width, int height,
                   guint32 rgba)
@@ -349,7 +337,6 @@ render_rect_alpha (EelCanvasRect *rect,
        guchar *data;
        int rowstride, i;
        guchar r, g, b, a;
-       cairo_t *cr;
 
        if (width <= 0 || height <= 0 ) {
                return;
@@ -375,10 +362,10 @@ render_rect_alpha (EelCanvasRect *rect,
                memcpy (data + i*rowstride, data, width*4);
        }
 
-       cr = gdk_cairo_create (drawable);
+       cairo_save (cr);
        gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
        cairo_paint (cr);
-       cairo_destroy (cr);
+       cairo_restore (cr);
 
        g_object_unref (pixbuf);
 }
@@ -386,23 +373,24 @@ render_rect_alpha (EelCanvasRect *rect,
 
 static void
 eel_canvas_rect_draw (GnomeCanvasItem *item,
-                     GdkDrawable *drawable,
-                     int x, int y,
-                     int width, int height)
+                      cairo_t         *cr,
+                      int              x,
+                      int              y,
+                      int              width,
+                      int              height)
 {
        EelCanvasRect *rect;
        EelCanvasRectDetails *details;
        double x1, y1, x2, y2;
        int cx1, cy1, cx2, cy2;
        double width_lt, width_rb;
-       cairo_t *cr;
 
        rect = EEL_CANVAS_RECT (item);
        details = rect->details;
 
        /* Update bounding box: */
-       width_lt = floor (details->width_pixels / 2.0) / item->canvas->pixels_per_unit;
-       width_rb = ceil (details->width_pixels / 2.0) / item->canvas->pixels_per_unit;
+       width_lt = floor (details->width_pixels / 2.0);
+       width_rb = ceil (details->width_pixels / 2.0);
 
        x1 = details->x1;
        y1 = details->y1;
@@ -423,7 +411,7 @@ eel_canvas_rect_draw (GnomeCanvasItem *item,
        cy2 = MIN (height, cy2 - y);
 
        render_rect_alpha (rect,
-                          drawable,
+                          cr,
                           cx1, cy1,
                           cx2 - cx1, cy2 - cy1,
                           details->fill_color);
@@ -433,7 +421,7 @@ eel_canvas_rect_draw (GnomeCanvasItem *item,
        gnome_canvas_w2c (item->canvas, x1, y1, &cx1, &cy1);
        gnome_canvas_w2c (item->canvas, x2, y2, &cx2, &cy2);
 
-       cr = gdk_cairo_create (drawable);
+       cairo_save (cr);
        cairo_set_line_width (cr, details->width_pixels);
        cairo_set_source_rgb (cr,
                              ((details->outline_color >> 24) & 0xff) / 255,
@@ -443,7 +431,7 @@ eel_canvas_rect_draw (GnomeCanvasItem *item,
                         cx1 - x + 0.5, cy1 - y + 0.5,
                         cx2 - cx1, cy2 - cy1);
        cairo_stroke (cr);
-       cairo_destroy (cr);
+       cairo_restore (cr);
 }
 
 static void
@@ -483,7 +471,6 @@ eel_canvas_rect_class_init (EelCanvasRectClass *class)
        item_class->update = eel_canvas_rect_update;
        item_class->draw = eel_canvas_rect_draw;
        item_class->point = eel_canvas_rect_point;
-       item_class->render = eel_canvas_rect_render;
        item_class->bounds = eel_canvas_rect_bounds;
 
         g_object_class_install_property (gobject_class,
@@ -525,10 +512,10 @@ eel_canvas_rect_class_init (EelCanvasRectClass *class)
 }
 
 
-static ArtDRect
+static EelDRect
 make_drect (double x0, double y0, double x1, double y1)
 {
-       ArtDRect r;
+       EelDRect r;
 
        r.x0 = x0;
        r.y0 = y0;
@@ -538,7 +525,7 @@ make_drect (double x0, double y0, double x1, double y1)
 }
 
 static gboolean
-rects_intersect (ArtDRect r1, ArtDRect r2)
+rects_intersect (EelDRect r1, EelDRect r2)
 {
        if (r1.x0 >= r2.x1) {
                return FALSE;
@@ -556,7 +543,7 @@ rects_intersect (ArtDRect r1, ArtDRect r2)
 }
 
 static void
-diff_rects_guts (ArtDRect ra, ArtDRect rb, int *count, ArtDRect result[4])
+diff_rects_guts (EelDRect ra, EelDRect rb, int *count, EelDRect result[4])
 {
        if (ra.x0 < rb.x0) {
                result[(*count)++] = make_drect (ra.x0, ra.y0, rb.x0, ra.y1);
@@ -573,7 +560,7 @@ diff_rects_guts (ArtDRect ra, ArtDRect rb, int *count, ArtDRect result[4])
 }
 
 static void
-diff_rects (ArtDRect r1, ArtDRect r2, int *count, ArtDRect result[4])
+diff_rects (EelDRect r1, EelDRect r2, int *count, EelDRect result[4])
 {
        g_assert (count != NULL);
        g_assert (result != NULL);
@@ -584,10 +571,10 @@ diff_rects (ArtDRect r1, ArtDRect r2, int *count, ArtDRect result[4])
                diff_rects_guts (r1, r2, count, result);
                diff_rects_guts (r2, r1, count, result);
        } else {
-               if (!art_drect_empty (&r1)) {
+               if (!_eel_drect_empty (&r1)) {
                        result[(*count)++] = r1;
                }
-               if (!art_drect_empty (&r2)) {
+               if (!_eel_drect_empty (&r2)) {
                        result[(*count)++] = r2;
                }
        }
diff --git a/src/libgnomecanvas/meson.build b/src/libgnomecanvas/meson.build
new file mode 100644
index 00000000..7fc67ec6
--- /dev/null
+++ b/src/libgnomecanvas/meson.build
@@ -0,0 +1,27 @@
+libgnomecanvas_srcs = [
+  'gailcanvas.c',
+  'gailcanvasgroup.c',
+  'gailcanvasgroupfactory.c',
+  'gailcanvasitem.c',
+  'gailcanvasitemfactory.c',
+  'gailcanvastext.c',
+  'gailcanvastextfactory.c',
+  'gailcanvaswidget.c',
+  'gailcanvaswidgetfactory.c',
+  'gnome-canvas-line.c',
+  'gnome-canvas-pixbuf.c',
+  'gnome-canvas-rect.c',
+  'gnome-canvas-text.c',
+  'gnome-canvas-util.c',
+  'gnome-canvas-widget.c',
+  'gnome-canvas.c',
+  'libgnomecanvastypes.c',
+]
+
+gnomecanvas_lib = static_library(
+  'gnomecanvas',
+  sources: libgnomecanvas_srcs,
+  include_directories: [toplevel_inc, src_inc],
+  dependencies: [gtk_dep, gail_dep],
+  c_args: '-DG_LOG_DOMAIN="GnomeCanvas"',
+)
diff --git a/src/meson.build b/src/meson.build
index 772a3195..6e0af959 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,3 +1,6 @@
+src_inc = include_directories('.')
+subdir('libgnomecanvas')
+
 libplanner_app_srcs = [
   'eel-canvas-rect.c',
   'dummy-canvas-item.c',
@@ -73,17 +76,17 @@ planner_marshal_srcs = gnome.genmarshal('planner-marshal',
   sources: 'planner-marshal.list',
   prefix: 'planner_marshal',
 )
-planner_inc = include_directories('.')
 
 libplanner_app_library = static_library('libplannerapp',
   [libplanner_app_srcs, gantt_task_srcs, resource_srcs, usage_srcs, planner_marshal_srcs, resources],
   dependencies: [planner_deps, m_dep],
-  include_directories: [toplevel_inc, planner_inc],
+  include_directories: [toplevel_inc, src_inc],
+  link_with: gnomecanvas_lib,
   install: false,
 )
 libplanner_app_dep = declare_dependency(
   link_with: libplanner_app_library,
-  include_directories: planner_inc,
+  include_directories: src_inc,
   dependencies: [planner_deps, libplanner_dep],
 )
 planner_app = executable('planner',
diff --git a/src/planner-canvas-line.c b/src/planner-canvas-line.c
index 1d56ea07..4c62e299 100644
--- a/src/planner-canvas-line.c
+++ b/src/planner-canvas-line.c
@@ -26,12 +26,11 @@
 
 static void   mcl_init      (PlannerCanvasLine       *mcl);
 static void   mcl_class_init (PlannerCanvasLineClass  *klass);
-static double mcl_point      (GnomeCanvasItem    *item,
-                             double              x,
-                             double              y,
-                             int                 cx,
-                             int                 cy,
-                             GnomeCanvasItem   **actual_item);
+static GnomeCanvasItem * mcl_point (GnomeCanvasItem    *item,
+                                   double              x,
+                                   double              y,
+                                   int                 cx,
+                                   int                 cy);
 
 
 GType
@@ -75,15 +74,14 @@ mcl_init (PlannerCanvasLine *item)
 {
 }
 
-static double
+static GnomeCanvasItem *
 mcl_point (GnomeCanvasItem  *item,
           double            x,
           double            y,
           int               cx,
-          int               cy,
-          GnomeCanvasItem **actual_item)
+          int               cy)
 {
-       *actual_item = item;
-
-       return 1000.0;
+       /* TODO: Test over the behaviour from gnomecanvas gtk3 port;
+        * it was reporting distance of 1000.0 before */
+       return NULL;
 }
diff --git a/src/planner-gantt-background.c b/src/planner-gantt-background.c
index 050f03f0..b7b9bb72 100644
--- a/src/planner-gantt-background.c
+++ b/src/planner-gantt-background.c
@@ -67,19 +67,17 @@ static void     gantt_background_set_property     (GObject                *objec
                                                   const GValue           *value,
                                                   GParamSpec             *pspec);
 static void     gantt_background_update           (GnomeCanvasItem        *item,
-                                                  double                 *affine,
-                                                  ArtSVP                 *clip_path,
+                                                  const cairo_matrix_t   *i2c,
                                                   gint                    flags);
-static double   gantt_background_point            (GnomeCanvasItem        *item,
+static GnomeCanvasItem * gantt_background_point   (GnomeCanvasItem        *item,
                                                   double                  x,
                                                   double                  y,
                                                   gint                    cx,
-                                                  gint                    cy,
-                                                  GnomeCanvasItem       **actual_item);
+                                                  gint                    cy);
 static void     gantt_background_realize          (GnomeCanvasItem        *item);
 static void     gantt_background_unrealize        (GnomeCanvasItem        *item);
 static void     gantt_background_draw             (GnomeCanvasItem        *item,
-                                                  GdkDrawable            *drawable,
+                                                  cairo_t                *cr,
                                                   gint                    x,
                                                   gint                    y,
                                                   gint                    width,
@@ -255,17 +253,16 @@ gantt_background_get_bounds (PlannerGanttBackground *background,
        *py2 = G_MAXINT;
 }
 
-static double
+static GnomeCanvasItem *
 gantt_background_point (GnomeCanvasItem  *item,
                        double            x,
                        double            y,
                        gint              cx,
-                       gint              cy,
-                       GnomeCanvasItem **actual_item)
+                       gint              cy)
 {
-       *actual_item = item;
-
-       return 1000;
+       /* TODO: Test over the behaviour from gnomecanvas gtk3 port;
+        * it was reporting distance of 1000 before */
+       return NULL;
 }
 
 static void
@@ -334,10 +331,9 @@ gantt_background_set_property (GObject      *object,
 }
 
 static void
-gantt_background_update (GnomeCanvasItem *item,
-                        double          *affine,
-                        ArtSVP          *clip_path,
-                        int              flags)
+gantt_background_update (GnomeCanvasItem      *item,
+                         const cairo_matrix_t *i2c,
+                         int                   flags)
 {
        PlannerGanttBackground *background;
        double             x1, y1, x2, y2;
@@ -345,8 +341,7 @@ gantt_background_update (GnomeCanvasItem *item,
        background = PLANNER_GANTT_BACKGROUND (item);
 
        GNOME_CANVAS_ITEM_CLASS (parent_class)->update (item,
-                                                       affine,
-                                                       clip_path,
+                                                       i2c,
                                                        flags);
 
        gantt_background_get_bounds (background, &x1, &y1, &x2, &y2);
@@ -406,7 +401,7 @@ gantt_background_update_timeline (gpointer data)
 
 static void
 gantt_background_draw (GnomeCanvasItem *item,
-                      GdkDrawable     *drawable,
+                      cairo_t         *cr,
                       int              x,
                       int              y,
                       int              width,
@@ -414,7 +409,6 @@ gantt_background_draw (GnomeCanvasItem *item,
 {
        PlannerGanttBackground     *background;
        PlannerGanttBackgroundPriv *priv;
-       cairo_t               *cr;
        gint                   cx1, cx2;  /* Canvas pixel coordinates */
        gint                   cy1, cy2;
        gdouble                wx1, wx2;  /* World coordinates */
@@ -437,7 +431,7 @@ gantt_background_draw (GnomeCanvasItem *item,
                return;
        }
 
-       cr = gdk_cairo_create (drawable);
+       cairo_save (cr);
        cairo_set_line_width (cr, 1.0);
        cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
 
@@ -614,7 +608,7 @@ gantt_background_draw (GnomeCanvasItem *item,
                cairo_stroke (cr);
        }
 
-       cairo_destroy (cr);
+       cairo_restore (cr);
 }
 
 static void
diff --git a/src/planner-gantt-chart.c b/src/planner-gantt-chart.c
index 39055bc8..f8dd7418 100644
--- a/src/planner-gantt-chart.c
+++ b/src/planner-gantt-chart.c
@@ -81,6 +81,8 @@ struct _PlannerGanttChartPriv {
 
        GtkAdjustment   *hadjustment;
        GtkAdjustment   *vadjustment;
+       guint            hscroll_policy : 1;
+       guint            vscroll_policy : 1;
 
        GtkTreeModel    *model;
        TreeNode        *tree;
@@ -123,7 +125,12 @@ enum {
        PROP_0,
        PROP_HEADER_HEIGHT,
        PROP_ROW_HEIGHT,
-       PROP_MODEL
+       PROP_MODEL,
+       /* Scrollable interface */
+       PROP_HADJUSTMENT,
+       PROP_VADJUSTMENT,
+       PROP_HSCROLL_POLICY,
+       PROP_VSCROLL_POLICY
 };
 
 enum {
@@ -143,7 +150,7 @@ static void        gantt_chart_get_property             (GObject            *obj
                                                         guint               prop_id,
                                                         GValue             *value,
                                                         GParamSpec         *pspec);
-static void        gantt_chart_destroy                  (GtkObject          *object);
+static void        gantt_chart_destroy                  (GtkWidget          *widget);
 static void        gantt_chart_style_set                (GtkWidget          *widget,
                                                         GtkStyle           *prev_style);
 static void        gantt_chart_realize                  (GtkWidget          *widget);
@@ -151,8 +158,9 @@ static void        gantt_chart_unrealize                (GtkWidget          *wid
 static void        gantt_chart_map                      (GtkWidget          *widget);
 static void        gantt_chart_size_allocate            (GtkWidget          *widget,
                                                         GtkAllocation      *allocation);
-static void        gantt_chart_set_adjustments          (PlannerGanttChart       *chart,
-                                                        GtkAdjustment      *hadj,
+static void        gantt_chart_set_hadjustment          (PlannerGanttChart  *chart,
+                                                        GtkAdjustment      *hadj);
+static void        gantt_chart_set_vadjustment          (PlannerGanttChart  *chart,
                                                         GtkAdjustment      *vadj);
 static void        gantt_chart_row_changed              (GtkTreeModel       *model,
                                                         GtkTreePath        *path,
@@ -238,8 +246,16 @@ planner_gantt_chart_get_type (void)
                        (GInstanceInitFunc) gantt_chart_init
                };
 
+               static const GInterfaceInfo scrollable_info = {
+                       (GInterfaceInitFunc) NULL,
+                       NULL,
+                       NULL
+               };
+
                type = g_type_register_static (GTK_TYPE_VBOX, "PlannerGanttChart",
                                               &info, 0);
+
+               g_type_add_interface_static (type, GTK_TYPE_SCROLLABLE, &scrollable_info);
        }
 
        return type;
@@ -249,39 +265,24 @@ static void
 gantt_chart_class_init (PlannerGanttChartClass *class)
 {
        GObjectClass      *o_class;
-       GtkObjectClass    *object_class;
        GtkWidgetClass    *widget_class;
 
        parent_class = g_type_class_peek_parent (class);
 
        o_class         = (GObjectClass *) class;
-       object_class    = (GtkObjectClass *) class;
        widget_class    = (GtkWidgetClass *) class;
 
        o_class->set_property = gantt_chart_set_property;
        o_class->get_property = gantt_chart_get_property;
        o_class->finalize     = gantt_chart_finalize;
 
-       object_class->destroy = gantt_chart_destroy;
-
+       widget_class->destroy       = gantt_chart_destroy;
        widget_class->style_set     = gantt_chart_style_set;
        widget_class->realize       = gantt_chart_realize;
        widget_class->map           = gantt_chart_map;
        widget_class->unrealize     = gantt_chart_unrealize;
        widget_class->size_allocate = gantt_chart_size_allocate;
 
-       class->set_scroll_adjustments = gantt_chart_set_adjustments;
-
-       widget_class->set_scroll_adjustments_signal =
-               g_signal_new ("set_scroll_adjustments",
-                             G_TYPE_FROM_CLASS (object_class),
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (PlannerGanttChartClass, set_scroll_adjustments),
-                             NULL, NULL,
-                             planner_marshal_VOID__OBJECT_OBJECT,
-                             G_TYPE_NONE, 2,
-                             GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
-
        signals[STATUS_UPDATED] =
                g_signal_new ("status-updated",
                              G_TYPE_FROM_CLASS (class),
@@ -301,6 +302,12 @@ gantt_chart_class_init (PlannerGanttChartClass *class)
                              G_TYPE_NONE, 1,
                              MRP_TYPE_RESOURCE);
 
+       /* GtkScrollable interface properties */
+       g_object_class_override_property (o_class, PROP_HADJUSTMENT,    "hadjustment");
+       g_object_class_override_property (o_class, PROP_VADJUSTMENT,    "vadjustment");
+       g_object_class_override_property (o_class, PROP_HSCROLL_POLICY, "hscroll-policy");
+       g_object_class_override_property (o_class, PROP_VSCROLL_POLICY, "vscroll-policy");
+
        /* Properties. */
        g_object_class_install_property (o_class,
                                         PROP_MODEL,
@@ -364,8 +371,10 @@ gantt_chart_init (PlannerGanttChart *chart)
                            0);         /* padding */
 
        priv->canvas = GNOME_CANVAS (gnome_canvas_new ());
+       /* TODO: Consider porting these over to gtk3
        priv->canvas->close_enough = 5;
        gnome_canvas_set_center_scroll_region (priv->canvas, FALSE);
+        */
 
        /* Easiest way to get access to the chart from the canvas items. */
        g_object_set_data (G_OBJECT (priv->canvas), "chart", chart);
@@ -399,6 +408,17 @@ gantt_chart_init (PlannerGanttChart *chart)
                        "show_guidelines",
                        priv->guidelines,
                        NULL);
+
+       /* TODO: Is this an OK way to share the adjustments? Probably could just set them in set_property 
instead for simplicity? */
+       g_object_bind_property (chart, "hadjustment",
+                               priv->header, "hadjustment",
+                               G_BINDING_DEFAULT);
+       g_object_bind_property (chart, "hadjustment",
+                               priv->canvas, "hadjustment",
+                               G_BINDING_DEFAULT);
+       g_object_bind_property (chart, "vadjustment",
+                               priv->canvas, "vadjustment",
+                               G_BINDING_DEFAULT);
 }
 
 static void
@@ -427,6 +447,21 @@ gantt_chart_set_property (GObject      *object,
                              NULL);
                gantt_chart_reflow (chart, TRUE);
                break;
+       case PROP_HADJUSTMENT:
+               gantt_chart_set_hadjustment (chart, g_value_get_object (value));
+               break;
+       case PROP_VADJUSTMENT:
+               gantt_chart_set_vadjustment (chart, g_value_get_object (value));
+               break;
+       case PROP_HSCROLL_POLICY:
+               chart->priv->hscroll_policy = g_value_get_enum (value);
+               gtk_widget_queue_resize (GTK_WIDGET (chart));
+               break;
+       case PROP_VSCROLL_POLICY:
+               chart->priv->hscroll_policy = g_value_get_enum (value);
+               gtk_widget_queue_resize (GTK_WIDGET (chart));
+               break;
+
        default:
                break;
        }
@@ -446,6 +481,18 @@ gantt_chart_get_property (GObject    *object,
        case PROP_MODEL:
                g_value_set_object (value, G_OBJECT (chart->priv->model));
                break;
+       case PROP_HADJUSTMENT:
+               g_value_set_object (value, chart->priv->hadjustment);
+               break;
+       case PROP_VADJUSTMENT:
+               g_value_set_object (value, chart->priv->vadjustment);
+               break;
+       case PROP_HSCROLL_POLICY:
+               g_value_set_enum (value, chart->priv->hscroll_policy);
+               break;
+       case PROP_VSCROLL_POLICY:
+               g_value_set_enum (value, chart->priv->vscroll_policy);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -467,9 +514,9 @@ gantt_chart_finalize (GObject *object)
 }
 
 static void
-gantt_chart_destroy (GtkObject *object)
+gantt_chart_destroy (GtkWidget *widget)
 {
-       PlannerGanttChart *chart = PLANNER_GANTT_CHART (object);
+       PlannerGanttChart *chart = PLANNER_GANTT_CHART (widget);
 
        planner_gantt_chart_set_model (chart, NULL);
 
@@ -484,8 +531,8 @@ gantt_chart_destroy (GtkObject *object)
                chart->priv->model = NULL;
        }
 
-       if (GTK_OBJECT_CLASS (parent_class)->destroy) {
-               (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+       if (GTK_WIDGET_CLASS (parent_class)->destroy) {
+               (* GTK_WIDGET_CLASS (parent_class)->destroy) (widget);
        }
 }
 
@@ -527,7 +574,6 @@ gantt_chart_realize (GtkWidget *widget)
 {
        PlannerGanttChart     *chart;
        PlannerGanttChartPriv *priv;
-       GdkColormap           *colormap;
        GtkStyle              *style;
        GtkWidget             *canvas;
 
@@ -542,9 +588,7 @@ gantt_chart_realize (GtkWidget *widget)
 
        /* Set the background to white. */
        style = gtk_style_copy (gtk_widget_get_style (canvas));
-       colormap = gtk_widget_get_colormap (canvas);
        gdk_color_parse ("white", &style->bg[GTK_STATE_NORMAL]);
-       gdk_colormap_alloc_color (colormap, &style->bg[GTK_STATE_NORMAL], FALSE, TRUE);
        gtk_widget_set_style (canvas, style);
        g_object_unref (style);
 
@@ -596,56 +640,59 @@ gantt_chart_size_allocate (GtkWidget     *widget,
 }
 
 static void
-gantt_chart_set_adjustments (PlannerGanttChart *chart,
-                            GtkAdjustment     *hadj,
-                            GtkAdjustment     *vadj)
+gantt_chart_set_hadjustment (PlannerGanttChart *chart,
+                             GtkAdjustment     *hadj)
 {
-       PlannerGanttChartPriv *priv;
-       gboolean               need_adjust = FALSE;
-
-       g_return_if_fail (hadj == NULL || GTK_IS_ADJUSTMENT (hadj));
-       g_return_if_fail (vadj == NULL || GTK_IS_ADJUSTMENT (vadj));
-
-       priv = chart->priv;
+       if (hadj && chart->priv->hadjustment == hadj)
+               return;
 
-       if (hadj == NULL) {
+       if (hadj)
+               g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
+       else
                hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
-       }
-       if (vadj == NULL) {
-               vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
-       }
 
-       if (priv->hadjustment && (priv->hadjustment != hadj)) {
-               g_object_unref (priv->hadjustment);
+       if (chart->priv->hadjustment != NULL) {
+               g_signal_handlers_disconnect_matched (chart->priv->hadjustment,
+                                                     G_SIGNAL_MATCH_DATA,
+                                                     0, 0, NULL, NULL,
+                                                     chart);
+               g_object_unref (chart->priv->hadjustment);
        }
 
-       if (priv->vadjustment && (priv->vadjustment != vadj)) {
-               g_object_unref (priv->vadjustment);
-       }
+       /* TODO: value-changed handler? If not adding, disconnecting above is probably unnecessary too */
+       chart->priv->hadjustment = g_object_ref_sink (hadj);
+       /* TODO: Do we need to set the initial hadj values? */
+       /* TODO: Share the hadjustment with header and canvas? */
 
-       if (priv->hadjustment != hadj) {
-               priv->hadjustment = hadj;
-               g_object_ref_sink (priv->hadjustment);
-
-               gtk_widget_set_scroll_adjustments (priv->header,
-                                                  hadj,
-                                                  NULL);
+       g_object_notify (G_OBJECT (chart), "hadjustment");
+}
 
-               need_adjust = TRUE;
-       }
+static void
+gantt_chart_set_vadjustment (PlannerGanttChart *chart,
+                             GtkAdjustment     *vadj)
+{
+       if (vadj && chart->priv->vadjustment == vadj)
+               return;
 
-       if (priv->vadjustment != vadj) {
-               priv->vadjustment = vadj;
-               g_object_ref_sink (priv->vadjustment);
+       if (vadj)
+               g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
+       else
+               vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
 
-               need_adjust = TRUE;
+       if (chart->priv->vadjustment != NULL) {
+               g_signal_handlers_disconnect_matched (chart->priv->vadjustment,
+                                                     G_SIGNAL_MATCH_DATA,
+                                                     0, 0, NULL, NULL,
+                                                     chart);
+               g_object_unref (chart->priv->vadjustment);
        }
 
-       if (need_adjust) {
-               gtk_widget_set_scroll_adjustments (GTK_WIDGET (priv->canvas),
-                                                  hadj,
-                                                  vadj);
-       }
+       /* TODO: value-changed handler? If not adding, disconnecting above is probably unnecessary too */
+       chart->priv->vadjustment = g_object_ref_sink (vadj);
+       /* TODO: Do we need to set the initial vadj values? */
+       /* TODO: Share the vadjustment with canvas? */
+
+       g_object_notify (G_OBJECT (chart), "vadjustment");
 }
 
 static void
@@ -746,7 +793,7 @@ gantt_chart_remove_children (PlannerGanttChart *chart,
        }
 
        if (node->item) {
-               gtk_object_destroy (GTK_OBJECT (node->item));
+               g_object_run_dispose (G_OBJECT (node->item));
                node->item = NULL;
        }
        node->task = NULL;
@@ -1273,7 +1320,7 @@ gantt_chart_relation_removed (MrpTask           *task,
        if (arrow != NULL) {
                g_hash_table_remove (chart->priv->relation_hash, relation);
 
-               gtk_object_destroy (GTK_OBJECT (arrow));
+               g_object_run_dispose (G_OBJECT (arrow));
                gantt_chart_reflow (chart, FALSE);
        }
 }
diff --git a/src/planner-gantt-header.c b/src/planner-gantt-header.c
index e8a7c272..19607b2e 100644
--- a/src/planner-gantt-header.c
+++ b/src/planner-gantt-header.c
@@ -37,6 +37,8 @@ struct _PlannerGanttHeaderPriv {
        GdkWindow          *bin_window;
 
        GtkAdjustment      *hadjustment;
+       guint               hscroll_policy : 1;
+       guint               vscroll_policy : 1;
 
        PangoLayout        *layout;
 
@@ -64,7 +66,12 @@ enum {
        PROP_X1,
        PROP_X2,
        PROP_SCALE,
-       PROP_ZOOM
+       PROP_ZOOM,
+       /* Scrollable interface */
+       PROP_HADJUSTMENT,
+       PROP_VADJUSTMENT,
+       PROP_HSCROLL_POLICY,
+       PROP_VSCROLL_POLICY
 };
 
 enum {
@@ -88,15 +95,14 @@ static void     gantt_header_realize             (GtkWidget               *widge
 static void     gantt_header_unrealize           (GtkWidget               *widget);
 static void     gantt_header_size_allocate       (GtkWidget               *widget,
                                                  GtkAllocation           *allocation);
-static gboolean gantt_header_expose_event        (GtkWidget               *widget,
-                                                 GdkEventExpose          *event);
+static gboolean gantt_header_draw                (GtkWidget               *widget,
+                                                 cairo_t                 *cr);
 static gboolean gantt_header_motion_notify_event (GtkWidget               *widget,
                                                  GdkEventMotion          *event);
 static gboolean gantt_header_leave_notify_event  (GtkWidget              *widget,
                                                  GdkEventCrossing        *event);
-static void     gantt_header_set_adjustments     (PlannerGanttHeader      *header,
-                                                 GtkAdjustment           *hadj,
-                                                 GtkAdjustment           *vadj);
+static void     gantt_header_set_hadjustment     (PlannerGanttHeader      *header,
+                                                 GtkAdjustment           *hadj);
 static void     gantt_header_adjustment_changed  (GtkAdjustment           *adjustment,
                                                  PlannerGanttHeader      *header);
 
@@ -124,11 +130,21 @@ planner_gantt_header_get_type (void)
                        (GInstanceInitFunc) gantt_header_init
                };
 
+               static const GInterfaceInfo scrollable_info = {
+                       (GInterfaceInitFunc) NULL,
+                       NULL,
+                       NULL
+               };
+
                planner_gantt_header_type = g_type_register_static (
                        GTK_TYPE_WIDGET,
                        "PlannerGanttHeader",
                        &planner_gantt_header_info,
                        0);
+
+               g_type_add_interface_static (planner_gantt_header_type,
+                                            GTK_TYPE_SCROLLABLE,
+                                            &scrollable_info);
        }
 
        return planner_gantt_header_type;
@@ -155,22 +171,16 @@ gantt_header_class_init (PlannerGanttHeaderClass *class)
        widget_class->realize = gantt_header_realize;
        widget_class->unrealize = gantt_header_unrealize;
        widget_class->size_allocate = gantt_header_size_allocate;
-       widget_class->expose_event = gantt_header_expose_event;
+       widget_class->draw = gantt_header_draw;
        widget_class->leave_notify_event = gantt_header_leave_notify_event;
 
        widget_class->motion_notify_event = gantt_header_motion_notify_event;
 
-       class->set_scroll_adjustments = gantt_header_set_adjustments;
-
-       widget_class->set_scroll_adjustments_signal =
-               g_signal_new ("set_scroll_adjustments",
-                             G_TYPE_FROM_CLASS (class),
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (PlannerGanttHeaderClass, set_scroll_adjustments),
-                             NULL, NULL,
-                             planner_marshal_VOID__OBJECT_OBJECT,
-                             G_TYPE_NONE, 2,
-                             GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
+       /* GtkScrollable interface properties */
+       g_object_class_override_property (o_class, PROP_HADJUSTMENT,    "hadjustment");
+       g_object_class_override_property (o_class, PROP_VADJUSTMENT,    "vadjustment");
+       g_object_class_override_property (o_class, PROP_HSCROLL_POLICY, "hscroll-policy");
+       g_object_class_override_property (o_class, PROP_VSCROLL_POLICY, "vscroll-policy");
 
        /* Properties. */
        g_object_class_install_property (
@@ -239,8 +249,6 @@ gantt_header_init (PlannerGanttHeader *header)
        priv = g_new0 (PlannerGanttHeaderPriv, 1);
        header->priv = priv;
 
-       gantt_header_set_adjustments (header, NULL, NULL);
-
        priv->hscale = 1.0;
        priv->x1 = 0;
        priv->x2 = 0;
@@ -318,6 +326,20 @@ gantt_header_set_property (GObject      *object,
        case PROP_ZOOM:
                gantt_header_set_zoom (header, g_value_get_double (value));
                break;
+       case PROP_HADJUSTMENT:
+               gantt_header_set_hadjustment (header, g_value_get_object (value));
+               break;
+       case PROP_VADJUSTMENT:
+               /* TODO: g_assert_not_reached (); */
+               break;
+       case PROP_HSCROLL_POLICY:
+               priv->hscroll_policy = g_value_get_enum (value);
+               gtk_widget_queue_resize (GTK_WIDGET (header));
+               break;
+       case PROP_VSCROLL_POLICY:
+               priv->hscroll_policy = g_value_get_enum (value);
+               gtk_widget_queue_resize (GTK_WIDGET (header));
+               break;
        default:
                break;
        }
@@ -355,7 +377,23 @@ gantt_header_get_property (GObject    *object,
                           GValue     *value,
                           GParamSpec *pspec)
 {
+       PlannerGanttHeader     *header;
+
+       header = PLANNER_GANTT_HEADER (object);
+
        switch (prop_id) {
+       case PROP_HADJUSTMENT:
+               g_value_set_object (value, header->priv->hadjustment);
+               break;
+       case PROP_VADJUSTMENT:
+               /* TODO: g_assert_not_reached (); */
+               break;
+       case PROP_HSCROLL_POLICY:
+               g_value_set_enum (value, header->priv->hscroll_policy);
+               break;
+       case PROP_VSCROLL_POLICY:
+               g_value_set_enum (value, header->priv->vscroll_policy);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -413,10 +451,9 @@ gantt_header_realize (GtkWidget *widget)
        attributes.height = allocation.height;
        attributes.wclass = GDK_INPUT_OUTPUT;
        attributes.visual = gtk_widget_get_visual (widget);
-       attributes.colormap = gtk_widget_get_colormap (widget);
        attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
 
-       attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+       attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
 
        window = gdk_window_new (gtk_widget_get_parent_window (widget),
                                 &attributes, attributes_mask);
@@ -429,7 +466,7 @@ gantt_header_realize (GtkWidget *widget)
        attributes.width = header->priv->width;
        gtk_widget_get_allocation (widget, &allocation);
        attributes.height = allocation.height;
-       attributes.event_mask = GDK_EXPOSURE_MASK |
+       attributes.event_mask = GDK_EXPOSURE_MASK | /* TODO: Do we need exposure mask anymore? */
                GDK_SCROLL_MASK |
                GDK_POINTER_MOTION_MASK |
                GDK_ENTER_NOTIFY_MASK |
@@ -490,15 +527,16 @@ gantt_header_size_allocate (GtkWidget     *widget,
 }
 
 static gboolean
-gantt_header_expose_event (GtkWidget      *widget,
-                          GdkEventExpose *event)
+gantt_header_draw (GtkWidget *widget,
+                   cairo_t   *cr)
 {
        PlannerGanttHeader     *header;
        PlannerGanttHeaderPriv *priv;
-       cairo_t                *cr;
+       GdkWindow              *bin_window;
+       GdkRectangle            clip;
        gint                    height;
        gdouble                 hscale;
-       gint                    x;
+       gint                    x, tr_x, tr_y;
        mrptime                 t0;
        mrptime                 t1;
        mrptime                 t;
@@ -506,38 +544,45 @@ gantt_header_expose_event (GtkWidget      *widget,
        gint                    minor_width;
        gint                    major_width;
 
-       cr = gdk_cairo_create (event->window);
-       cairo_set_line_width (cr, 1.0);
-       cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
-
        header = PLANNER_GANTT_HEADER (widget);
        priv = header->priv;
        hscale = priv->hscale;
 
-       t0 = floor ((priv->x1 + event->area.x) / hscale + 0.5);
-       t1 = floor ((priv->x1 + event->area.x + event->area.width) / hscale + 0.5);
+       bin_window = priv->bin_window;
+       if (!gtk_cairo_should_draw_window (cr, bin_window)) {
+               return FALSE;
+       }
+       gdk_window_get_position (bin_window, &tr_x, &tr_y);
+       cairo_translate (cr, tr_x, tr_y);
 
-       height = gdk_window_get_height (event->window);
+       gdk_cairo_get_clip_rectangle (cr, &clip);
+
+       cairo_set_line_width (cr, 1.0);
+       cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
+
+       t0 = floor ((priv->x1 + clip.x) / hscale + 0.5);
+       t1 = floor ((priv->x1 + clip.x + clip.width) / hscale + 0.5);
+
+       height = gdk_window_get_height (bin_window);
 
        /* Draw background. We only draw over the exposed area, padding with +/-
         * 5 so we don't mess up the header with button edges all over.
         */
        gtk_paint_box (gtk_widget_get_style (widget),
-                      event->window,
+                      cr,
                       GTK_STATE_NORMAL,
                       GTK_SHADOW_OUT,
-                      &event->area,
                       widget,
                       "button",
-                      event->area.x - 5,
+                      clip.x - 5,
                       0,
-                      event->area.width + 10,
+                      clip.width + 10,
                       height);
 
        // Horizontal full width line between week number and date rows
        gdk_cairo_set_source_color (cr, &gtk_widget_get_style (widget)->fg[GTK_STATE_INSENSITIVE]);
-       cairo_move_to (cr, event->area.x + 0.5, height / 2 + 0.5);
-       cairo_line_to (cr, event->area.x + event->area.width + 0.5, height / 2 + 0.5);
+       cairo_move_to (cr, clip.x + 0.5, height / 2 + 0.5);
+       cairo_line_to (cr, clip.x + clip.width + 0.5, height / 2 + 0.5);
        cairo_stroke (cr);
 
        /* Get the widths of major/minor ticks so that we know how wide to make
@@ -624,8 +669,6 @@ gantt_header_expose_event (GtkWidget      *widget,
        }
 
  done:
-       cairo_destroy (cr);
-
        return TRUE;
 }
 
@@ -678,31 +721,33 @@ gantt_header_leave_notify_event (GtkWidget          *widget,
 
 /* Callbacks */
 static void
-gantt_header_set_adjustments (PlannerGanttHeader *header,
-                             GtkAdjustment      *hadj,
-                             GtkAdjustment      *vadj)
+gantt_header_set_hadjustment (PlannerGanttHeader *header,
+                             GtkAdjustment      *hadj)
 {
-       if (hadj == NULL) {
+       if (hadj && header->priv->hadjustment == hadj)
+               return;
+
+       if (hadj)
+               g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
+       else
                hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
-       }
 
-       if (header->priv->hadjustment && (header->priv->hadjustment != hadj)) {
+       if (header->priv->hadjustment != NULL) {
+               g_signal_handlers_disconnect_matched (header->priv->hadjustment,
+                                                     G_SIGNAL_MATCH_DATA,
+                                                     0, 0, NULL, NULL,
+                                                     header);
                g_object_unref (header->priv->hadjustment);
        }
 
-       if (header->priv->hadjustment != hadj) {
-               header->priv->hadjustment = hadj;
-               g_object_ref_sink (header->priv->hadjustment);
+       g_signal_connect (hadj,
+                         "value-changed",
+                         G_CALLBACK (gantt_header_adjustment_changed),
+                         header);
+       header->priv->hadjustment = g_object_ref_sink (hadj);
+       /* TODO: Do we need to set the initial hadj values? */
 
-               g_signal_connect (hadj,
-                                 "value_changed",
-                                 G_CALLBACK (gantt_header_adjustment_changed),
-                                 header);
-
-               gtk_widget_set_scroll_adjustments (GTK_WIDGET (header),
-                                                  hadj,
-                                                  NULL);
-       }
+       g_object_notify (G_OBJECT (header), "hadjustment");
 }
 
 static void
diff --git a/src/planner-gantt-row.c b/src/planner-gantt-row.c
index a87e636b..30858f63 100644
--- a/src/planner-gantt-row.c
+++ b/src/planner-gantt-row.c
@@ -147,7 +147,7 @@ struct _PlannerGanttRowPriv {
 
 static void     gantt_row_class_init                  (PlannerGanttRowClass  *class);
 static void     gantt_row_init                        (PlannerGanttRow       *row);
-static void     gantt_row_destroy                     (GtkObject             *object);
+static void     gantt_row_dispose                     (GObject               *object);
 static void     gantt_row_set_property                (GObject               *object,
                                                       guint                  param_id,
                                                       const GValue          *value,
@@ -157,21 +157,19 @@ static void     gantt_row_get_property                (GObject               *ob
                                                       GValue                *value,
                                                       GParamSpec            *pspec);
 static void     gantt_row_update                      (GnomeCanvasItem       *item,
-                                                      double                *affine,
-                                                      ArtSVP                *clip_path,
+                                                      const cairo_matrix_t  *i2c,
                                                       int                    flags);
 static void     gantt_row_draw                        (GnomeCanvasItem       *item,
-                                                      GdkDrawable           *drawable,
+                                                      cairo_t               *cr,
                                                       gint                   x,
                                                       gint                   y,
                                                       gint                   width,
                                                       gint                   height);
-static double   gantt_row_point                       (GnomeCanvasItem       *item,
+static GnomeCanvasItem * gantt_row_point              (GnomeCanvasItem       *item,
                                                       double                 x,
                                                       double                 y,
                                                       gint                   cx,
-                                                      gint                   cy,
-                                                      GnomeCanvasItem      **actual_item);
+                                                      gint                   cy);
 static void     gantt_row_bounds                      (GnomeCanvasItem       *item,
                                                       double                *x1,
                                                       double                *y1,
@@ -292,11 +290,9 @@ static void
 gantt_row_class_init (PlannerGanttRowClass *class)
 {
        GObjectClass         *gobject_class;
-       GtkObjectClass       *object_class;
        GnomeCanvasItemClass *item_class;
 
        gobject_class = (GObjectClass *) class;
-       object_class = (GtkObjectClass *) class;
        item_class = (GnomeCanvasItemClass *) class;
 
        parent_class = g_type_class_peek_parent (class);
@@ -377,7 +373,7 @@ gantt_row_class_init (PlannerGanttRowClass *class)
                                   -1, G_MAXINT, -1,
                                   G_PARAM_WRITABLE));
 
-       object_class->destroy = gantt_row_destroy;
+       gobject_class->dispose = gantt_row_dispose;
 
        item_class->update = gantt_row_update;
        item_class->draw = gantt_row_draw;
@@ -414,7 +410,7 @@ gantt_row_init (PlannerGanttRow *row)
 }
 
 static void
-gantt_row_destroy (GtkObject *object)
+gantt_row_dispose (GObject *object)
 {
        PlannerGanttRow     *row;
        PlannerGanttRowPriv *priv;
@@ -436,8 +432,8 @@ gantt_row_destroy (GtkObject *object)
                row->priv = NULL;
        }
 
-       if (GTK_OBJECT_CLASS (parent_class)->destroy) {
-               (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+       if (G_OBJECT_CLASS (parent_class)->dispose) {
+               G_OBJECT_CLASS (parent_class)->dispose (object);
        }
 }
 
@@ -784,8 +780,7 @@ gantt_row_update_resources (PlannerGanttRow *row)
 
 static void
 gantt_row_update (GnomeCanvasItem *item,
-                 double          *affine,
-                 ArtSVP          *clip_path,
+                 const cairo_matrix_t  *i2c,
                  gint             flags)
 {
        PlannerGanttRow *row;
@@ -794,8 +789,7 @@ gantt_row_update (GnomeCanvasItem *item,
        row = PLANNER_GANTT_ROW (item);
 
        GNOME_CANVAS_ITEM_CLASS (parent_class)->update (item,
-                                                       affine,
-                                                       clip_path,
+                                                       i2c,
                                                        flags);
 
        gantt_row_ensure_layout (row);
@@ -1029,7 +1023,7 @@ static gboolean gantt_draw_tasktime(cairo_t *cr,
 
 static void
 gantt_row_draw (GnomeCanvasItem *item,
-               GdkDrawable     *drawable,
+               cairo_t         *cr,
                gint             x,
                gint             y,
                gint             width,
@@ -1038,7 +1032,6 @@ gantt_row_draw (GnomeCanvasItem *item,
        PlannerGanttRow     *row;
        PlannerGanttRowPriv *priv;
        PlannerGanttChart   *chart;
-       cairo_t             *cr;
        gdouble              i2w_dx;
        gdouble              i2w_dy;
        gdouble              dx1, dy1, dx2, dy2, dshay1, dshay2;
@@ -1169,7 +1162,7 @@ gantt_row_draw (GnomeCanvasItem *item,
                return;
        }
 
-       cr = gdk_cairo_create (drawable);
+       cairo_save (cr);
        cairo_set_line_width (cr, 1.0);
        cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
 
@@ -1772,28 +1765,24 @@ gantt_row_draw (GnomeCanvasItem *item,
                }
        }
 
-       cairo_destroy (cr);
+       cairo_restore (cr);
 }
 
-static double
+static GnomeCanvasItem *
 gantt_row_point (GnomeCanvasItem  *item,
                 double            x,
                 double            y,
                 gint              cx,
-                gint              cy,
-                GnomeCanvasItem **actual_item)
+                gint              cy)
 {
        PlannerGanttRow     *row;
        PlannerGanttRowPriv *priv;
        gint                 text_width;
        gdouble              x1, y1, x2, y2;
-       gdouble              dx, dy;
 
        row = PLANNER_GANTT_ROW (item);
        priv = row->priv;
 
-       *actual_item = item;
-
        text_width = priv->text_width;
        if (text_width > 0) {
                text_width += TEXT_PADDING;
@@ -1805,29 +1794,11 @@ gantt_row_point (GnomeCanvasItem  *item,
        y2 = y1 + priv->height;
 
        if (x > x1 && x < x2 && y > y1 && y < y2) {
-               return 0.0;
+               return item;
        }
 
        /* Point is outside rectangle */
-       if (x < x1) {
-               dx = x1 - x;
-       }
-       else if (x > x2) {
-               dx = x - x2;
-       } else {
-               dx = 0.0;
-       }
-
-       if (y < y1) {
-               dy = y1 - y;
-       }
-       else if (y > y2) {
-               dy = y - y2;
-       } else {
-               dy = 0.0;
-       }
-
-       return sqrt (dx * dx + dy * dy);
+       return NULL;
 }
 
 static void
@@ -2492,7 +2463,7 @@ gantt_row_event (GnomeCanvasItem *item, GdkEvent *event)
                                                                   "arrow_shape_c", 3.0,
                                                                   "fill_color", "black",
                                                                   "width_pixels", (guint) 0,
-                                                                  "join_style", GDK_JOIN_MITER,
+                                                                  "join_style", CAIRO_LINE_JOIN_MITER,
                                                                   NULL);
                                gnome_canvas_item_hide (drag_item);
 
@@ -2542,7 +2513,8 @@ gantt_row_event (GnomeCanvasItem *item, GdkEvent *event)
                                                GDK_BUTTON_PRESS_MASK |
                                                GDK_BUTTON_RELEASE_MASK,
                                                NULL,
-                                               event->button.time);
+                                               gdk_event_get_device (event),
+                                               gdk_event_get_time (event));
 
                        drag_wx1 = event->button.x;
                        drag_wy1 = event->button.y;
@@ -2683,9 +2655,9 @@ gantt_row_event (GnomeCanvasItem *item, GdkEvent *event)
                                      "work", work,
                                      NULL);
                        */
-                       gtk_object_destroy (GTK_OBJECT (drag_item));
+                       g_object_run_dispose (G_OBJECT (drag_item));
                        drag_item = NULL;
-                       gtk_object_destroy (GTK_OBJECT (scroll_region_extender));
+                       g_object_run_dispose (G_OBJECT (scroll_region_extender));
                        scroll_region_extender = NULL;
 
                        planner_gantt_chart_status_updated (chart, NULL);
@@ -2711,7 +2683,7 @@ gantt_row_event (GnomeCanvasItem *item, GdkEvent *event)
                                priv->scroll_timeout_id = 0;
                        }
 
-                       gtk_object_destroy (GTK_OBJECT (drag_item));
+                       g_object_run_dispose (G_OBJECT (drag_item));
                        drag_item = NULL;
 
                        planner_gantt_chart_status_updated (chart, NULL);
@@ -2730,7 +2702,7 @@ gantt_row_event (GnomeCanvasItem *item, GdkEvent *event)
                                priv->scroll_timeout_id = 0;
                        }
 
-                       gtk_object_destroy (GTK_OBJECT (drag_item));
+                       g_object_run_dispose (G_OBJECT (drag_item));
                        drag_item = NULL;
 
                        target_item = gnome_canvas_get_item_at (item->canvas,
diff --git a/src/planner-gantt-view.c b/src/planner-gantt-view.c
index ff72c070..927489a3 100644
--- a/src/planner-gantt-view.c
+++ b/src/planner-gantt-view.c
@@ -49,7 +49,7 @@ struct _PlannerGanttViewPriv {
        GtkUIManager          *ui_manager;
        GtkActionGroup        *actions;
        guint                  merged_id;
-       gulong                 expose_id;
+       gulong                 draw_signal_id;
 };
 
 static void          gantt_view_finalize                  (GObject           *object);
@@ -92,8 +92,8 @@ static void          gantt_view_nonstandard_days_cb       (GtkAction         *ac
                                                           gpointer           data);
 static void          gantt_view_edit_columns_cb           (GtkAction         *action,
                                                           gpointer           data);
-static gboolean      gantt_view_expose_cb                 (GtkWidget         *widget,
-                                                          GdkEventExpose    *event,
+static gboolean      gantt_view_draw_cb                   (GtkWidget         *widget,
+                                                          cairo_t           *cr,
                                                           gpointer           user_data);
 static void          gantt_view_update_row_height         (PlannerGanttView  *view);
 static void          gantt_view_tree_style_set_cb         (GtkWidget         *tree,
@@ -498,11 +498,11 @@ gantt_view_task_inserted_cb (MrpProject   *project,
                             MrpTask      *task,
                             PlannerGanttView *view)
 {
-       if(view->priv->expose_id == 0) {
-               view->priv->expose_id = g_signal_connect_after (view->priv->tree,
-                                                               "expose_event",
-                                                               G_CALLBACK (gantt_view_expose_cb),
-                                                               view);
+       if(view->priv->draw_signal_id == 0) {
+               view->priv->draw_signal_id = g_signal_connect_after (view->priv->tree,
+                                                                    "draw",
+                                                                    G_CALLBACK (gantt_view_draw_cb),
+                                                                    view);
        }
 }
 
@@ -520,52 +520,14 @@ gantt_view_project_loaded_cb (MrpProject  *project,
        planner_gantt_chart_set_model (PLANNER_GANTT_CHART (view->priv->gantt),
                                       model);
 
-       view->priv->expose_id = g_signal_connect_after (view->priv->tree,
-                                                       "expose_event",
-                                                       G_CALLBACK (gantt_view_expose_cb),
-                                                       view);
+       view->priv->draw_signal_id = g_signal_connect_after (view->priv->tree,
+                                                            "draw",
+                                                            G_CALLBACK (gantt_view_draw_cb),
+                                                            view);
 
        g_object_unref (model);
 }
 
-static void
-gantt_view_tree_view_size_request_cb (GtkWidget      *widget,
-                                     GtkRequisition *req,
-                                     gpointer        data)
-{
-       req->height = -1;
-}
-
-static gboolean
-gantt_view_tree_view_scroll_event_cb (GtkWidget      *widget,
-                                     GdkEventScroll *event,
-                                     gpointer        data)
-{
-       GtkAdjustment *adj;
-       GtkTreeView   *tv = GTK_TREE_VIEW (widget);
-       gdouble        new_value;
-
-       if (event->direction != GDK_SCROLL_UP &&
-           event->direction != GDK_SCROLL_DOWN) {
-               return FALSE;
-       }
-
-       adj = gtk_tree_view_get_vadjustment (tv);
-
-       if (event->direction == GDK_SCROLL_UP) {
-               new_value = gtk_adjustment_get_value (adj) - gtk_adjustment_get_page_increment (adj) / 2;
-       } else {
-               new_value = gtk_adjustment_get_value (adj) + gtk_adjustment_get_page_increment (adj) / 2;
-       }
-
-       new_value = CLAMP (new_value,
-                          gtk_adjustment_get_lower (adj),
-                          gtk_adjustment_get_upper (adj) - gtk_adjustment_get_page_size (adj));
-       gtk_adjustment_set_value (adj, new_value);
-
-       return TRUE;
-}
-
 static void
 gantt_view_tree_view_columns_changed_cb (GtkTreeView *tree_view,
                                         PlannerGanttView *view)
@@ -591,10 +553,8 @@ gantt_view_create_widget (PlannerGanttView *view)
        PlannerGanttViewPriv  *priv;
        GtkWidget        *tree;
        GtkWidget        *sw;
-       GtkWidget        *frame;
-       GtkWidget        *vbox;
        GtkWidget        *hpaned;
-       GtkAdjustment    *hadj, *vadj;
+       GtkAdjustment    *vadj;
        GtkTreeModel     *model;
        MrpProject       *project;
        GtkTreeSelection *selection;
@@ -697,46 +657,29 @@ gantt_view_create_widget (PlannerGanttView *view)
                          G_CALLBACK (gantt_view_relations_changed_cb),
                          view);
 
-       vbox = gtk_vbox_new (FALSE, 3);
-
-       gtk_box_pack_start (GTK_BOX (vbox), tree, TRUE, TRUE, 0);
-
-       hadj = gtk_tree_view_get_hadjustment (GTK_TREE_VIEW (tree));
-       gtk_box_pack_start (GTK_BOX (vbox), gtk_hscrollbar_new (hadj), FALSE, TRUE, 0);
-
-       frame = gtk_frame_new (NULL);
-       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-       gtk_container_add (GTK_CONTAINER (frame), vbox);
+       sw = gtk_scrolled_window_new (NULL, NULL);
+       /* TODO: Consider changing vertical policy to GTK_POLICY_EXTERNAL once we depend on gtk 3.16 */
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+                                       GTK_POLICY_AUTOMATIC,
+                                       GTK_POLICY_AUTOMATIC);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
+       gtk_container_add (GTK_CONTAINER (sw), tree);
 
        hpaned = gtk_hpaned_new ();
-       gtk_paned_add1 (GTK_PANED (hpaned), frame);
-
-       g_signal_connect_after (tree,
-                               "size_request",
-                               G_CALLBACK (gantt_view_tree_view_size_request_cb),
-                               NULL);
+       gtk_paned_add1 (GTK_PANED (hpaned), sw);
 
-       g_signal_connect_after (tree,
-                               "scroll_event",
-                               G_CALLBACK (gantt_view_tree_view_scroll_event_cb),
-                               view);
-
-       hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 0, 90, 250, 2000));
-       vadj = gtk_tree_view_get_vadjustment (GTK_TREE_VIEW (tree));
-
-       sw = gtk_scrolled_window_new (hadj, vadj);
+       /* TODO: Exclude the scrollbar from the gantt header, like the GtkTreeView does */
+       vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sw));
+       sw = gtk_scrolled_window_new (NULL, vadj);
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
-                                       GTK_POLICY_ALWAYS,
+                                       GTK_POLICY_AUTOMATIC,
                                        GTK_POLICY_AUTOMATIC);
-
-       frame = gtk_frame_new (NULL);
-       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-       gtk_container_add (GTK_CONTAINER (frame), sw);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
 
        gtk_container_add (GTK_CONTAINER (sw),
                           GTK_WIDGET (priv->gantt));
 
-       gtk_paned_add2 (GTK_PANED (hpaned), frame);
+       gtk_paned_add2 (GTK_PANED (hpaned), sw);
 
        gtk_paned_set_position (GTK_PANED (hpaned), 250);
 
@@ -1018,7 +961,7 @@ gantt_view_update_row_height (PlannerGanttView *view)
        for (l = cols; l; l = l->next) {
                col = l->data;
 
-               gtk_widget_size_request (col->button, &req);
+               gtk_widget_size_request (gtk_tree_view_column_get_button (col), &req);
                header_height = MAX (header_height, req.height);
 
                gtk_tree_view_column_cell_get_size (col,
@@ -1049,16 +992,16 @@ gantt_view_update_row_height (PlannerGanttView *view)
 }
 
 static gboolean
-gantt_view_expose_cb (GtkWidget      *widget,
-                     GdkEventExpose *event,
-                     gpointer        data)
+gantt_view_draw_cb (GtkWidget *widget,
+                    cairo_t   *cr,
+                    gpointer   data)
 {
        PlannerGanttView     *view = PLANNER_GANTT_VIEW (data);
 
        gantt_view_update_row_height (view);
 
        g_signal_handler_disconnect (view->priv->tree,
-                                    view->priv->expose_id);
+                                    view->priv->draw_signal_id);
 
        return FALSE;
 }
diff --git a/src/planner-relation-arrow.c b/src/planner-relation-arrow.c
index 1c93ba28..57a98ee0 100644
--- a/src/planner-relation-arrow.c
+++ b/src/planner-relation-arrow.c
@@ -127,21 +127,19 @@ static void    relation_arrow_set_property (GObject               *object,
                                            const GValue          *value,
                                            GParamSpec            *pspec);
 static void    relation_arrow_update       (GnomeCanvasItem       *item,
-                                           gdouble               *affine,
-                                           ArtSVP                *clip_path,
+                                           const cairo_matrix_t  *i2c,
                                            gint                   flags);
 static void    relation_arrow_draw         (GnomeCanvasItem       *item,
-                                           GdkDrawable           *drawable,
+                                           cairo_t               *cr,
                                            gint                   x,
                                            gint                   y,
                                            gint                   width,
                                            gint                   height);
-static gdouble relation_arrow_point        (GnomeCanvasItem       *item,
-                                           gdouble                x,
-                                           gdouble                y,
-                                           gint                   cx,
-                                           gint                   cy,
-                                           GnomeCanvasItem      **actual_item);
+static GnomeCanvasItem * relation_arrow_point (GnomeCanvasItem  *item,
+                                               gdouble           x,
+                                               gdouble           y,
+                                               gint              cx,
+                                               gint              cy);
 
 /* Properties */
 enum {
@@ -636,10 +634,9 @@ relation_arrow_get_bounds (PlannerRelationArrow *arrow,
 }
 
 static void
-relation_arrow_update (GnomeCanvasItem *item,
-                      double          *affine,
-                      ArtSVP          *clip_path,
-                      gint             flags)
+relation_arrow_update (GnomeCanvasItem      *item,
+                       const cairo_matrix_t *i2c,
+                       gint                  flags)
 {
        PlannerRelationArrow *arrow;
        gdouble               x1, y1, x2, y2;
@@ -647,8 +644,7 @@ relation_arrow_update (GnomeCanvasItem *item,
        arrow = PLANNER_RELATION_ARROW (item);
 
        GNOME_CANVAS_ITEM_CLASS (parent_class)->update (item,
-                                                       affine,
-                                                       clip_path,
+                                                       i2c,
                                                        flags);
 
        relation_arrow_get_bounds (arrow, &x1, &y1, &x2, &y2);
@@ -695,7 +691,7 @@ relation_arrow_setup_arrow (PlannerArrowDir dir,
 
 static void
 relation_arrow_draw (GnomeCanvasItem *item,
-                    GdkDrawable     *drawable,
+                    cairo_t         *cr,
                     gint             x,
                     gint             y,
                     gint             width,
@@ -707,13 +703,12 @@ relation_arrow_draw (GnomeCanvasItem *item,
        gdouble                   i2w_dy;
        gdouble                   dx1, dy1, dx2, dy2;
        gint                      cx1, cy1, cx2, cy2;
-       cairo_t                  *cr;
        gint                      i;
 
        arrow = PLANNER_RELATION_ARROW (item);
        priv = arrow->priv;
 
-       cr = gdk_cairo_create (drawable);
+       cairo_save (cr);
        cairo_set_line_width (cr, 1.0);
        cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
        cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
@@ -761,19 +756,18 @@ relation_arrow_draw (GnomeCanvasItem *item,
                                    cx2 + 0.5, cy2 + 0.5);
        cairo_fill (cr);
 
-       cairo_destroy (cr);
+       cairo_restore (cr);
 }
 
-static double
+static GnomeCanvasItem *
 relation_arrow_point (GnomeCanvasItem  *item,
                      gdouble           x,
                      gdouble           y,
                      gint              cx,
-                     gint              cy,
-                     GnomeCanvasItem **actual_item)
+                     gint              cy)
 {
-       *actual_item = item;
-
-       return 10.0;
+       /* TODO: Test over the behaviour from gnomecanvas gtk3 port;
+        * it was reporting distance of 10.0 before */
+       return NULL;
 }
 
diff --git a/src/planner-resource-view.c b/src/planner-resource-view.c
index 5d21580e..9514cf6a 100644
--- a/src/planner-resource-view.c
+++ b/src/planner-resource-view.c
@@ -467,8 +467,7 @@ resource_view_get_widget (PlannerView *view)
        PlannerResourceViewPriv *priv;
        GtkWidget               *resource_table;
        GtkWidget               *sw;
-       GtkWidget               *frame;
-       GtkTreeModel            *model;
+       GtkTreeModel            *model;
        MrpProject              *project;
        GtkTreeSelection        *selection;
 
@@ -532,18 +531,15 @@ resource_view_get_widget (PlannerView *view)
                          G_CALLBACK (resource_view_selection_changed_cb),
                          view);
 
-       frame = gtk_frame_new (NULL);
-       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
-
        sw = gtk_scrolled_window_new (NULL, NULL);
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
                                        GTK_POLICY_AUTOMATIC,
                                        GTK_POLICY_AUTOMATIC);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
 
        gtk_container_add (GTK_CONTAINER (sw), resource_table);
-       gtk_container_add (GTK_CONTAINER (frame), sw);
 
-       return frame;
+       return sw;
 }
 
 static void
diff --git a/src/planner-task-view.c b/src/planner-task-view.c
index d2ac262a..d7348276 100644
--- a/src/planner-task-view.c
+++ b/src/planner-task-view.c
@@ -41,7 +41,7 @@
 
 struct _PlannerTaskViewPriv {
        GtkWidget              *tree;
-       GtkWidget              *frame;
+       GtkWidget              *sw;
        PlannerTablePrintSheet *print_sheet;
        GtkUIManager           *ui_manager;
        GtkActionGroup         *actions;
@@ -330,7 +330,6 @@ task_view_get_widget (PlannerView *view)
 {
        PlannerTaskViewPriv *priv;
        MrpProject          *project;
-       GtkWidget           *sw;
        PlannerGanttModel   *model;
 
        priv = PLANNER_TASK_VIEW (view)->priv;
@@ -343,16 +342,12 @@ task_view_get_widget (PlannerView *view)
                                  G_CALLBACK (task_view_project_loaded_cb),
                                  view);
 
-               sw = gtk_scrolled_window_new (NULL, NULL);
-               gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+               priv->sw = gtk_scrolled_window_new (NULL, NULL);
+               gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->sw),
                                                GTK_POLICY_AUTOMATIC,
                                                GTK_POLICY_AUTOMATIC);
-
-               priv->frame = gtk_frame_new (NULL);
-               gtk_frame_set_shadow_type (GTK_FRAME (priv->frame), GTK_SHADOW_IN);
-
-               gtk_container_add (GTK_CONTAINER (priv->frame), sw);
-
+               gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->sw),
+                                                    GTK_SHADOW_IN);
                model = planner_gantt_model_new (project);
 
                priv->tree = planner_task_tree_new (view->main_window,
@@ -384,7 +379,7 @@ task_view_get_widget (PlannerView *view)
 
                task_view_load_columns (view);
 
-               gtk_container_add (GTK_CONTAINER (sw), priv->tree);
+               gtk_container_add (GTK_CONTAINER (priv->sw), priv->tree);
 
                g_signal_connect (priv->tree,
                                  "columns-changed",
@@ -412,11 +407,10 @@ task_view_get_widget (PlannerView *view)
                                  view);
 
                gtk_widget_show (priv->tree);
-               gtk_widget_show (sw);
-               gtk_widget_show (priv->frame);
+               gtk_widget_show (priv->sw);
        }
 
-       return priv->frame;
+       return priv->sw;
 }
 
 static void
diff --git a/src/planner-usage-chart.c b/src/planner-usage-chart.c
index e9a5e03e..dacfc6b6 100644
--- a/src/planner-usage-chart.c
+++ b/src/planner-usage-chart.c
@@ -78,6 +78,8 @@ struct _PlannerUsageChartPriv {
 
        GtkAdjustment   *hadjustment;
        GtkAdjustment   *vadjustment;
+       guint            hscroll_policy : 1;
+       guint            vscroll_policy : 1;
 
        GtkTreeModel    *model;
        TreeNode        *tree;
@@ -100,7 +102,12 @@ enum {
        PROP_0,
        PROP_HEADER_HEIGHT,
        PROP_ROW_HEIGHT,
-       PROP_MODEL
+       PROP_MODEL,
+       /* Scrollable interface */
+       PROP_HADJUSTMENT,
+       PROP_VADJUSTMENT,
+       PROP_HSCROLL_POLICY,
+       PROP_VSCROLL_POLICY
 };
 
 enum {
@@ -122,7 +129,7 @@ static void      usage_chart_get_property          (GObject                 *obj
                                                     GParamSpec              *spec);
 static void      usage_chart_set_zoom              (PlannerUsageChart      *chart,
                                                     gdouble                  level);
-static void      usage_chart_destroy               (GtkObject               *object);
+static void      usage_chart_destroy               (GtkWidget               *widget);
 static void      usage_chart_style_set             (GtkWidget               *widget,
                                                     GtkStyle                *prev_style);
 static void      usage_chart_realize               (GtkWidget               *widget);
@@ -130,9 +137,10 @@ static void      usage_chart_map                   (GtkWidget               *wid
 static void      usage_chart_unrealize             (GtkWidget               *widget);
 static void      usage_chart_size_allocate         (GtkWidget               *widget,
                                                     GtkAllocation           *allocation);
-static void      usage_chart_set_adjustments       (PlannerUsageChart      *chart,
-                                                    GtkAdjustment           *hadj,
-                                                    GtkAdjustment           *vadj);
+static void      usage_chart_set_hadjustment       (PlannerUsageChart       *chart,
+                                                   GtkAdjustment           *hadj);
+static void      usage_chart_set_vadjustment       (PlannerUsageChart       *chart,
+                                                   GtkAdjustment           *vadj);
 static void      usage_chart_reflow_now            (PlannerUsageChart      *chart);
 static void      usage_chart_reflow                (PlannerUsageChart      *chart,
                                                     gboolean                 height_changed);
@@ -218,9 +226,18 @@ planner_usage_chart_get_type (void)
                        0,      /* n_preallocs */
                        (GInstanceInitFunc) usage_chart_init
                };
+
+               static const GInterfaceInfo scrollable_info = {
+                       (GInterfaceInitFunc) NULL,
+                       NULL,
+                       NULL
+               };
+
                type = g_type_register_static (GTK_TYPE_VBOX,
                                               "PlannerUsageChart", &info,
                                               0);
+
+               g_type_add_interface_static (type, GTK_TYPE_SCROLLABLE, &scrollable_info);
        }
        return type;
 }
@@ -229,39 +246,24 @@ static void
 usage_chart_class_init (PlannerUsageChartClass * class)
 {
        GObjectClass      *o_class;
-       GtkObjectClass    *object_class;
        GtkWidgetClass    *widget_class;
 
        parent_class = g_type_class_peek_parent (class);
 
        o_class = (GObjectClass *) class;
-       object_class = (GtkObjectClass *) class;
        widget_class = (GtkWidgetClass *) class;
 
        o_class->set_property = usage_chart_set_property;
        o_class->get_property = usage_chart_get_property;
        o_class->finalize = usage_chart_finalize;
 
-       object_class->destroy = usage_chart_destroy;
-
+       widget_class->destroy = usage_chart_destroy;
        widget_class->style_set = usage_chart_style_set;
        widget_class->realize = usage_chart_realize;
        widget_class->map = usage_chart_map;
        widget_class->unrealize = usage_chart_unrealize;
        widget_class->size_allocate = usage_chart_size_allocate;
 
-       class->set_scroll_adjustments = usage_chart_set_adjustments;
-
-       widget_class->set_scroll_adjustments_signal =
-               g_signal_new ("set_scroll_adjustments",
-                             G_TYPE_FROM_CLASS (object_class),
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (PlannerUsageChartClass,
-                                              set_scroll_adjustments), NULL,
-                             NULL, planner_marshal_VOID__OBJECT_OBJECT,
-                             G_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT,
-                             GTK_TYPE_ADJUSTMENT);
-
        signals[STATUS_UPDATED] =
                g_signal_new ("status_updated",
                              G_TYPE_FROM_CLASS (class),
@@ -269,8 +271,14 @@ usage_chart_class_init (PlannerUsageChartClass * class)
                              0, NULL, NULL,
                              planner_marshal_VOID__POINTER,
                              G_TYPE_NONE, 1, G_TYPE_POINTER);
-       /* Properties. */
 
+       /* GtkScrollable interface properties */
+       g_object_class_override_property (o_class, PROP_HADJUSTMENT,    "hadjustment");
+       g_object_class_override_property (o_class, PROP_VADJUSTMENT,    "vadjustment");
+       g_object_class_override_property (o_class, PROP_HSCROLL_POLICY, "hscroll-policy");
+       g_object_class_override_property (o_class, PROP_VSCROLL_POLICY, "vscroll-policy");
+
+       /* Properties. */
        g_object_class_install_property (o_class,
                                         PROP_MODEL,
                                         g_param_spec_object ("model",
@@ -339,8 +347,10 @@ usage_chart_init (PlannerUsageChart * chart)
                            0);
 
        priv->canvas = GNOME_CANVAS (gnome_canvas_new ());
+       /* TODO: Consider porting these over to gtk3
        priv->canvas->close_enough = 5;
        gnome_canvas_set_center_scroll_region (priv->canvas, FALSE);
+        */
 
        /* Easiest way to get access to the chart from the canvas items. */
        g_object_set_data (G_OBJECT (priv->canvas), "chart", chart);
@@ -356,6 +366,14 @@ usage_chart_init (PlannerUsageChart * chart)
                                       PLANNER_TYPE_GANTT_BACKGROUND, "scale",
                                       SCALE (priv->zoom), "zoom", priv->zoom,
                                       NULL);
+
+       g_object_bind_property (chart, "hadjustment",
+                               priv->header, "hadjustment",
+                               G_BINDING_DEFAULT);
+       g_object_bind_property (chart, "hadjustment",
+                               priv->canvas, "hadjustment",
+                               G_BINDING_DEFAULT);
+
 }
 
 static TreeNode *
@@ -389,6 +407,20 @@ usage_chart_set_property (GObject * object,
                chart->priv->row_height = g_value_get_int (value);
                usage_chart_reflow (chart, TRUE);
                break;
+       case PROP_HADJUSTMENT:
+               usage_chart_set_hadjustment (chart, g_value_get_object (value));
+               break;
+       case PROP_VADJUSTMENT:
+               usage_chart_set_vadjustment (chart, g_value_get_object (value));
+               break;
+       case PROP_HSCROLL_POLICY:
+               chart->priv->hscroll_policy = g_value_get_enum (value);
+               gtk_widget_queue_resize (GTK_WIDGET (chart));
+               break;
+       case PROP_VSCROLL_POLICY:
+               chart->priv->hscroll_policy = g_value_get_enum (value);
+               gtk_widget_queue_resize (GTK_WIDGET (chart));
+               break;
        default:
                break;
        }
@@ -406,6 +438,18 @@ usage_chart_get_property (GObject * object,
        case PROP_MODEL:
                g_value_set_object (value, G_OBJECT (chart->priv->model));
                break;
+       case PROP_HADJUSTMENT:
+               g_value_set_object (value, chart->priv->hadjustment);
+               break;
+       case PROP_VADJUSTMENT:
+               g_value_set_object (value, chart->priv->vadjustment);
+               break;
+       case PROP_HSCROLL_POLICY:
+               g_value_set_enum (value, chart->priv->hscroll_policy);
+               break;
+       case PROP_VSCROLL_POLICY:
+               g_value_set_enum (value, chart->priv->vscroll_policy);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
                break;
@@ -590,11 +634,11 @@ usage_chart_finalize (GObject *object)
 }
 
 static void
-usage_chart_destroy (GtkObject *object)
+usage_chart_destroy (GtkWidget *widget)
 {
        PlannerUsageChart *chart;
 
-       chart = PLANNER_USAGE_CHART (object);
+       chart = PLANNER_USAGE_CHART (widget);
 
        if (chart->priv->model != NULL) {
                usage_chart_disconnect_signals (chart);
@@ -602,8 +646,8 @@ usage_chart_destroy (GtkObject *object)
                chart->priv->model = NULL;
        }
 
-       if (GTK_OBJECT_CLASS (parent_class)->destroy) {
-               (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+       if (GTK_WIDGET_CLASS (parent_class)->destroy) {
+               (*GTK_WIDGET_CLASS (parent_class)->destroy) (widget);
        }
 }
 
@@ -641,7 +685,6 @@ usage_chart_realize (GtkWidget *widget)
        PlannerUsageChartPriv *priv;
        GtkWidget              *canvas;
        GtkStyle               *style;
-       GdkColormap            *colormap;
 
        chart = PLANNER_USAGE_CHART (widget);
        priv = chart->priv;
@@ -654,9 +697,7 @@ usage_chart_realize (GtkWidget *widget)
 
        /* Set the background to white. */
        style = gtk_style_copy (gtk_widget_get_style (canvas));
-       colormap = gtk_widget_get_colormap (canvas);
        gdk_color_parse ("white", &style->bg[GTK_STATE_NORMAL]);
-       gdk_colormap_alloc_color (colormap, &style->bg[GTK_STATE_NORMAL], FALSE, TRUE);
        gtk_widget_set_style (canvas, style);
        g_object_unref (style);
 
@@ -706,48 +747,63 @@ usage_chart_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
 }
 
 static void
-usage_chart_set_adjustments (PlannerUsageChart *chart,
-                             GtkAdjustment      *hadj,
-                             GtkAdjustment      *vadj)
+usage_chart_set_hadjustment (PlannerUsageChart *chart,
+                             GtkAdjustment     *hadj)
 {
-       PlannerUsageChartPriv *priv;
-
-       gboolean need_adjust = FALSE;
+       if (hadj && chart->priv->hadjustment == hadj)
+               return;
 
-       g_return_if_fail (hadj == NULL || GTK_IS_ADJUSTMENT (hadj));
-       g_return_if_fail (vadj == NULL || GTK_IS_ADJUSTMENT (vadj));
+       if (hadj)
+               g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
+       else
+               hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
 
-       priv = chart->priv;
+       if (chart->priv->hadjustment != NULL) {
+               g_signal_handlers_disconnect_matched (chart->priv->hadjustment,
+                                                     G_SIGNAL_MATCH_DATA,
+                                                     0, 0, NULL, NULL,
+                                                     chart);
+               g_object_unref (chart->priv->hadjustment);
+       }
 
        if (hadj == NULL) {
                hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
        }
-       if (vadj == NULL) {
+
+       /* TODO: value-changed handler? If not adding, disconnecting above is probably unnecessary too */
+       chart->priv->hadjustment = g_object_ref_sink (hadj);
+       /* TODO: Do we need to set the initial hadj values? */
+       /* TODO: Share the hadjustment with header and canvas? */
+
+       g_object_notify (G_OBJECT (chart), "hadjustment");
+}
+
+static void
+usage_chart_set_vadjustment (PlannerUsageChart *chart,
+                             GtkAdjustment     *vadj)
+{
+       if (vadj && chart->priv->vadjustment == vadj)
+               return;
+
+       if (vadj)
+               g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
+       else
                vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
-       }
-       if (priv->hadjustment && (priv->hadjustment != hadj)) {
-               g_object_unref (priv->hadjustment);
-       }
-       if (priv->vadjustment && (priv->vadjustment != hadj)) {
-               g_object_unref (priv->vadjustment);
-       }
 
-       if (priv->hadjustment != hadj) {
-               priv->hadjustment = hadj;
-               g_object_ref_sink (priv->hadjustment);
-               gtk_widget_set_scroll_adjustments (priv->header, hadj, NULL);
-               need_adjust = TRUE;
-       }
-       if (priv->vadjustment != vadj) {
-               priv->vadjustment = vadj;
-               g_object_ref_sink (priv->vadjustment);
-               need_adjust = TRUE;
+       if (chart->priv->vadjustment != NULL) {
+               g_signal_handlers_disconnect_matched (chart->priv->vadjustment,
+                                                     G_SIGNAL_MATCH_DATA,
+                                                     0, 0, NULL, NULL,
+                                                     chart);
+               g_object_unref (chart->priv->vadjustment);
        }
 
-       if (need_adjust) {
-               gtk_widget_set_scroll_adjustments (GTK_WIDGET (priv->canvas),
-                                                  hadj, vadj);
-       }
+       /* TODO: value-changed handler? If not adding, disconnecting above is probably unnecessary too */
+       chart->priv->vadjustment = g_object_ref_sink (vadj);
+       /* TODO: Do we need to set the initial vadj values? */
+       /* TODO: Share the vadjustment with canvas? */
+
+       g_object_notify (G_OBJECT (chart), "vadjustment");
 }
 
 static gboolean
@@ -1515,7 +1571,7 @@ usage_chart_remove_children (PlannerUsageChart *chart, TreeNode *node)
                usage_chart_remove_children (chart, node->children[i]);
        }
 
-       gtk_object_destroy (GTK_OBJECT (node->item));
+       g_object_run_dispose (G_OBJECT (node->item));
        node->item = NULL;
 
        node->assignment = NULL;
diff --git a/src/planner-usage-row.c b/src/planner-usage-row.c
index d8146ed6..648e6b7b 100644
--- a/src/planner-usage-row.c
+++ b/src/planner-usage-row.c
@@ -112,7 +112,7 @@ struct _PlannerUsageRowPriv {
 
 static void     usage_row_class_init                   (PlannerUsageRowClass  *class);
 static void     usage_row_init                         (PlannerUsageRow       *row);
-static void     usage_row_destroy                      (GtkObject              *object);
+static void     usage_row_dispose                      (GObject               *object);
 static void     usage_row_set_property                 (GObject                *object,
                                                         guint                   param_id,
                                                         const GValue           *value,
@@ -122,21 +122,19 @@ static void     usage_row_get_property                 (GObject                *
                                                         GValue                 *value,
                                                         GParamSpec             *pspec);
 static void     usage_row_update                       (GnomeCanvasItem        *item,
-                                                        double                 *affine,
-                                                        ArtSVP                 *clip_path,
-                                                        int                     flags);
+                                                       const cairo_matrix_t  *i2c,
+                                                       int                     flags);
 static void     usage_row_draw                         (GnomeCanvasItem        *item,
-                                                        GdkDrawable            *drawable,
+                                                        cairo_t               *cr,
                                                         gint                    x,
                                                         gint                    y,
                                                         gint                    width,
                                                         gint                    height);
-static double   usage_row_point                        (GnomeCanvasItem        *item,
+static GnomeCanvasItem * usage_row_point               (GnomeCanvasItem        *item,
                                                         double                  x,
                                                         double                  y,
                                                         gint                    cx,
-                                                        gint                    cy,
-                                                        GnomeCanvasItem       **actual_item);
+                                                        gint                    cy);
 static void     usage_row_bounds                       (GnomeCanvasItem        *item,
                                                         double                 *x1,
                                                         double                 *y1,
@@ -193,11 +191,9 @@ static void
 usage_row_class_init (PlannerUsageRowClass * class)
 {
         GObjectClass         *gobject_class;
-        GtkObjectClass       *object_class;
         GnomeCanvasItemClass *item_class;
 
         gobject_class = (GObjectClass *) class;
-        object_class = (GtkObjectClass *) class;
         item_class = (GnomeCanvasItemClass *) class;
 
         parent_class = g_type_class_peek_parent (class);
@@ -277,7 +273,7 @@ usage_row_class_init (PlannerUsageRowClass * class)
                  g_param_spec_boolean ("highlight", NULL, NULL,
                                        FALSE, G_PARAM_READWRITE));
 
-        object_class->destroy = usage_row_destroy;
+        gobject_class->dispose = usage_row_dispose;
 
         item_class->update = usage_row_update;
         item_class->draw = usage_row_draw;
@@ -307,7 +303,7 @@ usage_row_init (PlannerUsageRow * row)
 }
 
 static void
-usage_row_destroy (GtkObject * object)
+usage_row_dispose (GObject *object)
 {
         PlannerUsageRow     *row;
         PlannerUsageRowPriv *priv;
@@ -327,8 +323,8 @@ usage_row_destroy (GtkObject * object)
                 row->priv = NULL;
         }
 
-        if (GTK_OBJECT_CLASS (parent_class)->destroy) {
-                (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+        if (G_OBJECT_CLASS (parent_class)->dispose) {
+                G_OBJECT_CLASS (parent_class)->dispose (object);
         }
 }
 
@@ -681,10 +677,9 @@ usage_row_update_resources (PlannerUsageRow *row)
 }
 
 static void
-usage_row_update (GnomeCanvasItem *item,
-                   double          *affine,
-                  ArtSVP          *clip_path,
-                  gint             flags)
+usage_row_update (GnomeCanvasItem      *item,
+                  const cairo_matrix_t *i2c,
+                  gint                  flags)
 {
         PlannerUsageRow *row;
         double            x1, y1, x2, y2;
@@ -692,8 +687,8 @@ usage_row_update (GnomeCanvasItem *item,
         row = PLANNER_USAGE_ROW (item);
 
         GNOME_CANVAS_ITEM_CLASS (parent_class)->update (item,
-                                                        affine,
-                                                        clip_path, flags);
+                                                        i2c,
+                                                        flags);
 
         usage_row_ensure_layout (row);
         usage_row_get_bounds (row, &x1, &y1, &x2, &y2);
@@ -782,7 +777,7 @@ usage_row_draw_resource_ival (mrptime          start,
                                mrptime          end,
                                gint             units,
                                RowChunk         chunk,
-                               GdkDrawable     *drawable,
+                               cairo_t         *cr,
                                GnomeCanvasItem *item,
                                gint             x,
                               gint             y,
@@ -791,7 +786,6 @@ usage_row_draw_resource_ival (mrptime          start,
 {
         PlannerUsageRow     *row;
         PlannerUsageRowPriv *priv;
-        cairo_t             *cr;
 
         /* World coord */
         gdouble               xoffset, yoffset;
@@ -876,7 +870,7 @@ usage_row_draw_resource_ival (mrptime          start,
                 return;
         }
 
-        cr = gdk_cairo_create (drawable);
+        cairo_save (cr);
         cairo_set_line_width (cr, 1.0);
         cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
 
@@ -988,17 +982,17 @@ usage_row_draw_resource_ival (mrptime          start,
        }
 
         cairo_stroke (cr);
-        cairo_destroy (cr);
+        cairo_restore (cr);
 }
 
 static void
 usage_row_draw_resource (PlannerUsageRow *row,
-                          GdkDrawable      *drawable,
-                          GnomeCanvasItem  *item,
-                          gint              x,
-                         gint              y,
-                         gint              width,
-                         gint              height)
+                         cairo_t         *cr,
+                         GnomeCanvasItem *item,
+                         gint             x,
+                         gint             y,
+                         gint             width,
+                         gint             height)
 {
         GList         *dates;
         MrpResource   *resource;
@@ -1066,7 +1060,7 @@ usage_row_draw_resource (PlannerUsageRow *row,
                                                        date->time,
                                                        units,
                                                        chunk,
-                                                       drawable, item,
+                                                       cr, item,
                                                        x, y, width, height);
 
                         chunk &= ~ROW_START;
@@ -1088,7 +1082,7 @@ usage_row_draw_resource (PlannerUsageRow *row,
                                                finish,
                                                units,
                                                chunk,
-                                               drawable, item,
+                                               cr, item,
                                                x, y, width, height);
         }
 }
@@ -1097,14 +1091,13 @@ static void
 usage_row_draw_assignment (PlannerUsageRow *row,
                             MrpAssignment    *assign,
                             GnomeCanvasItem  *item,
-                            GdkDrawable      *drawable,
+                            cairo_t          *cr,
                             gint              x,
                            gint              y,
                            gint              width,
                            gint              height)
 {
         PlannerUsageRowPriv  *priv;
-        cairo_t              *cr;
         MrpTask              *task;
         gdouble               i2w_dx;
         gdouble               i2w_dy;
@@ -1146,7 +1139,7 @@ usage_row_draw_assignment (PlannerUsageRow *row,
                 return;
         }
 
-        cr = gdk_cairo_create (drawable);
+        cairo_save (cr);
         cairo_set_line_width (cr, 1.0);
         cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
 
@@ -1246,12 +1239,12 @@ usage_row_draw_assignment (PlannerUsageRow *row,
                pango_cairo_show_layout (cr, priv->layout);
        }
 
-        cairo_destroy (cr);
+        cairo_restore (cr);
 }
 
 static void
 usage_row_draw (GnomeCanvasItem *item,
-                 GdkDrawable     *drawable,
+                 cairo_t        *cr,
                  gint             x,
                 gint             y,
                 gint             width,
@@ -1265,32 +1258,28 @@ usage_row_draw (GnomeCanvasItem *item,
                 usage_row_draw_assignment (row,
                                             row->priv->assignment,
                                             item,
-                                            drawable, x, y, width, height);
+                                            cr, x, y, width, height);
         }
        else if (row->priv->resource) {
-                usage_row_draw_resource (row, drawable, item, x, y, width, height);
+                usage_row_draw_resource (row, cr, item, x, y, width, height);
         }
 }
 
-static double
+static GnomeCanvasItem *
 usage_row_point (GnomeCanvasItem  *item,
                   double            x,
                   double            y,
                  gint              cx,
-                 gint              cy,
-                 GnomeCanvasItem **actual_item)
+                 gint              cy)
 {
         PlannerUsageRow     *row;
         PlannerUsageRowPriv *priv;
         gint                  text_width;
         gdouble               x1, y1, x2, y2;
-        gdouble               dx, dy;
 
         row = PLANNER_USAGE_ROW (item);
         priv = row->priv;
 
-        *actual_item = item;
-
         text_width = priv->text_width;
         if (text_width > 0) {
                text_width += TEXT_PADDING;
@@ -1302,29 +1291,11 @@ usage_row_point (GnomeCanvasItem  *item,
         y2 = y1 + priv->height;
 
         if (x > x1 && x < x2 && y > y1 && y < y2) {
-                return 0.0;
+                return item;
         }
 
         /* Point is outside rectangle */
-        if (x < x1) {
-                dx = x1 - x;
-        }
-       else if (x > x2) {
-                dx = x - x2;
-        } else {
-                dx = 0.0;
-        }
-
-        if (y < y1) {
-                dy = y1 - y;
-        }
-       else if (y > y2) {
-                dy = y - y2;
-        } else {
-                dy = 0.0;
-        }
-
-        return sqrt (dx * dx + dy * dy);
+        return NULL;
 }
 
 static void
diff --git a/src/planner-usage-view.c b/src/planner-usage-view.c
index 5a100869..7cf70d26 100644
--- a/src/planner-usage-view.c
+++ b/src/planner-usage-view.c
@@ -43,7 +43,7 @@ struct _PlannerUsageViewPriv {
        GtkUIManager           *ui_manager;
        GtkActionGroup         *actions;
        guint                   merged_id;
-       gulong                  expose_id;
+       gulong                  draw_signal_id;
 };
 
 static void         usage_view_finalize                (GObject           *object);
@@ -61,8 +61,8 @@ static void         usage_view_resource_added_cb       (MrpProject        *proje
                                                        PlannerView       *view);
 static void         usage_view_project_loaded_cb       (MrpProject        *project,
                                                        PlannerView       *view);
-static gboolean     usage_view_expose_cb               (GtkWidget         *widget,
-                                                       GdkEventExpose    *event,
+static gboolean     usage_view_draw_cb                 (GtkWidget         *widget,
+                                                       cairo_t           *cr,
                                                        gpointer           user_data);
 static void         usage_view_tree_style_set_cb       (GtkWidget         *tree,
                                                        GtkStyle          *prev_style,
@@ -381,39 +381,6 @@ usage_view_edit_columns_cb (GtkAction *action,
                                    GTK_TREE_VIEW (priv->tree));
 }
 
-static void
-usage_view_tree_view_size_request_cb (GtkWidget      *widget,
-                                     GtkRequisition *req,
-                                     gpointer        data)
-{
-        req->height = -1;
-}
-
-static gboolean
-usage_view_tree_view_scroll_event_cb (GtkWidget      *widget,
-                                     GdkEventScroll *event,
-                                     gpointer        data)
-{
-        GtkAdjustment *adj;
-        GtkTreeView *tv = GTK_TREE_VIEW (widget);
-        gdouble new_value;
-        if (event->direction != GDK_SCROLL_UP &&
-            event->direction != GDK_SCROLL_DOWN) {
-                return FALSE;
-        }
-        adj = gtk_tree_view_get_vadjustment (tv);
-        if (event->direction == GDK_SCROLL_UP) {
-                new_value = gtk_adjustment_get_value (adj) - gtk_adjustment_get_page_increment (adj) / 2;
-        } else {
-                new_value = gtk_adjustment_get_value (adj) + gtk_adjustment_get_page_increment (adj) / 2;
-        }
-        new_value = CLAMP (new_value,
-                          gtk_adjustment_get_lower (adj),
-                          gtk_adjustment_get_upper (adj) - gtk_adjustment_get_page_size (adj));
-        gtk_adjustment_set_value (adj, new_value);
-        return TRUE;
-}
-
 static void
 usage_view_tree_view_columns_changed_cb (GtkTreeView      *tree_view,
                                         PlannerUsageView *view)
@@ -439,14 +406,11 @@ usage_view_create_widget (PlannerView *view)
         PlannerUsageViewPriv *priv;
         MrpProject           *project;
         GtkWidget            *hpaned;
-        GtkWidget            *left_frame;
-        GtkWidget            *right_frame;
         PlannerUsageModel    *model;
         GtkWidget            *tree;
-        GtkWidget            *vbox;
         GtkWidget            *sw;
         GtkWidget            *chart;
-       GtkAdjustment        *hadj, *vadj;
+       GtkAdjustment        *vadj;
 
         project = planner_window_get_project (view->main_window);
         priv = PLANNER_USAGE_VIEW (view)->priv;
@@ -465,18 +429,16 @@ usage_view_create_widget (PlannerView *view)
         model = planner_usage_model_new (project);
         tree = planner_usage_tree_new (view->main_window, model);
         priv->tree = tree;
-        left_frame = gtk_frame_new (NULL);
-        right_frame = gtk_frame_new (NULL);
-
-        vbox = gtk_vbox_new (FALSE, 3);
-        gtk_box_pack_start (GTK_BOX (vbox), tree, TRUE, TRUE, 0);
-        hadj = gtk_tree_view_get_hadjustment (GTK_TREE_VIEW (tree));
-        gtk_box_pack_start (GTK_BOX (vbox), gtk_hscrollbar_new (hadj), FALSE,
-                            TRUE, 0);
-        gtk_container_add (GTK_CONTAINER (left_frame), vbox);
+        hpaned = gtk_hpaned_new ();
 
-        hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 0, 90, 250, 2000));
-        vadj = gtk_tree_view_get_vadjustment (GTK_TREE_VIEW (tree));
+       sw = gtk_scrolled_window_new (NULL, NULL);
+       /* TODO: Consider changing vertical policy to GTK_POLICY_EXTERNAL once we depend on gtk 3.16 */
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+                                       GTK_POLICY_AUTOMATIC,
+                                       GTK_POLICY_AUTOMATIC);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
+       gtk_container_add (GTK_CONTAINER (sw), tree);
+       gtk_paned_add1 (GTK_PANED (hpaned), sw);
 
         chart = planner_usage_chart_new_with_model (GTK_TREE_MODEL (model));
         priv->chart = PLANNER_USAGE_CHART (chart);
@@ -489,18 +451,14 @@ usage_view_create_widget (PlannerView *view)
        g_signal_connect (priv->chart, "scroll-event",
                     G_CALLBACK (usage_view_chart_scroll_event), view);
 
-        sw = gtk_scrolled_window_new (hadj, vadj);
+       vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sw));
+        sw = gtk_scrolled_window_new (NULL, vadj);
         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
-                                        GTK_POLICY_ALWAYS,
+                                        GTK_POLICY_AUTOMATIC,
                                         GTK_POLICY_AUTOMATIC);
-        gtk_container_add (GTK_CONTAINER (right_frame), sw);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
         gtk_container_add (GTK_CONTAINER (sw), chart);
-
-        hpaned = gtk_hpaned_new ();
-        gtk_frame_set_shadow_type (GTK_FRAME (left_frame), GTK_SHADOW_IN);
-        gtk_frame_set_shadow_type (GTK_FRAME (right_frame), GTK_SHADOW_IN);
-        gtk_paned_add1 (GTK_PANED (hpaned), left_frame);
-        gtk_paned_add2 (GTK_PANED (hpaned), right_frame);
+        gtk_paned_add2 (GTK_PANED (hpaned), sw);
 
        usage_view_load_columns (PLANNER_USAGE_VIEW (view));
 
@@ -530,16 +488,6 @@ usage_view_create_widget (PlannerView *view)
                          "status_updated",
                           G_CALLBACK (usage_view_usage_status_updated),
                           view);
-        g_signal_connect_after (tree,
-                               "size_request",
-                                G_CALLBACK
-                                (usage_view_tree_view_size_request_cb),
-                                NULL);
-        g_signal_connect_after (tree,
-                               "scroll_event",
-                                G_CALLBACK
-                                (usage_view_tree_view_scroll_event_cb),
-                                view);
        g_signal_connect (tree,
                          "style_set",
                          G_CALLBACK (usage_view_tree_style_set_cb),
@@ -589,7 +537,7 @@ usage_view_update_row_and_header_height (PlannerView *view)
        for (l = cols; l; l = l->next) {
                col = l->data;
 
-               gtk_widget_size_request (col->button, &req);
+               gtk_widget_size_request (gtk_tree_view_column_get_button (col), &req);
                header_height = MAX (header_height, req.height);
 
                gtk_tree_view_column_cell_get_size (col,
@@ -621,16 +569,16 @@ usage_view_update_row_and_header_height (PlannerView *view)
 }
 
 static gboolean
-usage_view_expose_cb (GtkWidget      *widget,
-                     GdkEventExpose *event,
-                     gpointer        data)
+usage_view_draw_cb (GtkWidget *widget,
+                    cairo_t   *cr,
+                    gpointer   data)
 {
        PlannerUsageView     *view = PLANNER_USAGE_VIEW (data);
 
        usage_view_update_row_and_header_height (PLANNER_VIEW(view));
 
        g_signal_handler_disconnect (view->priv->tree,
-                                    view->priv->expose_id);
+                                    view->priv->draw_signal_id);
 
        return FALSE;
 }
@@ -663,11 +611,11 @@ usage_view_resource_added_cb (MrpProject  *project,
 
        priv = PLANNER_USAGE_VIEW (view)->priv;
 
-       if (priv->expose_id == 0) {
-               priv->expose_id = g_signal_connect_after (priv->tree,
-                                                         "expose_event",
-                                                         G_CALLBACK (usage_view_expose_cb),
-                                                         view);
+       if (priv->draw_signal_id == 0) {
+               priv->draw_signal_id = g_signal_connect_after (priv->tree,
+                                                              "draw",
+                                                              G_CALLBACK (usage_view_draw_cb),
+                                                              view);
        }
 }
 
@@ -699,10 +647,10 @@ usage_view_project_loaded_cb (MrpProject *project, PlannerView *view)
                                      PLANNER_USAGE_MODEL (model));
         planner_usage_chart_set_model (PLANNER_USAGE_CHART (priv->chart), model);
 
-       priv->expose_id = g_signal_connect_after (priv->tree,
-                                                 "expose_event",
-                                                 G_CALLBACK (usage_view_expose_cb),
-                                                 view);
+       priv->draw_signal_id = g_signal_connect_after (priv->tree,
+                                                      "draw",
+                                                      G_CALLBACK (usage_view_draw_cb),
+                                                      view);
 
        g_object_unref (model);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]