mirror of https://github.com/GNOME/gimp.git
712 lines
26 KiB
C
712 lines
26 KiB
C
/* 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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gegl.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
#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;
|
|
gdouble ratio;
|
|
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,
|
|
GIMP_MIN_IMAGE_SIZE, GIMP_MAX_IMAGE_SIZE, GIMP_MIN_IMAGE_SIZE,
|
|
GIMP_PARAM_READWRITE |
|
|
G_PARAM_EXPLICIT_NOTIFY |
|
|
G_PARAM_CONSTRUCT);
|
|
props[PROP_HEIGHT] = g_param_spec_int ("height",
|
|
"Height in pixel",
|
|
NULL,
|
|
GIMP_MIN_IMAGE_SIZE, GIMP_MAX_IMAGE_SIZE, GIMP_MIN_IMAGE_SIZE,
|
|
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;
|
|
|
|
g_return_if_fail (entry->height != 0);
|
|
|
|
/* Initial ratio is from the initial values. */
|
|
entry->ratio = (gdouble) entry->width / (gdouble) entry->height;
|
|
|
|
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_object (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_object (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)
|
|
{
|
|
g_object_freeze_notify (G_OBJECT (entry));
|
|
|
|
if (entry->keep_ratio && entry->width != 0)
|
|
{
|
|
gint height;
|
|
|
|
height = (gint) ((gdouble) width / entry->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]);
|
|
|
|
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)
|
|
{
|
|
g_object_freeze_notify (G_OBJECT (entry));
|
|
|
|
if (entry->keep_ratio && entry->height != 0)
|
|
{
|
|
gint width;
|
|
|
|
width = (gint) ((gdouble) height * entry->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]);
|
|
|
|
g_object_thaw_notify (G_OBJECT (entry));
|
|
}
|
|
}
|
|
|
|
void
|
|
gimp_resolution_entry_set_pixel_density (GimpResolutionEntry *entry,
|
|
gdouble ppi)
|
|
{
|
|
if (entry->ppi != ppi)
|
|
{
|
|
entry->ppi = ppi;
|
|
g_object_notify_by_pspec (G_OBJECT (entry), props[PROP_PIXEL_DENSITY]);
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
if (entry->keep_ratio)
|
|
entry->ratio = (gdouble) entry->width / (gdouble) entry->height;
|
|
|
|
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_name (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;
|
|
}
|