2023-08-28 12:42:39 -07:00
|
|
|
/* LIBGIMP - The GIMP Library
|
|
|
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
|
|
|
*
|
|
|
|
|
* gimpdrawablechooser.h
|
|
|
|
|
* Copyright (C) 2023 Jehan
|
|
|
|
|
*
|
|
|
|
|
* 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 "gimpdrawablechooser.h"
|
|
|
|
|
#include "gimpuimarshal.h"
|
|
|
|
|
|
|
|
|
|
#include "libgimp-intl.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* SECTION: gimpdrawablechooser
|
|
|
|
|
* @title: GimpDrawableChooser
|
|
|
|
|
* @short_description: A widget allowing to select a drawable.
|
|
|
|
|
*
|
|
|
|
|
* The chooser contains an optional label and a button which queries the core
|
|
|
|
|
* process to pop up a drawable selection dialog.
|
|
|
|
|
*
|
|
|
|
|
* Since: 3.0
|
2025-11-16 16:09:30 -08:00
|
|
|
*
|
|
|
|
|
* Deprecated: 3.2: Use GimpItemChooser.
|
2023-08-28 12:42:39 -07:00
|
|
|
**/
|
|
|
|
|
|
|
|
|
|
#define CELL_SIZE 40
|
|
|
|
|
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
PROP_0,
|
|
|
|
|
PROP_TITLE,
|
|
|
|
|
PROP_LABEL,
|
|
|
|
|
PROP_DRAWABLE,
|
2023-09-05 13:39:04 -07:00
|
|
|
PROP_DRAWABLE_TYPE,
|
2023-08-28 12:42:39 -07:00
|
|
|
N_PROPS
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct _GimpDrawableChooser
|
|
|
|
|
{
|
|
|
|
|
GtkBox parent_instance;
|
|
|
|
|
|
2023-09-05 13:39:04 -07:00
|
|
|
GType drawable_type;
|
2023-08-28 12:42:39 -07:00
|
|
|
GimpDrawable *drawable;
|
|
|
|
|
gchar *title;
|
|
|
|
|
gchar *label;
|
|
|
|
|
gchar *callback;
|
|
|
|
|
|
|
|
|
|
GBytes *thumbnail;
|
|
|
|
|
GimpDrawable *thumbnail_drawable;
|
|
|
|
|
gint width;
|
|
|
|
|
gint height;
|
|
|
|
|
gint bpp;
|
|
|
|
|
|
|
|
|
|
GtkWidget *label_widget;
|
|
|
|
|
GtkWidget *preview_frame;
|
|
|
|
|
GtkWidget *preview;
|
|
|
|
|
GtkWidget *preview_title;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* local function prototypes */
|
|
|
|
|
|
|
|
|
|
static void gimp_drawable_chooser_constructed (GObject *object);
|
|
|
|
|
static void gimp_drawable_chooser_dispose (GObject *object);
|
|
|
|
|
static void gimp_drawable_chooser_finalize (GObject *object);
|
|
|
|
|
|
|
|
|
|
static void gimp_drawable_chooser_set_property (GObject *object,
|
|
|
|
|
guint property_id,
|
|
|
|
|
const GValue *value,
|
|
|
|
|
GParamSpec *pspec);
|
|
|
|
|
static void gimp_drawable_chooser_get_property (GObject *object,
|
|
|
|
|
guint property_id,
|
|
|
|
|
GValue *value,
|
|
|
|
|
GParamSpec *pspec);
|
|
|
|
|
|
|
|
|
|
static void gimp_drawable_chooser_clicked (GimpDrawableChooser *chooser);
|
|
|
|
|
|
|
|
|
|
static GimpValueArray * gimp_temp_callback_run (GimpProcedure *procedure,
|
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
|
GimpDrawableChooser *chooser);
|
|
|
|
|
static gboolean gimp_drawable_select_remove_after_run (const gchar *procedure_name);
|
|
|
|
|
|
|
|
|
|
static void gimp_drawable_chooser_draw (GimpDrawableChooser *chooser);
|
|
|
|
|
static void gimp_drawable_chooser_get_thumbnail (GimpDrawableChooser *chooser,
|
|
|
|
|
gint width,
|
|
|
|
|
gint height);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static GParamSpec *drawable_button_props[N_PROPS] = { NULL, };
|
|
|
|
|
|
|
|
|
|
G_DEFINE_FINAL_TYPE (GimpDrawableChooser, gimp_drawable_chooser, GTK_TYPE_BOX)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gimp_drawable_chooser_class_init (GimpDrawableChooserClass *klass)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
|
|
object_class->constructed = gimp_drawable_chooser_constructed;
|
|
|
|
|
object_class->dispose = gimp_drawable_chooser_dispose;
|
|
|
|
|
object_class->finalize = gimp_drawable_chooser_finalize;
|
|
|
|
|
object_class->set_property = gimp_drawable_chooser_set_property;
|
|
|
|
|
object_class->get_property = gimp_drawable_chooser_get_property;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GimpDrawableChooser:title:
|
|
|
|
|
*
|
|
|
|
|
* The title to be used for the drawable selection popup dialog.
|
|
|
|
|
*
|
|
|
|
|
* Since: 3.0
|
|
|
|
|
*/
|
|
|
|
|
drawable_button_props[PROP_TITLE] =
|
|
|
|
|
g_param_spec_string ("title",
|
|
|
|
|
"Title",
|
|
|
|
|
"The title to be used for the drawable selection popup dialog",
|
|
|
|
|
"Drawable Selection",
|
|
|
|
|
GIMP_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GimpDrawableChooser:label:
|
|
|
|
|
*
|
|
|
|
|
* Label text with mnemonic.
|
|
|
|
|
*
|
|
|
|
|
* Since: 3.0
|
|
|
|
|
*/
|
|
|
|
|
drawable_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);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GimpDrawableChooser:drawable:
|
|
|
|
|
*
|
|
|
|
|
* The currently selected drawable.
|
|
|
|
|
*
|
|
|
|
|
* Since: 3.0
|
|
|
|
|
*/
|
|
|
|
|
drawable_button_props[PROP_DRAWABLE] =
|
|
|
|
|
gimp_param_spec_drawable ("drawable",
|
|
|
|
|
"Drawable",
|
|
|
|
|
"The currently selected drawable",
|
|
|
|
|
TRUE,
|
|
|
|
|
GIMP_PARAM_READWRITE |
|
|
|
|
|
G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
|
|
2023-09-05 13:39:04 -07:00
|
|
|
/**
|
|
|
|
|
* GimpDrawableChooser:drawable-type:
|
|
|
|
|
*
|
|
|
|
|
* Allowed drawable types, which must be either GIMP_TYPE_DRAWABLE or a
|
|
|
|
|
* subtype.
|
|
|
|
|
*
|
|
|
|
|
* Since: 3.0
|
|
|
|
|
*/
|
|
|
|
|
drawable_button_props[PROP_DRAWABLE_TYPE] =
|
|
|
|
|
g_param_spec_gtype ("drawable-type",
|
|
|
|
|
"Allowed drawable Type",
|
|
|
|
|
"The GType of the drawable property",
|
|
|
|
|
GIMP_TYPE_DRAWABLE,
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
GIMP_PARAM_READWRITE);
|
|
|
|
|
|
2023-08-28 12:42:39 -07:00
|
|
|
g_object_class_install_properties (object_class,
|
|
|
|
|
N_PROPS, drawable_button_props);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gimp_drawable_chooser_init (GimpDrawableChooser *chooser)
|
|
|
|
|
{
|
|
|
|
|
gtk_orientable_set_orientation (GTK_ORIENTABLE (chooser),
|
|
|
|
|
GTK_ORIENTATION_HORIZONTAL);
|
|
|
|
|
gtk_box_set_spacing (GTK_BOX (chooser), 6);
|
|
|
|
|
|
|
|
|
|
chooser->thumbnail_drawable = NULL;
|
|
|
|
|
chooser->thumbnail = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gimp_drawable_chooser_constructed (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
GimpDrawableChooser *chooser = GIMP_DRAWABLE_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_show (GTK_WIDGET (chooser->label_widget));
|
|
|
|
|
|
|
|
|
|
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_show (button);
|
|
|
|
|
|
|
|
|
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
|
|
|
|
|
gtk_container_add (GTK_CONTAINER (button), box);
|
|
|
|
|
gtk_widget_show (box);
|
|
|
|
|
|
|
|
|
|
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_show (chooser->preview_frame);
|
|
|
|
|
|
|
|
|
|
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_show (chooser->preview);
|
|
|
|
|
|
|
|
|
|
chooser->preview_title = gtk_label_new (_("Browse..."));
|
|
|
|
|
gtk_box_pack_start (GTK_BOX (box), chooser->preview_title, FALSE, FALSE, 0);
|
|
|
|
|
gtk_widget_show (chooser->preview_title);
|
|
|
|
|
|
|
|
|
|
g_signal_connect_swapped (button, "clicked",
|
|
|
|
|
G_CALLBACK (gimp_drawable_chooser_clicked),
|
|
|
|
|
chooser);
|
|
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (gimp_drawable_chooser_parent_class)->constructed (object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gimp_drawable_chooser_dispose (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
GimpDrawableChooser *chooser = GIMP_DRAWABLE_CHOOSER (object);
|
|
|
|
|
|
|
|
|
|
if (chooser->callback)
|
|
|
|
|
{
|
app, libgimp, plug-ins: move our code to use only non-deprecated code.
- Though GimpDrawableChooser itself is deprecated, make it call the
new items popup API, which will work just as well.
- gimp_procedure_dialog_get_widget() will now return a GimpItemChooser
widget by default. I did hesitate if for API behavior stability, it
should not still return a GimpDrawableChooser, but considered that if
someone set G_TYPE_NONE, they want our "best choice" and are not
considering tweaking it. If someone wants to make sure this function
always returns a specific widget type, they should specify said type.
So I also added a note in the function docs related to this
assumption.
- Van Gogh plug-in must now use the GimpItemChooser API to set the item
to show. Also I am specifying the widget type, even though it is now
the new default, because of the previous point. Since we tweak further
the widget with its API, let's specify so that any further defaults
update doesn't break this code.
- Adding some pragma to ignore warnings on the few pieces of code where
we have to call deprecated functions (because inside other deprecated
functions themselves).
- gui_pdb_dialog_*() API should just always create GimpItemSelect
dialogs now. Also I ref rather than peek the class, because even if
the class has not been instanciated yet (a case I ran into), we still
want to obtain the class structure.
2025-11-17 03:27:52 -08:00
|
|
|
gimp_items_close_popup (chooser->callback);
|
2023-08-28 12:42:39 -07:00
|
|
|
|
|
|
|
|
gimp_plug_in_remove_temp_procedure (gimp_get_plug_in (), chooser->callback);
|
|
|
|
|
g_clear_pointer (&chooser->callback, g_free);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (gimp_drawable_chooser_parent_class)->dispose (object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gimp_drawable_chooser_finalize (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
GimpDrawableChooser *chooser = GIMP_DRAWABLE_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_drawable_chooser_parent_class)->finalize (object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gimp_drawable_chooser_set_property (GObject *object,
|
|
|
|
|
guint property_id,
|
|
|
|
|
const GValue *gvalue,
|
|
|
|
|
GParamSpec *pspec)
|
|
|
|
|
{
|
|
|
|
|
GimpDrawableChooser *chooser = GIMP_DRAWABLE_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_DRAWABLE:
|
2023-09-05 13:39:04 -07:00
|
|
|
g_return_if_fail (g_value_get_object (gvalue) == NULL ||
|
|
|
|
|
g_type_is_a (G_TYPE_FROM_INSTANCE (g_value_get_object (gvalue)),
|
|
|
|
|
chooser->drawable_type));
|
app, libgimp, plug-ins: move our code to use only non-deprecated code.
- Though GimpDrawableChooser itself is deprecated, make it call the
new items popup API, which will work just as well.
- gimp_procedure_dialog_get_widget() will now return a GimpItemChooser
widget by default. I did hesitate if for API behavior stability, it
should not still return a GimpDrawableChooser, but considered that if
someone set G_TYPE_NONE, they want our "best choice" and are not
considering tweaking it. If someone wants to make sure this function
always returns a specific widget type, they should specify said type.
So I also added a note in the function docs related to this
assumption.
- Van Gogh plug-in must now use the GimpItemChooser API to set the item
to show. Also I am specifying the widget type, even though it is now
the new default, because of the previous point. Since we tweak further
the widget with its API, let's specify so that any further defaults
update doesn't break this code.
- Adding some pragma to ignore warnings on the few pieces of code where
we have to call deprecated functions (because inside other deprecated
functions themselves).
- gui_pdb_dialog_*() API should just always create GimpItemSelect
dialogs now. Also I ref rather than peek the class, because even if
the class has not been instanciated yet (a case I ran into), we still
want to obtain the class structure.
2025-11-17 03:27:52 -08:00
|
|
|
#pragma GCC diagnostic push
|
|
|
|
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
2023-08-28 12:42:39 -07:00
|
|
|
gimp_drawable_chooser_set_drawable (chooser, g_value_get_object (gvalue));
|
app, libgimp, plug-ins: move our code to use only non-deprecated code.
- Though GimpDrawableChooser itself is deprecated, make it call the
new items popup API, which will work just as well.
- gimp_procedure_dialog_get_widget() will now return a GimpItemChooser
widget by default. I did hesitate if for API behavior stability, it
should not still return a GimpDrawableChooser, but considered that if
someone set G_TYPE_NONE, they want our "best choice" and are not
considering tweaking it. If someone wants to make sure this function
always returns a specific widget type, they should specify said type.
So I also added a note in the function docs related to this
assumption.
- Van Gogh plug-in must now use the GimpItemChooser API to set the item
to show. Also I am specifying the widget type, even though it is now
the new default, because of the previous point. Since we tweak further
the widget with its API, let's specify so that any further defaults
update doesn't break this code.
- Adding some pragma to ignore warnings on the few pieces of code where
we have to call deprecated functions (because inside other deprecated
functions themselves).
- gui_pdb_dialog_*() API should just always create GimpItemSelect
dialogs now. Also I ref rather than peek the class, because even if
the class has not been instanciated yet (a case I ran into), we still
want to obtain the class structure.
2025-11-17 03:27:52 -08:00
|
|
|
#pragma GCC diagnostic pop
|
2023-08-28 12:42:39 -07:00
|
|
|
break;
|
|
|
|
|
|
2023-09-05 13:39:04 -07:00
|
|
|
case PROP_DRAWABLE_TYPE:
|
|
|
|
|
chooser->drawable_type = g_value_get_gtype (gvalue);
|
|
|
|
|
break;
|
|
|
|
|
|
2023-08-28 12:42:39 -07:00
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gimp_drawable_chooser_get_property (GObject *object,
|
|
|
|
|
guint property_id,
|
|
|
|
|
GValue *value,
|
|
|
|
|
GParamSpec *pspec)
|
|
|
|
|
{
|
|
|
|
|
GimpDrawableChooser *chooser = GIMP_DRAWABLE_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_DRAWABLE:
|
|
|
|
|
g_value_set_object (value, chooser->drawable);
|
|
|
|
|
break;
|
|
|
|
|
|
2023-09-05 13:39:04 -07:00
|
|
|
case PROP_DRAWABLE_TYPE:
|
|
|
|
|
g_value_set_gtype (value, chooser->drawable_type);
|
|
|
|
|
break;
|
|
|
|
|
|
2023-08-28 12:42:39 -07:00
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gimp_drawable_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.
|
2023-09-05 13:39:04 -07:00
|
|
|
* @drawable_type: the acceptable subtype of choosable drawables.
|
2023-08-28 12:42:39 -07:00
|
|
|
* @drawable: (nullable): Initial drawable.
|
|
|
|
|
*
|
2023-09-05 13:39:04 -07:00
|
|
|
* Creates a new #GtkWidget that lets a user choose a drawable which must be of
|
|
|
|
|
* type @drawable_type. @drawable_type of values %G_TYPE_NONE and
|
|
|
|
|
* %GIMP_TYPE_DRAWABLE are equivalent. Otherwise it must be a subtype of
|
|
|
|
|
* %GIMP_TYPE_DRAWABLE.
|
2023-08-28 12:42:39 -07:00
|
|
|
*
|
|
|
|
|
* When @drawable is %NULL, initial choice is from context.
|
|
|
|
|
*
|
2023-10-01 15:07:46 -07:00
|
|
|
* Returns: A [class@GimpUi.DrawableChooser.
|
2023-08-28 12:42:39 -07:00
|
|
|
*
|
|
|
|
|
* Since: 3.0
|
2025-11-16 16:09:30 -08:00
|
|
|
*
|
|
|
|
|
* Deprecated: 3.2: Use gimp_item_chooser_new().
|
2023-08-28 12:42:39 -07:00
|
|
|
*/
|
|
|
|
|
GtkWidget *
|
|
|
|
|
gimp_drawable_chooser_new (const gchar *title,
|
|
|
|
|
const gchar *label,
|
2023-09-05 13:39:04 -07:00
|
|
|
GType drawable_type,
|
2023-08-28 12:42:39 -07:00
|
|
|
GimpDrawable *drawable)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *chooser;
|
|
|
|
|
|
2023-09-05 13:39:04 -07:00
|
|
|
if (drawable_type == G_TYPE_NONE)
|
|
|
|
|
drawable_type = GIMP_TYPE_DRAWABLE;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (g_type_is_a (drawable_type, GIMP_TYPE_DRAWABLE), NULL);
|
|
|
|
|
g_return_val_if_fail (drawable == NULL ||
|
|
|
|
|
g_type_is_a (G_TYPE_FROM_INSTANCE (drawable), drawable_type),
|
|
|
|
|
NULL);
|
|
|
|
|
|
2023-08-28 12:42:39 -07:00
|
|
|
chooser = g_object_new (GIMP_TYPE_DRAWABLE_CHOOSER,
|
2023-09-05 13:39:04 -07:00
|
|
|
"title", title,
|
|
|
|
|
"label", label,
|
|
|
|
|
"drawable", drawable,
|
|
|
|
|
"drawable-type", drawable_type,
|
2023-08-28 12:42:39 -07:00
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
return chooser;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gimp_drawable_chooser_get_drawable:
|
|
|
|
|
* @chooser: A #GimpDrawableChooser
|
|
|
|
|
*
|
|
|
|
|
* Gets the currently selected drawable.
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer none): an internal copy of the drawable which must not be freed.
|
|
|
|
|
*
|
|
|
|
|
* Since: 3.0
|
2025-11-16 16:09:30 -08:00
|
|
|
*
|
|
|
|
|
* Deprecated: 3.2: Use gimp_item_chooser_get_item().
|
2023-08-28 12:42:39 -07:00
|
|
|
*/
|
|
|
|
|
GimpDrawable *
|
|
|
|
|
gimp_drawable_chooser_get_drawable (GimpDrawableChooser *chooser)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE_CHOOSER (chooser), NULL);
|
|
|
|
|
|
|
|
|
|
return chooser->drawable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gimp_drawable_chooser_set_drawable:
|
|
|
|
|
* @chooser: A #GimpDrawableChooser
|
|
|
|
|
* @drawable: Drawable to set.
|
|
|
|
|
*
|
|
|
|
|
* Sets the currently selected drawable.
|
|
|
|
|
* This will select the drawable in both the button and any chooser popup.
|
|
|
|
|
*
|
|
|
|
|
* Since: 3.0
|
2025-11-16 16:09:30 -08:00
|
|
|
*
|
|
|
|
|
* Deprecated: 3.2: Use gimp_item_chooser_set_item().
|
2023-08-28 12:42:39 -07:00
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
gimp_drawable_chooser_set_drawable (GimpDrawableChooser *chooser,
|
|
|
|
|
GimpDrawable *drawable)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (GIMP_IS_DRAWABLE_CHOOSER (chooser));
|
|
|
|
|
g_return_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable));
|
|
|
|
|
|
|
|
|
|
chooser->drawable = drawable;
|
|
|
|
|
|
|
|
|
|
if (chooser->callback)
|
app, libgimp, plug-ins: move our code to use only non-deprecated code.
- Though GimpDrawableChooser itself is deprecated, make it call the
new items popup API, which will work just as well.
- gimp_procedure_dialog_get_widget() will now return a GimpItemChooser
widget by default. I did hesitate if for API behavior stability, it
should not still return a GimpDrawableChooser, but considered that if
someone set G_TYPE_NONE, they want our "best choice" and are not
considering tweaking it. If someone wants to make sure this function
always returns a specific widget type, they should specify said type.
So I also added a note in the function docs related to this
assumption.
- Van Gogh plug-in must now use the GimpItemChooser API to set the item
to show. Also I am specifying the widget type, even though it is now
the new default, because of the previous point. Since we tweak further
the widget with its API, let's specify so that any further defaults
update doesn't break this code.
- Adding some pragma to ignore warnings on the few pieces of code where
we have to call deprecated functions (because inside other deprecated
functions themselves).
- gui_pdb_dialog_*() API should just always create GimpItemSelect
dialogs now. Also I ref rather than peek the class, because even if
the class has not been instanciated yet (a case I ran into), we still
want to obtain the class structure.
2025-11-17 03:27:52 -08:00
|
|
|
gimp_items_set_popup (chooser->callback, GIMP_ITEM (chooser->drawable));
|
2023-08-28 12:42:39 -07:00
|
|
|
|
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (chooser), drawable_button_props[PROP_DRAWABLE]);
|
|
|
|
|
|
|
|
|
|
gimp_drawable_chooser_draw (chooser);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gimp_drawable_chooser_get_label:
|
|
|
|
|
* @widget: A [class@DrawableChooser].
|
|
|
|
|
*
|
|
|
|
|
* Returns the label widget.
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer none): the [class@Gtk.Widget] showing the label text.
|
2025-11-16 16:09:30 -08:00
|
|
|
*
|
2023-08-28 12:42:39 -07:00
|
|
|
* Since: 3.0
|
2025-11-16 16:09:30 -08:00
|
|
|
*
|
|
|
|
|
* Deprecated: 3.2: Use gimp_item_chooser_get_label().
|
2023-08-28 12:42:39 -07:00
|
|
|
*/
|
|
|
|
|
GtkWidget *
|
|
|
|
|
gimp_drawable_chooser_get_label (GimpDrawableChooser *chooser)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_DRAWABLE_CHOOSER (chooser), NULL);
|
|
|
|
|
|
|
|
|
|
return chooser->label_widget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* private functions */
|
|
|
|
|
|
|
|
|
|
static GimpValueArray *
|
|
|
|
|
gimp_temp_callback_run (GimpProcedure *procedure,
|
|
|
|
|
GimpProcedureConfig *config,
|
|
|
|
|
GimpDrawableChooser *chooser)
|
|
|
|
|
{
|
|
|
|
|
GimpDrawable *drawable;
|
|
|
|
|
gboolean closing;
|
|
|
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
|
"drawable", &drawable,
|
|
|
|
|
"closing", &closing,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
g_object_set (chooser, "drawable", drawable, NULL);
|
|
|
|
|
|
|
|
|
|
if (closing)
|
|
|
|
|
{
|
|
|
|
|
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
|
|
|
|
|
(GSourceFunc) gimp_drawable_select_remove_after_run,
|
|
|
|
|
g_strdup (gimp_procedure_get_name (procedure)),
|
|
|
|
|
g_free);
|
|
|
|
|
g_clear_pointer (&chooser->callback, g_free);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_clear_object (&drawable);
|
|
|
|
|
|
|
|
|
|
return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
gimp_drawable_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_drawable_chooser_clicked (GimpDrawableChooser *chooser)
|
|
|
|
|
{
|
|
|
|
|
if (chooser->callback)
|
|
|
|
|
{
|
|
|
|
|
/* Popup already created. Calling setter raises the popup. */
|
app, libgimp, plug-ins: move our code to use only non-deprecated code.
- Though GimpDrawableChooser itself is deprecated, make it call the
new items popup API, which will work just as well.
- gimp_procedure_dialog_get_widget() will now return a GimpItemChooser
widget by default. I did hesitate if for API behavior stability, it
should not still return a GimpDrawableChooser, but considered that if
someone set G_TYPE_NONE, they want our "best choice" and are not
considering tweaking it. If someone wants to make sure this function
always returns a specific widget type, they should specify said type.
So I also added a note in the function docs related to this
assumption.
- Van Gogh plug-in must now use the GimpItemChooser API to set the item
to show. Also I am specifying the widget type, even though it is now
the new default, because of the previous point. Since we tweak further
the widget with its API, let's specify so that any further defaults
update doesn't break this code.
- Adding some pragma to ignore warnings on the few pieces of code where
we have to call deprecated functions (because inside other deprecated
functions themselves).
- gui_pdb_dialog_*() API should just always create GimpItemSelect
dialogs now. Also I ref rather than peek the class, because even if
the class has not been instanciated yet (a case I ran into), we still
want to obtain the class structure.
2025-11-17 03:27:52 -08:00
|
|
|
gimp_items_set_popup (chooser->callback, GIMP_ITEM (chooser->drawable));
|
2023-08-28 12:42:39 -07:00
|
|
|
}
|
|
|
|
|
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);
|
2024-06-12 09:53:12 -07:00
|
|
|
gimp_procedure_add_drawable_argument (callback_procedure, "drawable",
|
|
|
|
|
"Drawable", "The selected drawable",
|
|
|
|
|
TRUE, G_PARAM_READWRITE);
|
|
|
|
|
gimp_procedure_add_boolean_argument (callback_procedure, "closing",
|
|
|
|
|
"Closing", "If the dialog was closing",
|
|
|
|
|
FALSE, G_PARAM_READWRITE);
|
2023-08-28 12:42:39 -07:00
|
|
|
|
|
|
|
|
gimp_plug_in_add_temp_procedure (plug_in, callback_procedure);
|
|
|
|
|
g_object_unref (callback_procedure);
|
|
|
|
|
g_free (callback_name);
|
|
|
|
|
|
app, libgimp, plug-ins: move our code to use only non-deprecated code.
- Though GimpDrawableChooser itself is deprecated, make it call the
new items popup API, which will work just as well.
- gimp_procedure_dialog_get_widget() will now return a GimpItemChooser
widget by default. I did hesitate if for API behavior stability, it
should not still return a GimpDrawableChooser, but considered that if
someone set G_TYPE_NONE, they want our "best choice" and are not
considering tweaking it. If someone wants to make sure this function
always returns a specific widget type, they should specify said type.
So I also added a note in the function docs related to this
assumption.
- Van Gogh plug-in must now use the GimpItemChooser API to set the item
to show. Also I am specifying the widget type, even though it is now
the new default, because of the previous point. Since we tweak further
the widget with its API, let's specify so that any further defaults
update doesn't break this code.
- Adding some pragma to ignore warnings on the few pieces of code where
we have to call deprecated functions (because inside other deprecated
functions themselves).
- gui_pdb_dialog_*() API should just always create GimpItemSelect
dialogs now. Also I ref rather than peek the class, because even if
the class has not been instanciated yet (a case I ran into), we still
want to obtain the class structure.
2025-11-17 03:27:52 -08:00
|
|
|
if (gimp_items_popup (gimp_procedure_get_name (callback_procedure), chooser->title,
|
|
|
|
|
g_type_name (chooser->drawable_type), GIMP_ITEM (chooser->drawable), handle))
|
2023-08-28 12:42:39 -07:00
|
|
|
{
|
|
|
|
|
/* Allow callbacks to be watched */
|
2024-09-29 09:43:49 -07:00
|
|
|
gimp_plug_in_persistent_enable (plug_in);
|
2023-08-28 12:42:39 -07:00
|
|
|
|
|
|
|
|
chooser->callback = g_strdup (gimp_procedure_get_name (callback_procedure));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
g_warning ("%s: failed to open remote drawable select dialog.", G_STRFUNC);
|
|
|
|
|
gimp_plug_in_remove_temp_procedure (plug_in, gimp_procedure_get_name (callback_procedure));
|
|
|
|
|
return;
|
|
|
|
|
}
|
app, libgimp, plug-ins: move our code to use only non-deprecated code.
- Though GimpDrawableChooser itself is deprecated, make it call the
new items popup API, which will work just as well.
- gimp_procedure_dialog_get_widget() will now return a GimpItemChooser
widget by default. I did hesitate if for API behavior stability, it
should not still return a GimpDrawableChooser, but considered that if
someone set G_TYPE_NONE, they want our "best choice" and are not
considering tweaking it. If someone wants to make sure this function
always returns a specific widget type, they should specify said type.
So I also added a note in the function docs related to this
assumption.
- Van Gogh plug-in must now use the GimpItemChooser API to set the item
to show. Also I am specifying the widget type, even though it is now
the new default, because of the previous point. Since we tweak further
the widget with its API, let's specify so that any further defaults
update doesn't break this code.
- Adding some pragma to ignore warnings on the few pieces of code where
we have to call deprecated functions (because inside other deprecated
functions themselves).
- gui_pdb_dialog_*() API should just always create GimpItemSelect
dialogs now. Also I ref rather than peek the class, because even if
the class has not been instanciated yet (a case I ran into), we still
want to obtain the class structure.
2025-11-17 03:27:52 -08:00
|
|
|
gimp_items_set_popup (chooser->callback, GIMP_ITEM (chooser->drawable));
|
2023-08-28 12:42:39 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gimp_drawable_chooser_draw (GimpDrawableChooser *chooser)
|
|
|
|
|
{
|
|
|
|
|
GimpPreviewArea *area = GIMP_PREVIEW_AREA (chooser->preview);
|
|
|
|
|
GtkAllocation allocation;
|
|
|
|
|
gint x = 0;
|
|
|
|
|
gint y = 0;
|
|
|
|
|
|
|
|
|
|
gtk_widget_get_allocation (chooser->preview, &allocation);
|
|
|
|
|
|
|
|
|
|
gimp_drawable_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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gimp_drawable_chooser_get_thumbnail (GimpDrawableChooser *chooser,
|
|
|
|
|
gint width,
|
|
|
|
|
gint height)
|
|
|
|
|
{
|
|
|
|
|
if (chooser->drawable == chooser->thumbnail_drawable &&
|
|
|
|
|
chooser->width == width &&
|
|
|
|
|
chooser->height == height)
|
|
|
|
|
/* Let's assume drawable contents is not changing in a single run. */
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
g_clear_pointer (&chooser->thumbnail, g_bytes_unref);
|
|
|
|
|
chooser->width = chooser->height = 0;
|
|
|
|
|
|
|
|
|
|
chooser->thumbnail_drawable = chooser->drawable;
|
|
|
|
|
if (chooser->drawable)
|
|
|
|
|
chooser->thumbnail = gimp_drawable_get_thumbnail_data (chooser->drawable,
|
|
|
|
|
width, height,
|
|
|
|
|
&chooser->width,
|
|
|
|
|
&chooser->height,
|
|
|
|
|
&chooser->bpp);
|
|
|
|
|
}
|