274 lines
9.4 KiB
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;
|
|
}
|