[libadwaita/wip/exalm/browsing-view] a
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libadwaita/wip/exalm/browsing-view] a
- Date: Wed, 12 Oct 2022 03:19:01 +0000 (UTC)
commit e69ecb410983e2dd32142c3689f2954e3d0bf609
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Wed Oct 12 07:18:28 2022 +0400
a
src/adw-browsing-view.c | 221 ++++++++++++++++++++++++++++++++++++++----------
src/adw-browsing-view.h | 7 ++
2 files changed, 181 insertions(+), 47 deletions(-)
---
diff --git a/src/adw-browsing-view.c b/src/adw-browsing-view.c
index 7f354192..8c363e7e 100644
--- a/src/adw-browsing-view.c
+++ b/src/adw-browsing-view.c
@@ -76,8 +76,14 @@ struct _AdwBrowsingView
AdwAnimation *transition;
AdwBrowsingViewChild *hiding_child;
gboolean transition_pop;
+ gboolean transition_phony;
AdwShadowHelper *shadow_helper;
+
+ AdwBrowsingViewChild *last_child;
+
+ AdwBrowsingView *previous_view;
+ AdwBrowsingView *next_view;
};
static void adw_browsing_view_buildable_init (GtkBuildableIface *iface);
@@ -333,6 +339,7 @@ switch_child (AdwBrowsingView *self,
GtkRoot *root;
g_assert (child != prev_child);
+ g_assert (child || prev_child);
if (gtk_widget_in_destruction (GTK_WIDGET (self)))
return;
@@ -373,21 +380,23 @@ switch_child (AdwBrowsingView *self,
}
}
+ adw_animation_reset (self->transition);
+
self->hiding_child = prev_child;
self->transition_pop = pop;
+ self->transition_phony = FALSE;
+
+ if (!child)
+ self->last_child = prev_child;
if (self->hiding_child)
g_signal_emit (self->hiding_child, child_signals[CHILD_SIGNAL_HIDING], 0);
- adw_animation_reset (self->transition);
-
- if (animate && child && prev_child)
+ if (animate)
adw_animation_play (self->transition);
else
adw_animation_skip (self->transition);
- gtk_widget_queue_resize (GTK_WIDGET (self));
-
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_VISIBLE_CHILD]);
}
@@ -411,6 +420,21 @@ push_to_stack (AdwBrowsingView *self,
switch_child (self, previous_child, child, FALSE, animate);
+ if (!previous_child && self->previous_view) {
+ AdwBrowsingViewChild *prev_visible_child = adw_browsing_view_get_visible_child (self->previous_view);
+
+ adw_animation_reset (self->previous_view->transition);
+
+ self->previous_view->hiding_child = prev_visible_child;
+ self->previous_view->transition_pop = FALSE;
+ self->previous_view->transition_phony = TRUE;
+
+ if (animate)
+ adw_animation_play (self->previous_view->transition);
+ else
+ adw_animation_skip (self->previous_view->transition);
+ }
+
g_signal_emit (self, signals[SIGNAL_PUSHED], 0);
}
@@ -418,20 +442,35 @@ static void
pop_from_stack (AdwBrowsingView *self,
gboolean animate)
{
- AdwBrowsingViewChild *previous_child;
- AdwBrowsingViewChild *new_child = NULL;
+ AdwBrowsingViewChild *visible_child;
+ AdwBrowsingViewChild *new_child;
g_assert (self->navigation_stack);
- previous_child = adw_browsing_view_get_visible_child (self);
+ visible_child = adw_browsing_view_get_visible_child (self);
- self->navigation_stack = g_slist_remove (self->navigation_stack, previous_child);
+ self->navigation_stack = g_slist_remove (self->navigation_stack, visible_child);
new_child = adw_browsing_view_get_visible_child (self);
- switch_child (self, previous_child, new_child, TRUE, animate);
+ switch_child (self, visible_child, new_child, TRUE, animate);
+
+ if (!new_child && self->previous_view) {
+ AdwBrowsingViewChild *prev_visible_child = adw_browsing_view_get_visible_child (self->previous_view);
+
+ adw_animation_reset (self->previous_view->transition);
+
+ self->previous_view->hiding_child = prev_visible_child;
+ self->previous_view->transition_pop = TRUE;
+ self->previous_view->transition_phony = TRUE;
- g_signal_emit (self, signals[SIGNAL_POPPED], 0, previous_child);
+ if (animate)
+ adw_animation_play (self->previous_view->transition);
+ else
+ adw_animation_skip (self->previous_view->transition);
+ }
+
+ g_signal_emit (self, signals[SIGNAL_POPPED], 0, visible_child);
}
static void
@@ -444,18 +483,20 @@ transition_cb (double value,
static void
transition_done_cb (AdwBrowsingView *self)
{
- AdwBrowsingViewChild *visible_child = NULL;
-
if (self->hiding_child) {
- g_signal_emit (self->hiding_child, child_signals[CHILD_SIGNAL_HIDDEN], 0);
- gtk_widget_set_child_visible (GTK_WIDGET (self->hiding_child), FALSE);
+ if (!self->transition_phony) {
+ g_signal_emit (self->hiding_child, child_signals[CHILD_SIGNAL_HIDDEN], 0);
+ gtk_widget_set_child_visible (GTK_WIDGET (self->hiding_child), FALSE);
+ }
self->hiding_child = NULL;
}
- visible_child = adw_browsing_view_get_visible_child (self);
+ if (!self->transition_phony) {
+ AdwBrowsingViewChild *visible_child = adw_browsing_view_get_visible_child (self);
- if (visible_child)
- g_signal_emit (visible_child, child_signals[CHILD_SIGNAL_SHOWN], 0);
+ if (visible_child)
+ g_signal_emit (visible_child, child_signals[CHILD_SIGNAL_SHOWN], 0);
+ }
gtk_widget_queue_allocate (GTK_WIDGET (self));
}
@@ -624,20 +665,18 @@ adw_browsing_view_size_allocate (GtkWidget *widget,
{
AdwBrowsingView *self = ADW_BROWSING_VIEW (widget);
AdwBrowsingViewChild *visible_child = NULL;
- GtkWidget *static_child, *moving_child;
+ GtkWidget *static_child = NULL, *moving_child = NULL;
gboolean is_rtl;
double progress;
int offset;
visible_child = adw_browsing_view_get_visible_child (self);
- if (!visible_child)
- return;
-
is_rtl = gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL;
- if (adw_animation_get_state (self->transition) != ADW_ANIMATION_PLAYING || !self->hiding_child) {
- gtk_widget_allocate (GTK_WIDGET (visible_child), width, height, baseline, NULL);
+ if (adw_animation_get_state (self->transition) != ADW_ANIMATION_PLAYING) {
+ if (visible_child)
+ gtk_widget_allocate (GTK_WIDGET (visible_child), width, height, baseline, NULL);
adw_shadow_helper_size_allocate (self->shadow_helper, 0, 0,
baseline, 0, 0, 0,
@@ -646,11 +685,15 @@ adw_browsing_view_size_allocate (GtkWidget *widget,
}
if (self->transition_pop) {
- static_child = GTK_WIDGET (visible_child);
- moving_child = GTK_WIDGET (self->hiding_child);
+ if (visible_child)
+ static_child = GTK_WIDGET (visible_child);
+ if (self->hiding_child && visible_child != self->hiding_child)
+ moving_child = GTK_WIDGET (self->hiding_child);
} else {
- static_child = GTK_WIDGET (self->hiding_child);
- moving_child = GTK_WIDGET (visible_child);
+ if (self->hiding_child)
+ static_child = GTK_WIDGET (self->hiding_child);
+ if (visible_child && visible_child != self->hiding_child)
+ moving_child = GTK_WIDGET (visible_child);
}
progress = adw_animation_get_value (self->transition);
@@ -660,18 +703,21 @@ adw_browsing_view_size_allocate (GtkWidget *widget,
offset = (int) round (progress * width);
- gtk_widget_allocate (static_child, width, height, baseline, NULL);
+ if (static_child)
+ gtk_widget_allocate (static_child, width, height, baseline, NULL);
if (is_rtl) {
- gtk_widget_allocate (moving_child, width, height, baseline,
- gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (-offset, 0)));
+ if (moving_child)
+ gtk_widget_allocate (moving_child, width, height, baseline,
+ gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (-offset, 0)));
adw_shadow_helper_size_allocate (self->shadow_helper, offset, height,
baseline, width - offset, 0, progress,
GTK_PAN_DIRECTION_LEFT);
} else {
- gtk_widget_allocate (moving_child, width, height, baseline,
- gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (offset, 0)));
+ if (moving_child)
+ gtk_widget_allocate (moving_child, width, height, baseline,
+ gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (offset, 0)));
adw_shadow_helper_size_allocate (self->shadow_helper, offset, height,
baseline, 0, 0, progress,
@@ -685,28 +731,32 @@ adw_browsing_view_snapshot (GtkWidget *widget,
{
AdwBrowsingView *self = ADW_BROWSING_VIEW (widget);
AdwBrowsingViewChild *visible_child = NULL;
- GtkWidget *static_child, *moving_child;
+ GtkWidget *static_child = NULL, *moving_child = NULL;
int width, height;
int offset;
int clip_x, clip_width;
double progress;
- if (adw_animation_get_state (self->transition) != ADW_ANIMATION_PLAYING || !self->hiding_child) {
+ if (adw_animation_get_state (self->transition) != ADW_ANIMATION_PLAYING) {
+ if (self->next_view && adw_browsing_view_get_visible_child (self->next_view))
+ return;
+
GTK_WIDGET_CLASS (adw_browsing_view_parent_class)->snapshot (widget, snapshot);
return;
}
visible_child = adw_browsing_view_get_visible_child (self);
- if (!visible_child)
- return;
-
if (self->transition_pop) {
- static_child = GTK_WIDGET (visible_child);
- moving_child = GTK_WIDGET (self->hiding_child);
+ if (visible_child)
+ static_child = GTK_WIDGET (visible_child);
+ if (self->hiding_child && visible_child != self->hiding_child)
+ moving_child = GTK_WIDGET (self->hiding_child);
} else {
- static_child = GTK_WIDGET (self->hiding_child);
- moving_child = GTK_WIDGET (visible_child);
+ if (self->hiding_child)
+ static_child = GTK_WIDGET (self->hiding_child);
+ if (visible_child && visible_child != self->hiding_child)
+ moving_child = GTK_WIDGET (visible_child);
}
width = gtk_widget_get_width (widget);
@@ -726,13 +776,41 @@ adw_browsing_view_snapshot (GtkWidget *widget,
clip_width = offset;
}
- gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (clip_x, 0, clip_width, height));
- gtk_widget_snapshot_child (widget, static_child, snapshot);
- gtk_snapshot_pop (snapshot);
+ if (static_child) {
+ gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (clip_x, 0, clip_width, height));
+ gtk_widget_snapshot_child (widget, static_child, snapshot);
+ gtk_snapshot_pop (snapshot);
+ }
- gtk_widget_snapshot_child (widget, moving_child, snapshot);
+ if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL) {
+ clip_x = 0;
+ clip_width = width - offset;
+ } else {
+ clip_x = offset;
+ clip_width = width - offset;
+ }
+
+ if (moving_child) {
+ gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (clip_x, 0, clip_width, height));
+ gtk_widget_snapshot_child (widget, moving_child, snapshot);
+ gtk_snapshot_pop (snapshot);
+ }
+
+ if (!self->transition_phony)
+ adw_shadow_helper_snapshot (self->shadow_helper, snapshot);
+}
+
+static gboolean
+adw_browsing_view_contains (GtkWidget *widget,
+ double x,
+ double y)
+{
+ AdwBrowsingView *self = ADW_BROWSING_VIEW (widget);
- adw_shadow_helper_snapshot (self->shadow_helper, snapshot);
+ if (self->previous_view && !adw_browsing_view_get_visible_child (self))
+ return FALSE;
+
+ return GTK_WIDGET_CLASS (adw_browsing_view_parent_class)->contains (widget, x, y);
}
static void
@@ -809,6 +887,7 @@ adw_browsing_view_class_init (AdwBrowsingViewClass *klass)
widget_class->measure = adw_browsing_view_measure;
widget_class->size_allocate = adw_browsing_view_size_allocate;
widget_class->snapshot = adw_browsing_view_snapshot;
+ widget_class->contains = adw_browsing_view_contains;
widget_class->get_request_mode = adw_widget_get_request_mode;
widget_class->compute_expand = adw_widget_compute_expand;
@@ -878,6 +957,7 @@ adw_browsing_view_class_init (AdwBrowsingViewClass *klass)
NULL, NULL,
ADW_TYPE_BROWSING_VIEW_CHILD,
0);
+
gtk_widget_class_install_action (widget_class, "browsing.push", "s",
(GtkWidgetActionActivateFunc) browsing_push_cb);
gtk_widget_class_install_action (widget_class, "browsing.pop", NULL,
@@ -1421,5 +1501,52 @@ adw_browsing_view_get_previous_child (AdwBrowsingView *self,
if (l && l->next)
return l->next->data;
+ if (l && self->previous_view)
+ return adw_browsing_view_get_visible_child (self->previous_view);
+
return NULL;
}
+
+void
+adw_browsing_view_merge (AdwBrowsingView *self,
+ AdwBrowsingView *next)
+{
+ g_return_if_fail (ADW_IS_BROWSING_VIEW (self));
+ g_return_if_fail (ADW_IS_BROWSING_VIEW (next));
+
+ if (self->next_view == next && next->previous_view == self)
+ return;
+
+ self->next_view = next;
+ next->previous_view = self;
+
+ // TODO weak refs
+ // TODO notify
+ g_signal_emit (self, signals[SIGNAL_PUSHED], 0); // FIXME this is wrong
+ g_signal_emit (next, signals[SIGNAL_PUSHED], 0); // FIXME this is wrong
+}
+
+void
+adw_browsing_view_unmerge (AdwBrowsingView *self,
+ AdwBrowsingView *next)
+{
+ g_return_if_fail (ADW_IS_BROWSING_VIEW (self));
+ g_return_if_fail (ADW_IS_BROWSING_VIEW (next));
+
+ if (self->next_view != next || next->previous_view != self)
+ return;
+
+ if (!adw_browsing_view_get_visible_child (next) && next->last_child) {
+ push_to_stack (next, next->last_child, FALSE);
+ next->last_child = NULL;
+ }
+
+ self->next_view = NULL;
+ next->previous_view = NULL;
+
+ // TODO weak refs
+ // TODO notify
+ g_signal_emit (self, signals[SIGNAL_PUSHED], 0); // FIXME this is wrong
+ g_signal_emit (next, signals[SIGNAL_PUSHED], 0); // FIXME this is wrong
+ // probably should be properties
+}
diff --git a/src/adw-browsing-view.h b/src/adw-browsing-view.h
index be26df3b..a8936a16 100644
--- a/src/adw-browsing-view.h
+++ b/src/adw-browsing-view.h
@@ -104,4 +104,11 @@ ADW_AVAILABLE_IN_1_3
AdwBrowsingViewChild *adw_browsing_view_get_previous_child (AdwBrowsingView *self,
AdwBrowsingViewChild *child);
+ADW_AVAILABLE_IN_1_3
+void adw_browsing_view_merge (AdwBrowsingView *self,
+ AdwBrowsingView *next);
+ADW_AVAILABLE_IN_1_3
+void adw_browsing_view_unmerge (AdwBrowsingView *self,
+ AdwBrowsingView *next);
+
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]