/* eLectrix - a pdf viewer
 * Copyright (C) 2010, 2011 Martin Linder <mali2297@users.sf.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, see <http://www.gnu.org/licenses/gpl-2.0.html>.
 */
#include <stdlib.h>
#include "e6x-common.h"
#include "e6x-page-selector.h"

#define MAX_DIGITS 3

#define E6X_PAGE_SELECTOR_GET_PRIVATE(o) \
  (G_TYPE_INSTANCE_GET_PRIVATE ((o), E6X_TYPE_PAGE_SELECTOR, E6xPageSelectorPrivate))

struct _E6xPageSelectorPrivate
{
  E6xDocument *doc;
  GtkWidget *entry;
  GtkWidget *prev_button;
  GtkWidget *next_button;
};

/* Standard GObject methods */
G_DEFINE_TYPE (E6xPageSelector, e6x_page_selector, GTK_TYPE_HBOX);
static void e6x_page_selector_finalize (GObject *object);
static void e6x_page_selector_dispose (GObject *object);
static void e6x_page_selector_class_init (E6xPageSelectorClass *klass);
static void e6x_page_selector_init (E6xPageSelector *selector);

/* Helpers */
static void e6x_page_selector_reset (E6xPageSelector *selector);
static GtkWidget *e6x_page_selector_create_button (E6xPageSelector *selector,
                                                   GtkArrowType arrow_type);

/* Callbacks */
static void e6x_page_selector_doc_changed (E6xDocument *doc, 
                                           E6xPageSelector *selector);
static void e6x_page_selector_activate (GtkEntry *entry, 
                                        E6xPageSelector *selector);
static gboolean e6x_page_selector_button_clicked (GtkWidget *widget, 
                                                  GdkEventButton *event,
                                                  E6xPageSelector *selector);

GtkWidget *
e6x_page_selector_new ()
{
  return g_object_new (E6X_TYPE_PAGE_SELECTOR, NULL);
}


void 
e6x_page_selector_set_document (E6xPageSelector *selector, 
                                E6xDocument *doc)
{
  E6xPageSelectorPrivate *priv = selector->priv;
  
  if (priv->doc)
  {
    g_signal_handlers_disconnect_by_func (priv->doc,
                                          e6x_page_selector_doc_changed,
                                          selector);
    g_object_unref (priv->doc);
  }

  priv->doc = doc;
  
  if (priv->doc)
  {
    g_object_ref (priv->doc);
    g_signal_connect (priv->doc, "changed::reload",
                      G_CALLBACK (e6x_page_selector_doc_changed), 
                      selector);
    g_signal_connect (priv->doc, "changed::page-no",
                      G_CALLBACK (e6x_page_selector_doc_changed), 
                      selector);
    g_signal_connect (priv->doc, "changed::multiple",
                      G_CALLBACK (e6x_page_selector_doc_changed), 
                      selector);
  }

  e6x_page_selector_reset (selector);
}


static void
e6x_page_selector_class_init (E6xPageSelectorClass *klass)
{
  g_type_class_add_private (klass, sizeof (E6xPageSelectorPrivate));

  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->dispose = e6x_page_selector_dispose;
  object_class->finalize = e6x_page_selector_finalize;
}

static void
e6x_page_selector_init (E6xPageSelector *selector)
{
  E6xPageSelectorPrivate *priv = E6X_PAGE_SELECTOR_GET_PRIVATE (selector);
  GtkWidget *label = NULL; 
  
  priv->doc = NULL;
  label = gtk_label_new_with_mnemonic (_("_Page"));
  gtk_box_pack_start (GTK_BOX (selector), label, FALSE, FALSE, 0);
  
  priv->prev_button = e6x_page_selector_create_button (selector,
                                                       GTK_ARROW_LEFT);
  gtk_box_pack_start (GTK_BOX (selector), priv->prev_button, FALSE, FALSE, 0);
  
  priv->entry = gtk_entry_new ();
  gtk_entry_set_width_chars (GTK_ENTRY (priv->entry), 2*MAX_DIGITS + 3);
  gtk_entry_set_alignment (GTK_ENTRY (priv->entry), 0.5);
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->entry);
  g_signal_connect (priv->entry, "activate",
                    G_CALLBACK (e6x_page_selector_activate), selector);
  gtk_box_pack_start (GTK_BOX (selector), priv->entry, FALSE, FALSE, 0);
  
  priv->next_button = e6x_page_selector_create_button (selector,
                                                       GTK_ARROW_RIGHT);
  gtk_box_pack_start (GTK_BOX (selector), priv->next_button, FALSE, FALSE, 0);
  
  selector->priv = priv;
  
  e6x_page_selector_reset (selector);
}


static void 
e6x_page_selector_finalize (GObject *object)
{
  G_OBJECT_CLASS (e6x_page_selector_parent_class)->finalize (object);
}


static void 
e6x_page_selector_dispose (GObject *object)
{
  E6xPageSelectorPrivate *priv = E6X_PAGE_SELECTOR (object)->priv;
  
  e6x_page_selector_set_document (E6X_PAGE_SELECTOR (object), NULL);
  priv->entry = NULL;
  priv->prev_button = NULL;
  priv->next_button = NULL;
  
  G_OBJECT_CLASS (e6x_page_selector_parent_class)->dispose (object);
}


static void 
e6x_page_selector_reset (E6xPageSelector *selector)
{
  E6xPageSelectorPrivate *priv = selector->priv;
  guint page_no = 0, n_pages = 0;
  gchar *string = NULL;
  
  if (priv->doc != NULL)
  {
    page_no = priv->doc->page_no;
    n_pages = priv->doc->n_pages;
  }

  if (priv->entry != NULL)
  {
    string = g_strdup_printf ("%u (%u)", page_no, n_pages);
    gtk_entry_set_text (GTK_ENTRY (priv->entry), string);
    g_free (string);
    
    gtk_widget_set_sensitive (priv->entry, priv->doc != NULL);
  }
  
  if (priv->prev_button != NULL)
    gtk_widget_set_sensitive (priv->prev_button, page_no > 1);
  if (priv->next_button != NULL)
    gtk_widget_set_sensitive (priv->next_button, page_no < n_pages);
}


static GtkWidget *
e6x_page_selector_create_button (E6xPageSelector *selector,
                                 GtkArrowType arrow_type)
{
  GtkWidget *button = NULL, *arrow = NULL;
  
  button = gtk_button_new ();
  gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
  gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
  g_signal_connect (button, 
                    "button-press-event",
                    G_CALLBACK (e6x_page_selector_button_clicked), 
                    selector);
  arrow = gtk_arrow_new (arrow_type, GTK_SHADOW_OUT);
  gtk_container_add (GTK_CONTAINER (button), arrow);
  
  return button;
}


static void 
e6x_page_selector_doc_changed (E6xDocument *doc, 
                               E6xPageSelector *selector)
{
  e6x_page_selector_reset (selector);
}


static void 
e6x_page_selector_activate (GtkEntry *entry, 
                            E6xPageSelector *selector)
{  
  E6xPageSelectorPrivate *priv = selector->priv;
  guint page_no = 0;
  
  if (priv->doc == NULL)
    return;
  
  page_no = atoi (gtk_entry_get_text (entry));
  if (page_no < 1 || page_no > priv->doc->n_pages)
    page_no = priv->doc->page_no;
  e6x_document_set_page_no (priv->doc, page_no);
}


static gboolean  
e6x_page_selector_button_clicked (GtkWidget *widget, 
                                  GdkEventButton *event,
                                  E6xPageSelector *selector)
{
  E6xPageSelectorPrivate *priv = selector->priv;
  
  if (priv->doc == NULL)
    return FALSE;
  
  
  if (event->button == 1)
  {
    if (widget == priv->prev_button)
      e6x_document_set_page_no (priv->doc, priv->doc->page_no - 1);    
    else if (widget == priv->next_button)
      e6x_document_set_page_no (priv->doc, priv->doc->page_no + 1);
  }
  else if (event->button == 3)
  {
    if (widget == priv->prev_button)
      e6x_document_set_page_no (priv->doc, 1);
    else if (widget == priv->next_button)
      e6x_document_set_page_no (priv->doc, priv->doc->n_pages);
  }
  
  return FALSE;
}

