/* LIBPIKA - The PIKA Library
 * Copyright (C) 1995-1999 Peter Mattis and Spencer Kimball
 *
 * pikaunitcombobox.c
 * Copyright (C) 2004, 2008  Sven Neumann <sven@gimp.org>
 *
 * This library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 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 Lesser General Public
 * License along with this library.  If not, see
 * <https://www.gnu.org/licenses/>.
 */

#include "config.h"

#include <gtk/gtk.h>

#include "pikawidgetstypes.h"

#include "pikaunitcombobox.h"
#include "pikaunitstore.h"


/**
 * SECTION: pikaunitcombobox
 * @title: PikaUnitComboBox
 * @short_description: A #GtkComboBox to select a #PikaUnit.
 * @see_also: #PikaUnit, #PikaUnitStore
 *
 * #PikaUnitComboBox selects units stored in a #PikaUnitStore.
 **/


static void pika_unit_combo_box_popup_shown (PikaUnitComboBox *widget);
static void pika_unit_combo_box_constructed (GObject          *object);

G_DEFINE_TYPE (PikaUnitComboBox, pika_unit_combo_box, GTK_TYPE_COMBO_BOX)

#define parent_class pika_unit_combo_box_parent_class


static void
pika_unit_combo_box_class_init (PikaUnitComboBoxClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->constructed = pika_unit_combo_box_constructed;
}

static void
pika_unit_combo_box_init (PikaUnitComboBox *combo)
{
  g_signal_connect (combo, "notify::popup-shown",
                    G_CALLBACK (pika_unit_combo_box_popup_shown),
                    NULL);
}

static void
pika_unit_combo_box_constructed (GObject *object)
{
  PikaUnitComboBox *combo = PIKA_UNIT_COMBO_BOX (object);

  G_OBJECT_CLASS (parent_class)->constructed (object);

  pika_unit_combo_box_popup_shown (combo);
}

static void
pika_unit_combo_box_popup_shown (PikaUnitComboBox *widget)
{
  PikaUnitStore   *store;
  gboolean         shown;
  GtkCellRenderer *cell;

  g_object_get (widget,
                "model",       &store,
                "popup-shown", &shown,
                NULL);

  if (store)
    {
      if (shown)
        _pika_unit_store_sync_units (store);

      g_object_unref (store);
    }

  gtk_cell_layout_clear (GTK_CELL_LAYOUT (widget));
  cell = gtk_cell_renderer_text_new ();

  if (shown)
    {
      gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), cell, TRUE);
      gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), cell,
                                      "text", PIKA_UNIT_STORE_UNIT_LONG_FORMAT,
                                      NULL);

      /* XXX This is ugly but it seems that GtkComboBox won't resize its popup
       * menu when the contents changes (it only resizes the main "chosen item"
       * area). We force a redraw by popping down then up after a contents
       * change.
       */
      g_signal_handlers_disconnect_by_func (widget,
                                            G_CALLBACK (pika_unit_combo_box_popup_shown),
                                            NULL);
      gtk_combo_box_popdown (GTK_COMBO_BOX (widget));
      gtk_combo_box_popup (GTK_COMBO_BOX (widget));
      g_signal_connect (widget, "notify::popup-shown",
                        G_CALLBACK (pika_unit_combo_box_popup_shown),
                        NULL);
    }
  else
    {
      gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), cell, FALSE);
      gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), cell,
                                      "text", PIKA_UNIT_STORE_UNIT_SHORT_FORMAT,
                                      NULL);
    }
}


/**
 * pika_unit_combo_box_new:
 *
 * Returns: a new #PikaUnitComboBox.
 **/
GtkWidget *
pika_unit_combo_box_new (void)
{
  GtkWidget     *combo_box;
  PikaUnitStore *store;

  store = pika_unit_store_new (0);

  combo_box = g_object_new (PIKA_TYPE_UNIT_COMBO_BOX,
                            "model",     store,
                            "id-column", PIKA_UNIT_STORE_UNIT_LONG_FORMAT,
                            NULL);

  g_object_unref (store);

  return combo_box;
}

/**
 * pika_unit_combo_box_new_with_model:
 * @model: a #PikaUnitStore
 *
 * Returns: a new #PikaUnitComboBox.
 **/
GtkWidget *
pika_unit_combo_box_new_with_model (PikaUnitStore *model)
{
  return g_object_new (PIKA_TYPE_UNIT_COMBO_BOX,
                       "model",     model,
                       "id-column", PIKA_UNIT_STORE_UNIT_LONG_FORMAT,
                       NULL);
}

/**
 * pika_unit_combo_box_get_active:
 * @combo: a #PikaUnitComboBox
 *
 * Returns the #PikaUnit currently selected in the combo box.
 *
 * Returns: (transfer none): The selected #PikaUnit.
 **/
PikaUnit
pika_unit_combo_box_get_active (PikaUnitComboBox *combo)
{
  GtkTreeIter iter;
  gint        unit;

  g_return_val_if_fail (PIKA_IS_UNIT_COMBO_BOX (combo), -1);

  gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter);

  gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (combo)), &iter,
                      PIKA_UNIT_STORE_UNIT, &unit,
                      -1);

  return (PikaUnit) unit;
}

/**
 * pika_unit_combo_box_set_active:
 * @combo: a #PikaUnitComboBox
 * @unit:  a #PikaUnit
 *
 * Sets @unit as the currently selected #PikaUnit on @combo.
 **/
void
pika_unit_combo_box_set_active (PikaUnitComboBox *combo,
                                PikaUnit          unit)
{
  GtkTreeModel *model;
  GtkTreeIter   iter;
  gboolean      iter_valid;

  g_return_if_fail (PIKA_IS_UNIT_COMBO_BOX (combo));

  model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));

  _pika_unit_store_sync_units (PIKA_UNIT_STORE (model));

  for (iter_valid = gtk_tree_model_get_iter_first (model, &iter);
       iter_valid;
       iter_valid = gtk_tree_model_iter_next (model, &iter))
    {
      gint iter_unit;

      gtk_tree_model_get (model, &iter,
                          PIKA_UNIT_STORE_UNIT, &iter_unit,
                          -1);

      if (unit == (PikaUnit) iter_unit)
        {
          gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &iter);
          break;
        }
    }
}
