[libhandy/wip/exalm/paginator-animate: 33/41] carousel-box: Allow children to have different sizes
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libhandy/wip/exalm/paginator-animate: 33/41] carousel-box: Allow children to have different sizes
- Date: Wed, 27 May 2020 15:54:44 +0000 (UTC)
commit 708a6971d25f86852275ee23625b4db45b890821
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Fri Dec 27 20:45:47 2019 +0500
carousel-box: Allow children to have different sizes
This is a prerequisite for animated addition and removal later.
Since sizes can be different, using page index as its snap point, or
scroll position as index, so make sure they are converted as needed.
Signed-off-by: Alexander Mikhaylenko <alexm gnome org>
src/hdy-carousel-box.c | 152 ++++++++++++++++++++++++++++++++++++-------------
src/hdy-carousel.c | 6 +-
2 files changed, 113 insertions(+), 45 deletions(-)
---
diff --git a/src/hdy-carousel-box.c b/src/hdy-carousel-box.c
index 59ca92c8..feae0336 100644
--- a/src/hdy-carousel-box.c
+++ b/src/hdy-carousel-box.c
@@ -34,6 +34,9 @@ struct _HdyCarouselBoxChildInfo
GdkWindow *window;
gint position;
gboolean visible;
+ gdouble size;
+ gdouble snap_point;
+
cairo_surface_t *surface;
cairo_region_t *dirty_region;
};
@@ -135,6 +138,25 @@ find_child_info_by_window (HdyCarouselBox *self,
return NULL;
}
+static HdyCarouselBoxChildInfo *
+get_closest_child_at (HdyCarouselBox *self,
+ gdouble position)
+{
+ GList *l;
+ HdyCarouselBoxChildInfo *closest_child = NULL;
+
+ for (l = self->children; l; l = l->next) {
+ HdyCarouselBoxChildInfo *child = l->data;
+
+ if (!closest_child ||
+ ABS (closest_child->snap_point - position) >
+ ABS (child->snap_point - position))
+ closest_child = child;
+ }
+
+ return closest_child;
+}
+
static void
free_child_info (HdyCarouselBoxChildInfo *info)
{
@@ -434,6 +456,17 @@ update_windows (HdyCarouselBox *self)
GtkAllocation alloc;
gint x, y, offset;
gboolean is_rtl;
+ gdouble snap_point;
+
+ snap_point = 0;
+
+ for (children = self->children; children; children = children->next) {
+ HdyCarouselBoxChildInfo *child_info = children->data;
+
+ child_info->snap_point = snap_point + child_info->size - 1;
+
+ snap_point += child_info->size;
+ }
if (!gtk_widget_get_realized (GTK_WIDGET (self)))
return;
@@ -479,11 +512,11 @@ update_windows (HdyCarouselBox *self)
invalidate_cache_for_child (self, child_info);
if (self->orientation == GTK_ORIENTATION_VERTICAL)
- y += self->distance;
+ y += self->distance * child_info->size;
else if (is_rtl)
- x -= self->distance;
+ x -= self->distance * child_info->size;
else
- x += self->distance;
+ x += self->distance * child_info->size;
}
}
@@ -624,7 +657,6 @@ hdy_carousel_box_remove (GtkContainer *container,
GtkWidget *widget)
{
HdyCarouselBox *self = HDY_CAROUSEL_BOX (container);
- gint index;
gdouble closest_point;
HdyCarouselBoxChildInfo *info;
@@ -635,14 +667,13 @@ hdy_carousel_box_remove (GtkContainer *container,
closest_point = hdy_carousel_box_get_closest_snap_point (self);
gtk_widget_unparent (widget);
- index = g_list_index (self->children, info);
self->children = g_list_remove (self->children, info);
if (gtk_widget_get_realized (GTK_WIDGET (container)))
unregister_window (info, self);
- if (closest_point >= index)
- shift_position (self, -1);
+ if (closest_point >= info->snap_point)
+ shift_position (self, -info->size);
else
gtk_widget_queue_allocate (GTK_WIDGET (self));
@@ -905,22 +936,35 @@ hdy_carousel_box_insert (HdyCarouselBox *self,
gint position)
{
HdyCarouselBoxChildInfo *info;
- gdouble closest_point;
+ gdouble orig_point, closest_point;
+ GList *prev_link;
g_return_if_fail (HDY_IS_CAROUSEL_BOX (self));
g_return_if_fail (GTK_IS_WIDGET (widget));
info = g_new0 (HdyCarouselBoxChildInfo, 1);
info->widget = widget;
+ info->size = 1;
if (gtk_widget_get_realized (GTK_WIDGET (self)))
register_window (info, self);
closest_point = hdy_carousel_box_get_closest_snap_point (self);
- self->children = g_list_insert (self->children, info, position);
- if (closest_point >= position && position >= 0)
- shift_position (self, 1);
+ if (position >= 0)
+ prev_link = g_list_nth (self->children, position);
+ else
+ prev_link = NULL;
+
+ if (prev_link)
+ orig_point = ((HdyCarouselBoxChildInfo *) prev_link->data)->snap_point;
+ else
+ orig_point = -1;
+
+ self->children = g_list_insert_before (self->children, prev_link, info);
+
+ if (closest_point >= orig_point && orig_point >= 0)
+ shift_position (self, info->size);
gtk_widget_set_parent (widget, GTK_WIDGET (self));
@@ -947,10 +991,10 @@ hdy_carousel_box_reorder (HdyCarouselBox *self,
GtkWidget *widget,
gint position)
{
- HdyCarouselBoxChildInfo *info;
- GList *link;
+ HdyCarouselBoxChildInfo *info, *prev_info;
+ GList *link, *prev_link;
gint old_position;
- gdouble closest_point;
+ gdouble closest_point, old_point, new_point;
g_return_if_fail (HDY_IS_CAROUSEL_BOX (self));
g_return_if_fail (GTK_IS_WIDGET (widget));
@@ -960,23 +1004,31 @@ hdy_carousel_box_reorder (HdyCarouselBox *self,
info = find_child_info (self, widget);
link = g_list_find (self->children, info);
old_position = g_list_position (self->children, link);
- self->children = g_list_delete_link (self->children, link);
- if (position < 0 || position >= hdy_carousel_box_get_n_pages (self))
- link = NULL;
- else {
- if (position > old_position)
- position--;
- link = g_list_nth (self->children, position);
- }
- self->children = g_list_insert_before (self->children, link, info);
+ if (position == old_position)
+ return;
- if (closest_point == old_position)
- shift_position (self, position - old_position);
- else if (old_position > closest_point && closest_point >= position)
- shift_position (self, 1);
- else if (position >= closest_point && closest_point > old_position)
- shift_position (self, -1);
+ old_point = ((HdyCarouselBoxChildInfo *) link->data)->snap_point;
+
+ if (position < 0 || position >= hdy_carousel_box_get_n_pages (self))
+ prev_link = g_list_last (self->children);
+ else
+ prev_link = g_list_nth (self->children, position);
+
+ prev_info = prev_link->data;
+ new_point = prev_info->snap_point;
+ if (new_point > old_point)
+ new_point -= prev_info->size;
+
+ self->children = g_list_remove_link (self->children, link);
+ self->children = g_list_insert_before (self->children, prev_link, link->data);
+
+ if (closest_point == old_point)
+ shift_position (self, new_point - old_point);
+ else if (old_point > closest_point && closest_point >= new_point)
+ shift_position (self, info->size);
+ else if (new_point >= closest_point && closest_point > old_point)
+ shift_position (self, -info->size);
}
/**
@@ -1044,12 +1096,14 @@ hdy_carousel_box_scroll_to (HdyCarouselBox *self,
GdkFrameClock *frame_clock;
gint64 frame_time;
gdouble position;
+ HdyCarouselBoxChildInfo *child;
g_return_if_fail (HDY_IS_CAROUSEL_BOX (self));
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (duration >= 0);
- position = find_child_index (self, widget);
+ child = find_child_info (self, widget);
+ position = child->snap_point;
hdy_carousel_box_stop_animation (self);
@@ -1237,14 +1291,20 @@ hdy_carousel_box_get_snap_points (HdyCarouselBox *self,
{
guint i, n_pages;
gdouble *points;
+ GList *l;
g_return_val_if_fail (HDY_IS_CAROUSEL_BOX (self), NULL);
- n_pages = hdy_carousel_box_get_n_pages (self);
+ n_pages = MAX (hdy_carousel_box_get_n_pages (self), 1);
+
+ points = g_new0 (gdouble, n_pages);
- points = g_new (gdouble, n_pages);
- for (i = 0; i < n_pages; i++)
- points[i] = i;
+ i = 0;
+ for (l = self->children; l; l = l->next) {
+ HdyCarouselBoxChildInfo *info = l->data;
+
+ points[i++] = info->snap_point;
+ }
if (n_snap_points)
*n_snap_points = n_pages;
@@ -1267,13 +1327,19 @@ hdy_carousel_box_get_range (HdyCarouselBox *self,
gdouble *lower,
gdouble *upper)
{
+ GList *l;
+ HdyCarouselBoxChildInfo *child;
+
g_return_if_fail (HDY_IS_CAROUSEL_BOX (self));
+ l = g_list_last (self->children);
+ child = l ? l->data : NULL;
+
if (lower)
*lower = 0;
if (upper)
- *upper = hdy_carousel_box_get_n_pages (self) - 1;
+ *upper = child ? child->snap_point : 0;
}
/**
@@ -1289,10 +1355,14 @@ hdy_carousel_box_get_range (HdyCarouselBox *self,
gdouble
hdy_carousel_box_get_closest_snap_point (HdyCarouselBox *self)
{
- g_return_val_if_fail (HDY_IS_CAROUSEL_BOX (self), 0);
+ HdyCarouselBoxChildInfo *closest_child;
+
+ closest_child = get_closest_child_at (self, self->position);
+
+ if (!closest_child)
+ return 0;
- return CLAMP (round (self->position), 0,
- hdy_carousel_box_get_n_pages (self) - 1);
+ return closest_child->snap_point;
}
/**
@@ -1313,7 +1383,7 @@ hdy_carousel_box_get_page_at_position (HdyCarouselBox *self,
gdouble position)
{
gdouble lower, upper;
- gint n;
+ HdyCarouselBoxChildInfo *child;
g_return_val_if_fail (HDY_IS_CAROUSEL_BOX (self), NULL);
@@ -1321,9 +1391,9 @@ hdy_carousel_box_get_page_at_position (HdyCarouselBox *self,
position = CLAMP (position, lower, upper);
- n = round (position);
+ child = get_closest_child_at (self, position);
- return hdy_carousel_box_get_nth_child (self, n);
+ return child->widget;
}
/**
diff --git a/src/hdy-carousel.c b/src/hdy-carousel.c
index 038a798e..1eff3407 100644
--- a/src/hdy-carousel.c
+++ b/src/hdy-carousel.c
@@ -228,11 +228,9 @@ static void
animation_stopped_cb (HdyCarousel *self,
HdyCarouselBox *box)
{
- gdouble position;
gint index;
- position = hdy_carousel_box_get_position (self->scrolling_box);
- index = round (position);
+ index = hdy_carousel_box_get_current_page_index (self->scrolling_box);
g_signal_emit (self, signals[SIGNAL_PAGE_CHANGED], 0, index);
}
@@ -562,7 +560,7 @@ handle_discrete_scroll_event (HdyCarousel *self,
if (index == 0)
return GDK_EVENT_PROPAGATE;
- index += (gint) round (hdy_carousel_get_position (self));
+ index += hdy_carousel_box_get_current_page_index (self->scrolling_box);
index = CLAMP (index, 0, (gint) hdy_carousel_get_n_pages (self) - 1);
hdy_carousel_scroll_to (self, hdy_carousel_box_get_nth_child (self->scrolling_box, index));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]