[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 39db30d2b363887028e3d95807ee720d80a13171
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Tue Oct 11 15:02:35 2022 +0400
a
src/adw-browsing-view.c | 216 ++++++++++++++++++++++++++++++++++++++++--------
src/adw-browsing-view.h | 8 +-
2 files changed, 182 insertions(+), 42 deletions(-)
---
diff --git a/src/adw-browsing-view.c b/src/adw-browsing-view.c
index bbb9bbc2..7f354192 100644
--- a/src/adw-browsing-view.c
+++ b/src/adw-browsing-view.c
@@ -71,7 +71,7 @@ struct _AdwBrowsingView
GtkWidget parent_instance;
GHashTable *child_mapping;
- GList *navigation_stack;
+ GSList *navigation_stack;
AdwAnimation *transition;
AdwBrowsingViewChild *hiding_child;
@@ -96,6 +96,7 @@ static GParamSpec *props[LAST_PROP];
enum {
SIGNAL_PUSHED,
SIGNAL_POPPED,
+ SIGNAL_GET_NEXT_CHILD,
LAST_SIGNAL,
};
@@ -400,13 +401,13 @@ push_to_stack (AdwBrowsingView *self,
if (child == previous_child)
return;
- if (g_list_find (self->navigation_stack, child)) {
+ if (g_slist_find (self->navigation_stack, child)) {
g_critical ("Child '%s' is already in navigation stack\n",
adw_browsing_view_child_get_title (child));
return;
}
- self->navigation_stack = g_list_prepend (self->navigation_stack, child);
+ self->navigation_stack = g_slist_prepend (self->navigation_stack, child);
switch_child (self, previous_child, child, FALSE, animate);
@@ -424,7 +425,7 @@ pop_from_stack (AdwBrowsingView *self,
previous_child = adw_browsing_view_get_visible_child (self);
- self->navigation_stack = g_list_remove (self->navigation_stack, previous_child);
+ self->navigation_stack = g_slist_remove (self->navigation_stack, previous_child);
new_child = adw_browsing_view_get_visible_child (self);
@@ -475,6 +476,111 @@ browsing_pop_cb (AdwBrowsingView *self)
adw_browsing_view_pop (self, TRUE);
}
+static AdwBrowsingViewChild *
+get_next_child (AdwBrowsingView *self)
+{
+ AdwBrowsingViewChild *child = NULL;
+
+ g_signal_emit (self, signals[SIGNAL_GET_NEXT_CHILD], 0, &child);
+
+ if (!child)
+ return NULL;
+
+ if (gtk_widget_get_parent (GTK_WIDGET (child)) != GTK_WIDGET (self)) {
+ // TODO: critical about it not being a child
+ return NULL;
+ }
+
+ return child;
+}
+
+static gboolean
+back_forward_shortcut_cb (AdwBrowsingView *self,
+ GVariant *args)
+{
+ gboolean is_pop = FALSE;
+
+ g_variant_get (args, "b", &is_pop);
+
+ if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL)
+ is_pop = !is_pop;
+
+ if (is_pop) {
+ AdwBrowsingViewChild *child = adw_browsing_view_get_visible_child (self);
+
+ if (!adw_browsing_view_get_previous_child (self, child))
+ return GDK_EVENT_PROPAGATE;
+
+ // TODO: check if it's enabled
+
+ adw_browsing_view_pop (self, TRUE);
+ } else {
+ AdwBrowsingViewChild *next_page = get_next_child (self);
+
+ if (!next_page)
+ return GDK_EVENT_PROPAGATE;
+
+ adw_browsing_view_push (self, GTK_WIDGET (next_page), TRUE);
+ }
+
+ return GDK_EVENT_STOP;
+}
+
+static void
+back_forward_button_pressed_cb (GtkGesture *gesture,
+ int n_press,
+ double x,
+ double y,
+ AdwBrowsingView *self)
+{
+ gboolean is_pop = FALSE;
+ guint button;
+
+ if (n_press > 1) {
+ gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_DENIED);
+ return;
+ }
+
+ button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
+
+ /* Unfortunately, there are no constants for these buttons */
+ if (button == 8) {
+ is_pop = TRUE;
+ } else if (button == 9) {
+ is_pop = FALSE;
+ } else {
+ gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_DENIED);
+ return;
+ }
+
+ if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL)
+ is_pop = !is_pop;
+
+ if (is_pop) {
+ AdwBrowsingViewChild *child = adw_browsing_view_get_visible_child (self);
+
+ if (!adw_browsing_view_get_previous_child (self, child)) {
+ gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_DENIED);
+ return;
+ }
+
+ // TODO: check if it's enabled
+
+ adw_browsing_view_pop (self, TRUE);
+ } else {
+ AdwBrowsingViewChild *next_page = get_next_child (self);
+
+ if (!next_page) {
+ gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_DENIED);
+ return;
+ }
+
+ adw_browsing_view_push (self, GTK_WIDGET (next_page), TRUE);
+ }
+
+ gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_CLAIMED);
+}
+
static void
adw_browsing_view_measure (GtkWidget *widget,
GtkOrientation orientation,
@@ -677,6 +783,19 @@ adw_browsing_view_set_property (GObject *object,
}
}
+static gboolean
+object_handled_accumulator (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer data)
+{
+ GObject *object = g_value_get_object (handler_return);
+
+ g_value_set_object (return_accu, object);
+
+ return !object;
+}
+
static void
adw_browsing_view_class_init (AdwBrowsingViewClass *klass)
{
@@ -741,11 +860,38 @@ adw_browsing_view_class_init (AdwBrowsingViewClass *klass)
1,
ADW_TYPE_BROWSING_VIEW_CHILD);
+ /**
+ * AdwBrowsingView::get-next-child:
+ *
+ * TODO
+ *
+ * Returns: (transfer none): TODO
+ *
+ * Since: 1.3
+ */
+ signals[SIGNAL_GET_NEXT_CHILD] =
+ g_signal_new ("get-next-child",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ object_handled_accumulator,
+ 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,
(GtkWidgetActionActivateFunc) browsing_pop_cb);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Back, 0,
+ (GtkShortcutFunc) back_forward_shortcut_cb, "b", TRUE);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Forward, 0,
+ (GtkShortcutFunc) back_forward_shortcut_cb, "b", FALSE);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Left, GDK_ALT_MASK,
+ (GtkShortcutFunc) back_forward_shortcut_cb, "b", TRUE);
+ gtk_widget_class_add_binding (widget_class, GDK_KEY_Right, GDK_ALT_MASK,
+ (GtkShortcutFunc) back_forward_shortcut_cb, "b", FALSE);
+
gtk_widget_class_set_css_name (widget_class, "browsingview");
}
@@ -753,6 +899,7 @@ static void
adw_browsing_view_init (AdwBrowsingView *self)
{
AdwAnimationTarget *target;
+ GtkGesture *gesture;
self->child_mapping = g_hash_table_new (g_direct_hash, g_direct_equal);
@@ -765,6 +912,11 @@ adw_browsing_view_init (AdwBrowsingView *self)
self->shadow_helper = adw_shadow_helper_new (GTK_WIDGET (self));
gtk_widget_set_overflow (GTK_WIDGET (self), GTK_OVERFLOW_HIDDEN);
+
+ gesture = gtk_gesture_click_new ();
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
+ g_signal_connect_object (gesture, "pressed", G_CALLBACK (back_forward_button_pressed_cb), self, 0);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
}
static void
@@ -965,6 +1117,8 @@ adw_browsing_view_child_set_child_name (AdwBrowsingViewChild *self,
if (!g_strcmp0 (priv->name, name))
return;
+ // TODO: check for duplicate names
+
g_free (priv->name);
priv->name = g_strdup (name);
@@ -1001,6 +1155,9 @@ adw_browsing_view_add (AdwBrowsingView *self,
{
g_return_if_fail (ADW_IS_BROWSING_VIEW (self));
g_return_if_fail (GTK_IS_WIDGET (child));
+ g_return_if_fail (gtk_widget_get_parent (GTK_WIDGET (child)) == NULL);
+
+ // TODO: check for duplicate names
gtk_widget_set_parent (GTK_WIDGET (child), GTK_WIDGET (self));
g_hash_table_insert (self->child_mapping, child, child);
@@ -1030,6 +1187,7 @@ adw_browsing_view_add_with_title (AdwBrowsingView *self,
g_return_if_fail (ADW_IS_BROWSING_VIEW (self));
g_return_if_fail (GTK_IS_WIDGET (child));
+ g_return_if_fail (gtk_widget_get_parent (GTK_WIDGET (child)) == NULL);
g_return_if_fail (title != NULL);
wrapper = adw_browsing_view_child_new (child, title);
@@ -1074,7 +1232,10 @@ adw_browsing_view_remove (AdwBrowsingView *self,
return;
}
- pop_from_stack (self, FALSE);
+ if (adw_browsing_view_get_visible_child (self) == ADW_BROWSING_VIEW_CHILD (wrapper))
+ pop_from_stack (self, FALSE);
+ else if (g_slist_find (self->navigation_stack, wrapper))
+ self->navigation_stack = g_slist_remove (self->navigation_stack, wrapper);
g_hash_table_remove (self->child_mapping, child);
@@ -1188,22 +1349,28 @@ adw_browsing_view_push_by_name (AdwBrowsingView *self,
*
* TODO
*
+ * Returns: TODO
+ *
* Since: 1.3
*/
-void
+gboolean
adw_browsing_view_pop (AdwBrowsingView *self,
gboolean animate)
{
- g_return_if_fail (ADW_IS_BROWSING_VIEW (self));
+ AdwBrowsingViewChild *child;
+
+ g_return_val_if_fail (ADW_IS_BROWSING_VIEW (self), FALSE);
animate = !!animate;
- if (!self->navigation_stack) {
- // TODO: critical
- return;
- }
+ child = adw_browsing_view_get_visible_child (self);
+
+ if (!adw_browsing_view_get_previous_child (self, child))
+ return FALSE;
pop_from_stack (self, animate);
+
+ return TRUE;
}
/**
@@ -1243,12 +1410,12 @@ AdwBrowsingViewChild *
adw_browsing_view_get_previous_child (AdwBrowsingView *self,
AdwBrowsingViewChild *child)
{
- GList *l;
+ GSList *l;
g_return_val_if_fail (ADW_IS_BROWSING_VIEW (self), NULL);
g_return_val_if_fail (ADW_IS_BROWSING_VIEW_CHILD (child), NULL);
- l = g_list_find (self->navigation_stack, child);
+ l = g_slist_find (self->navigation_stack, child);
/* The stack is reversed, so we get the next element instead */
if (l && l->next)
@@ -1256,26 +1423,3 @@ adw_browsing_view_get_previous_child (AdwBrowsingView *self,
return NULL;
}
-
-/**
- * adw_browsing_view_get_next_child:
- * @self: a browsing view
- * @child: TODO
- *
- * TODO
- *
- * Returns: TODO
- *
- * Since: 1.3
- */
-AdwBrowsingViewChild *
-adw_browsing_view_get_next_child (AdwBrowsingView *self,
- AdwBrowsingViewChild *child)
-{
- g_return_val_if_fail (ADW_IS_BROWSING_VIEW (self), NULL);
- g_return_val_if_fail (ADW_IS_BROWSING_VIEW_CHILD (child), NULL);
-
- // TODO: implement this
- //
- return NULL;
-}
diff --git a/src/adw-browsing-view.h b/src/adw-browsing-view.h
index f0fcf08c..be26df3b 100644
--- a/src/adw-browsing-view.h
+++ b/src/adw-browsing-view.h
@@ -94,8 +94,8 @@ void adw_browsing_view_push_by_name (AdwBrowsingView *self,
gboolean animate);
ADW_AVAILABLE_IN_1_3
-void adw_browsing_view_pop (AdwBrowsingView *self,
- gboolean animate);
+gboolean adw_browsing_view_pop (AdwBrowsingView *self,
+ gboolean animate);
ADW_AVAILABLE_IN_1_3
AdwBrowsingViewChild *adw_browsing_view_get_visible_child (AdwBrowsingView *self);
@@ -104,8 +104,4 @@ ADW_AVAILABLE_IN_1_3
AdwBrowsingViewChild *adw_browsing_view_get_previous_child (AdwBrowsingView *self,
AdwBrowsingViewChild *child);
-ADW_AVAILABLE_IN_1_3
-AdwBrowsingViewChild *adw_browsing_view_get_next_child (AdwBrowsingView *self,
- AdwBrowsingViewChild *child);
-
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]