diff options
author | Marco Melorio <marco.melorio@protonmail.com> | 2022-07-15 18:18:26 +0200 |
---|---|---|
committer | Marco Melorio <marco.melorio@protonmail.com> | 2022-07-15 23:01:23 +0200 |
commit | d8a73cbd03118e94bd75f5fa183a646fecb053ce (patch) | |
tree | 3a5766db3af7a9b714c2cb7a62d76af8cfe15213 /gtk/gtkpicture.c | |
parent | 7743f359720686b1183172a073fa210ba23faf15 (diff) | |
download | gtk+-d8a73cbd03118e94bd75f5fa183a646fecb053ce.tar.gz |
picture: Add content-fit property
It allows to specify the resize mode of the paintable inside the
GtkPicture allocation. This also deprecates the keep-aspect-ratio
property.
Fixes #5027.
Diffstat (limited to 'gtk/gtkpicture.c')
-rw-r--r-- | gtk/gtkpicture.c | 152 |
1 files changed, 131 insertions, 21 deletions
diff --git a/gtk/gtkpicture.c b/gtk/gtkpicture.c index 0712d1844f..eaabda7c74 100644 --- a/gtk/gtkpicture.c +++ b/gtk/gtkpicture.c @@ -27,6 +27,7 @@ #include "gtkintl.h" #include "gtkprivate.h" #include "gtksnapshot.h" +#include "gtktypebuiltins.h" #include "gtkwidgetprivate.h" #include "gdkpixbufutilsprivate.h" @@ -89,6 +90,7 @@ enum PROP_ALTERNATIVE_TEXT, PROP_KEEP_ASPECT_RATIO, PROP_CAN_SHRINK, + PROP_CONTENT_FIT, NUM_PROPERTIES }; @@ -100,8 +102,8 @@ struct _GtkPicture GFile *file; char *alternative_text; - guint keep_aspect_ratio : 1; guint can_shrink : 1; + GtkContentFit content_fit; }; struct _GtkPictureClass @@ -129,23 +131,47 @@ gtk_picture_snapshot (GtkWidget *widget, height = gtk_widget_get_height (widget); ratio = gdk_paintable_get_intrinsic_aspect_ratio (self->paintable); - if (!self->keep_aspect_ratio || ratio == 0) + if (self->content_fit == GTK_CONTENT_FIT_FILL || ratio == 0) { gdk_paintable_snapshot (self->paintable, snapshot, width, height); } else { double picture_ratio = (double) width / height; + int paintable_width = gdk_paintable_get_intrinsic_width (self->paintable); + int paintable_height = gdk_paintable_get_intrinsic_height (self->paintable); - if (ratio > picture_ratio) + if (self->content_fit == GTK_CONTENT_FIT_SCALE_DOWN && + width >= paintable_width && height >= paintable_height) { - w = width; - h = width / ratio; + w = paintable_width; + h = paintable_height; + } + else if (ratio > picture_ratio) + { + if (self->content_fit == GTK_CONTENT_FIT_COVER) + { + w = height * ratio; + h = height; + } + else + { + w = width; + h = width / ratio; + } } else { - w = height * ratio; - h = height; + if (self->content_fit == GTK_CONTENT_FIT_COVER) + { + w = width; + h = width / ratio; + } + else + { + w = height * ratio; + h = height; + } } x = (width - ceil (w)) / 2; @@ -246,13 +272,19 @@ gtk_picture_set_property (GObject *object, break; case PROP_KEEP_ASPECT_RATIO: + G_GNUC_BEGIN_IGNORE_DEPRECATIONS gtk_picture_set_keep_aspect_ratio (self, g_value_get_boolean (value)); + G_GNUC_END_IGNORE_DEPRECATIONS break; case PROP_CAN_SHRINK: gtk_picture_set_can_shrink (self, g_value_get_boolean (value)); break; + case PROP_CONTENT_FIT: + gtk_picture_set_content_fit (self, g_value_get_enum (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -282,13 +314,19 @@ gtk_picture_get_property (GObject *object, break; case PROP_KEEP_ASPECT_RATIO: - g_value_set_boolean (value, self->keep_aspect_ratio); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + g_value_set_boolean (value, gtk_picture_get_keep_aspect_ratio (self)); + G_GNUC_END_IGNORE_DEPRECATIONS break; case PROP_CAN_SHRINK: g_value_set_boolean (value, self->can_shrink); break; + case PROP_CONTENT_FIT: + g_value_set_enum (value, self->content_fit); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -394,11 +432,15 @@ gtk_picture_class_init (GtkPictureClass *class) * * Whether the GtkPicture will render its contents trying to preserve the aspect * ratio. + * + * Deprecated: 4.8: Use [property@Gtk.Picture:content-fit] instead. */ properties[PROP_KEEP_ASPECT_RATIO] = g_param_spec_boolean ("keep-aspect-ratio", NULL, NULL, TRUE, - GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); + GTK_PARAM_READWRITE | + G_PARAM_EXPLICIT_NOTIFY | + G_PARAM_DEPRECATED); /** * GtkPicture:can-shrink: (attributes org.gtk.Property.get=gtk_picture_get_can_shrink org.gtk.Property.set=gtk_picture_set_can_shrink) @@ -410,6 +452,17 @@ gtk_picture_class_init (GtkPictureClass *class) TRUE, GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); + /** + * GtkPicture:content-fit: (attributes org.gtk.Property.get=gtk_picture_get_content_fit org.gtk.Property.set=gtk_picture_set_content_fit) + * + * How the content should be resized to fit inside the `GtkPicture`. + */ + properties[PROP_CONTENT_FIT] = + g_param_spec_enum ("content-fit", NULL, NULL, + GTK_TYPE_CONTENT_FIT, + GTK_CONTENT_FIT_CONTAIN, + GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); + g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties); gtk_widget_class_set_css_name (widget_class, I_("picture")); @@ -420,7 +473,7 @@ static void gtk_picture_init (GtkPicture *self) { self->can_shrink = TRUE; - self->keep_aspect_ratio = TRUE; + self->content_fit = GTK_CONTENT_FIT_CONTAIN; } /** @@ -827,21 +880,20 @@ gtk_picture_get_paintable (GtkPicture *self) * * If set to %FALSE or if the contents provide no aspect ratio, * the contents will be stretched over the picture's whole area. + * + * Deprecated: 4.8: Use [method@Gtk.Picture.set_content_fit] instead. If still + * used, this method will always set the [property@Gtk.Picture:content-fit] + * property to `GTK_CONTENT_FIT_CONTAIN` if @keep_aspect_ratio is true, + * otherwise it will set it to `GTK_CONTENT_FIT_FILL`. */ void gtk_picture_set_keep_aspect_ratio (GtkPicture *self, gboolean keep_aspect_ratio) { - g_return_if_fail (GTK_IS_PICTURE (self)); - - if (self->keep_aspect_ratio == keep_aspect_ratio) - return; - - self->keep_aspect_ratio = keep_aspect_ratio; - - gtk_widget_queue_draw (GTK_WIDGET (self)); - - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_KEEP_ASPECT_RATIO]); + if (keep_aspect_ratio) + gtk_picture_set_content_fit (self, GTK_CONTENT_FIT_CONTAIN); + else + gtk_picture_set_content_fit (self, GTK_CONTENT_FIT_FILL); } /** @@ -851,13 +903,17 @@ gtk_picture_set_keep_aspect_ratio (GtkPicture *self, * Returns whether the `GtkPicture` preserves its contents aspect ratio. * * Returns: %TRUE if the self tries to keep the contents' aspect ratio + * + * Deprecated: 4.8: Use [method@Gtk.Picture.get_content_fit] instead. This will + * now return `FALSE` only if [property@Gtk.Picture:content-fit] is + * `GTK_CONTENT_FIT_FILL`. Returns `TRUE` otherwise. */ gboolean gtk_picture_get_keep_aspect_ratio (GtkPicture *self) { g_return_val_if_fail (GTK_IS_PICTURE (self), TRUE); - return self->keep_aspect_ratio; + return self->content_fit != GTK_CONTENT_FIT_FILL; } /** @@ -909,6 +965,60 @@ gtk_picture_get_can_shrink (GtkPicture *self) } /** + * gtk_picture_set_content_fit: (attributes org.gtk.Method.set_property=content-fit) + * @self: a `GtkPicture` + * @content_fit: the content fit mode + * + * Sets how the content should be resized to fit the `GtkPicture`. + * + * See [enum@Gtk.ContentFit] for details. + * + * If you use `GTK_CONTENT_FIT_COVER`, you may also want to set the + * [property@Gtk.Widget:overflow] to `GTK_OVERFLOW_HIDDEN`, otherwise the + * paintable will overflow the widget allocation if the aspect ratio of the + * paintable is different from the one of the `GtkPicture` allocation. + */ +void +gtk_picture_set_content_fit (GtkPicture *self, + GtkContentFit content_fit) +{ + g_return_if_fail (GTK_IS_PICTURE (self)); + + if (self->content_fit == content_fit) + return; + + gboolean notify_keep_aspect_ratio = (content_fit == GTK_CONTENT_FIT_FILL || + self->content_fit == GTK_CONTENT_FIT_FILL); + + self->content_fit = content_fit; + + gtk_widget_queue_draw (GTK_WIDGET (self)); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CONTENT_FIT]); + + if (notify_keep_aspect_ratio) + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_KEEP_ASPECT_RATIO]); +} + +/** + * gtk_picture_get_content_fit: (attributes org.gtk.Method.get_property=content-fit) + * @self: a `GtkPicture` + * + * Returns the fit mode for the content of the `GtkPicture`. + * + * See [enum@Gtk.ContentFit] for details. + * + * Returns: the content fit mode + */ +GtkContentFit +gtk_picture_get_content_fit (GtkPicture *self) +{ + g_return_val_if_fail (GTK_IS_PICTURE (self), FALSE); + + return self->content_fit; +} + +/** * gtk_picture_set_alternative_text: (attributes org.gtk.Method.set_property=alternative-text) * @self: a `GtkPicture` * @alternative_text: (nullable): a textual description of the contents |