widgets, pdb, libgimp: GimpProcedureDialog Item Widget

This patch adds a GimpItemChooser widget
for use in GimpProcedureDialog Item parameter
GUI creation.
This will deprecate the existing
GimpDrawableChooser, as it covers all the
same cases plus others such as GimpPath.
This commit is contained in:
Alx Sa 2025-11-16 16:42:24 +00:00
parent bb9c3a85dc
commit 37a0e37d25
23 changed files with 2122 additions and 5 deletions

View file

@ -419,6 +419,7 @@ gimp_pdb_dialog_new (Gimp *gimp,
g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
g_return_val_if_fail (g_type_is_a (contents_type, GIMP_TYPE_RESOURCE) ||
g_type_is_a (contents_type, GIMP_TYPE_DRAWABLE) ||
g_type_is_a (contents_type, GIMP_TYPE_ITEM) ||
g_type_is_a (contents_type, GIMP_TYPE_IMAGE), FALSE);
g_return_val_if_fail (object == NULL ||
g_type_is_a (G_TYPE_FROM_INSTANCE (object), contents_type), FALSE);
@ -453,6 +454,7 @@ gimp_pdb_dialog_set (Gimp *gimp,
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
g_return_val_if_fail (g_type_is_a (contents_type, GIMP_TYPE_RESOURCE) ||
contents_type == GIMP_TYPE_DRAWABLE ||
contents_type == GIMP_TYPE_ITEM ||
contents_type == GIMP_TYPE_IMAGE, FALSE);
g_return_val_if_fail (callback_name != NULL, FALSE);
g_return_val_if_fail (object == NULL || g_type_is_a (G_TYPE_FROM_INSTANCE (object), contents_type), FALSE);
@ -480,6 +482,7 @@ gimp_pdb_dialog_close (Gimp *gimp,
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
g_return_val_if_fail (g_type_is_a (contents_type, GIMP_TYPE_RESOURCE) ||
contents_type == GIMP_TYPE_DRAWABLE ||
contents_type == GIMP_TYPE_ITEM ||
contents_type == GIMP_TYPE_IMAGE, FALSE);
g_return_val_if_fail (callback_name != NULL, FALSE);

View file

@ -86,6 +86,7 @@
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpimageselect.h"
#include "widgets/gimpimageview.h"
#include "widgets/gimpitemselect.h"
#include "widgets/gimpmenufactory.h"
#include "widgets/gimppaletteselect.h"
#include "widgets/gimppatternselect.h"
@ -668,6 +669,11 @@ gui_pdb_dialog_new (Gimp *gimp,
dialog_type = GIMP_TYPE_PICKABLE_SELECT;
dialog_role = "gimp-pickable-selection";
}
else if (g_type_is_a (contents_type, GIMP_TYPE_ITEM))
{
dialog_type = GIMP_TYPE_ITEM_SELECT;
dialog_role = "gimp-item-selection";
}
else
{
g_return_val_if_reached (FALSE);
@ -675,10 +681,10 @@ gui_pdb_dialog_new (Gimp *gimp,
if (dialog_type != G_TYPE_NONE)
{
if (! object && ! g_type_is_a (contents_type, GIMP_TYPE_DRAWABLE))
if (! object && ! g_type_is_a (contents_type, GIMP_TYPE_ITEM))
object = gimp_context_get_by_type (context, contents_type);
if (object || g_type_is_a (contents_type, GIMP_TYPE_DRAWABLE))
if (object || g_type_is_a (contents_type, GIMP_TYPE_ITEM))
{
gint n_properties = 0;
gchar **names = NULL;
@ -794,6 +800,10 @@ gui_pdb_dialog_set (Gimp *gimp,
{
klass = g_type_class_peek (GIMP_TYPE_PICKABLE_SELECT);
}
else if (contents_type == GIMP_TYPE_ITEM)
{
klass = g_type_class_peek (GIMP_TYPE_ITEM_SELECT);
}
g_return_val_if_fail (klass != NULL, FALSE);
@ -848,6 +858,8 @@ gui_pdb_dialog_close (Gimp *gimp,
klass = g_type_class_peek (GIMP_TYPE_PATTERN_SELECT);
else if (contents_type == GIMP_TYPE_DRAWABLE)
klass = g_type_class_peek (GIMP_TYPE_PICKABLE_SELECT);
else if (contents_type == GIMP_TYPE_ITEM)
klass = g_type_class_peek (GIMP_TYPE_ITEM_SELECT);
if (klass)
{

View file

@ -30,7 +30,7 @@
#include "internal-procs.h"
/* 782 procedures registered total */
/* 785 procedures registered total */
void
internal_procs_init (GimpPDB *pdb)

View file

@ -31,6 +31,8 @@
#include "pdb-types.h"
#include "core/gimp.h"
#include "core/gimpdatafactory.h"
#include "core/gimpgrouplayer.h"
#include "core/gimpimage.h"
#include "core/gimpitem.h"
@ -1113,6 +1115,95 @@ item_get_parasite_list_invoker (GimpProcedure *procedure,
return return_vals;
}
static GimpValueArray *
items_popup_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
const gchar *callback;
const gchar *popup_title;
const gchar *item_type;
GimpItem *initial_item;
GBytes *parent_window;
callback = g_value_get_string (gimp_value_array_index (args, 0));
popup_title = g_value_get_string (gimp_value_array_index (args, 1));
item_type = g_value_get_string (gimp_value_array_index (args, 2));
initial_item = g_value_get_object (gimp_value_array_index (args, 3));
parent_window = g_value_get_boxed (gimp_value_array_index (args, 4));
if (success)
{
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, callback) ||
! gimp_pdb_dialog_new (gimp, context, progress,
g_type_from_name (item_type),
parent_window, popup_title, callback,
GIMP_OBJECT (initial_item),
NULL))
success = FALSE;
}
return gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
}
static GimpValueArray *
items_close_popup_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
const gchar *callback;
callback = g_value_get_string (gimp_value_array_index (args, 0));
if (success)
{
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, callback) ||
! gimp_pdb_dialog_close (gimp, GIMP_TYPE_ITEM, callback))
success = FALSE;
}
return gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
}
static GimpValueArray *
items_set_popup_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
const gchar *callback;
GimpItem *item;
callback = g_value_get_string (gimp_value_array_index (args, 0));
item = g_value_get_object (gimp_value_array_index (args, 1));
if (success)
{
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, callback) ||
! gimp_pdb_dialog_set (gimp, GIMP_TYPE_ITEM, callback, GIMP_OBJECT (item), NULL))
success = FALSE;
}
return gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
}
void
register_item_procs (GimpPDB *pdb)
{
@ -2201,4 +2292,108 @@ register_item_procs (GimpPDB *pdb)
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-items-popup
*/
procedure = gimp_procedure_new (items_popup_invoker, FALSE);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-items-popup");
gimp_procedure_set_static_help (procedure,
"Invokes the item selection dialog.",
"Opens a dialog letting a user choose an item .",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Alex S.",
"Alex S.",
"2025");
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("callback",
"callback",
"The callback PDB proc to call when user chooses an item",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("popup-title",
"popup title",
"Title of the item selection dialog",
FALSE, FALSE, FALSE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("item-type",
"item type",
"The name of the GIMP_TYPE_ITEM subtype",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_item ("initial-item",
"initial item",
"The item to set as the initial choice",
TRUE,
GIMP_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE));
gimp_procedure_add_argument (procedure,
g_param_spec_boxed ("parent-window",
"parent window",
"An optional parent window handle for the popup to be set transient to",
G_TYPE_BYTES,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-items-close-popup
*/
procedure = gimp_procedure_new (items_close_popup_invoker, FALSE);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-items-close-popup");
gimp_procedure_set_static_help (procedure,
"Close the item selection dialog.",
"Closes an open item selection dialog.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Alex S.",
"Alex S.",
"2025");
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("callback",
"callback",
"The name of the callback registered for this pop-up",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-items-set-popup
*/
procedure = gimp_procedure_new (items_set_popup_invoker, FALSE);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-items-set-popup");
gimp_procedure_set_static_help (procedure,
"Sets the selected item in a item selection dialog.",
"Sets the selected item in a item selection dialog.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Alex S.",
"Alex S.",
"2025");
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("callback",
"callback",
"The name of the callback registered for this pop-up",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_item ("item",
"item",
"The item to set as selected",
FALSE,
GIMP_PARAM_READWRITE | GIMP_PARAM_NO_VALIDATE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
}

View file

@ -0,0 +1,639 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpitemchooser.c
*
* 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 <gdk/gdkkeysyms.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "widgets-types.h"
#include "core/gimp.h"
#include "core/gimpchannel.h"
#include "core/gimpcontext.h"
#include "core/gimpimage.h"
#include "core/gimpitem.h"
#include "core/gimplayer.h"
#include "core/gimpviewable.h"
#include "path/gimppath.h"
#include "gimpcontainertreeview.h"
#include "gimpcontainerview.h"
#include "gimpitemchooser.h"
#include "gimpviewrenderer.h"
#include "gimp-intl.h"
enum
{
ACTIVATE,
LAST_SIGNAL
};
enum
{
PROP_0,
PROP_CONTEXT,
PROP_ITEM_TYPE,
PROP_ITEM,
PROP_VIEW_SIZE,
PROP_VIEW_BORDER_WIDTH
};
struct _GimpItemChooserPrivate
{
GType item_type;
GimpItem *item;
GimpContext *context;
gint view_size;
gint view_border_width;
GtkWidget *image_view;
GtkWidget *layer_view;
GtkWidget *channel_view;
GtkWidget *path_view;
GtkWidget *layer_label;
};
static void gimp_item_chooser_constructed (GObject *object);
static void gimp_item_chooser_finalize (GObject *object);
static void gimp_item_chooser_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_item_chooser_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_item_chooser_image_changed (GimpContext *context,
GimpImage *image,
GimpItemChooser *chooser);
static void gimp_item_chooser_item_activated (GimpContainerView *view,
GimpItem *item,
GimpItemChooser *chooser);
static void gimp_item_chooser_items_selected (GimpContainerView *view,
GimpItemChooser *chooser);
G_DEFINE_TYPE_WITH_PRIVATE (GimpItemChooser, gimp_item_chooser, GTK_TYPE_FRAME)
#define parent_class gimp_item_chooser_parent_class
static guint signals[LAST_SIGNAL];
static void
gimp_item_chooser_class_init (GimpItemChooserClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = gimp_item_chooser_constructed;
object_class->finalize = gimp_item_chooser_finalize;
object_class->get_property = gimp_item_chooser_get_property;
object_class->set_property = gimp_item_chooser_set_property;
/**
* GimpItemChooser::activate:
* @chooser:
*
* Emitted when a item is activated, which is mostly forwarding when
* "item-activated" signal is emitted from any of either the image, layer or
* channel view. E.g. this happens when one double-click on one of the
* items.
*/
signals[ACTIVATE] =
g_signal_new ("activate",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpItemChooserClass, activate),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
GIMP_TYPE_OBJECT);
g_object_class_install_property (object_class, PROP_CONTEXT,
g_param_spec_object ("context",
NULL, NULL,
GIMP_TYPE_CONTEXT,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class, PROP_ITEM_TYPE,
g_param_spec_gtype ("item-type",
NULL, NULL,
GIMP_TYPE_ITEM,
GIMP_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class, PROP_ITEM,
g_param_spec_object ("item",
NULL, NULL,
GIMP_TYPE_ITEM,
GIMP_PARAM_READWRITE |
G_PARAM_EXPLICIT_NOTIFY));
g_object_class_install_property (object_class, PROP_VIEW_SIZE,
g_param_spec_int ("view-size",
NULL, NULL,
1, GIMP_VIEWABLE_MAX_PREVIEW_SIZE,
GIMP_VIEW_SIZE_MEDIUM,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class, PROP_VIEW_BORDER_WIDTH,
g_param_spec_int ("view-border-width",
NULL, NULL,
0,
GIMP_VIEW_MAX_BORDER_WIDTH,
1,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
}
static void
gimp_item_chooser_init (GimpItemChooser *chooser)
{
chooser->priv = gimp_item_chooser_get_instance_private (chooser);
chooser->priv->view_size = GIMP_VIEW_SIZE_SMALL;
chooser->priv->view_border_width = 1;
chooser->priv->layer_view = NULL;
chooser->priv->channel_view = NULL;
}
static void
gimp_item_chooser_constructed (GObject *object)
{
GimpItemChooser *chooser = GIMP_ITEM_CHOOSER (object);
GtkWidget *hbox;
GtkWidget *vbox;
GtkWidget *label;
GtkWidget *notebook;
GimpImage *image;
G_OBJECT_CLASS (parent_class)->constructed (object);
gimp_assert (GIMP_IS_CONTEXT (chooser->priv->context));
gtk_frame_set_shadow_type (GTK_FRAME (chooser), GTK_SHADOW_OUT);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
gtk_container_add (GTK_CONTAINER (chooser), hbox);
gtk_widget_set_visible (hbox, TRUE);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
gtk_widget_set_visible (vbox, TRUE);
label = gtk_label_new (_("Images"));
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
gtk_widget_set_visible (label, TRUE);
chooser->priv->image_view =
gimp_container_tree_view_new (chooser->priv->context->gimp->images,
chooser->priv->context,
chooser->priv->view_size,
chooser->priv->view_border_width);
gimp_container_box_set_size_request (GIMP_CONTAINER_BOX (chooser->priv->image_view),
4 * (chooser->priv->view_size +
2 * chooser->priv->view_border_width),
4 * (chooser->priv->view_size +
2 * chooser->priv->view_border_width));
gtk_box_pack_start (GTK_BOX (vbox), chooser->priv->image_view, TRUE, TRUE, 0);
gtk_widget_set_visible (chooser->priv->image_view, TRUE);
g_signal_connect_object (chooser->priv->image_view, "item-activated",
G_CALLBACK (gimp_item_chooser_item_activated),
G_OBJECT (chooser), 0);
g_signal_connect_object (chooser->priv->image_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
gtk_widget_set_visible (vbox, TRUE);
chooser->priv->layer_label = label =
gtk_label_new (_("Select an image in the left pane"));
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
gtk_widget_set_visible (label, TRUE);
notebook = gtk_notebook_new ();
gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
gtk_widget_set_visible (notebook, TRUE);
if (g_type_is_a (GIMP_TYPE_LAYER, chooser->priv->item_type))
{
chooser->priv->layer_view =
gimp_container_tree_view_new (NULL,
chooser->priv->context,
chooser->priv->view_size,
chooser->priv->view_border_width);
gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (GIMP_CONTAINER_TREE_VIEW (chooser->priv->layer_view)->view),
TRUE);
gimp_container_box_set_size_request (GIMP_CONTAINER_BOX (chooser->priv->layer_view),
4 * (chooser->priv->view_size +
2 * chooser->priv->view_border_width),
4 * (chooser->priv->view_size +
2 * chooser->priv->view_border_width));
gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
chooser->priv->layer_view,
gtk_label_new (_("Layers")));
gtk_widget_set_visible (chooser->priv->layer_view, TRUE);
g_signal_connect_object (chooser->priv->layer_view, "item-activated",
G_CALLBACK (gimp_item_chooser_item_activated),
G_OBJECT (chooser), 0);
g_signal_connect_object (chooser->priv->layer_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
}
if (g_type_is_a (GIMP_TYPE_CHANNEL, chooser->priv->item_type))
{
chooser->priv->channel_view =
gimp_container_tree_view_new (NULL,
chooser->priv->context,
chooser->priv->view_size,
chooser->priv->view_border_width);
gimp_container_box_set_size_request (GIMP_CONTAINER_BOX (chooser->priv->channel_view),
4 * (chooser->priv->view_size +
2 * chooser->priv->view_border_width),
4 * (chooser->priv->view_size +
2 * chooser->priv->view_border_width));
gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
chooser->priv->channel_view,
gtk_label_new (_("Channels")));
gtk_widget_set_visible (chooser->priv->channel_view, TRUE);
g_signal_connect_object (chooser->priv->channel_view, "item-activated",
G_CALLBACK (gimp_item_chooser_item_activated),
G_OBJECT (chooser), 0);
g_signal_connect_object (chooser->priv->channel_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
}
if (g_type_is_a (GIMP_TYPE_PATH, chooser->priv->item_type))
{
chooser->priv->path_view =
gimp_container_tree_view_new (NULL,
chooser->priv->context,
chooser->priv->view_size,
chooser->priv->view_border_width);
gimp_container_box_set_size_request (GIMP_CONTAINER_BOX (chooser->priv->path_view),
4 * (chooser->priv->view_size +
2 * chooser->priv->view_border_width),
4 * (chooser->priv->view_size +
2 * chooser->priv->view_border_width));
gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
chooser->priv->path_view,
gtk_label_new (_("Paths")));
gtk_widget_set_visible (chooser->priv->path_view, TRUE);
g_signal_connect_object (chooser->priv->path_view, "item-activated",
G_CALLBACK (gimp_item_chooser_item_activated),
G_OBJECT (chooser), 0);
g_signal_connect_object (chooser->priv->path_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
}
g_signal_connect_object (chooser->priv->context, "image-changed",
G_CALLBACK (gimp_item_chooser_image_changed),
G_OBJECT (chooser), 0);
image = gimp_context_get_image (chooser->priv->context);
gimp_item_chooser_image_changed (chooser->priv->context, image, chooser);
}
static void
gimp_item_chooser_finalize (GObject *object)
{
GimpItemChooser *chooser = GIMP_ITEM_CHOOSER (object);
g_clear_object (&chooser->priv->item);
g_clear_object (&chooser->priv->context);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gimp_item_chooser_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpItemChooser *chooser = GIMP_ITEM_CHOOSER (object);
switch (property_id)
{
case PROP_CONTEXT:
chooser->priv->context = g_value_dup_object (value);
break;
case PROP_VIEW_SIZE:
chooser->priv->view_size = g_value_get_int (value);
break;
case PROP_VIEW_BORDER_WIDTH:
chooser->priv->view_border_width = g_value_get_int (value);
break;
case PROP_ITEM_TYPE:
g_return_if_fail (g_value_get_gtype (value) == GIMP_TYPE_LAYER ||
g_value_get_gtype (value) == GIMP_TYPE_CHANNEL ||
g_value_get_gtype (value) == GIMP_TYPE_DRAWABLE ||
g_value_get_gtype (value) == GIMP_TYPE_PATH ||
g_value_get_gtype (value) == GIMP_TYPE_IMAGE ||
g_value_get_gtype (value) == GIMP_TYPE_ITEM);
chooser->priv->item_type = g_value_get_gtype (value);
break;
case PROP_ITEM:
g_return_if_fail (g_value_get_object (value) == NULL ||
g_type_is_a (G_TYPE_FROM_INSTANCE (g_value_get_object (value)),
chooser->priv->item_type));
gimp_item_chooser_set_item (chooser, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_item_chooser_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpItemChooser *chooser = GIMP_ITEM_CHOOSER (object);
switch (property_id)
{
case PROP_CONTEXT:
g_value_set_object (value, chooser->priv->context);
break;
case PROP_ITEM_TYPE:
g_value_set_gtype (value, chooser->priv->item_type);
break;
case PROP_ITEM:
g_value_set_object (value, chooser->priv->item);
break;
case PROP_VIEW_SIZE:
g_value_set_int (value, chooser->priv->view_size);
break;
case PROP_VIEW_BORDER_WIDTH:
g_value_set_int (value, chooser->priv->view_border_width);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
GtkWidget *
gimp_item_chooser_new (GimpContext *context,
GType item_type,
gint view_size,
gint view_border_width)
{
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
g_return_val_if_fail (view_size > 0 &&
view_size <= GIMP_VIEWABLE_MAX_POPUP_SIZE, NULL);
g_return_val_if_fail (view_border_width >= 0 &&
view_border_width <= GIMP_VIEW_MAX_BORDER_WIDTH,
NULL);
return g_object_new (GIMP_TYPE_ITEM_CHOOSER,
"context", context,
"item-type", item_type,
"view-size", view_size,
"view-border-width", view_border_width,
NULL);
}
GimpItem *
gimp_item_chooser_get_item (GimpItemChooser *chooser)
{
g_return_val_if_fail (GIMP_IS_ITEM_CHOOSER (chooser), NULL);
return chooser->priv->item;
}
void
gimp_item_chooser_set_item (GimpItemChooser *chooser,
GimpItem *item)
{
if (! gtk_widget_in_destruction (GTK_WIDGET (chooser)))
{
g_signal_handlers_disconnect_by_func (chooser->priv->image_view,
G_CALLBACK (gimp_item_chooser_items_selected),
chooser);
if (chooser->priv->layer_view != NULL)
g_signal_handlers_disconnect_by_func (chooser->priv->layer_view,
G_CALLBACK (gimp_item_chooser_items_selected),
chooser);
else
g_return_if_fail (! GIMP_IS_LAYER (item));
if (chooser->priv->channel_view != NULL)
g_signal_handlers_disconnect_by_func (chooser->priv->channel_view,
G_CALLBACK (gimp_item_chooser_items_selected),
chooser);
else
g_return_if_fail (! GIMP_IS_CHANNEL (item));
if (chooser->priv->path_view != NULL)
g_signal_handlers_disconnect_by_func (chooser->priv->path_view,
G_CALLBACK (gimp_item_chooser_items_selected),
chooser);
else
g_return_if_fail (! GIMP_IS_PATH (item));
if (GIMP_IS_IMAGE (item))
{
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (chooser->priv->image_view),
GIMP_VIEWABLE (item));
gimp_context_set_image (chooser->priv->context, GIMP_IMAGE (item));
}
else if (GIMP_IS_LAYER (item))
{
gimp_context_set_image (chooser->priv->context, gimp_item_get_image (GIMP_ITEM (item)));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (chooser->priv->layer_view),
GIMP_VIEWABLE (item));
}
else if (GIMP_IS_CHANNEL (item))
{
gimp_context_set_image (chooser->priv->context, gimp_item_get_image (GIMP_ITEM (item)));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (chooser->priv->channel_view),
GIMP_VIEWABLE (item));
}
else if (GIMP_IS_PATH (item))
{
gimp_context_set_image (chooser->priv->context, gimp_item_get_image (GIMP_ITEM (item)));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (chooser->priv->path_view),
GIMP_VIEWABLE (item));
}
else
{
g_return_if_fail (item == NULL);
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (chooser->priv->image_view), NULL);
gimp_context_set_image (chooser->priv->context, NULL);
}
g_signal_connect_object (chooser->priv->image_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
if (chooser->priv->layer_view != NULL)
g_signal_connect_object (chooser->priv->layer_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
if (chooser->priv->channel_view != NULL)
g_signal_connect_object (chooser->priv->channel_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
if (chooser->priv->path_view != NULL)
g_signal_connect_object (chooser->priv->path_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
}
if (item != chooser->priv->item)
{
g_clear_object (&chooser->priv->item);
chooser->priv->item = (item != NULL ? g_object_ref (item) : NULL);
g_object_notify (G_OBJECT (chooser), "item");
}
}
/* private functions */
static void
gimp_item_chooser_image_changed (GimpContext *context,
GimpImage *image,
GimpItemChooser *chooser)
{
GimpContainer *layers = NULL;
GimpContainer *channels = NULL;
GimpContainer *paths = NULL;
if (image)
{
gchar *desc;
layers = gimp_image_get_layers (image);
channels = gimp_image_get_channels (image);
paths = gimp_image_get_paths (image);
desc = gimp_viewable_get_description (GIMP_VIEWABLE (image), NULL);
gtk_label_set_text (GTK_LABEL (chooser->priv->layer_label), desc);
g_free (desc);
}
else
{
gtk_label_set_text (GTK_LABEL (chooser->priv->layer_label),
_("Select an image in the left pane"));
}
g_signal_handlers_disconnect_by_func (chooser->priv->image_view,
G_CALLBACK (gimp_item_chooser_items_selected),
chooser);
if (chooser->priv->layer_view != NULL)
{
g_signal_handlers_disconnect_by_func (chooser->priv->layer_view,
G_CALLBACK (gimp_item_chooser_items_selected),
chooser);
gimp_container_view_set_container (GIMP_CONTAINER_VIEW (chooser->priv->layer_view),
layers);
g_signal_connect_object (chooser->priv->layer_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
}
if (chooser->priv->channel_view != NULL)
{
g_signal_handlers_disconnect_by_func (chooser->priv->channel_view,
G_CALLBACK (gimp_item_chooser_items_selected),
chooser);
gimp_container_view_set_container (GIMP_CONTAINER_VIEW (chooser->priv->channel_view),
channels);
g_signal_connect_object (chooser->priv->channel_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
}
if (chooser->priv->path_view != NULL)
{
g_signal_handlers_disconnect_by_func (chooser->priv->path_view,
G_CALLBACK (gimp_item_chooser_items_selected),
chooser);
gimp_container_view_set_container (GIMP_CONTAINER_VIEW (chooser->priv->path_view),
paths);
g_signal_connect_object (chooser->priv->path_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
}
g_signal_connect_object (chooser->priv->image_view, "selection-changed",
G_CALLBACK (gimp_item_chooser_items_selected),
G_OBJECT (chooser), 0);
}
static void
gimp_item_chooser_item_activated (GimpContainerView *view,
GimpItem *item,
GimpItemChooser *chooser)
{
g_signal_emit (chooser, signals[ACTIVATE], 0, item);
}
static void
gimp_item_chooser_items_selected (GimpContainerView *view,
GimpItemChooser *chooser)
{
GimpItem *item = NULL;
gint n_items;
GList *items;
n_items = gimp_container_view_get_selected (view, &items);
g_return_if_fail (n_items <= 1);
if (items)
item = items->data;
gimp_item_chooser_set_item (chooser, item);
}

View file

@ -0,0 +1,61 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpitemchooser.h
*
* 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/>.
*/
#pragma once
#define GIMP_TYPE_ITEM_CHOOSER (gimp_item_chooser_get_type ())
#define GIMP_ITEM_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_ITEM_CHOOSER, GimpItemChooser))
#define GIMP_ITEM_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_ITEM_CHOOSER, GimpItemChooserClass))
#define GIMP_IS_ITEM_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_ITEM_CHOOSER))
#define GIMP_IS_ITEM_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_ITEM_CHOOSER))
#define GIMP_ITEM_CHOOSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_ITEM_CHOOSER, GimpItemChooserClass))
typedef struct _GimpItemChooserPrivate GimpItemChooserPrivate;
typedef struct _GimpItemChooserClass GimpItemChooserClass;
struct _GimpItemChooser
{
GtkFrame parent_instance;
GimpItemChooserPrivate *priv;
};
struct _GimpItemChooserClass
{
GtkFrameClass parent_instance;
/* Signals. */
void (* activate) (GimpItemChooser *view,
GimpItem *item);
};
GType gimp_item_chooser_get_type (void) G_GNUC_CONST;
GtkWidget * gimp_item_chooser_new (GimpContext *context,
GType item_type,
gint view_size,
gint view_border_width);
GimpItem * gimp_item_chooser_get_item (GimpItemChooser *chooser);
void gimp_item_chooser_set_item (GimpItemChooser *chooser,
GimpItem *item);

View file

@ -0,0 +1,174 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpitemselect.c
*
* 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 "libgimpbase/gimpbase.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "widgets-types.h"
#include "gegl/gimp-babl-compat.h"
#include "core/gimp.h"
#include "core/gimpcontext.h"
#include "core/gimpimage.h"
#include "core/gimpitem.h"
#include "core/gimpparamspecs.h"
#include "core/gimptempbuf.h"
#include "pdb/gimppdb.h"
#include "gimpitemchooser.h"
#include "gimpitemselect.h"
#include "gimpcontainerbox.h"
#include "gimp-intl.h"
static void gimp_item_select_constructed (GObject *object);
static GimpValueArray * gimp_item_select_run_callback (GimpPdbDialog *dialog,
GimpObject *object,
gboolean closing,
GError **error);
static GimpObject * gimp_item_select_get_object (GimpPdbDialog *dialog);
static void gimp_item_select_set_object (GimpPdbDialog *dialog,
GimpObject *object);
static void gimp_item_select_activate (GimpItemSelect *select);
static void gimp_item_select_notify_item (GimpItemSelect *select);
G_DEFINE_TYPE (GimpItemSelect, gimp_item_select, GIMP_TYPE_PDB_DIALOG)
#define parent_class gimp_item_select_parent_class
static void
gimp_item_select_class_init (GimpItemSelectClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpPdbDialogClass *pdb_class = GIMP_PDB_DIALOG_CLASS (klass);
object_class->constructed = gimp_item_select_constructed;
pdb_class->run_callback = gimp_item_select_run_callback;
pdb_class->get_object = gimp_item_select_get_object;
pdb_class->set_object = gimp_item_select_set_object;
}
static void
gimp_item_select_init (GimpItemSelect *select)
{
}
static void
gimp_item_select_constructed (GObject *object)
{
GimpPdbDialog *dialog = GIMP_PDB_DIALOG (object);
GimpItemSelect *select = GIMP_ITEM_SELECT (object);
GtkWidget *content_area;
G_OBJECT_CLASS (parent_class)->constructed (object);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
select->chooser = gimp_item_chooser_new (dialog->context, dialog->select_type,
GIMP_VIEW_SIZE_LARGE, 1);
gimp_item_chooser_set_item (GIMP_ITEM_CHOOSER (select->chooser),
GIMP_ITEM (dialog->initial_object));
g_signal_connect_swapped (select->chooser, "notify::item",
G_CALLBACK (gimp_item_select_notify_item),
select);
g_signal_connect_swapped (select->chooser, "activate",
G_CALLBACK (gimp_item_select_activate),
select);
gtk_box_pack_start (GTK_BOX (content_area), select->chooser, TRUE, TRUE, 0);
gtk_widget_set_visible (select->chooser, TRUE);
}
static GimpValueArray *
gimp_item_select_run_callback (GimpPdbDialog *dialog,
GimpObject *object,
gboolean closing,
GError **error)
{
GimpItem *item = GIMP_ITEM (object);
GimpValueArray *return_vals;
return_vals =
gimp_pdb_execute_procedure_by_name (dialog->pdb,
dialog->caller_context,
NULL, error,
dialog->callback_name,
GIMP_TYPE_ITEM, item,
G_TYPE_BOOLEAN, closing,
G_TYPE_NONE);
return return_vals;
}
static GimpObject *
gimp_item_select_get_object (GimpPdbDialog *dialog)
{
GimpItemSelect *select = GIMP_ITEM_SELECT (dialog);
return (GimpObject *) gimp_item_chooser_get_item (GIMP_ITEM_CHOOSER (select->chooser));
}
static void
gimp_item_select_set_object (GimpPdbDialog *dialog,
GimpObject *object)
{
GimpItemSelect *select = GIMP_ITEM_SELECT (dialog);
gimp_item_chooser_set_item (GIMP_ITEM_CHOOSER (select->chooser), GIMP_ITEM (object));
}
static void
gimp_item_select_activate (GimpItemSelect *select)
{
gimp_pdb_dialog_run_callback ((GimpPdbDialog **) &select, TRUE);
gtk_widget_destroy (GTK_WIDGET (select));
}
static void
gimp_item_select_notify_item (GimpItemSelect *select)
{
GtkWidget *button;
GimpItemChooser *chooser = GIMP_ITEM_CHOOSER (select->chooser);
button = gtk_dialog_get_widget_for_response (GTK_DIALOG (select),
GTK_RESPONSE_OK);
/* Clicking Okay when an image but not an item has been
* selected causes the widget to "lock up" and not reappear when you
* click on it again. For now, we'll disable the Okay button until
* an item is selected */
if (GIMP_IS_IMAGE (gimp_item_chooser_get_item (chooser)))
gtk_widget_set_sensitive (button, FALSE);
else
gtk_widget_set_sensitive (button, TRUE);
gimp_pdb_dialog_run_callback ((GimpPdbDialog **) &select, FALSE);
}

View file

@ -0,0 +1,48 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpitemselect.h
*
* 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/>.
*/
#pragma once
#include "gimppdbdialog.h"
#define GIMP_TYPE_ITEM_SELECT (gimp_item_select_get_type ())
#define GIMP_ITEM_SELECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_ITEM_SELECT, GimpItemSelect))
#define GIMP_ITEM_SELECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_ITEM_SELECT, GimpItemSelectClass))
#define GIMP_IS_ITEM_SELECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_ITEM_SELECT))
#define GIMP_IS_ITEM_SELECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_ITEM_SELECT))
#define GIMP_ITEM_SELECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_ITEM_SELECT, GimpItemSelectClass))
typedef struct _GimpItemSelectClass GimpItemSelectClass;
struct _GimpItemSelect
{
GimpPdbDialog parent_instance;
GtkWidget *chooser;
};
struct _GimpItemSelectClass
{
GimpPdbDialogClass parent_class;
};
GType gimp_item_select_get_type (void) G_GNUC_CONST;

View file

@ -145,6 +145,8 @@ libappwidgets_sources = [
'gimpimagepropview.c',
'gimpimageselect.c',
'gimpimageview.c',
'gimpitemchooser.c',
'gimpitemselect.c',
'gimpitemtreeview.c',
'gimpitemtreeview-search.c',
'gimplanguagecombobox.c',

View file

@ -163,6 +163,7 @@ typedef struct _GimpBrushSelect GimpBrushSelect;
typedef struct _GimpFontSelect GimpFontSelect;
typedef struct _GimpGradientSelect GimpGradientSelect;
typedef struct _GimpImageSelect GimpImageSelect;
typedef struct _GimpItemSelect GimpItemSelect;
typedef struct _GimpPaletteSelect GimpPaletteSelect;
typedef struct _GimpPatternSelect GimpPatternSelect;
typedef struct _GimpPickableSelect GimpPickableSelect;
@ -210,6 +211,7 @@ typedef struct _GimpImageCommentEditor GimpImageCommentEditor;
typedef struct _GimpImageParasiteView GimpImageParasiteView;
typedef struct _GimpImageProfileView GimpImageProfileView;
typedef struct _GimpImagePropView GimpImagePropView;
typedef struct _GimpItemChooser GimpItemChooser;
typedef struct _GimpLanguageComboBox GimpLanguageComboBox;
typedef struct _GimpLanguageEntry GimpLanguageEntry;
typedef struct _GimpLanguageStore GimpLanguageStore;

View file

@ -643,6 +643,9 @@ EXPORTS
gimp_item_transform_scale
gimp_item_transform_shear
gimp_item_transform_translate
gimp_items_close_popup
gimp_items_popup
gimp_items_set_popup
gimp_layer_add_alpha
gimp_layer_add_mask
gimp_layer_color_space_get_type

View file

@ -1427,3 +1427,117 @@ gimp_item_get_parasite_list (GimpItem *item)
return parasites;
}
/**
* gimp_items_popup:
* @callback: The callback PDB proc to call when user chooses an item.
* @popup_title: Title of the item selection dialog.
* @item_type: The name of the GIMP_TYPE_ITEM subtype.
* @initial_item: (nullable): The item to set as the initial choice.
* @parent_window: (nullable): An optional parent window handle for the popup to be set transient to.
*
* Invokes the item selection dialog.
*
* Opens a dialog letting a user choose an item .
*
* Returns: TRUE on success.
**/
gboolean
gimp_items_popup (const gchar *callback,
const gchar *popup_title,
const gchar *item_type,
GimpItem *initial_item,
GBytes *parent_window)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean success = TRUE;
args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, callback,
G_TYPE_STRING, popup_title,
G_TYPE_STRING, item_type,
GIMP_TYPE_ITEM, initial_item,
G_TYPE_BYTES, parent_window,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-items-popup",
args);
gimp_value_array_unref (args);
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
gimp_value_array_unref (return_vals);
return success;
}
/**
* gimp_items_close_popup:
* @callback: The name of the callback registered for this pop-up.
*
* Close the item selection dialog.
*
* Closes an open item selection dialog.
*
* Returns: TRUE on success.
**/
gboolean
gimp_items_close_popup (const gchar *callback)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean success = TRUE;
args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, callback,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-items-close-popup",
args);
gimp_value_array_unref (args);
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
gimp_value_array_unref (return_vals);
return success;
}
/**
* gimp_items_set_popup:
* @callback: The name of the callback registered for this pop-up.
* @item: The item to set as selected.
*
* Sets the selected item in a item selection dialog.
*
* Sets the selected item in a item selection dialog.
*
* Returns: TRUE on success.
**/
gboolean
gimp_items_set_popup (const gchar *callback,
GimpItem *item)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean success = TRUE;
args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, callback,
GIMP_TYPE_ITEM, item,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-items-set-popup",
args);
gimp_value_array_unref (args);
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
gimp_value_array_unref (return_vals);
return success;
}

View file

@ -79,6 +79,14 @@ gboolean gimp_item_detach_parasite (GimpItem *item,
GimpParasite* gimp_item_get_parasite (GimpItem *item,
const gchar *name);
gchar** gimp_item_get_parasite_list (GimpItem *item);
gboolean gimp_items_popup (const gchar *callback,
const gchar *popup_title,
const gchar *item_type,
GimpItem *initial_item,
GBytes *parent_window);
gboolean gimp_items_close_popup (const gchar *callback);
gboolean gimp_items_set_popup (const gchar *callback,
GimpItem *item);
G_END_DECLS

630
libgimp/gimpitemchooser.c Normal file
View file

@ -0,0 +1,630 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpitemchooser.h
*
* 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 <gegl.h>
#include <gtk/gtk.h>
#include "libgimpwidgets/gimpwidgets.h"
#include "gimp.h"
#include "gimpuitypes.h"
#include "gimpitemchooser.h"
#include "gimpuimarshal.h"
#include "libgimp-intl.h"
/**
* SECTION: gimpitemchooser
* @title: GimpItemChooser
* @short_description: A widget allowing to select an item.
*
* The chooser contains an optional label and a button which queries the core
* process to pop up a item selection dialog.
*
* Since: 3.0
**/
#define CELL_SIZE 40
enum
{
PROP_0,
PROP_TITLE,
PROP_LABEL,
PROP_ITEM,
PROP_ITEM_TYPE,
N_PROPS
};
struct _GimpItemChooser
{
GtkBox parent_instance;
GType item_type;
GimpItem *item;
gchar *title;
gchar *label;
gchar *callback;
GBytes *thumbnail;
GimpItem *thumbnail_item;
gint width;
gint height;
gint bpp;
GtkWidget *label_widget;
GtkWidget *preview_frame;
GtkWidget *preview;
GtkWidget *preview_title;
};
/* local function prototypes */
static void gimp_item_chooser_constructed (GObject *object);
static void gimp_item_chooser_dispose (GObject *object);
static void gimp_item_chooser_finalize (GObject *object);
static void gimp_item_chooser_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_item_chooser_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static void gimp_item_chooser_clicked (GimpItemChooser *chooser);
static GimpValueArray * gimp_temp_callback_run (GimpProcedure *procedure,
GimpProcedureConfig *config,
GimpItemChooser *chooser);
static gboolean gimp_item_select_remove_after_run (const gchar *procedure_name);
static void gimp_item_chooser_draw (GimpItemChooser *chooser);
static void gimp_item_chooser_get_thumbnail (GimpItemChooser *chooser,
gint width,
gint height);
static GParamSpec *item_button_props[N_PROPS] = { NULL, };
G_DEFINE_FINAL_TYPE (GimpItemChooser, gimp_item_chooser, GTK_TYPE_BOX)
static void
gimp_item_chooser_class_init (GimpItemChooserClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = gimp_item_chooser_constructed;
object_class->dispose = gimp_item_chooser_dispose;
object_class->finalize = gimp_item_chooser_finalize;
object_class->set_property = gimp_item_chooser_set_property;
object_class->get_property = gimp_item_chooser_get_property;
/**
* GimpItemChooser:title:
*
* The title to be used for the item selection popup dialog.
*
* Since: 3.0
*/
item_button_props[PROP_TITLE] =
g_param_spec_string ("title",
"Title",
"The title to be used for the item selection popup dialog",
"Item Selection",
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
/**
* GimpItemChooser:label:
*
* Label text with mnemonic.
*
* Since: 3.0
*/
item_button_props[PROP_LABEL] =
g_param_spec_string ("label",
"Label",
"The label to be used next to the button",
NULL,
GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
/**
* GimpItemChooser:item:
*
* The currently selected item.
*
* Since: 3.0
*/
item_button_props[PROP_ITEM] =
gimp_param_spec_item ("item",
"Item",
"The currently selected item",
TRUE,
GIMP_PARAM_READWRITE |
G_PARAM_EXPLICIT_NOTIFY);
/**
* GimpItemChooser:item-type:
*
* Allowed item types, which must be either GIMP_TYPE_ITEM or a
* subtype.
*
* Since: 3.0
*/
item_button_props[PROP_ITEM_TYPE] =
g_param_spec_gtype ("item-type",
"Allowed item Type",
"The GType of the item property",
GIMP_TYPE_ITEM,
G_PARAM_CONSTRUCT_ONLY |
GIMP_PARAM_READWRITE);
g_object_class_install_properties (object_class,
N_PROPS, item_button_props);
}
static void
gimp_item_chooser_init (GimpItemChooser *chooser)
{
gtk_orientable_set_orientation (GTK_ORIENTABLE (chooser),
GTK_ORIENTATION_HORIZONTAL);
gtk_box_set_spacing (GTK_BOX (chooser), 6);
chooser->thumbnail_item = NULL;
chooser->thumbnail = NULL;
}
static void
gimp_item_chooser_constructed (GObject *object)
{
GimpItemChooser *chooser = GIMP_ITEM_CHOOSER (object);
GtkWidget *button;
GtkWidget *box;
gint scale_factor;
scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (chooser));
chooser->label_widget = gtk_label_new (NULL);
gtk_box_pack_start (GTK_BOX (chooser), chooser->label_widget, FALSE, FALSE, 0);
gtk_label_set_text_with_mnemonic (GTK_LABEL (chooser->label_widget), chooser->label);
gtk_widget_set_visible (GTK_WIDGET (chooser->label_widget), TRUE);
button = gtk_button_new ();
gtk_box_pack_start (GTK_BOX (chooser), button, FALSE, FALSE, 0);
gtk_label_set_mnemonic_widget (GTK_LABEL (chooser->label_widget), button);
gtk_widget_set_visible (button, TRUE);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
gtk_container_add (GTK_CONTAINER (button), box);
gtk_widget_set_visible (box, TRUE);
chooser->preview_frame = gtk_aspect_frame_new (NULL, 0.5, 0.5, 1.0, FALSE);
gtk_frame_set_shadow_type (GTK_FRAME (chooser->preview_frame), GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (box), chooser->preview_frame, FALSE, FALSE, 0);
gtk_widget_set_visible (chooser->preview_frame, TRUE);
chooser->preview = gimp_preview_area_new ();
gtk_widget_set_size_request (chooser->preview, scale_factor * CELL_SIZE, scale_factor * CELL_SIZE);
gtk_container_add (GTK_CONTAINER (chooser->preview_frame), chooser->preview);
gtk_widget_set_visible (chooser->preview, TRUE);
chooser->preview_title = gtk_label_new (_("Browse..."));
gtk_box_pack_start (GTK_BOX (box), chooser->preview_title, FALSE, FALSE, 0);
gtk_widget_set_visible (chooser->preview_title, TRUE);
g_signal_connect_swapped (button, "clicked",
G_CALLBACK (gimp_item_chooser_clicked),
chooser);
G_OBJECT_CLASS (gimp_item_chooser_parent_class)->constructed (object);
}
static void
gimp_item_chooser_dispose (GObject *object)
{
GimpItemChooser *chooser = GIMP_ITEM_CHOOSER (object);
if (chooser->callback)
{
gimp_items_close_popup (chooser->callback);
gimp_plug_in_remove_temp_procedure (gimp_get_plug_in (),
chooser->callback);
g_clear_pointer (&chooser->callback, g_free);
}
G_OBJECT_CLASS (gimp_item_chooser_parent_class)->dispose (object);
}
static void
gimp_item_chooser_finalize (GObject *object)
{
GimpItemChooser *chooser = GIMP_ITEM_CHOOSER (object);
g_clear_pointer (&chooser->title, g_free);
g_clear_pointer (&chooser->label, g_free);
g_clear_pointer (&chooser->thumbnail, g_bytes_unref);
G_OBJECT_CLASS (gimp_item_chooser_parent_class)->finalize (object);
}
static void
gimp_item_chooser_set_property (GObject *object,
guint property_id,
const GValue *gvalue,
GParamSpec *pspec)
{
GimpItemChooser *chooser = GIMP_ITEM_CHOOSER (object);
switch (property_id)
{
case PROP_TITLE:
chooser->title = g_value_dup_string (gvalue);
break;
case PROP_LABEL:
chooser->label = g_value_dup_string (gvalue);
break;
case PROP_ITEM:
g_return_if_fail (g_value_get_object (gvalue) == NULL ||
g_type_is_a (G_TYPE_FROM_INSTANCE (g_value_get_object (gvalue)),
chooser->item_type));
gimp_item_chooser_set_item (chooser, g_value_get_object (gvalue));
break;
case PROP_ITEM_TYPE:
chooser->item_type = g_value_get_gtype (gvalue);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gimp_item_chooser_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpItemChooser *chooser = GIMP_ITEM_CHOOSER (object);
switch (property_id)
{
case PROP_TITLE:
g_value_set_string (value, chooser->title);
break;
case PROP_LABEL:
g_value_set_string (value, chooser->label);
break;
case PROP_ITEM:
g_value_set_object (value, chooser->item);
break;
case PROP_ITEM_TYPE:
g_value_set_gtype (value, chooser->item_type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
/**
* gimp_item_chooser_new:
* @title: (nullable): Title of the dialog to use or %NULL to use the default title.
* @label: (nullable): Button label or %NULL for no label.
* @item_type: the acceptable subtype of choosable items.
* @item: (nullable): Initial item.
*
* Creates a new #GtkWidget that lets a user choose a item which must be of
* type @item_type. @item_type of values %G_TYPE_NONE and
* %GIMP_TYPE_ITEM are equivalent. Otherwise it must be a subtype of
* %GIMP_TYPE_ITEM.
*
* When @item is %NULL, initial choice is from context.
*
* Returns: A [class@GimpUi.ItemChooser.
*
* Since: 3.0
*/
GtkWidget *
gimp_item_chooser_new (const gchar *title,
const gchar *label,
GType item_type,
GimpItem *item)
{
GtkWidget *chooser;
if (item_type == G_TYPE_NONE)
item_type = GIMP_TYPE_ITEM;
g_return_val_if_fail (g_type_is_a (item_type, GIMP_TYPE_ITEM), NULL);
g_return_val_if_fail (item == NULL ||
g_type_is_a (G_TYPE_FROM_INSTANCE (item), item_type),
NULL);
chooser = g_object_new (GIMP_TYPE_ITEM_CHOOSER,
"title", title,
"label", label,
"item", item,
"item-type", item_type,
NULL);
return chooser;
}
/**
* gimp_item_chooser_get_item:
* @chooser: A #GimpItemChooser
*
* Gets the currently selected item.
*
* Returns: (transfer none): an internal copy of the item which must not be freed.
*
* Since: 3.0
*/
GimpItem *
gimp_item_chooser_get_item (GimpItemChooser *chooser)
{
g_return_val_if_fail (GIMP_IS_ITEM_CHOOSER (chooser), NULL);
return chooser->item;
}
/**
* gimp_item_chooser_set_item:
* @chooser: A #GimpItemChooser
* @item: Item to set.
*
* Sets the currently selected item.
* This will select the item in both the button and any chooser popup.
*
* Since: 3.0
*/
void
gimp_item_chooser_set_item (GimpItemChooser *chooser,
GimpItem *item)
{
g_return_if_fail (GIMP_IS_ITEM_CHOOSER (chooser));
g_return_if_fail (item == NULL || GIMP_IS_ITEM (item));
chooser->item = item;
if (chooser->callback)
gimp_items_set_popup (chooser->callback, chooser->item);
g_object_notify_by_pspec (G_OBJECT (chooser), item_button_props[PROP_ITEM]);
gimp_item_chooser_draw (chooser);
}
/**
* gimp_item_chooser_get_label:
* @widget: A [class@ItemChooser].
*
* Returns the label widget.
*
* Returns: (transfer none): the [class@Gtk.Widget] showing the label text.
* Since: 3.0
*/
GtkWidget *
gimp_item_chooser_get_label (GimpItemChooser *chooser)
{
g_return_val_if_fail (GIMP_IS_ITEM_CHOOSER (chooser), NULL);
return chooser->label_widget;
}
/* private functions */
static GimpValueArray *
gimp_temp_callback_run (GimpProcedure *procedure,
GimpProcedureConfig *config,
GimpItemChooser *chooser)
{
GimpItem *item;
gboolean closing;
g_object_get (config,
"item", &item,
"closing", &closing,
NULL);
g_object_set (chooser, "item", item, NULL);
if (closing)
{
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
(GSourceFunc) gimp_item_select_remove_after_run,
g_strdup (gimp_procedure_get_name (procedure)),
g_free);
g_clear_pointer (&chooser->callback, g_free);
}
g_clear_object (&item);
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
}
static gboolean
gimp_item_select_remove_after_run (const gchar *procedure_name)
{
gimp_plug_in_remove_temp_procedure (gimp_get_plug_in (), procedure_name);
return G_SOURCE_REMOVE;
}
static void
gimp_item_chooser_clicked (GimpItemChooser *chooser)
{
if (chooser->callback)
{
/* Popup already created. Calling setter raises the popup. */
gimp_items_set_popup (chooser->callback, chooser->item);
}
else
{
GimpPlugIn *plug_in = gimp_get_plug_in ();
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (chooser));
GBytes *handle = NULL;
gchar *callback_name;
GimpProcedure *callback_procedure;
if (GIMP_IS_DIALOG (toplevel))
handle = gimp_dialog_get_native_handle (GIMP_DIALOG (toplevel));
callback_name = gimp_pdb_temp_procedure_name (gimp_get_pdb ());
callback_procedure = gimp_procedure_new (plug_in,
callback_name,
GIMP_PDB_PROC_TYPE_TEMPORARY,
(GimpRunFunc) gimp_temp_callback_run,
g_object_ref (chooser),
(GDestroyNotify) g_object_unref);
gimp_procedure_add_item_argument (callback_procedure, "item",
"Item", "The selected item",
TRUE, G_PARAM_READWRITE);
gimp_procedure_add_boolean_argument (callback_procedure, "closing",
"Closing", "If the dialog was closing",
FALSE, G_PARAM_READWRITE);
gimp_plug_in_add_temp_procedure (plug_in, callback_procedure);
g_object_unref (callback_procedure);
g_free (callback_name);
if (gimp_items_popup (gimp_procedure_get_name (callback_procedure), chooser->title,
g_type_name (chooser->item_type), chooser->item, handle))
{
/* Allow callbacks to be watched */
gimp_plug_in_persistent_enable (plug_in);
chooser->callback = g_strdup (gimp_procedure_get_name (callback_procedure));
}
else
{
g_warning ("%s: failed to open remote item select dialog.", G_STRFUNC);
gimp_plug_in_remove_temp_procedure (plug_in, gimp_procedure_get_name (callback_procedure));
return;
}
gimp_items_set_popup (chooser->callback, chooser->item);
}
}
static void
gimp_item_chooser_draw (GimpItemChooser *chooser)
{
GimpPreviewArea *area = GIMP_PREVIEW_AREA (chooser->preview);
GtkAllocation allocation;
gint x = 0;
gint y = 0;
gtk_widget_get_allocation (chooser->preview, &allocation);
gimp_item_chooser_get_thumbnail (chooser, allocation.width, allocation.height);
if (chooser->width < allocation.width ||
chooser->height < allocation.height)
{
x = ((allocation.width - chooser->width) / 2);
y = ((allocation.height - chooser->height) / 2);
}
gimp_preview_area_reset (area);
if (chooser->thumbnail)
{
GimpImageType type;
gint rowstride;
rowstride = chooser->width * chooser->bpp;
switch (chooser->bpp)
{
case 1:
type = GIMP_GRAY_IMAGE;
break;
case 2:
type = GIMP_GRAYA_IMAGE;
break;
case 3:
type = GIMP_RGB_IMAGE;
break;
case 4:
type = GIMP_RGBA_IMAGE;
break;
default:
g_return_if_reached ();
}
gimp_preview_area_draw (area, x, y, chooser->width, chooser->height, type,
g_bytes_get_data (chooser->thumbnail, NULL), rowstride);
}
else
{
/* TODO: GimpItems like GimpPath do not have a built-in drawable,
* but it is possible to get a preview from it. We should add a
* standard way to generate this preview. */
if (chooser->item)
gtk_label_set_text (GTK_LABEL (chooser->preview_title),
gimp_item_get_name (chooser->item));
}
}
static void
gimp_item_chooser_get_thumbnail (GimpItemChooser *chooser,
gint width,
gint height)
{
if (chooser->item == chooser->thumbnail_item &&
chooser->width == width &&
chooser->height == height)
/* Let's assume item contents is not changing in a single run. */
return;
g_clear_pointer (&chooser->thumbnail, g_bytes_unref);
chooser->width = chooser->height = 0;
chooser->thumbnail_item = chooser->item;
if (chooser->item)
{
if (GIMP_IS_DRAWABLE (chooser->item))
{
chooser->thumbnail =
gimp_drawable_get_thumbnail_data (GIMP_DRAWABLE (chooser->item),
width, height,
&chooser->width,
&chooser->height,
&chooser->bpp);
}
}
}

47
libgimp/gimpitemchooser.h Normal file
View file

@ -0,0 +1,47 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpitemchooser.c
*
* 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
* Lesser 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/>.
*/
#if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION)
#error "Only <libgimp/gimpui.h> can be included directly."
#endif
#ifndef __GIMP_ITEM_CHOOSER_H__
#define __GIMP_ITEM_CHOOSER_H__
G_BEGIN_DECLS
#define GIMP_TYPE_ITEM_CHOOSER (gimp_item_chooser_get_type ())
G_DECLARE_FINAL_TYPE (GimpItemChooser, gimp_item_chooser, GIMP, ITEM_CHOOSER, GtkBox)
GtkWidget * gimp_item_chooser_new (const gchar *title,
const gchar *label,
GType item_type,
GimpItem *item);
GimpItem * gimp_item_chooser_get_item (GimpItemChooser *chooser);
void gimp_item_chooser_set_item (GimpItemChooser *chooser,
GimpItem *item);
GtkWidget * gimp_item_chooser_get_label (GimpItemChooser *widget);
G_END_DECLS
#endif /* __GIMP_ITEM_CHOOSER_H__ */

View file

@ -913,6 +913,10 @@ gimp_procedure_dialog_get_widget (GimpProcedureDialog *dialog,
{
widget = gimp_prop_drawable_chooser_new (G_OBJECT (priv->config), property, NULL);
}
else if (G_IS_PARAM_SPEC_OBJECT (pspec) && (pspec->value_type == GIMP_TYPE_PATH))
{
widget = gimp_prop_item_chooser_new (G_OBJECT (priv->config), property, NULL);
}
else if (G_IS_PARAM_SPEC_OBJECT (pspec) && pspec->value_type == GIMP_TYPE_IMAGE)
{
widget = gimp_prop_image_chooser_new (G_OBJECT (priv->config), property, NULL);
@ -966,6 +970,8 @@ gimp_procedure_dialog_get_widget (GimpProcedureDialog *dialog,
label = gimp_resource_chooser_get_label (GIMP_RESOURCE_CHOOSER (widget));
else if (GIMP_IS_DRAWABLE_CHOOSER (widget))
label = gimp_drawable_chooser_get_label (GIMP_DRAWABLE_CHOOSER (widget));
else if (GIMP_IS_ITEM_CHOOSER (widget))
label = gimp_item_chooser_get_label (GIMP_ITEM_CHOOSER (widget));
else if (GIMP_IS_IMAGE_CHOOSER (widget))
label = gimp_image_chooser_get_label (GIMP_IMAGE_CHOOSER (widget));
}
@ -2922,6 +2928,10 @@ gimp_procedure_dialog_check_mnemonic (GimpProcedureDialog *dialog,
{
label = gimp_drawable_chooser_get_label (GIMP_DRAWABLE_CHOOSER (widget));
}
else if (GIMP_IS_ITEM_CHOOSER (widget))
{
label = gimp_item_chooser_get_label (GIMP_ITEM_CHOOSER (widget));
}
else if (GIMP_IS_IMAGE_CHOOSER (widget))
{
label = gimp_image_chooser_get_label (GIMP_IMAGE_CHOOSER (widget));

View file

@ -206,6 +206,74 @@ gimp_prop_image_chooser_new (GObject *config,
return prop_chooser;
}
/**
* gimp_prop_item_chooser_new:
* @config: Object to which property is attached.
* @property_name: Name of a [class@Gimp.Item] property.
* @chooser_title: (nullable): title for the poppable dialog.
*
* Creates a [class@GimpUi.ItemChooser] controlled by the specified property.
*
* Returns: (transfer full): A new [class@GimpUi.ItemChooser].
*
* Since: 3.0
*/
GtkWidget *
gimp_prop_item_chooser_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title)
{
GParamSpec *param_spec;
GtkWidget *prop_chooser;
GimpItem *initial_item = NULL;
gchar *title = NULL;
const gchar *label;
param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config),
property_name);
g_return_val_if_fail (param_spec != NULL, NULL);
g_return_val_if_fail (g_type_is_a (G_TYPE_FROM_INSTANCE (param_spec), G_TYPE_PARAM_OBJECT) &&
g_type_is_a (param_spec->value_type, GIMP_TYPE_ITEM), NULL);
g_object_get (config,
property_name, &initial_item,
NULL);
label = g_param_spec_get_nick (param_spec);
if (chooser_title == NULL)
{
gchar *canonical;
canonical = gimp_utils_make_canonical_menu_label (label);
if (g_type_is_a (param_spec->value_type, GIMP_TYPE_LAYER))
title = g_strdup_printf (_("Choose layer: %s"), canonical);
if (g_type_is_a (param_spec->value_type, GIMP_TYPE_CHANNEL))
title = g_strdup_printf (_("Choose channel: %s"), canonical);
if (g_type_is_a (param_spec->value_type, GIMP_TYPE_PATH))
title = g_strdup_printf (_("Choose path: %s"), canonical);
else
title = g_strdup_printf (_("Choose item: %s"), canonical);
g_free (canonical);
}
else
{
title = g_strdup (chooser_title);
}
prop_chooser = gimp_item_chooser_new (title, label, param_spec->value_type,
initial_item);
g_clear_object (&initial_item);
g_free (title);
g_object_bind_property (prop_chooser, "item",
config, property_name,
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
return prop_chooser;
}
/**
* gimp_prop_drawable_chooser_new:
* @config: Object to which property is attached.

View file

@ -51,6 +51,9 @@ GtkWidget * gimp_prop_pattern_chooser_new (GObject *config,
GtkWidget * gimp_prop_image_chooser_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title);
GtkWidget * gimp_prop_item_chooser_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title);
GtkWidget * gimp_prop_drawable_chooser_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title);

View file

@ -29,6 +29,11 @@ EXPORTS
gimp_image_chooser_set_image
gimp_image_combo_box_get_type
gimp_image_combo_box_new
gimp_item_chooser_get_item
gimp_item_chooser_get_label
gimp_item_chooser_get_type
gimp_item_chooser_new
gimp_item_chooser_set_item
gimp_layer_combo_box_get_type
gimp_layer_combo_box_new
gimp_palette_chooser_get_type
@ -76,6 +81,7 @@ EXPORTS
gimp_prop_font_chooser_new
gimp_prop_gradient_chooser_new
gimp_prop_image_chooser_new
gimp_prop_item_chooser_new
gimp_prop_palette_chooser_new
gimp_prop_pattern_chooser_new
gimp_prop_resolution_entry_new

View file

@ -37,6 +37,7 @@
#include <libgimp/gimpgradientchooser.h>
#include <libgimp/gimpimagechooser.h>
#include <libgimp/gimpimagecombobox.h>
#include <libgimp/gimpitemchooser.h>
#include <libgimp/gimpitemcombobox.h>
#include <libgimp/gimppalettechooser.h>
#include <libgimp/gimppatternchooser.h>

View file

@ -51,6 +51,7 @@ typedef struct _GimpBrushChooser GimpBrushChooser;
typedef struct _GimpFontChooser GimpFontChooser;
typedef struct _GimpGradientChooser GimpGradientChooser;
typedef struct _GimpImageChooser GimpImageChooser;
typedef struct _GimpItemChooser GimpItemChooser;
typedef struct _GimpPaletteChooser GimpPaletteChooser;
typedef struct _GimpPatternChooser GimpPatternChooser;

View file

@ -305,6 +305,7 @@ libgimpui_sources_introspectable = [
'gimpgradientchooser.c',
'gimpimagechooser.c',
'gimpimagecombobox.c',
'gimpitemchooser.c',
'gimpitemcombobox.c',
'gimppalettechooser.c',
'gimppatternchooser.c',
@ -342,6 +343,7 @@ libgimpui_headers_introspectable = [
'gimpgradientchooser.h',
'gimpimagechooser.h',
'gimpimagecombobox.h',
'gimpitemchooser.h',
'gimpitemcombobox.h',
'gimppalettechooser.h',
'gimppatternchooser.h',

View file

@ -1121,7 +1121,92 @@ CODE
);
}
@headers = qw("core/gimpgrouplayer.h"
sub items_popup {
$blurb = 'Invokes the item selection dialog.';
$help = 'Opens a dialog letting a user choose an item .';
&alxsa_pdb_misc('2025');
@inargs = (
{ name => 'callback', type => 'string', non_empty => 1,
desc => 'The callback PDB proc to call when user chooses an item ' },
{ name => 'popup_title', type => 'string',
desc => 'Title of the item selection dialog' },
{ name => 'item_type', type => 'string', non_empty => 1,
desc => 'The name of the GIMP_TYPE_ITEM subtype' },
{ name => 'initial_item', type => 'item ', none_ok => 1, no_validate => 1,
desc => 'The item to set as the initial choice' },
{ name => 'parent_window', type => 'bytes', none_ok => 1,
desc => 'An optional parent window handle for the popup to be set transient to' }
);
%invoke = (
code => <<'CODE'
{
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, callback) ||
! gimp_pdb_dialog_new (gimp, context, progress,
g_type_from_name (item_type),
parent_window, popup_title, callback,
GIMP_OBJECT (initial_item),
NULL))
success = FALSE;
}
CODE
);
}
sub items_close_popup {
$blurb = 'Close the item selection dialog.';
$help = 'Closes an open item selection dialog.';
&alxsa_pdb_misc('2025');
@inargs = (
{ name => 'callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' }
);
%invoke = (
code => <<'CODE'
{
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, callback) ||
! gimp_pdb_dialog_close (gimp, GIMP_TYPE_ITEM, callback))
success = FALSE;
}
CODE
);
}
sub items_set_popup {
$blurb = 'Sets the selected item in a item selection dialog.';
$help = $blurb;
&alxsa_pdb_misc('2025');
@inargs = (
{ name => 'callback', type => 'string', non_empty => 1,
desc => 'The name of the callback registered for this pop-up' },
{ name => 'item', type => 'item', no_validate => 1,
desc => 'The item to set as selected' }
);
%invoke = (
code => <<'CODE'
{
if (gimp->no_interface ||
! gimp_pdb_lookup_procedure (gimp->pdb, callback) ||
! gimp_pdb_dialog_set (gimp, GIMP_TYPE_ITEM, callback, GIMP_OBJECT (item), NULL))
success = FALSE;
}
CODE
);
}
@headers = qw("core/gimp.h"
"core/gimpdatafactory.h"
"core/gimpgrouplayer.h"
"core/gimplayermask.h"
"core/gimplinklayer.h"
"core/gimplist.h"
@ -1159,7 +1244,10 @@ CODE
item_get_tattoo item_set_tattoo
item_attach_parasite item_detach_parasite
item_get_parasite
item_get_parasite_list);
item_get_parasite_list
items_popup
items_close_popup
items_set_popup);
%exports = (app => [@procs], lib => [@procs]);