/* GTK - The GIMP Toolkit
 * gtkrecentaction.c
 *
 * Copyright (C) 2006  Emmanuele Bassi
 *
 * 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 the Gnome Library; see the file COPYING.LIB.  If not,
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <config.h>

#include "gtkintl.h"
#include "gtkrecentaction.h"
#include "gtkrecentmanager.h"
#include "gtkrecentchooser.h"
#include "gtkrecentchooserutils.h"
#include "gtkrecentchooserprivate.h"
#include "gtkrecentchoosermenu.h"
#include "gtkmenutoolbutton.h"
#include "gtkimagemenuitem.h"
#include "gtkprivate.h"
#include "gtkalias.h"

#define FALLBACK_ITEM_LIMIT 	4

#define GTK_RECENT_ACTION_GET_PRIVATE(obj)	(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_RECENT_ACTION, GtkRecentActionPrivate))

struct _GtkRecentActionPrivate
{
  GtkRecentManager *manager;
  GtkWidget *chooser_menu;

  GtkRecentInfo *current_item;
  
  gint limit;
};

enum
{
  PROP_0,
  PROP_SHOW_NUMBERS
};

enum
{
  ITEM_ACTIVATED,
  LAST_SIGNAL
};

G_DEFINE_TYPE (GtkRecentAction, gtk_recent_action, GTK_TYPE_ACTION);

static guint recent_action_signals[LAST_SIGNAL] = { 0 };

static void
gtk_recent_action_finalize (GObject *gobject)
{
  GtkRecentActionPrivate *priv = GTK_RECENT_ACTION (gobject)->priv;

  if (priv->current_item)
    gtk_recent_info_unref (priv->current_item);
  
  G_OBJECT_CLASS (gtk_recent_action_parent_class)->finalize (gobject);
}

static void
gtk_recent_action_set_property (GObject      *gobject,
				guint         prop_id,
				const GValue *value,
				GParamSpec   *pspec)
{
  switch (prop_id)
    {
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
      break;
    }
}

static void
gtk_recent_action_get_property (GObject    *gobject,
				guint       prop_id,
				GValue     *value,
				GParamSpec *pspec)
{
  switch (prop_id)
    {
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
      break;
    }
}

static void
gtk_recent_action_activate (GtkAction *action)
{
  
}

static void
gtk_recent_action_connect_proxy (GtkAction *action,
				 GtkWidget *proxy)
{
  GTK_ACTION_CLASS (gtk_recent_action_parent_class)->connect_proxy (action, proxy);
}

static void
gtk_recent_action_disconnect_proxy (GtkAction *action,
				    GtkWidget *proxy)
{
  GTK_ACTION_CLASS (gtk_recent_action_parent_class)->disconnect_proxy (action, proxy);
}

static void
recent_chooser_item_activated_cb (GtkRecentChooser *chooser,
				  GtkRecentAction  *action)
{
  GtkRecentActionPrivate *priv = action->priv;
  GtkRecentInfo *current;

  if (priv->current_item)
    gtk_recent_info_unref (priv->current_item);

  current = gtk_recent_chooser_get_current_item (chooser);
  priv->current_item = gtk_recent_info_ref (current);
  
  g_signal_emit (action, recent_action_signals[ITEM_ACTIVATED], 0, current);
}

static GtkWidget *
gtk_recent_action_create_menu_item (GtkAction *action)
{
  GtkRecentAction *recent_action = GTK_RECENT_ACTION (action);
  GtkRecentActionPrivate *priv = recent_action->priv;
  GtkWidget *menuitem;
  GtkWidget *chooser_menu;

  if (!priv->manager)
    priv->manager = gtk_recent_manager_get_default ();
  
  chooser_menu = gtk_recent_chooser_menu_new_for_manager (priv->manager);
  g_signal_connect (chooser_menu, "item-activated",
		    G_CALLBACK (recent_chooser_item_activated_cb),
		    action);
  
  menuitem = g_object_new (GTK_TYPE_IMAGE_MENU_ITEM, NULL);
  
  gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem),
  			     chooser_menu);
  
  return menuitem;
}

static GtkWidget *
gtk_recent_action_create_tool_item (GtkAction *action)
{
  GtkRecentAction *recent_action = GTK_RECENT_ACTION (action);
  GtkRecentActionPrivate *priv = recent_action->priv;
  GtkWidget *chooser_menu;
  GtkWidget *toolitem;

  if (!priv->manager)
    priv->manager = gtk_recent_manager_get_default ();
 
  chooser_menu = gtk_recent_chooser_menu_new_for_manager (priv->manager);
  g_signal_connect (chooser_menu, "item-activated",
		    G_CALLBACK (recent_chooser_item_activated_cb),
		    action);

  toolitem = g_object_new (GTK_TYPE_MENU_TOOL_BUTTON, NULL);
  
  gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (toolitem),
		  		 chooser_menu);
  
  return toolitem;
}

static void
gtk_recent_action_class_init (GtkRecentActionClass *klass)
{
  GObjectClass *gobject_class;
  GtkActionClass *action_class;

  gobject_class = G_OBJECT_CLASS (klass);
  action_class = GTK_ACTION_CLASS (klass);

  gobject_class->finalize = gtk_recent_action_finalize;
  gobject_class->set_property = gtk_recent_action_set_property;
  gobject_class->get_property = gtk_recent_action_get_property;

  action_class->activate = gtk_recent_action_activate;
  action_class->connect_proxy = gtk_recent_action_connect_proxy;
  action_class->disconnect_proxy = gtk_recent_action_disconnect_proxy;

  action_class->menu_item_type = GTK_TYPE_IMAGE_MENU_ITEM;
  action_class->toolbar_item_type = GTK_TYPE_MENU_TOOL_BUTTON;

  action_class->create_menu_item = gtk_recent_action_create_menu_item;
  action_class->create_tool_item = gtk_recent_action_create_tool_item;

  recent_action_signals[ITEM_ACTIVATED] =
    g_signal_new (I_("item-activated"),
		  G_OBJECT_CLASS_TYPE (klass),
		  G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
		  G_STRUCT_OFFSET (GtkRecentActionClass, item_activated),
		  NULL, NULL,
		  g_cclosure_marshal_VOID__BOXED,
		  G_TYPE_NONE, 1, GTK_TYPE_RECENT_INFO);

  g_type_class_add_private (gobject_class, sizeof (GtkRecentActionPrivate));
}

static void
gtk_recent_action_init (GtkRecentAction *action)
{
  GtkRecentActionPrivate *priv = GTK_RECENT_ACTION_GET_PRIVATE (action);
  
  action->priv = priv;

  priv->current_item = NULL;
  priv->limit = FALLBACK_ITEM_LIMIT;
}

/**
 * gtk_recent_action_new:
 * @name:
 * @label:
 * @tooltip:
 * @stock_id:
 * @limit:
 *
 * Creates a new #GtkRecentAction used to display the list of
 * recently used files inside a menu or a toolbar created using
 * #GtkUIManager.
 *
 * Return value: a new #GtkRecentAction
 *
 * Since: 2.10
 */
GtkRecentAction *
gtk_recent_action_new (const gchar *name,
		       const gchar *label,
		       const gchar *tooltip,
		       const gchar *stock_id,
		       gint         limit)
{
  return g_object_new (GTK_TYPE_RECENT_ACTION,
		       "name", name,
		       "label", label,
		       "tooltip", tooltip,
		       "stock-id", stock_id,
		       NULL);
}

/**
 * gtk_recent_action_set_limit:
 * @action: a #GtkRecentAction
 * @limit: the number of recently used files to display, or -1
 *
 * Sets the number of recently used files that @action should
 * display. Use -1 for displaying all recently used files.
 *
 * Since: 2.10
 */
void
gtk_recent_action_set_limit (GtkRecentAction *action,
			     gint             limit)
{
  g_return_if_fail (GTK_IS_RECENT_ACTION (action));
  
  if (!action->priv->manager)
    action->priv->manager = gtk_recent_manager_get_default ();

  gtk_recent_manager_set_limit (action->priv->manager, limit);
}

/**
 * gtk_recent_action_get_limit:
 * @action: a #GtkRecentAction
 *
 * Gets the number of recently used files displayed by @action.
 *
 * Return value: the number of recently used files, or -1 for every file.
 *
 * Since: 2.10
 */
gint
gtk_recent_action_get_limit (GtkRecentAction *action)
{
  g_return_val_if_fail (GTK_IS_RECENT_ACTION (action), -1);

  if (!action->priv->manager)
    action->priv->manager = gtk_recent_manager_get_default ();

  return gtk_recent_manager_get_limit (action->priv->manager);
}

GtkRecentInfo *
gtk_recent_action_get_current_item (GtkRecentAction *action)
{
  g_return_val_if_fail (GTK_IS_RECENT_ACTION (action), NULL);

  return action->priv->current_item;
}

#define __GTK_RECENT_ACTION_C__
#include "gtkaliasdef.c"
