/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * glade-clipboard-view.c - The View for the Clipboard.
 *
 * Copyright (C) 2001 The GNOME Foundation.
 *
 * Author(s):
 *      Archit Baweja <bighead@users.sourceforge.net>
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 * USA.
 */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

/**
 * SECTION:glade-clipboard-view
 * @Short_Description: A widget to view and control the #GladeClipboard.
 *
 * The #GladeClipboardView is a widget to view the #GladeWidget objects
 * in the #GladeClipboard; the user can paste or delete objects on the clipboard.
 */

#include <glib/gi18n-lib.h>

#include "glade.h"
#include "glade-clipboard.h"
#include "glade-clipboard-view.h"
#include "glade-widget.h"
#include "glade-widget-adaptor.h"
#include "glade-popup.h"


const gint GLADE_CLIPBOARD_VIEW_WIDTH  = 230;
const gint GLADE_CLIPBOARD_VIEW_HEIGHT = 200;

static void
glade_clipboard_view_class_init (GladeClipboardViewClass *klass)
{

}

static void
glade_clipboard_view_init (GladeClipboardView *view)
{
	view->widget = NULL;
	view->clipboard = NULL;
	view->model = NULL;
}

GType
glade_clipboard_view_get_type ()
{
	static GType type = 0;

	if (!type) {
		static const GTypeInfo info = {
			sizeof (GladeClipboardViewClass),
			(GBaseInitFunc) NULL,
			(GBaseFinalizeFunc) NULL,
			(GClassInitFunc) glade_clipboard_view_class_init,
			(GClassFinalizeFunc) NULL,
			NULL,
			sizeof (GladeClipboardView),
			0,
			(GInstanceInitFunc) glade_clipboard_view_init
		};

		type = g_type_register_static (GTK_TYPE_WINDOW, "GladeClipboardView", &info, 0);
	}

	return type;
}

static void
gcv_foreach_add_selection (GtkTreeModel *model, 
			   GtkTreePath  *path,
			   GtkTreeIter  *iter, 
			   gpointer      data)
{
	GladeWidget        *widget = NULL;
	GladeClipboardView *view   = (GladeClipboardView *)data;
	gtk_tree_model_get (model, iter, 0, &widget, -1);
	glade_clipboard_selection_add (view->clipboard, (widget));
}

static void
glade_clipboard_view_selection_changed_cb (GtkTreeSelection   *sel,
					   GladeClipboardView *view)
{
	if (view->updating == FALSE)
	{
		glade_clipboard_selection_clear (view->clipboard);
		gtk_tree_selection_selected_foreach
			(sel, gcv_foreach_add_selection, view);
	}
}

static void
glade_clipboard_view_populate_model (GladeClipboardView *view)
{
	GladeClipboard   *clipboard;
	GtkTreeModel     *model;
	GladeWidget      *widget;
	GList            *list;
	GtkTreeIter       iter;

	clipboard = GLADE_CLIPBOARD (view->clipboard);
	model     = GTK_TREE_MODEL (view->model);

	for (list = clipboard->widgets; list; list = list->next) 
	{
		widget = list->data;
		view->updating = TRUE;
		gtk_list_store_append (GTK_LIST_STORE (model), &iter);
		gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, widget, -1);
		view->updating = FALSE;
	}
}

static void
glade_clipboard_view_cell_function (GtkTreeViewColumn *tree_column,
				    GtkCellRenderer *cell,
				    GtkTreeModel *tree_model,
				    GtkTreeIter *iter,
				    gpointer data)
{
	gboolean     is_icon = GPOINTER_TO_INT (data);
	GladeWidget *widget;

	gtk_tree_model_get (tree_model, iter, 0, &widget, -1);

	g_return_if_fail (GLADE_IS_WIDGET (widget));
	g_return_if_fail (widget->name != NULL);

	if (is_icon)
		g_object_set (G_OBJECT (cell),
			      "icon-name", widget->adaptor->icon_name,
			      "stock-size", GTK_ICON_SIZE_MENU,
			      NULL);
	else
		g_object_set (G_OBJECT (cell),
			      "text", widget->name,
			      NULL);

}

static gint
glade_clipboard_view_button_press_cb (GtkWidget          *widget,
				      GdkEventButton     *event,
				      GladeClipboardView *view)
{
	GtkTreeView      *tree_view = GTK_TREE_VIEW (widget);
	GtkTreePath      *path      = NULL;
	gboolean          handled   = FALSE;

	if (event->window == gtk_tree_view_get_bin_window (tree_view) &&
	    gtk_tree_view_get_path_at_pos (tree_view,
					   (gint) event->x, (gint) event->y,
					   &path, NULL, 
					   NULL, NULL) && path != NULL)
	{
		GtkTreeIter  iter;
		GladeWidget *widget = NULL;
		if (gtk_tree_model_get_iter (GTK_TREE_MODEL (view->model),
					     &iter, path))
		{
			/* Alright, now we can obtain 
			 * the widget from the iter.
			 */
			gtk_tree_model_get (GTK_TREE_MODEL (view->model), &iter,
					    0, &widget, -1);
			if (widget != NULL &&
				    event->button == 3)
			{
				glade_popup_clipboard_pop (widget, event);
				handled = TRUE;
			}
			gtk_tree_path_free (path);
		}
	}
	return handled;
}

static void
glade_clipboard_view_create_tree_view (GladeClipboardView *view)
{
	GtkTreeSelection  *sel;
	GtkCellRenderer   *renderer;
	GtkTreeViewColumn *column;

	view->widget =
	    gtk_tree_view_new_with_model (GTK_TREE_MODEL (view->model));

	column = gtk_tree_view_column_new ();
	gtk_tree_view_column_set_title (column, _("Widget"));

	renderer = gtk_cell_renderer_pixbuf_new ();
	gtk_tree_view_column_pack_start (column, renderer, FALSE);
	gtk_tree_view_column_set_cell_data_func (column, renderer,
						 glade_clipboard_view_cell_function,
						 GINT_TO_POINTER (1), NULL);

	renderer = gtk_cell_renderer_text_new ();
	g_object_set (G_OBJECT (renderer), 
		      "xpad", 6, NULL);
	gtk_tree_view_column_pack_start (column, renderer, TRUE);
	gtk_tree_view_column_set_cell_data_func (column, renderer,
						 glade_clipboard_view_cell_function,
						 GINT_TO_POINTER (0), NULL);

	gtk_tree_view_append_column (GTK_TREE_VIEW (view->widget), column);

	sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view->widget));
	gtk_tree_selection_set_mode (sel, GTK_SELECTION_MULTIPLE);
	
	g_signal_connect_data (G_OBJECT (sel), "changed",
			       G_CALLBACK (glade_clipboard_view_selection_changed_cb),
			       view, NULL, 0);

	/* Popup menu */
	g_signal_connect (G_OBJECT (view->widget), "button-press-event",
			  G_CALLBACK (glade_clipboard_view_button_press_cb), view);

}

static void
glade_clipboard_view_construct (GladeClipboardView *view)
{
	GtkWidget *scrolled_window, *viewport;

	view->model = gtk_list_store_new (1, G_TYPE_POINTER);

	glade_clipboard_view_populate_model (view);
	glade_clipboard_view_create_tree_view (view);
	glade_clipboard_view_refresh_sel (view);

	viewport = gtk_viewport_new (NULL, NULL);
	gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_OUT);

	scrolled_window = gtk_scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_shadow_type
		(GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
	gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 
					6);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
					GTK_POLICY_AUTOMATIC,
					GTK_POLICY_AUTOMATIC);
	gtk_container_add (GTK_CONTAINER (scrolled_window), view->widget);
	gtk_container_add (GTK_CONTAINER (viewport), scrolled_window);
	gtk_container_add (GTK_CONTAINER (view), viewport);

	gtk_window_set_default_size (GTK_WINDOW (view),
				     GLADE_CLIPBOARD_VIEW_WIDTH,
				     GLADE_CLIPBOARD_VIEW_HEIGHT);

	gtk_window_set_type_hint (GTK_WINDOW (view), GDK_WINDOW_TYPE_HINT_UTILITY);

	gtk_widget_show_all (scrolled_window);

	return;
}

/**
 * glade_clipboard_view_new:
 * @clipboard: a #GladeClipboard
 * 
 * Create a new #GladeClipboardView widget for @clipboard.
 *
 * Returns: a new #GladeClipboardView cast to be a #GtkWidget
 */
GtkWidget *
glade_clipboard_view_new (GladeClipboard *clipboard)
{
	GladeClipboardView *view;

	g_return_val_if_fail (GLADE_IS_CLIPBOARD (clipboard), NULL);

	view = gtk_type_new (glade_clipboard_view_get_type ());
	view->clipboard = clipboard;
	glade_clipboard_view_construct (view);

	return GTK_WIDGET (view);
}

/**
 * glade_clipboard_view_add:
 * @view: a #GladeClipboardView
 * @widget: a #GladeWidget
 *
 * Adds @widget to @view.
 */
void
glade_clipboard_view_add (GladeClipboardView *view, GladeWidget *widget)
{
	GtkTreeIter iter;

	g_return_if_fail (GLADE_IS_CLIPBOARD_VIEW (view));
	g_return_if_fail (GLADE_IS_WIDGET (widget));

	view->updating = TRUE;
	gtk_list_store_append (view->model, &iter);
	gtk_list_store_set    (view->model, &iter, 0, widget, -1);
	view->updating = FALSE;
}

/**
 * glade_cliboard_view_remove:
 * @view: a #GladeClipboardView
 * @widget: a #GladeWidget
 *
 * Removes @widget from @view.
 */
void
glade_clipboard_view_remove (GladeClipboardView *view, GladeWidget *widget)
{
	GtkTreeIter   iter;
	GtkTreeModel *model;
	GladeWidget  *clip_widget;

	g_return_if_fail (GLADE_IS_CLIPBOARD_VIEW (view));
	g_return_if_fail (GLADE_IS_WIDGET (widget));

	model = GTK_TREE_MODEL (view->model);
	if (gtk_tree_model_get_iter_first (model, &iter)) 
	{
		do 
		{
			gtk_tree_model_get (model, &iter, 0, &clip_widget, -1);
			if (widget == clip_widget)
				break;
		}
		while (gtk_tree_model_iter_next (model, &iter));
	}

	view->updating = TRUE;
	gtk_list_store_remove (view->model, &iter);
	view->updating = FALSE;
}

/**
 * glade_clipboard_view_refresh_sel:
 * @view: a #GladeClipboardView
 *
 * Synchronizes the treeview selection to the clipboard selection.
 */
void
glade_clipboard_view_refresh_sel (GladeClipboardView *view)
{
	GladeWidget      *widget;
	GtkTreeSelection *sel;
	GList            *list;
	GtkTreeIter      *iter;
	
	g_return_if_fail (GLADE_IS_CLIPBOARD_VIEW (view));

	if (view->updating) return;
	view->updating = TRUE;

	sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view->widget));

	gtk_tree_selection_unselect_all (sel);
	for (list = view->clipboard->selection; 
	     list && list->data; list = list->next)
	{
		widget = list->data;
		if ((iter = glade_util_find_iter_by_widget 
		     (GTK_TREE_MODEL (view->model), widget, 0)) != NULL)
		{
			gtk_tree_selection_select_iter (sel, iter);
			/* gtk_tree_iter_free (iter); */
		}
	}
	view->updating = FALSE;
}


syntax highlighted by Code2HTML, v. 0.9.1