[libadwaita/wip/exalm/browsing-view] browsing view



commit 821a426d1b55006652c8761d3eabca56d538854e
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Fri Oct 14 00:22:44 2022 +0400

    browsing view

 src/adw-browsing-view.c | 145 +++++++++++++++++++++++++++++++++++++-----------
 src/adw-browsing-view.h |  14 +++--
 2 files changed, 122 insertions(+), 37 deletions(-)
---
diff --git a/src/adw-browsing-view.c b/src/adw-browsing-view.c
index 8c363e7e..c7dd4203 100644
--- a/src/adw-browsing-view.c
+++ b/src/adw-browsing-view.c
@@ -84,6 +84,7 @@ struct _AdwBrowsingView
 
   AdwBrowsingView *previous_view;
   AdwBrowsingView *next_view;
+  gboolean inside_set_previous_next_child;
 };
 
 static void adw_browsing_view_buildable_init (GtkBuildableIface *iface);
@@ -94,6 +95,8 @@ G_DEFINE_FINAL_TYPE_WITH_CODE (AdwBrowsingView, adw_browsing_view, GTK_TYPE_WIDG
 enum {
   PROP_0,
   PROP_VISIBLE_CHILD,
+  PROP_PREVIOUS_VIEW,
+  PROP_NEXT_VIEW,
   LAST_PROP
 };
 
@@ -403,7 +406,8 @@ switch_child (AdwBrowsingView      *self,
 static void
 push_to_stack (AdwBrowsingView      *self,
                AdwBrowsingViewChild *child,
-               gboolean              animate)
+               gboolean              animate,
+               gboolean              emit_signal)
 {
   AdwBrowsingViewChild *previous_child = adw_browsing_view_get_visible_child (self);
 
@@ -842,6 +846,12 @@ adw_browsing_view_get_property (GObject    *object,
   case PROP_VISIBLE_CHILD:
     g_value_set_object (value, adw_browsing_view_get_visible_child (self));
     break;
+  case PROP_PREVIOUS_VIEW:
+    g_value_set_object (value, adw_browsing_view_get_previous_view (self));
+    break;
+  case PROP_NEXT_VIEW:
+    g_value_set_object (value, adw_browsing_view_get_next_view (self));
+    break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   }
@@ -903,6 +913,30 @@ adw_browsing_view_class_init (AdwBrowsingViewClass *klass)
                          ADW_TYPE_BROWSING_VIEW_CHILD,
                          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
+  /**
+   * AdwBrowsingView:previous-view: (attributes 
org.gtk.Property.get=adw_browsing_view_child_get_previous_view 
org.gtk.Property.set=adw_browsing_view_child_set_previous_view)
+   *
+   * TODO
+   *
+   * Since: 1.3
+   */
+  props[PROP_PREVIOUS_VIEW] =
+    g_param_spec_object ("previous-view", NULL, NULL,
+                         ADW_TYPE_BROWSING_VIEW,
+                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  /**
+   * AdwBrowsingView:next-view: (attributes org.gtk.Property.get=adw_browsing_view_child_get_next_view 
org.gtk.Property.set=adw_browsing_view_child_set_next_view)
+   *
+   * TODO
+   *
+   * Since: 1.3
+   */
+  props[PROP_NEXT_VIEW] =
+    g_param_spec_object ("next-view", NULL, NULL,
+                         ADW_TYPE_BROWSING_VIEW,
+                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
   g_object_class_install_properties (object_class, LAST_PROP, props);
 
   /**
@@ -1245,7 +1279,7 @@ adw_browsing_view_add (AdwBrowsingView      *self,
   if (self->navigation_stack)
     gtk_widget_set_child_visible (GTK_WIDGET (child), FALSE);
   else
-    push_to_stack (self, child, FALSE);
+    push_to_stack (self, child, FALSE, TRUE);
 }
 
 /**
@@ -1278,7 +1312,7 @@ adw_browsing_view_add_with_title (AdwBrowsingView *self,
   if (self->navigation_stack)
     gtk_widget_set_child_visible (wrapper, FALSE);
   else
-    push_to_stack (self, ADW_BROWSING_VIEW_CHILD (wrapper), FALSE);
+    push_to_stack (self, ADW_BROWSING_VIEW_CHILD (wrapper), FALSE, TRUE);
 }
 
 /**
@@ -1387,7 +1421,7 @@ adw_browsing_view_push (AdwBrowsingView *self,
     return;
   }
 
-  push_to_stack (self, wrapper, animate);
+  push_to_stack (self, wrapper, animate, TRUE);
 }
 
 /**
@@ -1419,7 +1453,7 @@ adw_browsing_view_push_by_name (AdwBrowsingView *self,
     return;
   }
 
-  push_to_stack (self, wrapper, animate);
+  push_to_stack (self, wrapper, animate, TRUE);
 }
 
 /**
@@ -1507,46 +1541,91 @@ adw_browsing_view_get_previous_child (AdwBrowsingView      *self,
   return NULL;
 }
 
-void
-adw_browsing_view_merge (AdwBrowsingView *self,
-                         AdwBrowsingView *next)
+AdwBrowsingView *
+adw_browsing_view_get_previous_view (AdwBrowsingView *self)
 {
-  g_return_if_fail (ADW_IS_BROWSING_VIEW (self));
-  g_return_if_fail (ADW_IS_BROWSING_VIEW (next));
+  g_return_val_if_fail (ADW_IS_BROWSING_VIEW (self), NULL);
 
-  if (self->next_view == next && next->previous_view == self)
-    return;
+  return self->previous_view;
+}
 
-  self->next_view = next;
-  next->previous_view = self;
+AdwBrowsingView *
+adw_browsing_view_get_next_view (AdwBrowsingView *self)
+{
+  g_return_val_if_fail (ADW_IS_BROWSING_VIEW (self), 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
+  return self->next_view;
+}
+
+static void
+set_next_view (AdwBrowsingView *self,
+               AdwBrowsingView *next_view)
+{
+  AdwBrowsingView *old_next = self->next_view;
+  AdwBrowsingView *old_next_prev = next_view ? next_view->previous_view : NULL;
+  gboolean pushed = FALSE;
+
+  // TODO: weak refs
+
+  if (old_next_prev)
+    old_next_prev->next_view = NULL;
+
+  if (old_next) {
+    old_next->previous_view = NULL;
+
+    if (!adw_browsing_view_get_visible_child (old_next) && old_next->last_child) {
+      g_object_freeze_notify (G_OBJECT (old_next));
+      pushed = TRUE;
+      push_to_stack (old_next, old_next->last_child, FALSE, FALSE);
+      old_next->last_child = NULL;
+    }
+  }
+
+  self->next_view = next_view;
+
+  if (next_view)
+    next_view->previous_view = self;
+
+  if (old_next_prev)
+    g_object_notify_by_pspec (G_OBJECT (old_next_prev), props[PROP_NEXT_VIEW]);
+  if (old_next)
+    g_object_notify_by_pspec (G_OBJECT (old_next), props[PROP_PREVIOUS_VIEW]);
+  if (next_view)
+    g_object_notify_by_pspec (G_OBJECT (next_view), props[PROP_PREVIOUS_VIEW]);
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_NEXT_VIEW]);
+
+  if (pushed) {
+    g_object_thaw_notify (G_OBJECT (old_next));
+    g_signal_emit (self, signals[SIGNAL_PUSHED], 0);
+  }
 }
 
 void
-adw_browsing_view_unmerge (AdwBrowsingView *self,
-                           AdwBrowsingView *next)
+adw_browsing_view_connect (AdwBrowsingView *self,
+                           AdwBrowsingView *next_view)
 {
   g_return_if_fail (ADW_IS_BROWSING_VIEW (self));
-  g_return_if_fail (ADW_IS_BROWSING_VIEW (next));
+  g_return_if_fail (ADW_IS_BROWSING_VIEW (next_view));
+  g_return_if_fail (self != next_view);
 
-  if (self->next_view != next || next->previous_view != self)
+  if (self->next_view == next_view)
     return;
 
-  if (!adw_browsing_view_get_visible_child (next) && next->last_child) {
-    push_to_stack (next, next->last_child, FALSE);
-    next->last_child = NULL;
-  }
+  set_next_view (self, next_view);
+}
 
-  self->next_view = NULL;
-  next->previous_view = NULL;
+void
+adw_browsing_view_disconnect (AdwBrowsingView *self,
+                              AdwBrowsingView *other_view)
+{
+  g_return_if_fail (ADW_IS_BROWSING_VIEW (self));
+  g_return_if_fail (ADW_IS_BROWSING_VIEW (other_view));
+  g_return_if_fail (self != other_view);
 
-  // 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
+  if (self->next_view == other_view)
+    set_next_view (self, NULL);
+  else if (other_view->next_view == self)
+    set_next_view (other_view, NULL);
+  else
+    g_critical ("Can't disconnect AdwBrowsingView %p and %p as they haven't connected'", self, other_view);
 }
diff --git a/src/adw-browsing-view.h b/src/adw-browsing-view.h
index a8936a16..5df3b8d3 100644
--- a/src/adw-browsing-view.h
+++ b/src/adw-browsing-view.h
@@ -105,10 +105,16 @@ AdwBrowsingViewChild *adw_browsing_view_get_previous_child (AdwBrowsingView
                                                             AdwBrowsingViewChild *child);
 
 ADW_AVAILABLE_IN_1_3
-void adw_browsing_view_merge   (AdwBrowsingView *self,
-                                AdwBrowsingView *next);
+AdwBrowsingView *adw_browsing_view_get_previous_view (AdwBrowsingView *self);
 ADW_AVAILABLE_IN_1_3
-void adw_browsing_view_unmerge (AdwBrowsingView *self,
-                                AdwBrowsingView *next);
+AdwBrowsingView *adw_browsing_view_get_next_view (AdwBrowsingView *self);
+
+ADW_AVAILABLE_IN_1_3
+void             adw_browsing_view_connect (AdwBrowsingView *self,
+                                            AdwBrowsingView *next_view);
+
+ADW_AVAILABLE_IN_1_3
+void             adw_browsing_view_disconnect (AdwBrowsingView *self,
+                                               AdwBrowsingView *other_view);
 
 G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]