/* PIKA - Photo and Image Kooker Application
 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
 *
 * Original copyright, applying to most contents (license remains unchanged): 
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * pikatooleditor.c
 * Copyright (C) 2001-2009 Michael Natterer <mitch@gimp.org>
 *                         Stephen Griffiths <scgmk5@gmail.com>
 *
 * 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 3 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 <https://www.gnu.org/licenses/>.
 */

#include "config.h"

#include <gegl.h>
#include <gtk/gtk.h>

#include "libpikaconfig/pikaconfig.h"
#include "libpikawidgets/pikawidgets.h"

#include "widgets-types.h"

#include "core/pika.h"
#include "core/pikacontainer.h"
#include "core/pikacontext.h"
#include "core/pikatoolgroup.h"
#include "core/pikatreehandler.h"

#include "tools/pika-tools.h"

#include "pikacontainertreestore.h"
#include "pikacontainerview.h"
#include "pikadnd.h"
#include "pikaviewrenderer.h"
#include "pikatooleditor.h"
#include "pikahelp-ids.h"
#include "pikawidgets-utils.h"

#include "pika-intl.h"


struct _PikaToolEditorPrivate
{
  PikaContainer   *container;
  PikaContext     *context;

  GtkWidget       *scrolled;

  GtkWidget       *new_group_button;
  GtkWidget       *raise_button;
  GtkWidget       *lower_button;
  GtkWidget       *delete_button;
  GtkWidget       *reset_button;

  PikaTreeHandler *tool_item_notify_handler;

  /* State of tools at creation of the editor, stored to support
   * reverting changes
   */
  gchar           *initial_tool_state;
};


/*  local function prototypes  */

static void            pika_tool_editor_view_iface_init           (PikaContainerViewInterface *iface);

static void            pika_tool_editor_constructed               (GObject                    *object);

static gboolean        pika_tool_editor_select_items              (PikaContainerView          *view,
                                                                   GList                      *items,
                                                                   GList                      *paths);
static void            pika_tool_editor_set_container             (PikaContainerView          *container_view,
                                                                   PikaContainer              *container);
static void            pika_tool_editor_set_context               (PikaContainerView          *container_view,
                                                                   PikaContext                *context);

static gboolean        pika_tool_editor_drop_possible             (PikaContainerTreeView      *tree_view,
                                                                   PikaDndType                 src_type,
                                                                   GList                      *src_viewables,
                                                                   PikaViewable               *dest_viewable,
                                                                   GtkTreePath                *drop_path,
                                                                   GtkTreeViewDropPosition     drop_pos,
                                                                   GtkTreeViewDropPosition    *return_drop_pos,
                                                                   GdkDragAction              *return_drag_action);
static void            pika_tool_editor_drop_viewables            (PikaContainerTreeView      *tree_view,
                                                                   GList                      *src_viewables,
                                                                   PikaViewable               *dest_viewable,
                                                                   GtkTreeViewDropPosition     drop_pos);

static void            pika_tool_editor_tool_item_notify         (PikaToolItem                *tool_item,
                                                                  GParamSpec                  *pspec,
                                                                  PikaToolEditor              *tool_editor);

static void            pika_tool_editor_eye_data_func            (GtkTreeViewColumn           *tree_column,
                                                                  GtkCellRenderer             *cell,
                                                                  GtkTreeModel                *tree_model,
                                                                  GtkTreeIter                 *iter,
                                                                  gpointer                     data);
static void            pika_tool_editor_eye_clicked              (GtkCellRendererToggle       *toggle,
                                                                  gchar                       *path_str,
                                                                  GdkModifierType              state,
                                                                  PikaToolEditor              *tool_editor);

static void            pika_tool_editor_new_group_clicked        (GtkButton                   *button,
                                                                  PikaToolEditor              *tool_editor);
static void            pika_tool_editor_raise_clicked            (GtkButton                   *button,
                                                                  PikaToolEditor              *tool_editor);
static void            pika_tool_editor_raise_extend_clicked     (GtkButton                   *button,
                                                                  GdkModifierType              mask,
                                                                  PikaToolEditor              *tool_editor);
static void            pika_tool_editor_lower_clicked            (GtkButton                   *button,
                                                                  PikaToolEditor              *tool_editor);
static void            pika_tool_editor_lower_extend_clicked     (GtkButton                   *button,
                                                                  GdkModifierType              mask,
                                                                  PikaToolEditor              *tool_editor);
static void            pika_tool_editor_delete_clicked           (GtkButton                   *button,
                                                                  PikaToolEditor              *tool_editor);
static void            pika_tool_editor_reset_clicked            (GtkButton                   *button,
                                                                  PikaToolEditor              *tool_editor);

static PikaToolItem  * pika_tool_editor_get_selected_tool_item   (PikaToolEditor              *tool_editor);
static PikaContainer * pika_tool_editor_get_tool_item_container  (PikaToolEditor              *tool_editor,
                                                                  PikaToolItem                *tool_item);

static void            pika_tool_editor_update_container         (PikaToolEditor              *tool_editor);
static void            pika_tool_editor_update_sensitivity       (PikaToolEditor              *tool_editor);


G_DEFINE_TYPE_WITH_CODE (PikaToolEditor, pika_tool_editor,
                         PIKA_TYPE_CONTAINER_TREE_VIEW,
                         G_ADD_PRIVATE (PikaToolEditor)
                         G_IMPLEMENT_INTERFACE (PIKA_TYPE_CONTAINER_VIEW,
                                                pika_tool_editor_view_iface_init))

#define parent_class pika_tool_editor_parent_class

static PikaContainerViewInterface *parent_view_iface = NULL;


/*  private functions  */

static void
pika_tool_editor_class_init (PikaToolEditorClass *klass)
{
  GObjectClass               *object_class    = G_OBJECT_CLASS (klass);
  PikaContainerTreeViewClass *tree_view_class = PIKA_CONTAINER_TREE_VIEW_CLASS (klass);

  object_class->constructed       = pika_tool_editor_constructed;

  tree_view_class->drop_possible  = pika_tool_editor_drop_possible;
  tree_view_class->drop_viewables = pika_tool_editor_drop_viewables;
}

static void
pika_tool_editor_view_iface_init (PikaContainerViewInterface *iface)
{
  parent_view_iface = g_type_interface_peek_parent (iface);

  if (! parent_view_iface)
    parent_view_iface = g_type_default_interface_peek (PIKA_TYPE_CONTAINER_VIEW);

  iface->select_items  = pika_tool_editor_select_items;
  iface->set_container = pika_tool_editor_set_container;
  iface->set_context   = pika_tool_editor_set_context;
}

static void
pika_tool_editor_init (PikaToolEditor *tool_editor)
{
  tool_editor->priv = pika_tool_editor_get_instance_private (tool_editor);
}

static void
pika_tool_editor_constructed (GObject *object)
{
  PikaToolEditor        *tool_editor    = PIKA_TOOL_EDITOR (object);
  PikaContainerTreeView *tree_view      = PIKA_CONTAINER_TREE_VIEW (object);
  PikaContainerView     *container_view = PIKA_CONTAINER_VIEW (object);
  gint                   view_size;
  gint                   border_width;

  G_OBJECT_CLASS (parent_class)->constructed (object);

  view_size = pika_container_view_get_view_size (container_view,
                                                 &border_width);

  pika_editor_set_show_name (PIKA_EDITOR (tool_editor), FALSE);

  gtk_tree_view_set_level_indentation (tree_view->view,
                                       0.8 * (view_size + 2 * border_width));

  pika_dnd_viewable_dest_add (GTK_WIDGET (tree_view->view),
                              PIKA_TYPE_TOOL_ITEM,
                              NULL, NULL);

  /* construct tree view */
  {
    GtkTreeViewColumn *column;
    GtkCellRenderer   *eye_cell;
    GtkStyleContext   *tree_style;
    GtkBorder          border;
    gint               icon_size;

    tree_style = gtk_widget_get_style_context (GTK_WIDGET (tool_editor));

    gtk_style_context_get_border (tree_style, 0, &border);

    column = gtk_tree_view_column_new ();
    gtk_tree_view_insert_column (tree_view->view, column, 0);

    eye_cell = pika_cell_renderer_toggle_new (PIKA_ICON_VISIBLE);

    g_object_get (eye_cell, "icon-size", &icon_size, NULL);
    icon_size = MIN (icon_size, MAX (view_size - (border.left + border.right),
                                     view_size - (border.top + border.bottom)));
    g_object_set (eye_cell, "icon-size", icon_size, NULL);

    gtk_tree_view_column_pack_start (column, eye_cell, FALSE);
    gtk_tree_view_column_set_cell_data_func  (column, eye_cell,
                                              pika_tool_editor_eye_data_func,
                                              tree_view, NULL);

    pika_container_tree_view_add_toggle_cell (tree_view, eye_cell);

    g_signal_connect (eye_cell, "clicked",
                      G_CALLBACK (pika_tool_editor_eye_clicked),
                      tool_editor);
  }

  /* buttons */
  tool_editor->priv->new_group_button =
    pika_editor_add_button (PIKA_EDITOR (tool_editor), PIKA_ICON_FOLDER_NEW,
                            _("Create a new tool group"), NULL,
                            G_CALLBACK (pika_tool_editor_new_group_clicked),
                            NULL,
                            G_OBJECT (tool_editor));

  tool_editor->priv->raise_button =
    pika_editor_add_button (PIKA_EDITOR (tool_editor), PIKA_ICON_GO_UP,
                            _("Raise this item"),
                            _("Raise this item to the top"),
                            G_CALLBACK (pika_tool_editor_raise_clicked),
                            G_CALLBACK (pika_tool_editor_raise_extend_clicked),
                            G_OBJECT (tool_editor));

  tool_editor->priv->lower_button =
    pika_editor_add_button (PIKA_EDITOR (tool_editor), PIKA_ICON_GO_DOWN,
                            _("Lower this item"),
                            _("Lower this item to the bottom"),
                            G_CALLBACK (pika_tool_editor_lower_clicked),
                            G_CALLBACK (pika_tool_editor_lower_extend_clicked),
                            G_OBJECT (tool_editor));

  tool_editor->priv->delete_button =
    pika_editor_add_button (PIKA_EDITOR (tool_editor), PIKA_ICON_EDIT_DELETE,
                            _("Delete this tool group"), NULL,
                            G_CALLBACK (pika_tool_editor_delete_clicked),
                            NULL,
                            G_OBJECT (tool_editor));

  tool_editor->priv->reset_button =
    pika_editor_add_button (PIKA_EDITOR (tool_editor), PIKA_ICON_RESET,
                            _("Reset tool order and visibility"), NULL,
                            G_CALLBACK (pika_tool_editor_reset_clicked),
                            NULL,
                            G_OBJECT (tool_editor));

  pika_tool_editor_update_sensitivity (tool_editor);
}

static gboolean
pika_tool_editor_select_items (PikaContainerView   *container_view,
                               GList               *viewables,
                               GList               *paths)
{
  PikaToolEditor *tool_editor = PIKA_TOOL_EDITOR (container_view);
  gboolean        result;

  result = parent_view_iface->select_items (container_view,
                                            viewables, paths);

  pika_tool_editor_update_sensitivity (tool_editor);

  return result;
}

static void
pika_tool_editor_set_container (PikaContainerView *container_view,
                                PikaContainer     *container)
{
  PikaToolEditor *tool_editor = PIKA_TOOL_EDITOR (container_view);

  parent_view_iface->set_container (container_view, container);

  pika_tool_editor_update_container (tool_editor);
}

static void
pika_tool_editor_set_context (PikaContainerView *container_view,
                              PikaContext       *context)
{
  PikaToolEditor *tool_editor = PIKA_TOOL_EDITOR (container_view);

  parent_view_iface->set_context (container_view, context);

  pika_tool_editor_update_container (tool_editor);
}

static gboolean
pika_tool_editor_drop_possible (PikaContainerTreeView   *tree_view,
                                PikaDndType              src_type,
                                GList                   *src_viewables,
                                PikaViewable            *dest_viewable,
                                GtkTreePath             *drop_path,
                                GtkTreeViewDropPosition  drop_pos,
                                GtkTreeViewDropPosition *return_drop_pos,
                                GdkDragAction           *return_drag_action)
{
  if (PIKA_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_possible (
        tree_view,
        src_type, src_viewables, dest_viewable, drop_path, drop_pos,
        return_drop_pos, return_drag_action))
    {
      if (pika_viewable_get_parent (dest_viewable)       ||
          (pika_viewable_get_children (dest_viewable)    &&
           (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
            drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)))
        {
          GList *iter;

          for (iter = src_viewables; iter; iter = iter->next)
            {
              PikaViewable *src_viewable = iter->data;

              if (pika_viewable_get_children (src_viewable))
                return FALSE;
            }
        }

      return TRUE;
    }

  return FALSE;
}

static void
pika_tool_editor_drop_viewables (PikaContainerTreeView   *tree_view,
                                 GList                   *src_viewables,
                                 PikaViewable            *dest_viewable,
                                 GtkTreeViewDropPosition  drop_pos)
{
  PikaContainerView *container_view = PIKA_CONTAINER_VIEW (tree_view);

  PIKA_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_viewables (tree_view,
                                                                 src_viewables,
                                                                 dest_viewable,
                                                                 drop_pos);

  if (src_viewables)
    pika_container_view_select_items (container_view, src_viewables);
}

static void
pika_tool_editor_new_group_clicked (GtkButton      *button,
                                    PikaToolEditor *tool_editor)
{
  PikaContainerView *container_view = PIKA_CONTAINER_VIEW (tool_editor);
  PikaContainer     *container;
  PikaToolItem      *tool_item;
  PikaToolGroup     *group;
  gint               index = 0;

  tool_item = pika_tool_editor_get_selected_tool_item (tool_editor);

  if (tool_item)
    {
      if (pika_viewable_get_parent (PIKA_VIEWABLE (tool_item)) != NULL)
        return;

      container = pika_tool_editor_get_tool_item_container (tool_editor,
                                                            tool_item);

      index = pika_container_get_child_index (container,
                                              PIKA_OBJECT (tool_item));
    }
  else
    {
      container = tool_editor->priv->container;
    }

  if (container)
    {
      group = pika_tool_group_new ();

      pika_container_insert (container, PIKA_OBJECT (group), index);

      g_object_unref (group);

      pika_container_view_select_item (container_view, PIKA_VIEWABLE (group));
    }
}

static void
pika_tool_editor_raise_clicked (GtkButton      *button,
                                PikaToolEditor *tool_editor)
{
  PikaToolItem *tool_item;

  tool_item = pika_tool_editor_get_selected_tool_item (tool_editor);

  if (tool_item)
    {
      PikaContainer *container;
      gint           index;

      container = pika_tool_editor_get_tool_item_container (tool_editor,
                                                            tool_item);

      index = pika_container_get_child_index (container,
                                              PIKA_OBJECT (tool_item));

      if (index > 0)
        {
          pika_container_reorder (container,
                                  PIKA_OBJECT (tool_item), index - 1);
        }
    }
}

static void
pika_tool_editor_raise_extend_clicked (GtkButton       *button,
                                       GdkModifierType  mask,
                                       PikaToolEditor  *tool_editor)
{
  PikaToolItem *tool_item;

  tool_item = pika_tool_editor_get_selected_tool_item (tool_editor);

  if (tool_item && (mask & GDK_SHIFT_MASK))
    {
      PikaContainer *container;
      gint           index;

      container = pika_tool_editor_get_tool_item_container (tool_editor,
                                                            tool_item);

      index = pika_container_get_child_index (container,
                                              PIKA_OBJECT (tool_item));

      if (index > 0)
        {
          pika_container_reorder (container,
                                  PIKA_OBJECT (tool_item), 0);
        }
    }
}

static void
pika_tool_editor_lower_clicked (GtkButton      *button,
                                PikaToolEditor *tool_editor)
{
  PikaToolItem *tool_item;

  tool_item = pika_tool_editor_get_selected_tool_item (tool_editor);

  if (tool_item)
    {
      PikaContainer *container;
      gint           index;

      container = pika_tool_editor_get_tool_item_container (tool_editor,
                                                            tool_item);

      index = pika_container_get_child_index (container,
                                              PIKA_OBJECT (tool_item));

      if (index + 1 < pika_container_get_n_children (container))
        {
          pika_container_reorder (container,
                                  PIKA_OBJECT (tool_item), index + 1);
        }
    }
}

static void
pika_tool_editor_lower_extend_clicked (GtkButton       *button,
                                       GdkModifierType  mask,
                                       PikaToolEditor  *tool_editor)
{
  PikaToolItem *tool_item;

  tool_item = pika_tool_editor_get_selected_tool_item (tool_editor);

  if (tool_item && (mask & GDK_SHIFT_MASK))
    {
      PikaContainer *container;
      gint           index;

      container = pika_tool_editor_get_tool_item_container (tool_editor,
                                                            tool_item);

      index = pika_container_get_n_children (container) - 1;
      index = MAX (index, 0);

      pika_container_reorder (container,
                              PIKA_OBJECT (tool_item), index);
    }
}

static void
pika_tool_editor_delete_clicked (GtkButton      *button,
                                 PikaToolEditor *tool_editor)
{
  PikaContainerView *container_view = PIKA_CONTAINER_VIEW (tool_editor);
  PikaToolItem     *tool_item;

  tool_item = pika_tool_editor_get_selected_tool_item (tool_editor);

  if (tool_item)
    {
      PikaContainer *src_container;
      PikaContainer *dest_container;
      gint           index;
      gint           dest_index;

      src_container  = pika_viewable_get_children (PIKA_VIEWABLE (tool_item));
      dest_container = pika_tool_editor_get_tool_item_container (tool_editor,
                                                                 tool_item);

      if (! src_container)
        return;

      index      = pika_container_get_child_index (dest_container,
                                                   PIKA_OBJECT (tool_item));
      dest_index = index;

      g_object_ref (tool_item);

      pika_container_freeze (src_container);
      pika_container_freeze (dest_container);

      pika_container_remove (dest_container, PIKA_OBJECT (tool_item));

      while (! pika_container_is_empty (src_container))
        {
          PikaObject *object = pika_container_get_first_child (src_container);

          g_object_ref (object);

          pika_container_remove (src_container,  object);
          pika_container_insert (dest_container, object, dest_index++);

          g_object_unref (object);
        }

      pika_container_thaw (dest_container);
      pika_container_thaw (src_container);

      pika_container_view_select_item (
        container_view,
        PIKA_VIEWABLE (pika_container_get_child_by_index (dest_container,
                                                          index)));

      g_object_unref (tool_item);
    }
}

static void
pika_tool_editor_reset_clicked (GtkButton      *button,
                                PikaToolEditor *tool_editor)
{
  pika_tools_reset (tool_editor->priv->context->pika,
                    tool_editor->priv->container,
                    FALSE);
}

static void
pika_tool_editor_tool_item_notify (PikaToolItem   *tool_item,
                                   GParamSpec     *pspec,
                                   PikaToolEditor *tool_editor)
{
  PikaContainerTreeView *tree_view      = PIKA_CONTAINER_TREE_VIEW (tool_editor);
  PikaContainerView     *container_view = PIKA_CONTAINER_VIEW (tool_editor);
  GtkTreeIter           *iter;

  iter = pika_container_view_lookup (container_view,
                                     PIKA_VIEWABLE (tool_item));

  if (iter)
    {
      GtkTreePath *path;

      path = gtk_tree_model_get_path (tree_view->model, iter);

      gtk_tree_model_row_changed (tree_view->model, path, iter);

      gtk_tree_path_free (path);
    }
}

static void
pika_tool_editor_eye_data_func (GtkTreeViewColumn *tree_column,
                                GtkCellRenderer   *cell,
                                GtkTreeModel      *tree_model,
                                GtkTreeIter       *iter,
                                gpointer           data)
{
  PikaViewRenderer *renderer;
  PikaToolItem     *tool_item;

  gtk_tree_model_get (tree_model, iter,
                      PIKA_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
                      -1);

  tool_item = PIKA_TOOL_ITEM (renderer->viewable);

  g_object_set (cell,
                "active",       pika_tool_item_get_visible (tool_item),
                "inconsistent", pika_tool_item_get_visible (tool_item) &&
                                ! pika_tool_item_get_shown (tool_item),
                NULL);

  g_object_unref (renderer);
}

static void
pika_tool_editor_eye_clicked (GtkCellRendererToggle *toggle,
                              gchar                 *path_str,
                              GdkModifierType        state,
                              PikaToolEditor        *tool_editor)
{
  PikaContainerTreeView *tree_view = PIKA_CONTAINER_TREE_VIEW (tool_editor);
  GtkTreePath           *path;
  GtkTreeIter            iter;

  path = gtk_tree_path_new_from_string (path_str);

  if (gtk_tree_model_get_iter (tree_view->model, &iter, path))
    {
      PikaViewRenderer *renderer;
      PikaToolItem     *tool_item;
      gboolean          active;

      gtk_tree_model_get (tree_view->model, &iter,
                          PIKA_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
                          -1);

      tool_item = PIKA_TOOL_ITEM (renderer->viewable);

      g_object_get (toggle,
                    "active", &active,
                    NULL);

      pika_tool_item_set_visible (tool_item, ! active);

      g_object_unref (renderer);
    }

  gtk_tree_path_free (path);
}

static PikaToolItem *
pika_tool_editor_get_selected_tool_item (PikaToolEditor *tool_editor)
{
  PikaContainerTreeView *tree_view = PIKA_CONTAINER_TREE_VIEW (tool_editor);

  if (tool_editor->priv->container)
    {
      PikaViewRenderer *renderer;
      PikaToolItem     *tool_item;
      GtkTreeSelection *selection;
      GtkTreeModel     *model;
      GtkTreeIter       iter;

      selection = gtk_tree_view_get_selection (tree_view->view);

      if (! gtk_tree_selection_get_selected (selection, &model, &iter))
        return NULL;

      gtk_tree_model_get (model, &iter,
                          PIKA_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
                          -1);

      tool_item = PIKA_TOOL_ITEM (renderer->viewable);

      g_object_unref (renderer);

      return tool_item;
    }

  return NULL;
}

static PikaContainer *
pika_tool_editor_get_tool_item_container (PikaToolEditor *tool_editor,
                                          PikaToolItem   *tool_item)
{
  PikaViewable *parent;

  parent = pika_viewable_get_parent (PIKA_VIEWABLE (tool_item));

  if (parent)
    {
      return pika_viewable_get_children (parent);
    }
  else
    {
      return tool_editor->priv->container;
    }
}

static void
pika_tool_editor_update_container (PikaToolEditor *tool_editor)
{
  PikaContainerView *container_view = PIKA_CONTAINER_VIEW (tool_editor);
  PikaContainer     *container;
  PikaContext       *context;

  g_clear_pointer (&tool_editor->priv->tool_item_notify_handler,
                   pika_tree_handler_disconnect);

  g_clear_pointer (&tool_editor->priv->initial_tool_state, g_free);

  container = pika_container_view_get_container (container_view);
  context   = pika_container_view_get_context   (container_view);

  if (container && context)
    {
      GString          *string;
      PikaConfigWriter *writer;

      tool_editor->priv->container = container;
      tool_editor->priv->context   = context;

      tool_editor->priv->tool_item_notify_handler = pika_tree_handler_connect (
        container, "notify",
        G_CALLBACK (pika_tool_editor_tool_item_notify),
        tool_editor);

      /* save initial tool order */
      string = g_string_new (NULL);

      writer = pika_config_writer_new_from_string (string);

      pika_tools_serialize (context->pika, container, writer);

      pika_config_writer_finish (writer, NULL, NULL);

      tool_editor->priv->initial_tool_state = g_string_free (string, FALSE);
    }
}

static void
pika_tool_editor_update_sensitivity (PikaToolEditor *tool_editor)
{
  PikaToolItem *tool_item;

  tool_item = pika_tool_editor_get_selected_tool_item (tool_editor);

  if (tool_item)
    {
      PikaContainer *container;
      gint           index;

      container = pika_tool_editor_get_tool_item_container (tool_editor,
                                                            tool_item);

      index = pika_container_get_child_index (container,
                                              PIKA_OBJECT (tool_item));

      gtk_widget_set_sensitive (
        tool_editor->priv->new_group_button,
        pika_viewable_get_parent (PIKA_VIEWABLE (tool_item)) == NULL);

      gtk_widget_set_sensitive (
        tool_editor->priv->raise_button,
        index > 0);

      gtk_widget_set_sensitive (
        tool_editor->priv->lower_button,
        index < pika_container_get_n_children (container) - 1);

      gtk_widget_set_sensitive (
        tool_editor->priv->delete_button,
        pika_viewable_get_children (PIKA_VIEWABLE (tool_item)) != NULL);
    }
  else
    {
      gtk_widget_set_sensitive (tool_editor->priv->new_group_button, TRUE);
      gtk_widget_set_sensitive (tool_editor->priv->raise_button,     FALSE);
      gtk_widget_set_sensitive (tool_editor->priv->lower_button,     FALSE);
      gtk_widget_set_sensitive (tool_editor->priv->delete_button,    FALSE);
    }
}


/*  public functions  */

GtkWidget *
pika_tool_editor_new (PikaContainer *container,
                      PikaContext   *context,
                      gint           view_size,
                      gint           view_border_width)
{
  PikaContainerView *container_view;

  g_return_val_if_fail (PIKA_IS_CONTAINER (container), NULL);
  g_return_val_if_fail (PIKA_IS_CONTEXT (context), NULL);

  container_view = g_object_new (PIKA_TYPE_TOOL_EDITOR,
                                 "view-size",         view_size,
                                 "view-border-width", view_border_width,
                                 NULL);

  pika_container_view_set_context     (container_view, context);
  pika_container_view_set_container   (container_view, container);
  pika_container_view_set_reorderable (container_view, TRUE);

  return GTK_WIDGET (container_view);
}

/**
 * pika_tool_editor_revert_changes:
 * @tool_editor:
 *
 * Reverts the tool order and visibility to the state at creation.
 **/
void
pika_tool_editor_revert_changes (PikaToolEditor *tool_editor)
{
  GScanner *scanner;

  g_return_if_fail (PIKA_IS_TOOL_EDITOR (tool_editor));

  scanner = pika_scanner_new_string (tool_editor->priv->initial_tool_state, -1,
                                     NULL);

  pika_tools_deserialize (tool_editor->priv->context->pika,
                          tool_editor->priv->container,
                          scanner);

  pika_scanner_unref (scanner);
}
