PIKApp/app/widgets/pikatooleditor.c

858 lines
30 KiB
C

/* 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);
}