2023-08-18 05:02:38 +08:00
|
|
|
/* LIBGIMP - The GIMP Library
|
|
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
|
|
*
|
|
|
|
* gimppropwidgets.c
|
|
|
|
* Copyright (C) 2023 Jehan
|
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "libgimp/gimpui.h"
|
|
|
|
|
2023-08-29 03:42:39 +08:00
|
|
|
#include "libgimp-intl.h"
|
|
|
|
|
2023-10-02 06:00:15 +08:00
|
|
|
/*
|
|
|
|
* This is a complement of libgimpwidgets/gimppropwidgets.c
|
|
|
|
* These are property functions for types from libgimp, such as
|
2023-08-18 05:02:38 +08:00
|
|
|
* [class@Gimp.Resource] or [class@Gimp.Item] subclasses.
|
2023-10-02 06:00:15 +08:00
|
|
|
*/
|
2023-08-18 05:02:38 +08:00
|
|
|
|
|
|
|
|
|
|
|
typedef GtkWidget* (*GimpResourceWidgetCreator) (const gchar *title,
|
|
|
|
const gchar *label,
|
|
|
|
GimpResource *initial_resource);
|
|
|
|
|
|
|
|
|
|
|
|
/* utility function prototypes */
|
|
|
|
|
2023-08-29 03:42:39 +08:00
|
|
|
static GtkWidget * gimp_prop_resource_chooser_factory (GimpResourceWidgetCreator widget_creator_func,
|
|
|
|
GObject *config,
|
|
|
|
const gchar *property_name,
|
|
|
|
const gchar *chooser_title);
|
|
|
|
static gchar * gimp_utils_make_canonical_menu_label (const gchar *path);
|
2023-08-18 05:02:38 +08:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_prop_brush_chooser_new:
|
|
|
|
* @config: Object to which property is attached.
|
|
|
|
* @property_name: Name of a [class@Gimp.Brush] property.
|
2023-10-02 06:07:46 +08:00
|
|
|
* @chooser_title: (nullable): title for the poppable dialog.
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
2024-06-11 18:34:15 +08:00
|
|
|
* Creates a [class@GimpUi.BrushChooser] controlled by the specified property.
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
2023-10-02 06:07:46 +08:00
|
|
|
* Returns: (transfer full): A new [class@GimpUi.BrushChooser].
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
|
|
|
* Since: 3.0
|
|
|
|
*/
|
|
|
|
GtkWidget *
|
|
|
|
gimp_prop_brush_chooser_new (GObject *config,
|
|
|
|
const gchar *property_name,
|
|
|
|
const gchar *chooser_title)
|
|
|
|
{
|
2023-08-19 07:22:09 +08:00
|
|
|
return gimp_prop_resource_chooser_factory (gimp_brush_chooser_new,
|
2023-08-18 05:02:38 +08:00
|
|
|
config, property_name, chooser_title);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_prop_font_chooser_new:
|
|
|
|
* @config: Object to which property is attached.
|
|
|
|
* @property_name: Name of a [class@Gimp.Font] property.
|
2023-10-02 06:07:46 +08:00
|
|
|
* @chooser_title: (nullable): title for the poppable dialog.
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
2023-10-02 06:07:46 +08:00
|
|
|
* Creates a [class@GimpUi.FontChooser] controlled by the specified property.
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
2023-10-02 06:07:46 +08:00
|
|
|
* Returns: (transfer full): A new [class@GimpUi.FontChooser].
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
|
|
|
* Since: 3.0
|
|
|
|
*/
|
|
|
|
GtkWidget *
|
|
|
|
gimp_prop_font_chooser_new (GObject *config,
|
|
|
|
const gchar *property_name,
|
|
|
|
const gchar *chooser_title)
|
|
|
|
{
|
2023-08-19 07:22:09 +08:00
|
|
|
return gimp_prop_resource_chooser_factory (gimp_font_chooser_new,
|
2023-08-18 05:02:38 +08:00
|
|
|
config, property_name, chooser_title);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_prop_gradient_chooser_new:
|
|
|
|
* @config: Object to which property is attached.
|
|
|
|
* @property_name: Name of a [class@Gimp.Gradient] property.
|
2023-10-02 06:07:46 +08:00
|
|
|
* @chooser_title: (nullable): title for the poppable dialog.
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
2023-10-02 06:07:46 +08:00
|
|
|
* Creates a [class@GimpUi.GradientChooser] controlled by the specified property.
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
2023-10-02 06:07:46 +08:00
|
|
|
* Returns: (transfer full): A new [class@GimpUi.GradientChooser].
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
|
|
|
* Since: 3.0
|
|
|
|
*/
|
|
|
|
GtkWidget *
|
|
|
|
gimp_prop_gradient_chooser_new (GObject *config,
|
|
|
|
const gchar *property_name,
|
|
|
|
const gchar *chooser_title)
|
|
|
|
{
|
2023-08-19 07:22:09 +08:00
|
|
|
return gimp_prop_resource_chooser_factory (gimp_gradient_chooser_new,
|
2023-08-18 05:02:38 +08:00
|
|
|
config, property_name, chooser_title);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_prop_palette_chooser_new:
|
|
|
|
* @config: Object to which property is attached.
|
|
|
|
* @property_name: Name of a [class@Gimp.Palette] property.
|
2023-10-02 06:07:46 +08:00
|
|
|
* @chooser_title: (nullable): title for the poppable dialog.
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
2023-10-02 06:07:46 +08:00
|
|
|
* Creates a [class@GimpUi.PaletteChooser] controlled by the specified property.
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
2023-10-02 06:07:46 +08:00
|
|
|
* Returns: (transfer full): A new [class@GimpUi.PaletteChooser].
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
|
|
|
* Since: 3.0
|
|
|
|
*/
|
|
|
|
GtkWidget *
|
|
|
|
gimp_prop_palette_chooser_new (GObject *config,
|
|
|
|
const gchar *property_name,
|
|
|
|
const gchar *chooser_title)
|
|
|
|
{
|
2023-08-19 07:22:09 +08:00
|
|
|
return gimp_prop_resource_chooser_factory (gimp_palette_chooser_new,
|
2023-08-18 05:02:38 +08:00
|
|
|
config, property_name, chooser_title);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gimp_prop_pattern_chooser_new:
|
|
|
|
* @config: Object to which property is attached.
|
|
|
|
* @property_name: Name of a [class@Gimp.Pattern] property.
|
2023-10-02 06:07:46 +08:00
|
|
|
* @chooser_title: (nullable): title for the poppable dialog.
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
2023-10-02 06:07:46 +08:00
|
|
|
* Creates a [class@GimpUi.PatternChooser] controlled by the specified property.
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
2023-10-02 06:07:46 +08:00
|
|
|
* Returns: (transfer full): A new [class@GimpUi.PatternChooser].
|
2023-08-18 05:02:38 +08:00
|
|
|
*
|
|
|
|
* Since: 3.0
|
|
|
|
*/
|
|
|
|
GtkWidget *
|
|
|
|
gimp_prop_pattern_chooser_new (GObject *config,
|
|
|
|
const gchar *property_name,
|
|
|
|
const gchar *chooser_title)
|
|
|
|
{
|
2023-08-19 07:22:09 +08:00
|
|
|
return gimp_prop_resource_chooser_factory (gimp_pattern_chooser_new,
|
2023-08-18 05:02:38 +08:00
|
|
|
config, property_name, chooser_title);
|
|
|
|
}
|
|
|
|
|
2023-08-29 03:42:39 +08:00
|
|
|
/**
|
|
|
|
* gimp_prop_drawable_chooser_new:
|
|
|
|
* @config: Object to which property is attached.
|
|
|
|
* @property_name: Name of a [class@Gimp.Drawable] property.
|
2023-10-02 06:07:46 +08:00
|
|
|
* @chooser_title: (nullable): title for the poppable dialog.
|
2023-08-29 03:42:39 +08:00
|
|
|
*
|
2023-10-02 06:07:46 +08:00
|
|
|
* Creates a [class@GimpUi.DrawableChooser] controlled by the specified property.
|
2023-08-29 03:42:39 +08:00
|
|
|
*
|
2023-10-02 06:07:46 +08:00
|
|
|
* Returns: (transfer full): A new [class@GimpUi.DrawableChooser].
|
2023-08-29 03:42:39 +08:00
|
|
|
*
|
|
|
|
* Since: 3.0
|
|
|
|
*/
|
|
|
|
GtkWidget *
|
|
|
|
gimp_prop_drawable_chooser_new (GObject *config,
|
|
|
|
const gchar *property_name,
|
|
|
|
const gchar *chooser_title)
|
|
|
|
{
|
|
|
|
GParamSpec *param_spec;
|
|
|
|
GtkWidget *prop_chooser;
|
|
|
|
GimpDrawable *initial_drawable = 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_DRAWABLE), NULL);
|
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
property_name, &initial_drawable,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
label = g_param_spec_get_nick (param_spec);
|
|
|
|
|
|
|
|
if (chooser_title == NULL)
|
|
|
|
{
|
|
|
|
gchar *canonical;
|
|
|
|
|
|
|
|
canonical = gimp_utils_make_canonical_menu_label (label);
|
2023-09-06 04:39:04 +08:00
|
|
|
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);
|
|
|
|
else
|
|
|
|
title = g_strdup_printf (_("Choose drawable: %s"), canonical);
|
2023-08-29 03:42:39 +08:00
|
|
|
g_free (canonical);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
title = g_strdup (chooser_title);
|
|
|
|
}
|
|
|
|
|
2023-09-06 04:39:04 +08:00
|
|
|
prop_chooser = gimp_drawable_chooser_new (title, label, param_spec->value_type, initial_drawable);
|
2023-08-29 03:42:39 +08:00
|
|
|
g_clear_object (&initial_drawable);
|
|
|
|
g_free (title);
|
|
|
|
|
|
|
|
g_object_bind_property (prop_chooser, "drawable",
|
|
|
|
config, property_name,
|
|
|
|
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
|
|
|
|
|
|
|
return prop_chooser;
|
|
|
|
}
|
2023-08-18 05:02:38 +08:00
|
|
|
|
|
|
|
/*******************************/
|
|
|
|
/* private utility functions */
|
|
|
|
/*******************************/
|
|
|
|
|
|
|
|
static GtkWidget *
|
|
|
|
gimp_prop_resource_chooser_factory (GimpResourceWidgetCreator widget_creator_func,
|
|
|
|
GObject *config,
|
|
|
|
const gchar *property_name,
|
|
|
|
const gchar *chooser_title)
|
|
|
|
{
|
|
|
|
GParamSpec *param_spec;
|
|
|
|
GtkWidget *prop_chooser;
|
|
|
|
GimpResource *initial_resource;
|
|
|
|
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_RESOURCE), NULL);
|
|
|
|
|
|
|
|
g_object_get (config,
|
|
|
|
property_name, &initial_resource,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
label = g_param_spec_get_nick (param_spec);
|
|
|
|
|
2023-08-19 07:22:09 +08:00
|
|
|
/* Create the wrapped widget. For example, call gimp_font_chooser_new.
|
2023-08-18 05:02:38 +08:00
|
|
|
* When initial_resource is NULL, the widget creator will set it's resource
|
|
|
|
* property from context.
|
|
|
|
*/
|
|
|
|
prop_chooser = widget_creator_func (chooser_title, label, initial_resource);
|
2023-10-11 20:59:27 +08:00
|
|
|
g_clear_object (&initial_resource);
|
2023-08-18 05:02:38 +08:00
|
|
|
|
|
|
|
g_object_bind_property (prop_chooser, "resource",
|
|
|
|
config, property_name,
|
|
|
|
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
|
|
|
|
|
|
|
return prop_chooser;
|
|
|
|
}
|
2023-08-29 03:42:39 +08:00
|
|
|
|
|
|
|
/* This is a copy of the similarly-named function in app/widgets/gimpwidgets-utils.c
|
|
|
|
* I hesitated to put this maybe in libgimpwidgets/gimpwidgetsutils.h but for
|
|
|
|
* now, let's not. If it's useful to more people, it's always easier to move the
|
|
|
|
* function in rather than deprecating it.
|
|
|
|
*/
|
|
|
|
static gchar *
|
|
|
|
gimp_utils_make_canonical_menu_label (const gchar *path)
|
|
|
|
{
|
|
|
|
gchar **split_path;
|
|
|
|
gchar *canon_path;
|
|
|
|
|
|
|
|
/* The first underscore of each path item is a mnemonic. */
|
|
|
|
split_path = g_strsplit (path, "_", 2);
|
|
|
|
canon_path = g_strjoinv ("", split_path);
|
|
|
|
g_strfreev (split_path);
|
|
|
|
|
|
|
|
return canon_path;
|
|
|
|
}
|