/* 
 * Copyright (C) 2004 Hiroyuki Ikezoe <poincare@ikezoe.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/*
 * The original code is gtkcomboboxentry.h in GTK-2.4.4. 
 * Copyright (C) 2002, 2003  Kristian Rietveld <kris@gtk.org>
 */

#include "kz-comboboxentry.h"

#include <config.h>
#include <glib/gi18n.h>

#include "kz-entry.h"

typedef struct _KzComboBoxEntryPrivate      KzComboBoxEntryPrivate;
struct _KzComboBoxEntryPrivate
{
	GtkWidget *entry;

	GtkCellRenderer *text_renderer;
	gint text_column;
};
#define KZ_COMBO_BOX_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), KZ_TYPE_COMBO_BOX_ENTRY, KzComboBoxEntryPrivate))

static void kz_combo_box_entry_class_init       (KzComboBoxEntryClass *klass);
static void kz_combo_box_entry_init             (KzComboBoxEntry      *entry_box);

static void kz_combo_box_entry_set_property     (GObject               *object,
						 guint                  prop_id,
						 const GValue          *value,
						 GParamSpec            *pspec);
static void kz_combo_box_entry_get_property     (GObject               *object,
						 guint                  prop_id,
						 GValue                *value,
						 GParamSpec            *pspec);

static void kz_combo_box_entry_active_changed   (GtkComboBox           *combo_box,
						 gpointer               user_data);
static void kz_combo_box_entry_contents_changed (GtkEntry              *entry,
						 gpointer               user_data);
static gboolean kz_combo_box_entry_mnemonic_activate (GtkWidget        *entry,
						      gboolean          group_cycling);
/*
static void has_frame_changed                    (KzComboBoxEntry      *entry_box,
						  GParamSpec            *pspec,
						  gpointer               data);
*/
enum
{
	PROP_0,
	PROP_TEXT_COLUMN
};


GType
kz_combo_box_entry_get_type (void)
{
	static GType combo_box_entry_type = 0;

	if (!combo_box_entry_type)
	{
		static const GTypeInfo combo_box_entry_info =
		{
			sizeof (KzComboBoxEntryClass),
			NULL, /* base_init */
			NULL, /* base_finalize */
			(GClassInitFunc) kz_combo_box_entry_class_init,
			NULL, /* class_finalize */
			NULL, /* class_data */
			sizeof (KzComboBoxEntry),
			0,
			(GInstanceInitFunc) kz_combo_box_entry_init
		};

		combo_box_entry_type = g_type_register_static (GTK_TYPE_COMBO_BOX,
				"KzComboBoxEntry",
				&combo_box_entry_info,
				0);
	}

	return combo_box_entry_type;
}

static void
kz_combo_box_entry_class_init (KzComboBoxEntryClass *klass)
{
	GObjectClass *object_class;
	GtkWidgetClass *widget_class;

	object_class = (GObjectClass *)klass;
	object_class->set_property = kz_combo_box_entry_set_property;
	object_class->get_property = kz_combo_box_entry_get_property;

	widget_class = (GtkWidgetClass *)klass;
	widget_class->mnemonic_activate = kz_combo_box_entry_mnemonic_activate;

	g_object_class_install_property (
			object_class,
			PROP_TEXT_COLUMN,
			g_param_spec_int ("text_column",
				_("Text Column"),
				_("A column in the data source model to get the strings from"),
				-1,
				G_MAXINT,
				-1,
				G_PARAM_READWRITE));

	g_type_class_add_private ((GObjectClass *) klass,
				  sizeof (KzComboBoxEntryPrivate));
}

static void
kz_combo_box_entry_init (KzComboBoxEntry *entry_box)
{
	KzComboBoxEntryPrivate *priv = KZ_COMBO_BOX_ENTRY_GET_PRIVATE (entry_box);
	priv->text_column = -1;

	priv->entry = kz_entry_new ();
	/* this flag is a hack to tell the entry to fill its allocation.
	 */
	GTK_ENTRY (priv->entry)->is_cell_renderer = TRUE;
	gtk_container_add (GTK_CONTAINER (entry_box), priv->entry);
	gtk_widget_show (priv->entry);

	priv->text_renderer = gtk_cell_renderer_text_new ();
	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (entry_box),
			priv->text_renderer, TRUE);

	gtk_combo_box_set_active (GTK_COMBO_BOX (entry_box), -1);

	g_signal_connect (priv->entry, "changed",
			G_CALLBACK (kz_combo_box_entry_contents_changed),
			entry_box);
	g_signal_connect (entry_box, "changed",
			G_CALLBACK (kz_combo_box_entry_active_changed), NULL);
	/*	
	has_frame_changed (entry_box, NULL, NULL);
	g_signal_connect (entry_box, "notify::has-frame", G_CALLBACK (has_frame_changed), NULL);
	*/
}

static void
kz_combo_box_entry_set_property (GObject      *object,
				 guint         prop_id,
				 const GValue *value,
				 GParamSpec   *pspec)
{
	KzComboBoxEntry *entry_box = KZ_COMBO_BOX_ENTRY (object);

	switch (prop_id)
	{
		case PROP_TEXT_COLUMN:
			kz_combo_box_entry_set_text_column (entry_box,
					g_value_get_int (value));
			break;
		default:
			break;
	}
}

static void
kz_combo_box_entry_get_property (GObject    *object,
				 guint       prop_id,
				 GValue     *value,
				 GParamSpec *pspec)
{
	KzComboBoxEntryPrivate *priv = KZ_COMBO_BOX_ENTRY_GET_PRIVATE (object);

	switch (prop_id)
	{
		case PROP_TEXT_COLUMN:
			g_value_set_int (value, priv->text_column);
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
			break;
	}
}

static void
kz_combo_box_entry_active_changed (GtkComboBox *combo_box,
				   gpointer     user_data)
{
	KzComboBoxEntry *entry_box = KZ_COMBO_BOX_ENTRY (combo_box);
	KzComboBoxEntryPrivate *priv = KZ_COMBO_BOX_ENTRY_GET_PRIVATE (entry_box);
	GtkTreeModel *model;
	GtkTreeIter iter;
	gchar *str = NULL;

	if (gtk_combo_box_get_active_iter (combo_box, &iter))
	{
		g_signal_handlers_block_by_func (priv->entry,
				kz_combo_box_entry_contents_changed,
				combo_box);

		model = gtk_combo_box_get_model (combo_box);

		gtk_tree_model_get (model, &iter, 
				priv->text_column, &str, 
				-1);
		gtk_entry_set_text (GTK_ENTRY (priv->entry), str);
		g_free (str);

		g_signal_handlers_unblock_by_func (priv->entry,
				kz_combo_box_entry_contents_changed,
				combo_box);
	}
}
/*
static void 
has_frame_changed (KzComboBoxEntry *entry_box,
		   GParamSpec       *pspec,
		   gpointer          data)
{
	gboolean has_frame;

	g_object_get (entry_box, "has_frame", &has_frame, NULL);

	gtk_entry_set_has_frame (GTK_ENTRY (entry_box->priv->entry), has_frame);
}
*/
static void
kz_combo_box_entry_contents_changed (GtkEntry *entry,
				     gpointer  user_data)
{
	GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);

	g_signal_handlers_block_by_func (combo_box,
			kz_combo_box_entry_active_changed,
			NULL);
	gtk_combo_box_set_active (combo_box, -1);
	g_signal_handlers_unblock_by_func (combo_box,
			kz_combo_box_entry_active_changed,
			NULL);
}

/* public API */
GtkWidget *
kz_combo_box_entry_new (void)
{
	return GTK_WIDGET (g_object_new (kz_combo_box_entry_get_type (), NULL));
}

GtkWidget *
kz_combo_box_entry_new_with_model (GtkTreeModel *model,
				   gint          text_column)
{
	GtkWidget *ret;

	g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
	g_return_val_if_fail (text_column >= 0, NULL);
	g_return_val_if_fail (text_column < gtk_tree_model_get_n_columns (model), NULL);

	ret = g_object_new (kz_combo_box_entry_get_type (),
			"model", model,
			"text_column", text_column,
			NULL);

	return ret;
}

void
kz_combo_box_entry_set_text_column (KzComboBoxEntry *entry_box,
				    gint              text_column)
{
	KzComboBoxEntryPrivate *priv = KZ_COMBO_BOX_ENTRY_GET_PRIVATE (entry_box);
	g_return_if_fail (text_column >= 0);
	g_return_if_fail (text_column < gtk_tree_model_get_n_columns (gtk_combo_box_get_model (GTK_COMBO_BOX (entry_box))));
	g_return_if_fail (priv->text_column == -1);

	priv->text_column = text_column;

	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (entry_box),
			priv->text_renderer,
			"text", text_column,
			NULL);
}

gint
kz_combo_box_entry_get_text_column (KzComboBoxEntry *entry_box)
{
	KzComboBoxEntryPrivate *priv;
	g_return_val_if_fail (GTK_IS_COMBO_BOX_ENTRY (entry_box), 0);
	priv = KZ_COMBO_BOX_ENTRY_GET_PRIVATE (entry_box);

	return priv->text_column;
}

static gboolean
kz_combo_box_entry_mnemonic_activate (GtkWidget *widget,
				      gboolean   group_cycling)
{
	KzComboBoxEntryPrivate *priv = KZ_COMBO_BOX_ENTRY_GET_PRIVATE (widget);

	gtk_widget_grab_focus (priv->entry);

	return TRUE;
}


/* convenience API for simple text combos */

GtkWidget *
kz_combo_box_entry_new_text (void)
{
	GtkWidget *entry_box;
	GtkListStore *store;

	store = gtk_list_store_new (1, G_TYPE_STRING);
	entry_box = kz_combo_box_entry_new_with_model (GTK_TREE_MODEL (store), 0);
	g_object_unref (store);

	return entry_box;
}
