/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 2003-2005 Imendio AB
 * Copyright (C) 2003 Benjamin BAYART <benjamin@sitadelle.com>
 * Copyright (C) 2003 Xavier Ordoquy <xordoquy@wanadoo.fr>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include <config.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <libplanner/mrp-task.h>
#include <libplanner/mrp-resource.h>
#include "libplanner/mrp-paths.h"
#include "planner-usage-view.h"
#include "planner-usage-model.h"
#include "planner-usage-tree.h"
#include "planner-usage-chart.h"
#include "planner-column-dialog.h"

struct _PlannerUsageViewPriv {
        GtkWidget              *paned;
        GtkWidget              *tree;
        MrpProject             *project;

        PlannerUsageChart     *chart;
        /*PlannerUsagePrintData *print_data;*/

	GtkUIManager           *ui_manager;
	GtkActionGroup         *actions;
	guint                   merged_id;
	gulong                  draw_signal_id;
};

static void         usage_view_finalize                (GObject           *object);
static void         usage_view_zoom_out_cb             (GtkAction         *action,
							gpointer           data);
static void         usage_view_zoom_in_cb              (GtkAction         *action,
							gpointer           data);
static void         usage_view_zoom_to_fit_cb          (GtkAction         *action,
							gpointer           data);
static void         usage_view_edit_columns_cb         (GtkAction         *action,
							gpointer           data);
static GtkWidget *  usage_view_create_widget           (PlannerView       *view);
static void         usage_view_resource_added_cb       (MrpProject        *project,
							MrpResource       *resource,
							PlannerView       *view);
static void         usage_view_project_loaded_cb       (MrpProject        *project,
							PlannerView       *view);
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,
							PlannerView       *view);
static void         usage_view_row_expanded            (GtkTreeView       *tree_view,
							GtkTreeIter       *iter,
							GtkTreePath       *path,
							gpointer           data);
static void         usage_view_row_collapsed           (GtkTreeView       *tree_view,
							GtkTreeIter       *iter,
							GtkTreePath       *path,
							gpointer           data);
static void         usage_view_expand_all              (PlannerUsageTree  *tree,
							PlannerUsageChart *chart);
static void         usage_view_collapse_all            (PlannerUsageTree  *tree,
							PlannerUsageChart *chart);
static void         usage_view_usage_status_updated    (PlannerUsageChart *chart,
							const gchar       *message,
							PlannerView       *view);
static void         usage_view_update_zoom_sensitivity (PlannerView       *view);
static void         usage_view_activate                (PlannerView       *view);
static void         usage_view_deactivate              (PlannerView       *view);
static void         usage_view_setup                   (PlannerView       *view,
							PlannerWindow     *window);
static const gchar *usage_view_get_label               (PlannerView       *view);
static const gchar *usage_view_get_menu_label          (PlannerView       *view);
static const gchar *usage_view_get_icon                (PlannerView       *view);
static const gchar *usage_view_get_name                (PlannerView       *view);
static GtkWidget *  usage_view_get_widget              (PlannerView       *view);
static void         usage_view_print_init              (PlannerView       *view,
							PlannerPrintJob   *job);
static void         usage_view_print                   (PlannerView       *view,
							gint               page_nr);
static gint         usage_view_print_get_n_pages       (PlannerView       *view);
static void         usage_view_print_cleanup           (PlannerView       *view);
static void         usage_view_save_columns            (PlannerUsageView  *view);
static void         usage_view_load_columns            (PlannerUsageView  *view);


static PlannerViewClass *parent_class = NULL;

static const GtkActionEntry entries[] = {
        { "ZoomOut",   GTK_STOCK_ZOOM_OUT, N_("Zoom out"),
	  NULL, N_("Zoom out"),
	  G_CALLBACK (usage_view_zoom_out_cb) },
        { "ZoomIn",    GTK_STOCK_ZOOM_IN,  N_("Zoom in"),
	  NULL, N_("Zoom in"),
	  G_CALLBACK (usage_view_zoom_in_cb) },
        { "ZoomToFit", GTK_STOCK_ZOOM_FIT, N_("Zoom to fit"),
	  NULL, N_("Zoom to fit the entire project"),
	  G_CALLBACK (usage_view_zoom_to_fit_cb) },
	{ "EditColumns", NULL, N_("Edit _Visible Columns"),
	  NULL, N_("Edit visible columns"),
	  G_CALLBACK (usage_view_edit_columns_cb) }
};

G_DEFINE_TYPE (PlannerUsageView, planner_usage_view, PLANNER_TYPE_VIEW);

static gboolean
usage_view_chart_scroll_event (GtkWidget * gki, GdkEventScroll * event, PlannerView *view)
{
	gboolean dontpropagate = FALSE;

	gboolean can_in, can_out;
	PlannerUsageViewPriv *priv;
	gdouble delta_y;

	if (event->state & GDK_CONTROL_MASK) {
		priv = PLANNER_USAGE_VIEW (view)->priv;
		planner_usage_chart_can_zoom (priv->chart, &can_in, &can_out);
		/* TODO: Why is the canvas area getting GDK_SCROLL_SMOOTH but header not? */
		switch (event->direction) {
			case GDK_SCROLL_UP: {
				dontpropagate = TRUE;
				if (can_in)
					usage_view_zoom_in_cb  (NULL, view);
				break;
			}
			case GDK_SCROLL_DOWN:
				dontpropagate = TRUE;
				if (can_out)
					usage_view_zoom_out_cb  (NULL, view);
				break;
			case GDK_SCROLL_SMOOTH:
				/* TODO: Test over with different input methods (that give values other than 1 or -1),
				* possibly gather deltas together to handle the smoothness */
				/* TODO: First wheel event seems to carry a delta of zero and thus do nothing */
				gdk_event_get_scroll_deltas ((GdkEvent *)event, NULL, &delta_y);
				if (can_in && delta_y < 0)
					usage_view_zoom_in_cb (NULL, view);
				else if (can_out && delta_y > 0)
					usage_view_zoom_out_cb (NULL, view);
				break;
			default:
				break;
		}
    	}

	return dontpropagate;
}


static void
planner_usage_view_class_init (PlannerUsageViewClass *klass)
{
	GObjectClass     *o_class;
	PlannerViewClass *view_class;

	parent_class = g_type_class_peek_parent (klass);

	o_class = (GObjectClass *) klass;
	view_class = PLANNER_VIEW_CLASS (klass);

	o_class->finalize = usage_view_finalize;

	view_class->setup = usage_view_setup;
	view_class->get_label = usage_view_get_label;
	view_class->get_menu_label = usage_view_get_menu_label;
	view_class->get_icon = usage_view_get_icon;
	view_class->get_name = usage_view_get_name;
	view_class->get_widget = usage_view_get_widget;
	view_class->activate = usage_view_activate;
	view_class->deactivate = usage_view_deactivate;
	view_class->print_init = usage_view_print_init;
	view_class->print_get_n_pages = usage_view_print_get_n_pages;
	view_class->print = usage_view_print;
	view_class->print_cleanup = usage_view_print_cleanup;
}

static void
planner_usage_view_init (PlannerUsageView *view)
{
	view->priv = g_new0 (PlannerUsageViewPriv, 1);
}

static void
usage_view_finalize (GObject *object)
{
	PlannerUsageView *view;

	view = PLANNER_USAGE_VIEW (object);

	if (PLANNER_VIEW (view)->activated) {
		usage_view_deactivate (PLANNER_VIEW (view));
	}

	g_free (view->priv);

	if (G_OBJECT_CLASS (parent_class)->finalize) {
		(*G_OBJECT_CLASS (parent_class)->finalize) (object);
	}
}

static void
usage_view_activate (PlannerView *view)
{
	PlannerUsageViewPriv *priv;
	gchar		     *filename;

	priv = PLANNER_USAGE_VIEW (view)->priv;

	priv->actions = gtk_action_group_new ("TimeTableView");
	gtk_action_group_set_translation_domain (priv->actions, GETTEXT_PACKAGE);

	gtk_action_group_add_actions (priv->actions, entries, G_N_ELEMENTS (entries), view);

	gtk_ui_manager_insert_action_group (priv->ui_manager, priv->actions, 0);
	filename = mrp_paths_get_ui_dir ("time-table-view.ui");
	priv->merged_id = gtk_ui_manager_add_ui_from_file (priv->ui_manager,
							   filename,
							   NULL);
	g_free (filename);
	gtk_ui_manager_ensure_update (priv->ui_manager);

        usage_view_update_zoom_sensitivity (view);

	gtk_widget_grab_focus (priv->tree);
}

static void
usage_view_deactivate (PlannerView *view)
{
	PlannerUsageViewPriv *priv;

	priv = PLANNER_USAGE_VIEW (view)->priv;
	gtk_ui_manager_remove_ui (priv->ui_manager, priv->merged_id);
	gtk_ui_manager_remove_action_group (priv->ui_manager, priv->actions);
	g_object_unref (priv->actions);
	priv->actions = NULL;
}

static void
usage_view_setup (PlannerView *view, PlannerWindow *main_window)
{
	PlannerUsageViewPriv *priv;

	priv = PLANNER_USAGE_VIEW (view)->priv;

	priv->ui_manager = planner_window_get_ui_manager(main_window);
}

static const gchar *
usage_view_get_label (PlannerView *view)
{
	/* i18n: Label used for the sidebar. Please try to make it short and use
	 * a linebreak if necessary/possible.
	 */
        return _("Resource\nUsage");
}

static const gchar *
usage_view_get_menu_label (PlannerView *view)
{
        return _("Resource _Usage");
}

static const gchar *
usage_view_get_icon (PlannerView *view)
{
	static gchar *filename = NULL;

	if (!filename) {
		filename = mrp_paths_get_image_dir ("resources_usage.png");
	}

        return filename;
}

static const gchar *
usage_view_get_name (PlannerView *view)
{
        return "resource_usage_view";
}

static GtkWidget *
usage_view_get_widget (PlannerView *view)
{
        PlannerUsageViewPriv *priv;

        priv = PLANNER_USAGE_VIEW (view)->priv;
        if (priv->paned == NULL) {
                priv->paned = usage_view_create_widget (view);
                gtk_widget_show_all (priv->paned);
        }

        return PLANNER_USAGE_VIEW (view)->priv->paned;
}

static void
usage_view_print_init (PlannerView *view, PlannerPrintJob *job)
{
	/* FIXME: initialize usage view printing
	  PlannerUsageViewPriv *priv;

	  priv = PLANNER_USAGE_VIEW (view)->priv;
	*/

        /*priv->print_data = planner_usage_print_data_new (view, job);*/
}

static void
usage_view_print (PlannerView *view, gint page_nr)
{
        /*planner_usage_print_do (PLANNER_USAGE_VIEW (view)->priv->print_data);*/
}

static gint
usage_view_print_get_n_pages (PlannerView *view)
{
        return 0; /*planner_usage_print_get_n_pages (PLANNER_USAGE_VIEW (view)->priv->print_data);*/
}

static void
usage_view_print_cleanup (PlannerView *view)
{
        /*planner_usage_print_data_free (PLANNER_USAGE_VIEW (view)->priv->print_data);*/
        /*PLANNER_USAGE_VIEW (view)->priv->print_data = NULL;*/
}

static void
usage_view_zoom_out_cb (GtkAction *action,
			gpointer   data)
{
        PlannerView *view;

        view = PLANNER_VIEW (data);

        planner_usage_chart_zoom_out (PLANNER_USAGE_VIEW (view)->priv->chart);
        usage_view_update_zoom_sensitivity (view);
}

static void
usage_view_zoom_in_cb (GtkAction *action,
		       gpointer   data)
{
        PlannerView *view;

        view = PLANNER_VIEW (data);

        planner_usage_chart_zoom_in (PLANNER_USAGE_VIEW (view)->priv->chart);
        usage_view_update_zoom_sensitivity (view);
}

static void
usage_view_zoom_to_fit_cb (GtkAction *action,
			   gpointer   data)
{
        PlannerView *view;

        view = PLANNER_VIEW (data);

        planner_usage_chart_zoom_to_fit (PLANNER_USAGE_VIEW (view)->priv->chart);
        usage_view_update_zoom_sensitivity (view);
}

static void
usage_view_edit_columns_cb (GtkAction *action,
			    gpointer   data)
{
	PlannerUsageView     *view;
	PlannerUsageViewPriv *priv;

	view = PLANNER_USAGE_VIEW (data);
	priv = view->priv;

	planner_column_dialog_show (PLANNER_VIEW (view)->main_window,
				    _("Edit Resource Usage Columns"),
				    GTK_TREE_VIEW (priv->tree));
}

static void
usage_view_tree_view_columns_changed_cb (GtkTreeView      *tree_view,
					 PlannerUsageView *view)
{
	usage_view_save_columns (view);
}

static void
usage_view_tree_view_destroy_cb (GtkTreeView      *tree_view,
				 PlannerUsageView *view)
{
	/* Block, we don't want to save the column configuration when they are
	 * removed by the destruction.
	 */
	g_signal_handlers_block_by_func (tree_view,
					 usage_view_tree_view_columns_changed_cb,
					 view);
}

static GtkWidget *
usage_view_create_widget (PlannerView *view)
{
        PlannerUsageViewPriv *priv;
        MrpProject           *project;
        GtkWidget            *hpaned;
        PlannerUsageModel    *model;
        GtkWidget            *tree;
        GtkWidget            *sw;
        GtkWidget            *chart;
	GtkAdjustment        *vadj;

        project = planner_window_get_project (view->main_window);
        priv = PLANNER_USAGE_VIEW (view)->priv;
        priv->project = project;

        g_signal_connect (project,
                          "loaded",
                          G_CALLBACK (usage_view_project_loaded_cb),
			  view);

	g_signal_connect (project,
			  "resource_added",
			  G_CALLBACK (usage_view_resource_added_cb),
			  view);

        model = planner_usage_model_new (project);
        tree = planner_usage_tree_new (view->main_window, model);
        priv->tree = tree;
        hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);

	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);

	planner_usage_chart_set_view (PLANNER_USAGE_CHART (priv->chart),
				      PLANNER_USAGE_TREE  (priv->tree));

	gtk_widget_set_events (GTK_WIDGET (priv->chart), GDK_SCROLL_MASK);

	g_signal_connect (priv->chart, "scroll-event",
                    G_CALLBACK (usage_view_chart_scroll_event), view);

	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_AUTOMATIC,
                                        GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
        gtk_container_add (GTK_CONTAINER (sw), chart);
        gtk_paned_add2 (GTK_PANED (hpaned), sw);

	usage_view_load_columns (PLANNER_USAGE_VIEW (view));

	g_signal_connect (tree,
			  "columns-changed",
			  G_CALLBACK (usage_view_tree_view_columns_changed_cb),
			  view);

	g_signal_connect (tree,
			  "destroy",
			  G_CALLBACK (usage_view_tree_view_destroy_cb),
			  view);

        g_signal_connect (tree,
			  "row_expanded",
                          G_CALLBACK (usage_view_row_expanded), chart);
        g_signal_connect (tree,
			  "row_collapsed",
                          G_CALLBACK (usage_view_row_collapsed), chart);
        g_signal_connect (tree,
			  "expand_all",
                          G_CALLBACK (usage_view_expand_all), chart);
        g_signal_connect (tree,
			  "collapse_all",
                          G_CALLBACK (usage_view_collapse_all), chart);
        g_signal_connect (chart,
			  "status_updated",
                          G_CALLBACK (usage_view_usage_status_updated),
                          view);
	g_signal_connect (tree,
			  "style_set",
			  G_CALLBACK (usage_view_tree_style_set_cb),
			  view);

        gtk_tree_view_expand_all (GTK_TREE_VIEW (tree));

	planner_usage_chart_expand_all (PLANNER_USAGE_CHART (chart));

	g_object_unref (model);

        return hpaned;
}

static void
usage_view_usage_status_updated (PlannerUsageChart *chart,
				 const gchar        *message,
				 PlannerView        *view)
{
	planner_window_set_status (view->main_window, message);
}

static void
usage_view_update_row_and_header_height (PlannerView *view)
{
	GtkTreeView        *tv;
	PlannerUsageChart  *chart;
	gint                row_height;
	gint                header_height;
	gint                height;
	GList              *cols, *l;
	GtkTreeViewColumn  *col;
	GtkRequisition      req;
	GtkTreePath       *path;
	GdkRectangle       rect;

	tv = GTK_TREE_VIEW (PLANNER_USAGE_VIEW (view)->priv->tree);
	chart = PLANNER_USAGE_VIEW (view)->priv->chart;

	/* Get the row and header heights. */
	cols = gtk_tree_view_get_columns (tv);
	row_height = 0;
	header_height = 0;

	path = gtk_tree_path_new_first ();

	for (l = cols; l; l = l->next) {
		col = l->data;

		gtk_widget_get_preferred_size (gtk_tree_view_column_get_button (col), &req, NULL);
		header_height = MAX (header_height, req.height);

		gtk_tree_view_column_cell_get_size (col,
						    NULL,
						    NULL,
						    NULL,
						    NULL,
						    &height);
		row_height = MAX (row_height, height);

		gtk_tree_view_get_background_area (tv,
						   path,
						   col,
						   &rect);

		row_height = MAX (row_height, rect.height);
	}

	if (path)
		gtk_tree_path_free (path);

	g_list_free (cols);

	/* Sync with the chart widget. */
	g_object_set (chart,
		      "header_height", header_height,
		      "row_height", row_height,
		      NULL);
}

static gboolean
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->draw_signal_id);

	return FALSE;
}

static gboolean
idle_update_heights (PlannerView *view)
{
	usage_view_update_row_and_header_height (view);
	return FALSE;
}

static void
usage_view_tree_style_set_cb (GtkWidget   *tree,
			      GtkStyle    *prev_style,
			      PlannerView *view)
{
	if (prev_style) {
		g_idle_add ((GSourceFunc) idle_update_heights, view);
	} else {
		idle_update_heights (view);
	}
}

static void
usage_view_resource_added_cb (MrpProject  *project,
			      MrpResource *resource,
			      PlannerView *view)
{
	PlannerUsageViewPriv *priv;

	priv = PLANNER_USAGE_VIEW (view)->priv;

	if (priv->draw_signal_id == 0) {
		priv->draw_signal_id = g_signal_connect_after (priv->tree,
							       "draw",
							       G_CALLBACK (usage_view_draw_cb),
							       view);
	}
}

static void
usage_view_project_loaded_cb (MrpProject *project, PlannerView *view)
{
	PlannerUsageViewPriv *priv;
        GtkTreeModel         *model;

	priv = PLANNER_USAGE_VIEW (view)->priv;

	/* FIXME: This is not working so well. Look at how the gantt view
	 * handles this. (The crux is that the root task for example might
	 * change when a project is loaded, so we need to rconnect signals
	 * etc.)
	 */
        if (project == priv->project) {
		/* FIXME: Due to the above, we have this hack. */
		planner_usage_chart_setup_root_task (priv->chart);

                gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->tree));
                planner_usage_chart_expand_all (priv->chart);
                return;
        }

	model = GTK_TREE_MODEL (planner_usage_model_new (project));

	planner_usage_tree_set_model (PLANNER_USAGE_TREE (priv->tree),
				      PLANNER_USAGE_MODEL (model));
        planner_usage_chart_set_model (PLANNER_USAGE_CHART (priv->chart), model);

	priv->draw_signal_id = g_signal_connect_after (priv->tree,
						       "draw",
						       G_CALLBACK (usage_view_draw_cb),
						       view);

	g_object_unref (model);

	gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->tree));
        planner_usage_chart_expand_all (priv->chart);
}

static void
usage_view_row_expanded (GtkTreeView *tree_view,
			 GtkTreeIter *iter,
			 GtkTreePath *path,
			 gpointer     data)
{
        PlannerUsageChart *chart = data;

        planner_usage_chart_expand_row (chart, path);
}

static void
usage_view_row_collapsed (GtkTreeView *tree_view,
			  GtkTreeIter *iter,
			  GtkTreePath *path,
			  gpointer     data)
{
        PlannerUsageChart *chart = data;

	planner_usage_chart_collapse_row (chart, path);
}

static void
usage_view_expand_all (PlannerUsageTree *tree, PlannerUsageChart *chart)
{
        g_signal_handlers_block_by_func (tree,
                                         usage_view_row_expanded, chart);

        planner_usage_tree_expand_all (tree);
        planner_usage_chart_expand_all (chart);

        g_signal_handlers_unblock_by_func (tree,
                                           usage_view_row_expanded, chart);
}

static void
usage_view_collapse_all (PlannerUsageTree  *tree,
			 PlannerUsageChart *chart)
{
        g_signal_handlers_block_by_func (tree,
                                         usage_view_row_collapsed, chart);

        planner_usage_tree_collapse_all (tree);
        planner_usage_chart_collapse_all (chart);

        g_signal_handlers_unblock_by_func (tree,
                                           usage_view_row_collapsed, chart);
}

static void
usage_view_update_zoom_sensitivity (PlannerView *view)
{
	PlannerUsageViewPriv *priv;
        gboolean              in, out;

	priv = PLANNER_USAGE_VIEW (view)->priv;

        planner_usage_chart_can_zoom (priv->chart, &in, &out);

	g_object_set (gtk_action_group_get_action (
			      GTK_ACTION_GROUP (priv->actions),
			      "ZoomIn"),
		      "sensitive", in,
		      NULL);

	g_object_set (gtk_action_group_get_action (
			      GTK_ACTION_GROUP (priv->actions),
			      "ZoomOut"),
		      "sensitive", out,
		      NULL);
}

static void
usage_view_save_columns (PlannerUsageView *view)
{
	PlannerUsageViewPriv *priv;

	priv = view->priv;

	planner_view_column_save_helper (PLANNER_VIEW (view),
					 GTK_TREE_VIEW (priv->tree), "usage");
}

static void
usage_view_load_columns (PlannerUsageView *view)
{
	PlannerUsageViewPriv *priv;

	priv = view->priv;

	/* Load the columns. */
	planner_view_column_load_helper (PLANNER_VIEW (view),
					 GTK_TREE_VIEW (priv->tree), "usage");
}

PlannerView *
planner_usage_view_new (void)
{
	PlannerView *view;

	view = g_object_new (PLANNER_TYPE_USAGE_VIEW, NULL);

	return view;
}


/*
  TODO:
  planner_usage_print_data_new
  planner_usage_print_do
  planner_usage_print_get_n_pages
*/
