PIKApp/libpika/pikapropwidgets.c

274 lines
9.4 KiB
C

/* LIBPIKA - The PIKA Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* pikapropwidgets.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 "libpika/pikaui.h"
#include "libpika-intl.h"
/*
* This is a complement of libpikawidgets/pikapropwidgets.c
* These are property functions for types from libpika, such as
* [class@Gimp.Resource] or [class@Gimp.Item] subclasses.
*/
typedef GtkWidget* (*PikaResourceWidgetCreator) (const gchar *title,
const gchar *label,
PikaResource *initial_resource);
/* utility function prototypes */
static GtkWidget * pika_prop_resource_chooser_factory (PikaResourceWidgetCreator widget_creator_func,
GObject *config,
const gchar *property_name,
const gchar *chooser_title);
static gchar * pika_utils_make_canonical_menu_label (const gchar *path);
/**
* pika_prop_brush_chooser_new:
* @config: Object to which property is attached.
* @property_name: Name of a [class@Gimp.Brush] property.
* @chooser_title: (nullable): title for the poppable dialog.
*
* Creates a [class@Gimp.Brush.Chooser] controlled by the specified property.
*
* Returns: (transfer full): A new [class@GimpUi.BrushChooser].
*
* Since: 3.0
*/
GtkWidget *
pika_prop_brush_chooser_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title)
{
return pika_prop_resource_chooser_factory (pika_brush_chooser_new,
config, property_name, chooser_title);
}
/**
* pika_prop_font_chooser_new:
* @config: Object to which property is attached.
* @property_name: Name of a [class@Gimp.Font] property.
* @chooser_title: (nullable): title for the poppable dialog.
*
* Creates a [class@GimpUi.FontChooser] controlled by the specified property.
*
* Returns: (transfer full): A new [class@GimpUi.FontChooser].
*
* Since: 3.0
*/
GtkWidget *
pika_prop_font_chooser_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title)
{
return pika_prop_resource_chooser_factory (pika_font_chooser_new,
config, property_name, chooser_title);
}
/**
* pika_prop_gradient_chooser_new:
* @config: Object to which property is attached.
* @property_name: Name of a [class@Gimp.Gradient] property.
* @chooser_title: (nullable): title for the poppable dialog.
*
* Creates a [class@GimpUi.GradientChooser] controlled by the specified property.
*
* Returns: (transfer full): A new [class@GimpUi.GradientChooser].
*
* Since: 3.0
*/
GtkWidget *
pika_prop_gradient_chooser_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title)
{
return pika_prop_resource_chooser_factory (pika_gradient_chooser_new,
config, property_name, chooser_title);
}
/**
* pika_prop_palette_chooser_new:
* @config: Object to which property is attached.
* @property_name: Name of a [class@Gimp.Palette] property.
* @chooser_title: (nullable): title for the poppable dialog.
*
* Creates a [class@GimpUi.PaletteChooser] controlled by the specified property.
*
* Returns: (transfer full): A new [class@GimpUi.PaletteChooser].
*
* Since: 3.0
*/
GtkWidget *
pika_prop_palette_chooser_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title)
{
return pika_prop_resource_chooser_factory (pika_palette_chooser_new,
config, property_name, chooser_title);
}
/**
* pika_prop_pattern_chooser_new:
* @config: Object to which property is attached.
* @property_name: Name of a [class@Gimp.Pattern] property.
* @chooser_title: (nullable): title for the poppable dialog.
*
* Creates a [class@GimpUi.PatternChooser] controlled by the specified property.
*
* Returns: (transfer full): A new [class@GimpUi.PatternChooser].
*
* Since: 3.0
*/
GtkWidget *
pika_prop_pattern_chooser_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title)
{
return pika_prop_resource_chooser_factory (pika_pattern_chooser_new,
config, property_name, chooser_title);
}
/**
* pika_prop_drawable_chooser_new:
* @config: Object to which property is attached.
* @property_name: Name of a [class@Gimp.Drawable] property.
* @chooser_title: (nullable): title for the poppable dialog.
*
* Creates a [class@GimpUi.DrawableChooser] controlled by the specified property.
*
* Returns: (transfer full): A new [class@GimpUi.DrawableChooser].
*
* Since: 3.0
*/
GtkWidget *
pika_prop_drawable_chooser_new (GObject *config,
const gchar *property_name,
const gchar *chooser_title)
{
GParamSpec *param_spec;
GtkWidget *prop_chooser;
PikaDrawable *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, PIKA_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 = pika_utils_make_canonical_menu_label (label);
if (g_type_is_a (param_spec->value_type, PIKA_TYPE_LAYER))
title = g_strdup_printf (_("Choose layer: %s"), canonical);
if (g_type_is_a (param_spec->value_type, PIKA_TYPE_CHANNEL))
title = g_strdup_printf (_("Choose channel: %s"), canonical);
else
title = g_strdup_printf (_("Choose drawable: %s"), canonical);
g_free (canonical);
}
else
{
title = g_strdup (chooser_title);
}
prop_chooser = pika_drawable_chooser_new (title, label, param_spec->value_type, initial_drawable);
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;
}
/*******************************/
/* private utility functions */
/*******************************/
static GtkWidget *
pika_prop_resource_chooser_factory (PikaResourceWidgetCreator widget_creator_func,
GObject *config,
const gchar *property_name,
const gchar *chooser_title)
{
GParamSpec *param_spec;
GtkWidget *prop_chooser;
PikaResource *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, PIKA_TYPE_RESOURCE), NULL);
g_object_get (config,
property_name, &initial_resource,
NULL);
label = g_param_spec_get_nick (param_spec);
/* Create the wrapped widget. For example, call pika_font_chooser_new.
* 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);
g_clear_object (&initial_resource);
g_object_bind_property (prop_chooser, "resource",
config, property_name,
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
return prop_chooser;
}
/* This is a copy of the similarly-named function in app/widgets/pikawidgets-utils.c
* I hesitated to put this maybe in libpikawidgets/pikawidgetsutils.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 *
pika_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;
}