/* 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);
}