diff --git a/libgimp/gimpresolutionentry-private.c b/libgimp/gimpresolutionentry-private.c new file mode 100644 index 0000000000..296ebb28ae --- /dev/null +++ b/libgimp/gimpresolutionentry-private.c @@ -0,0 +1,742 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpresolutionentry.c + * Copyright (C) 2024 Jehan + * + * 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 . + */ + +#include "config.h" + +#include +#include + +#include "libgimpwidgets/gimpwidgets.h" + +#include "gimp.h" +#include "gimpui.h" +#include "gimpresolutionentry-private.h" + +#include "libgimp-intl.h" + + +enum +{ + PROP_0, + PROP_WIDTH, + PROP_HEIGHT, + PROP_PIXEL_DENSITY, + PROP_UNIT, + PROP_KEEP_RATIO, + N_PROPS +}; + +struct _GimpResolutionEntry +{ + GtkGrid parent_instance; + + gint width; + gint height; + gdouble ppi; + GimpUnit unit; + gboolean keep_ratio; + + GtkWidget *phy_width_label; + GtkWidget *phy_height_label; + + GtkWidget *chainbutton; +}; + +G_DEFINE_FINAL_TYPE (GimpResolutionEntry, gimp_resolution_entry, GTK_TYPE_GRID) + +#define parent_class gimp_resolution_entry_parent_class + + +static void gimp_resolution_entry_class_init (GimpResolutionEntryClass *class); +static void gimp_resolution_entry_init (GimpResolutionEntry *gre); +static void gimp_resolution_entry_constructed (GObject *object); +static void gimp_resolution_entry_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_resolution_entry_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static GtkWidget * gimp_resolution_entry_attach_label (GimpResolutionEntry *entry, + const gchar *text, + gint row, + gint column, + gfloat alignment); +static void gimp_resolution_entry_format_label (GimpResolutionEntry *entry, + GtkWidget *label, + gdouble size); +static void gimp_resolution_entry_update_labels (GimpResolutionEntry *entry, + GParamSpec *param_spec, + GtkWidget *label); + +static gboolean gimp_resolution_entry_ppi_to_unit (GBinding *binding, + const GValue *from_value, + GValue *to_value, + GimpResolutionEntry *entry); +static gboolean gimp_resolution_entry_unit_to_ppi (GBinding *binding, + const GValue *from_value, + GValue *to_value, + GimpResolutionEntry *entry); + + +static GParamSpec *props[N_PROPS] = { NULL, }; + +static void +gimp_resolution_entry_class_init (GimpResolutionEntryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = gimp_resolution_entry_constructed; + object_class->set_property = gimp_resolution_entry_set_property; + object_class->get_property = gimp_resolution_entry_get_property; + + props[PROP_WIDTH] = g_param_spec_int ("width", + "Width in pixel", + NULL, + 0, GIMP_MAX_IMAGE_SIZE, 0, + GIMP_PARAM_READWRITE | + G_PARAM_EXPLICIT_NOTIFY | + G_PARAM_CONSTRUCT); + props[PROP_HEIGHT] = g_param_spec_int ("height", + "Height in pixel", + NULL, + 0, GIMP_MAX_IMAGE_SIZE, 0, + GIMP_PARAM_READWRITE | + G_PARAM_EXPLICIT_NOTIFY | + G_PARAM_CONSTRUCT); + props[PROP_PIXEL_DENSITY] = g_param_spec_double ("pixel-density", + "Pixel density in pixel per inch", + NULL, + GIMP_MIN_RESOLUTION, GIMP_MAX_RESOLUTION, 300.0, + GIMP_PARAM_READWRITE | + G_PARAM_EXPLICIT_NOTIFY | + G_PARAM_CONSTRUCT); + props[PROP_UNIT] = gimp_param_spec_unit ("unit", + "Physical unit for the pixel density", + "This unit is used to select the pixel density " + "and show dimensions in physical unit", + FALSE, FALSE, + GIMP_UNIT_INCH, + GIMP_PARAM_READWRITE | + G_PARAM_EXPLICIT_NOTIFY | + G_PARAM_CONSTRUCT); + props[PROP_KEEP_RATIO] = g_param_spec_boolean ("keep-ratio", + _("_Keep aspect ratio"), + _("Force dimensions with aspect ratio"), + TRUE, + GIMP_PARAM_READWRITE | + G_PARAM_EXPLICIT_NOTIFY | + G_PARAM_CONSTRUCT); + + g_object_class_install_properties (object_class, N_PROPS, props); +} + +static void +gimp_resolution_entry_init (GimpResolutionEntry *entry) +{ + entry->width = 0; + entry->height = 0; + entry->ppi = 300.0; + entry->unit = GIMP_UNIT_INCH; + entry->keep_ratio = TRUE; + + gtk_grid_set_row_spacing (GTK_GRID (entry), 2); + gtk_grid_set_column_spacing (GTK_GRID (entry), 4); +} + +static void +gimp_resolution_entry_constructed (GObject *object) +{ + GimpResolutionEntry *entry = GIMP_RESOLUTION_ENTRY (object); + GtkTreeModel *model; + GtkWidget *label; + GtkWidget *widget; + GBinding *binding; + GtkAdjustment *adj; + + widget = gimp_prop_spin_button_new (object, "pixel-density", 1.0, 10.0, 2); + adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget)); + binding = g_object_get_data (G_OBJECT (adj), "gimp-prop-adjustment-binding"); + g_binding_unbind (binding); + binding = g_object_bind_property_full (object, "pixel-density", + widget, "value", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE, + (GBindingTransformFunc) gimp_resolution_entry_ppi_to_unit, + (GBindingTransformFunc) gimp_resolution_entry_unit_to_ppi, + entry, NULL); + g_object_set_data (G_OBJECT (adj), "gimp-prop-adjustment-binding", binding); + gtk_grid_attach (GTK_GRID (entry), widget, 1, 3, 1, 1); + gtk_widget_show (widget); + + widget = gimp_prop_unit_combo_box_new (object, "unit"); + model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget)); + g_object_set (model, + "short-format", _("pixels/%a"), + "long-format", _("pixels/%a"), + NULL); + gtk_grid_attach (GTK_GRID (entry), widget, 3, 3, 1, 1); + gtk_widget_show (widget); + + widget = gimp_prop_spin_button_new (object, "width", 1.0, 10.0, 0); + gtk_grid_attach (GTK_GRID (entry), widget, 1, 1, 1, 1); + gtk_widget_show (widget); + + label = g_object_new (GTK_TYPE_LABEL, + "xalign", 0.0, + "yalign", 0.5, + NULL); + gimp_label_set_attributes (GTK_LABEL (label), + PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC, + -1); + gimp_resolution_entry_format_label (entry, label, + entry->width / entry->ppi); + entry->phy_width_label = label; + gtk_grid_attach (GTK_GRID (entry), entry->phy_width_label, 3, 1, 1, 1); + gtk_widget_show (entry->phy_width_label); + + widget = gimp_prop_spin_button_new (object, "height", 1.0, 10.0, 0); + gtk_grid_attach (GTK_GRID (entry), widget, 1, 2, 1, 1); + gtk_widget_show (widget); + + label = g_object_new (GTK_TYPE_LABEL, + "xalign", 0.0, + "yalign", 0.5, + NULL); + gimp_label_set_attributes (GTK_LABEL (label), + PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC, + -1); + gimp_resolution_entry_format_label (entry, label, + entry->height / entry->ppi); + entry->phy_height_label = label; + gtk_grid_attach (GTK_GRID (entry), entry->phy_height_label, 3, 2, 1, 1); + gtk_widget_show (entry->phy_height_label); + + g_signal_connect (object, "notify::width", + G_CALLBACK (gimp_resolution_entry_update_labels), + entry->phy_width_label); + g_signal_connect (object, "notify::height", + G_CALLBACK (gimp_resolution_entry_update_labels), + entry->phy_height_label); + g_signal_connect (object, "notify::pixel-density", + G_CALLBACK (gimp_resolution_entry_update_labels), + NULL); +} + +static void +gimp_resolution_entry_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpResolutionEntry *entry = GIMP_RESOLUTION_ENTRY (object); + + switch (property_id) + { + case PROP_WIDTH: + gimp_resolution_entry_set_width (entry, g_value_get_int (value)); + break; + case PROP_HEIGHT: + gimp_resolution_entry_set_height (entry, g_value_get_int (value)); + break; + case PROP_PIXEL_DENSITY: + gimp_resolution_entry_set_pixel_density (entry, g_value_get_double (value)); + break; + case PROP_UNIT: + gimp_resolution_entry_set_unit (entry, g_value_get_int (value)); + break; + case PROP_KEEP_RATIO: + gimp_resolution_entry_set_keep_ratio (entry, g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_resolution_entry_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpResolutionEntry *entry = GIMP_RESOLUTION_ENTRY (object); + + switch (property_id) + { + case PROP_WIDTH: + g_value_set_int (value, entry->width); + break; + case PROP_HEIGHT: + g_value_set_int (value, entry->height); + break; + case PROP_PIXEL_DENSITY: + g_value_set_double (value, entry->ppi); + break; + case PROP_UNIT: + g_value_set_int (value, entry->unit); + break; + case PROP_KEEP_RATIO: + g_value_set_boolean (value, entry->keep_ratio); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +GtkWidget * +gimp_prop_resolution_entry_new (GObject *config, + const gchar *width_prop, + const gchar *height_prop, + const gchar *ppi_prop, + const gchar *unit_prop) +{ + GtkWidget *widget; + GParamSpec *w_pspec; + GParamSpec *h_pspec; + GParamSpec *d_pspec; + GParamSpec *u_pspec; + gint width = 0; + gint height = 0; + gdouble ppi = 300.0; + GimpUnit unit = GIMP_UNIT_INCH; + + g_return_val_if_fail (G_IS_OBJECT (config), NULL); + g_return_val_if_fail (width_prop != NULL, NULL); + g_return_val_if_fail (height_prop != NULL, NULL); + g_return_val_if_fail (ppi_prop != NULL, NULL); + g_return_val_if_fail (unit_prop != NULL, NULL); + + w_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), width_prop); + h_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), height_prop); + d_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), ppi_prop); + u_pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), unit_prop); + + g_return_val_if_fail (w_pspec != NULL, NULL); + g_return_val_if_fail (h_pspec != NULL, NULL); + g_return_val_if_fail (d_pspec != NULL, NULL); + g_return_val_if_fail (u_pspec != NULL, NULL); + + g_object_get (config, + width_prop, &width, + height_prop, &height, + ppi_prop, &ppi, + unit_prop, &unit, + NULL); + + widget = gimp_resolution_entry_new (g_param_spec_get_nick (w_pspec), width, + g_param_spec_get_nick (h_pspec), height, + g_param_spec_get_nick (d_pspec), ppi, + unit); + + g_object_bind_property (config, width_prop, + widget, "width", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + g_object_bind_property (config, height_prop, + widget, "height", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + g_object_bind_property (config, ppi_prop, + widget, "pixel-density", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + g_object_bind_property (config, unit_prop, + widget, "unit", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + + return widget; +} + +/** + * gimp_resolution_entry_new: + * @width_label: Optional label for the width control. + * @width: Width of the item, specified in pixels. + * @height_label: Optional label for the height control. + * @height: Height of the item, specified in pixels. + * @res_label: Optional label for the resolution entry. + * @pixel_density: The initial resolution in pixel per inch. + * @display_unit: The display unit. + * + * Creates a new #GimpResolutionEntry widget. + * + * The #GimpResolutionEntry is derived from #GtkGrid and will have + * an empty border of one cell width on each side plus an empty column left + * of the #GimpUnitMenu to allow the caller to add labels or other widgets. + * + * A #GimpChainButton is displayed if independent is set to %TRUE. + * + * Returns: A pointer to the new #GimpResolutionEntry widget. + **/ +GtkWidget * +gimp_resolution_entry_new (const gchar *width_label, + gint width, + const gchar *height_label, + gint height, + const gchar *res_label, + gdouble pixel_density, + GimpUnit display_unit) +{ + GimpResolutionEntry *entry; + + entry = g_object_new (GIMP_TYPE_RESOLUTION_ENTRY, + "width", width, + "height", height, + "pixel-density", pixel_density, + "unit", display_unit, + NULL); + + if (width_label) + gimp_resolution_entry_attach_label (entry, width_label, 1, 0, 0.0); + + if (height_label) + gimp_resolution_entry_attach_label (entry, height_label, 2, 0, 0.0); + + if (res_label) + gimp_resolution_entry_attach_label (entry, res_label, 3, 0, 0.0); + + return GTK_WIDGET (entry); +} + +static gboolean +gimp_resolution_entry_idle_notify (GimpResolutionEntry *entry) +{ + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_WIDTH]); + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_HEIGHT]); + + return G_SOURCE_REMOVE; +} + +void +gimp_resolution_entry_set_width (GimpResolutionEntry *entry, + gint width) +{ + if (width == 0) + { + /* Do nothing, i.e. revert back to value it was. Yet notify after an idle + * source, otherwise the entry is not updated (the binding likely blocks + * notifications for this property to avoid infinite loops. + */ + g_idle_add ((GSourceFunc) gimp_resolution_entry_idle_notify, entry); + } + else if (entry->width != width) + { + gdouble inch_width = 0.0; + + if (entry->width != 0 && entry->height != 0 && entry->ppi != 0.0) + inch_width = (gdouble) entry->width / entry->ppi; + + g_object_freeze_notify (G_OBJECT (entry)); + + if (entry->keep_ratio && entry->width != 0) + { + gdouble ratio; + gint height; + + ratio = (gdouble) entry->height / (gdouble) entry->width; + height = (gint) (width * ratio); + + if (height != entry->height) + { + entry->height = height; + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_HEIGHT]); + } + } + + entry->width = width; + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_WIDTH]); + + if (inch_width != 0.0) + { + entry->ppi = (gdouble) entry->width / inch_width; + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_PIXEL_DENSITY]); + } + + g_object_thaw_notify (G_OBJECT (entry)); + } +} + +void +gimp_resolution_entry_set_height (GimpResolutionEntry *entry, + gint height) +{ + if (height == 0) + { + /* Do nothing, i.e. revert back to value it was. Yet notify after an idle + * source, otherwise the entry is not updated (the binding likely blocks + * notifications for this property to avoid infinite loops. + */ + g_idle_add ((GSourceFunc) gimp_resolution_entry_idle_notify, entry); + } + else if (entry->height != height) + { + gdouble inch_height = 0.0; + + if (entry->width != 0 && entry->height != 0 && entry->ppi != 0.0) + inch_height = (gdouble) entry->height / entry->ppi; + + g_object_freeze_notify (G_OBJECT (entry)); + + if (entry->keep_ratio && entry->height != 0) + { + gdouble ratio; + gint width; + + ratio = (gdouble) entry->width / (gdouble) entry->height; + width = (gint) (height * ratio); + + if (width != entry->width) + { + entry->width = width; + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_WIDTH]); + } + } + + entry->height = height; + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_HEIGHT]); + + if (inch_height != 0.0) + { + entry->ppi = (gdouble) entry->height / inch_height; + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_PIXEL_DENSITY]); + } + + g_object_thaw_notify (G_OBJECT (entry)); + } +} + +void +gimp_resolution_entry_set_pixel_density (GimpResolutionEntry *entry, + gdouble ppi) +{ + if (entry->ppi != ppi) + { + gdouble inch_width = entry->width / entry->ppi; + gdouble inch_height = entry->height / entry->ppi; + + g_object_freeze_notify (G_OBJECT (entry)); + entry->ppi = ppi; + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_PIXEL_DENSITY]); + + /* This test is just to check if we are in construction. */ + if (entry->phy_width_label) + { + entry->width = inch_width * ppi; + entry->height = inch_height * ppi; + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_WIDTH]); + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_HEIGHT]); + } + + g_object_thaw_notify (G_OBJECT (entry)); + } +} + +void +gimp_resolution_entry_set_unit (GimpResolutionEntry *entry, + GimpUnit unit) +{ + g_return_if_fail (unit != GIMP_UNIT_PIXEL); + g_return_if_fail (unit != GIMP_UNIT_PERCENT); + + if (entry->unit != unit) + { + entry->unit = unit; + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_UNIT]); + /* Even though the pixel density (in pixel per inch) has not in fact + * changed, we send a notification to force a refresh of the displayed + * pixel per other-unit value in the entry field. + */ + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_PIXEL_DENSITY]); + + if (entry->phy_width_label) + gimp_resolution_entry_format_label (entry, entry->phy_width_label, + gimp_unit_get_factor (entry->unit) * + entry->width / entry->ppi); + if (entry->phy_height_label) + gimp_resolution_entry_format_label (entry, entry->phy_height_label, + gimp_unit_get_factor (entry->unit) * + entry->height / entry->ppi); + } +} + +void +gimp_resolution_entry_set_keep_ratio (GimpResolutionEntry *entry, + gboolean keep_ratio) +{ + if (keep_ratio != entry->keep_ratio) + { + entry->keep_ratio = keep_ratio; + g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_KEEP_RATIO]); + } +} + +gint +gimp_resolution_entry_get_width (GimpResolutionEntry *entry) +{ + return entry->width; +} + +gint +gimp_resolution_entry_get_height (GimpResolutionEntry *entry) +{ + return entry->height; +} + +gdouble +gimp_resolution_entry_get_density (GimpResolutionEntry *entry) +{ + return entry->ppi; +} + +GimpUnit +gimp_resolution_entry_get_unit (GimpResolutionEntry *entry) +{ + return entry->unit; +} + +gboolean +gimp_resolution_entry_get_keep_ratio (GimpResolutionEntry *entry) +{ + return entry->keep_ratio; +} + + +/* Private functions. */ + +/** + * gimp_resolution_entry_attach_label: + * @gre: The #GimpResolutionEntry you want to add a label to. + * @text: The text of the label. + * @row: The row where the label will be attached. + * @column: The column where the label will be attached. + * @alignment: The horizontal alignment of the label. + * + * Attaches a #GtkLabel to the #GimpResolutionEntry (which is a #GtkGrid). + * + * Returns: A pointer to the new #GtkLabel widget. + **/ +static GtkWidget * +gimp_resolution_entry_attach_label (GimpResolutionEntry *gre, + const gchar *text, + gint row, + gint column, + gfloat alignment) +{ + GtkWidget *label; + + g_return_val_if_fail (GIMP_IS_RESOLUTION_ENTRY (gre), NULL); + g_return_val_if_fail (text != NULL, NULL); + + label = gtk_label_new_with_mnemonic (text); + + if (column == 0) + { + GList *children; + GList *list; + + children = gtk_container_get_children (GTK_CONTAINER (gre)); + + for (list = children; list; list = g_list_next (list)) + { + GtkWidget *child = list->data; + gint left_attach; + gint top_attach; + + gtk_container_child_get (GTK_CONTAINER (gre), child, + "left-attach", &left_attach, + "top-attach", &top_attach, + NULL); + + if (left_attach == 1 && top_attach == row) + { + gtk_label_set_mnemonic_widget (GTK_LABEL (label), child); + break; + } + } + + g_list_free (children); + } + + gtk_label_set_xalign (GTK_LABEL (label), alignment); + + gtk_grid_attach (GTK_GRID (gre), label, column, row, 1, 1); + gtk_widget_show (label); + + return label; +} + +static void +gimp_resolution_entry_format_label (GimpResolutionEntry *entry, + GtkWidget *label, + gdouble size_inch) +{ + gchar *format = g_strdup_printf ("%%.%df %%s", + gimp_unit_get_digits (entry->unit)); + gchar *text = g_strdup_printf (format, + size_inch * gimp_unit_get_factor (entry->unit), + gimp_unit_get_plural (entry->unit)); + g_free (format); + + gtk_label_set_text (GTK_LABEL (label), text); + g_free (text); +} + +static void +gimp_resolution_entry_update_labels (GimpResolutionEntry *entry, + GParamSpec *param_spec, + GtkWidget *label) +{ + if ((label == NULL && entry->phy_width_label != NULL) || + (label != NULL && label == entry->phy_width_label)) + gimp_resolution_entry_format_label (entry, entry->phy_width_label, + entry->width / entry->ppi); + + if ((label == NULL && entry->phy_height_label != NULL) || + (label != NULL && label == entry->phy_height_label)) + gimp_resolution_entry_format_label (entry, entry->phy_height_label, + entry->height / entry->ppi); +} + +static gboolean +gimp_resolution_entry_ppi_to_unit (GBinding *binding, + const GValue *from_value, + GValue *to_value, + GimpResolutionEntry *entry) +{ + gdouble ppi = g_value_get_double (from_value); + + g_value_set_double (to_value, ppi / gimp_unit_get_factor (entry->unit)); + + return TRUE; +} + +static gboolean +gimp_resolution_entry_unit_to_ppi (GBinding *binding, + const GValue *from_value, + GValue *to_value, + GimpResolutionEntry *entry) +{ + gdouble ppu = g_value_get_double (from_value); + + g_value_set_double (to_value, ppu * gimp_unit_get_factor (entry->unit)); + + return TRUE; +} diff --git a/libgimp/gimpresolutionentry-private.h b/libgimp/gimpresolutionentry-private.h new file mode 100644 index 0000000000..737f063cd4 --- /dev/null +++ b/libgimp/gimpresolutionentry-private.h @@ -0,0 +1,80 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpresolutionentry.h + * Copyright (C) 2024 Jehan + * + * 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 . + */ + +#if !defined (__GIMP_UI_H_INSIDE__) && !defined (GIMP_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GIMP_RESOLUTION_ENTRY__ +#define __GIMP_RESOLUTION_ENTRY__ + +G_BEGIN_DECLS + +/* For information look into the C source or the html documentation */ + +/* + * This widget was initially part of libgimpwidgets. Then it got removed and + * moved as private code to file-pdf-load plug-in. + * + * I'm adding it back for GIMP 3 release as its own code but not making it + * public (only to be used by GimpVectorLoadProcedure so far) so that we don't + * have to make sure the API is really right. + * + * TODO: we want to eventually get this back to public API in libgimpwidgets, + * with a much nicer API and also adding a property widget function. + */ +#define GIMP_TYPE_RESOLUTION_ENTRY (gimp_resolution_entry_get_type ()) +G_DECLARE_FINAL_TYPE (GimpResolutionEntry, gimp_resolution_entry, GIMP, RESOLUTION_ENTRY, GtkGrid) + +typedef struct _GimpResolutionEntry GimpResolutionEntry; + +GtkWidget * gimp_prop_resolution_entry_new (GObject *config, + const gchar *width_prop, + const gchar *height_prop, + const gchar *ppi_prop, + const gchar *unit_prop); +GtkWidget * gimp_resolution_entry_new (const gchar *width_label, + gint width, + const gchar *height_label, + gint height, + const gchar *res_label, + gdouble pixel_density, + GimpUnit display_unit); + +void gimp_resolution_entry_set_width (GimpResolutionEntry *entry, + gint width); +void gimp_resolution_entry_set_height (GimpResolutionEntry *entry, + gint height); +void gimp_resolution_entry_set_pixel_density (GimpResolutionEntry *entry, + gdouble ppi); +void gimp_resolution_entry_set_unit (GimpResolutionEntry *entry, + GimpUnit unit); +void gimp_resolution_entry_set_keep_ratio (GimpResolutionEntry *entry, + gboolean keep_ratio); + +gint gimp_resolution_entry_get_width (GimpResolutionEntry *entry); +gint gimp_resolution_entry_get_height (GimpResolutionEntry *entry); +gdouble gimp_resolution_entry_get_density (GimpResolutionEntry *entry); +GimpUnit gimp_resolution_entry_get_unit (GimpResolutionEntry *entry); +gboolean gimp_resolution_entry_get_keep_ratio (GimpResolutionEntry *entry); + +G_END_DECLS + +#endif /* __GIMP_RESOLUTION_ENTRY__ */ diff --git a/libgimp/gimpui.def b/libgimp/gimpui.def index a049891d25..f5e9cce2c6 100644 --- a/libgimp/gimpui.def +++ b/libgimp/gimpui.def @@ -73,6 +73,19 @@ EXPORTS gimp_prop_gradient_chooser_new gimp_prop_palette_chooser_new gimp_prop_pattern_chooser_new + gimp_prop_resolution_entry_new + gimp_resolution_entry_get_density + gimp_resolution_entry_get_height + gimp_resolution_entry_get_keep_ratio + gimp_resolution_entry_get_type + gimp_resolution_entry_get_unit + gimp_resolution_entry_get_width + gimp_resolution_entry_new + gimp_resolution_entry_set_height + gimp_resolution_entry_set_keep_ratio + gimp_resolution_entry_set_pixel_density + gimp_resolution_entry_set_unit + gimp_resolution_entry_set_width gimp_resource_chooser_get_label gimp_resource_chooser_get_resource gimp_resource_chooser_get_type diff --git a/libgimp/meson.build b/libgimp/meson.build index 5bdb6a5e24..979aab5295 100644 --- a/libgimp/meson.build +++ b/libgimp/meson.build @@ -296,6 +296,9 @@ libgimpui_sources_introspectable = [ libgimpui_sources = [ libgimpui_sources_introspectable, gimpuimarshal, + + # TODO: eventually move to libgimpwidgets. + 'gimpresolutionentry-private.c' ] libgimpui_headers_introspectable = [