[libhandy/wip/exalm/paginator-animate: 68/78] carousel-box: Shift position after page changes
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libhandy/wip/exalm/paginator-animate: 68/78] carousel-box: Shift position after page changes
- Date: Fri, 22 May 2020 13:34:28 +0000 (UTC)
commit 944b72995555d27a33d4b471b89714a2ba2d0dd6
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 48d05910..640dc42c 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)
{
@@ -993,6 +1001,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]