[libhandy/wip/exalm/paginator-animate: 31/41] carousel-box: Shift position after page changes
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libhandy/wip/exalm/paginator-animate: 31/41] carousel-box: Shift position after page changes
- Date: Wed, 27 May 2020 15:54:34 +0000 (UTC)
commit 2a0a1a3580283ce2523fa0503212c10d5a291164
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Thu Dec 26 15:06:20 2019 +0500
carousel-box: Shift position after page changes
Ensure the scrolling position doesn't jump after adding, removing or
reordering children, even during an ongoing gesture.
Use the closest snap point instead of just position when determining
whether to do the shift.
Add 'position-shifted' signal, connect to it from HdyCarousel and update
the HdySwipeTracker position accordingly.
Signed-off-by: Alexander Mikhaylenko <alexm gnome org>
src/hdy-carousel-box.c | 67 ++++++++++++++++++++++++++++++++++++++++----------
src/hdy-carousel.c | 9 +++++++
src/hdy-carousel.ui | 1 +
3 files changed, 64 insertions(+), 13 deletions(-)
---
diff --git a/src/hdy-carousel-box.c b/src/hdy-carousel-box.c
index d8d32c15..ecf8eb97 100644
--- a/src/hdy-carousel-box.c
+++ b/src/hdy-carousel-box.c
@@ -78,6 +78,7 @@ static GParamSpec *props[LAST_PROP];
enum {
SIGNAL_ANIMATION_STOPPED,
+ SIGNAL_POSITION_SHIFTED,
SIGNAL_LAST_SIGNAL,
};
static guint signals[SIGNAL_LAST_SIGNAL];
@@ -610,18 +611,29 @@ hdy_carousel_box_add (GtkContainer *container,
hdy_carousel_box_insert (self, widget, -1);
}
+static void
+shift_position (HdyCarouselBox *self,
+ gdouble delta)
+{
+ hdy_carousel_box_set_position (self, self->position + delta);
+ g_signal_emit (self, signals[SIGNAL_POSITION_SHIFTED], 0, delta);
+}
+
static void
hdy_carousel_box_remove (GtkContainer *container,
GtkWidget *widget)
{
HdyCarouselBox *self = HDY_CAROUSEL_BOX (container);
gint index;
+ gdouble closest_point;
HdyCarouselBoxChildInfo *info;
info = find_child_info (self, widget);
if (!info)
return;
+ 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);
@@ -629,13 +641,13 @@ hdy_carousel_box_remove (GtkContainer *container,
if (gtk_widget_get_realized (GTK_WIDGET (container)))
unregister_window (info, self);
- free_child_info (info);
-
- if (self->position >= index)
- hdy_carousel_box_set_position (self, self->position - 1);
+ if (closest_point >= index)
+ shift_position (self, -1);
else
gtk_widget_queue_allocate (GTK_WIDGET (self));
+ free_child_info (info);
+
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_N_PAGES]);
}
@@ -828,6 +840,25 @@ hdy_carousel_box_class_init (HdyCarouselBoxClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE,
0);
+
+ /**
+ * HdyCarouselBox::position-shifted:
+ * @self: The #HdyCarouselBox instance
+ * @delta: The amount to shift the position by
+ *
+ * This signal is emitted when position has been programmatically shifted.
+ *
+ * Since: 1.0
+ */
+ signals[SIGNAL_POSITION_SHIFTED] =
+ g_signal_new ("position-shifted",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_DOUBLE);
}
static void
@@ -874,6 +905,7 @@ hdy_carousel_box_insert (HdyCarouselBox *self,
gint position)
{
HdyCarouselBoxChildInfo *info;
+ gdouble closest_point;
g_return_if_fail (HDY_IS_CAROUSEL_BOX (self));
g_return_if_fail (GTK_IS_WIDGET (widget));
@@ -884,7 +916,11 @@ hdy_carousel_box_insert (HdyCarouselBox *self,
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);
gtk_widget_set_parent (widget, GTK_WIDGET (self));
@@ -913,29 +949,34 @@ hdy_carousel_box_reorder (HdyCarouselBox *self,
{
HdyCarouselBoxChildInfo *info;
GList *link;
- gint old_position, current_page;
+ gint old_position;
+ gdouble closest_point;
g_return_if_fail (HDY_IS_CAROUSEL_BOX (self));
g_return_if_fail (GTK_IS_WIDGET (widget));
+ closest_point = hdy_carousel_box_get_closest_snap_point (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
+ else {
+ if (position > old_position)
+ position--;
link = g_list_nth (self->children, position);
+ }
self->children = g_list_insert_before (self->children, link, info);
- current_page = round (self->position);
- if (current_page == old_position)
- hdy_carousel_box_set_position (self, position);
- else if (old_position > current_page && position <= current_page)
- hdy_carousel_box_set_position (self, self->position + 1);
- else if (old_position <= current_page && position > current_page)
- hdy_carousel_box_set_position (self, self->position - 1);
+ 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);
}
/**
diff --git a/src/hdy-carousel.c b/src/hdy-carousel.c
index c3ef4913..f5903236 100644
--- a/src/hdy-carousel.c
+++ b/src/hdy-carousel.c
@@ -240,6 +240,14 @@ animation_stopped_cb (HdyCarousel *self,
g_signal_emit (self, signals[SIGNAL_PAGE_CHANGED], 0, index);
}
+static void
+position_shifted_cb (HdyCarousel *self,
+ gdouble delta,
+ HdyCarouselBox *box)
+{
+ hdy_swipe_tracker_shift_position (self->tracker, delta);
+}
+
static GdkRGBA
get_color (GtkWidget *widget)
{
@@ -991,6 +999,7 @@ hdy_carousel_class_init (HdyCarouselClass *klass)
gtk_widget_class_bind_template_callback (widget_class, notify_position_cb);
gtk_widget_class_bind_template_callback (widget_class, notify_spacing_cb);
gtk_widget_class_bind_template_callback (widget_class, animation_stopped_cb);
+ gtk_widget_class_bind_template_callback (widget_class, position_shifted_cb);
gtk_widget_class_set_css_name (widget_class, "carousel");
}
diff --git a/src/hdy-carousel.ui b/src/hdy-carousel.ui
index dd7f7d45..87861ce7 100644
--- a/src/hdy-carousel.ui
+++ b/src/hdy-carousel.ui
@@ -21,6 +21,7 @@
<signal name="notify::position" handler="notify_position_cb" swapped="true"/>
<signal name="notify::spacing" handler="notify_spacing_cb" swapped="true"/>
<signal name="animation-stopped" handler="animation_stopped_cb" swapped="true"/>
+ <signal name="position-shifted" handler="position_shifted_cb" swapped="true"/>
</object>
</child>
<child>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]