From 105be5a457bb29a4e3316aa502e9764830e1e687 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 7 Mar 2023 05:29:31 +0100 Subject: [PATCH] gtk: Add GtkScrollInfo This struct carries information about scrolling a scrollable, so that individual scrollables can share this struct for their scrolling APIs. For now, there's not much information here, we're still trying to cook up an API that works well. --- gtk/gtk.h | 1 + gtk/gtkscrollinfo.c | 249 +++++++++++++++++++++++++++++++++++++ gtk/gtkscrollinfo.h | 61 +++++++++ gtk/gtkscrollinfoprivate.h | 42 +++++++ gtk/gtktypes.h | 1 + gtk/meson.build | 2 + 6 files changed, 356 insertions(+) create mode 100644 gtk/gtkscrollinfo.c create mode 100644 gtk/gtkscrollinfo.h create mode 100644 gtk/gtkscrollinfoprivate.h diff --git a/gtk/gtk.h b/gtk/gtk.h index c5f9b4b583..6a849ecf6c 100644 --- a/gtk/gtk.h +++ b/gtk/gtk.h @@ -223,6 +223,7 @@ #include #include #include +#include #include #include #include diff --git a/gtk/gtkscrollinfo.c b/gtk/gtkscrollinfo.c new file mode 100644 index 0000000000..513eccacc9 --- /dev/null +++ b/gtk/gtkscrollinfo.c @@ -0,0 +1,249 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2023 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 . + */ + +/** + * GtkScrollInfo: + * + * The `GtkScrollInfo` can be used to provide more accurate data on how a scroll + * operation should be performed. + * + * Scrolling functions usually allow passing a %NULL scroll info which will cause + * the default values to be used and just scroll the element into view. + * + * Since: 4.12 + */ + +#include "config.h" + +#include "gtkscrollinfoprivate.h" + +#include + +struct _GtkScrollInfo +{ + guint ref_count; + + gboolean enabled[2]; /* directions */ +}; + +static GtkScrollInfo default_scroll_info = { + 1, + { TRUE, TRUE } +}; + +G_DEFINE_BOXED_TYPE (GtkScrollInfo, gtk_scroll_info, + gtk_scroll_info_ref, + gtk_scroll_info_unref) + + +/** + * gtk_scroll_info_new: + * + * Creates a new scroll info for scrolling an element into view. + * + * Returns: A new scroll info + * + * Since: 4.12 + **/ +GtkScrollInfo * +gtk_scroll_info_new (void) +{ + GtkScrollInfo *self; + + self = g_new0 (GtkScrollInfo, 1); + self->ref_count = 1; + self->enabled[GTK_ORIENTATION_HORIZONTAL] = TRUE; + self->enabled[GTK_ORIENTATION_VERTICAL] = TRUE; + + return self; +} + +/** + * gtk_scroll_info_ref: + * @self: a `GtkScrollInfo` + * + * Increases the reference count of a `GtkScrollInfo` by one. + * + * Returns: the passed in `GtkScrollInfo`. + * + * Since: 4.12 + */ +GtkScrollInfo * +gtk_scroll_info_ref (GtkScrollInfo *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + self->ref_count++; + + return self; +} + +/** + * gtk_scroll_info_unref: + * @self: a `GtkScrollInfo` + * + * Decreases the reference count of a `GtkScrollInfo` by one. + * + * If the resulting reference count is zero, frees the self. + * + * Since: 4.12 + */ +void +gtk_scroll_info_unref (GtkScrollInfo *self) +{ + g_return_if_fail (self != NULL); + g_return_if_fail (self->ref_count > 0); + + self->ref_count--; + if (self->ref_count > 0) + return; + + g_free (self); +} + +/** + * gtk_scroll_info_set_enable_horizontal: + * @self: a `GtkScrollInfo` + * @horizontal: if scrolling in the horizontal direction + * should happen + * + * Turns horizontal scrolling on or off. + * + * Since: 4.12 + **/ +void +gtk_scroll_info_set_enable_horizontal (GtkScrollInfo *self, + gboolean horizontal) +{ + g_return_if_fail (self != NULL); + + self->enabled[GTK_ORIENTATION_HORIZONTAL] = horizontal; +} + +/** + * gtk_scroll_info_get_enable_horizontal: + * @self: a `GtkScrollInfo` + * + * Checks if horizontal scrolling is enabled. + * + * Returns: %TRUE if horizontal scrolling is enabled. + * + * Since: 4.12 + **/ +gboolean +gtk_scroll_info_get_enable_horizontal (GtkScrollInfo *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + + return self->enabled[GTK_ORIENTATION_HORIZONTAL]; +} + +/** + * gtk_scroll_info_set_enable_vertical: + * @self: a `GtkScrollInfo` + * @vertical: if scrolling in the vertical direction + * should happen + * + * Turns vertical scrolling on or off. + * + * Since: 4.12 + **/ +void +gtk_scroll_info_set_enable_vertical (GtkScrollInfo *self, + gboolean vertical) +{ + g_return_if_fail (self != NULL); + + self->enabled[GTK_ORIENTATION_VERTICAL] = vertical; +} + +/** + * gtk_scroll_info_get_enable_vertical: + * @self: a `GtkScrollInfo` + * + * Checks if vertical scrolling is enabled. + * + * Returns: %TRUE if vertical scrolling is enabled. + * + * Since: 4.12 + **/ +gboolean +gtk_scroll_info_get_enable_vertical (GtkScrollInfo *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + + return self->enabled[GTK_ORIENTATION_VERTICAL]; +} + +int +gtk_scroll_info_compute_for_orientation (GtkScrollInfo *self, + GtkOrientation orientation, + int area_origin, + int area_size, + int viewport_origin, + int viewport_size) +{ + float origin, size; + int delta; + + if (self == NULL) + self = &default_scroll_info; + + if (!self->enabled[orientation]) + return viewport_origin; + + origin = viewport_origin; + size = viewport_size; + + if (area_origin <= origin) + delta = area_origin - ceil (origin); + else if (area_origin + area_size > origin + size) + delta = area_origin + area_size - floor (origin + size); + else + delta = 0; + + return viewport_origin + delta; +} + +/* + * gtk_scroll_info_compute_scroll: + * @self: a `GtkScrollInfo` + * @area: area to scroll + * @viewport: viewport area to scroll into + * @out_x: (out): x coordinate to scroll viewport to + * @out_y: (out): y coordinate to scroll viewport to + * + * Computes The new x/y coordinate to move the viewport to + * according to this scroll info. + **/ +void +gtk_scroll_info_compute_scroll (GtkScrollInfo *self, + const cairo_rectangle_int_t *area, + const cairo_rectangle_int_t *viewport, + int *out_x, + int *out_y) +{ + *out_x = gtk_scroll_info_compute_for_orientation (self, + GTK_ORIENTATION_HORIZONTAL, + area->x, area->width, + viewport->x, viewport->width); + *out_y = gtk_scroll_info_compute_for_orientation (self, + GTK_ORIENTATION_VERTICAL, + area->y, area->height, + viewport->y, viewport->height); +} + diff --git a/gtk/gtkscrollinfo.h b/gtk/gtkscrollinfo.h new file mode 100644 index 0000000000..56cbf63d21 --- /dev/null +++ b/gtk/gtkscrollinfo.h @@ -0,0 +1,61 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2023 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 . + */ + +#pragma once + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + + +#include +#include +#include + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_SCROLL_INFO (gtk_scroll_info_get_type ()) + +GDK_AVAILABLE_IN_4_12 +GType gtk_scroll_info_get_type (void) G_GNUC_CONST; +GDK_AVAILABLE_IN_4_12 +GtkScrollInfo * gtk_scroll_info_new (void); + +GDK_AVAILABLE_IN_4_12 +GtkScrollInfo * gtk_scroll_info_ref (GtkScrollInfo *self); +GDK_AVAILABLE_IN_4_12 +void gtk_scroll_info_unref (GtkScrollInfo *self); + +GDK_AVAILABLE_IN_4_12 +void gtk_scroll_info_set_enable_horizontal (GtkScrollInfo *self, + gboolean horizontal); +GDK_AVAILABLE_IN_4_12 +gboolean gtk_scroll_info_get_enable_horizontal (GtkScrollInfo *self); + +GDK_AVAILABLE_IN_4_12 +void gtk_scroll_info_set_enable_vertical (GtkScrollInfo *self, + gboolean vertical); +GDK_AVAILABLE_IN_4_12 +gboolean gtk_scroll_info_get_enable_vertical (GtkScrollInfo *self); + + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkScrollInfo, gtk_scroll_info_unref) + +G_END_DECLS + diff --git a/gtk/gtkscrollinfoprivate.h b/gtk/gtkscrollinfoprivate.h new file mode 100644 index 0000000000..f1ac1a6b59 --- /dev/null +++ b/gtk/gtkscrollinfoprivate.h @@ -0,0 +1,42 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2023 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * 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 . + */ + +#pragma once + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + + +#include + +G_BEGIN_DECLS + +void gtk_scroll_info_compute_scroll (GtkScrollInfo *self, + const cairo_rectangle_int_t *area, + const cairo_rectangle_int_t *viewport, + int *out_x, + int *out_y); +int gtk_scroll_info_compute_for_orientation (GtkScrollInfo *self, + GtkOrientation orientation, + int area_origin, + int area_size, + int viewport_origin, + int viewport_size); + +G_END_DECLS + diff --git a/gtk/gtktypes.h b/gtk/gtktypes.h index 6efa78f837..e30194a1e5 100644 --- a/gtk/gtktypes.h +++ b/gtk/gtktypes.h @@ -46,6 +46,7 @@ typedef struct _GtkListItemFactory GtkListItemFactory; typedef struct _GtkNative GtkNative; typedef struct _GtkRequisition GtkRequisition; typedef struct _GtkRoot GtkRoot; +typedef struct _GtkScrollInfo GtkScrollInfo; typedef struct _GtkSettings GtkSettings; typedef struct _GtkShortcut GtkShortcut; typedef struct _GtkShortcutAction GtkShortcutAction; diff --git a/gtk/meson.build b/gtk/meson.build index 19bc221277..765925dc26 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -327,6 +327,7 @@ gtk_public_sources = files([ 'gtkscalebutton.c', 'gtkscrollable.c', 'gtkscrollbar.c', + 'gtkscrollinfo.c', 'gtkscrolledwindow.c', 'gtksearchbar.c', 'gtksearchentry.c', @@ -557,6 +558,7 @@ gtk_public_headers = files([ 'gtkscalebutton.h', 'gtkscrollable.h', 'gtkscrollbar.h', + 'gtkscrollinfo.h', 'gtkscrolledwindow.h', 'gtksearchbar.h', 'gtksearchentry.h', -- 2.30.2