phosh-arch/gtk3-mobile/Add-GtkHdyViewSwitcherBar.patch
2024-08-13 08:17:11 -07:00

509 lines
15 KiB
Diff

From: Adrien Plazas <kekun.plazas@laposte.net>
Date: Mon, 31 Aug 2020 10:40:14 +0200
Subject: Add GtkHdyViewSwitcherBar
This is imported from HdyViewSwitcherBar from libhandy 1.0.0.
---
gtk/hdy-view-switcher-bar-private.h | 38 ++++
gtk/hdy-view-switcher-bar.c | 398 ++++++++++++++++++++++++++++++++++++
gtk/meson.build | 2 +
gtk/ui/hdy-view-switcher-bar.ui | 20 ++
4 files changed, 458 insertions(+)
create mode 100644 gtk/hdy-view-switcher-bar-private.h
create mode 100644 gtk/hdy-view-switcher-bar.c
create mode 100644 gtk/ui/hdy-view-switcher-bar.ui
diff --git a/gtk/hdy-view-switcher-bar-private.h b/gtk/hdy-view-switcher-bar-private.h
new file mode 100644
index 0000000..a1d942a
--- /dev/null
+++ b/gtk/hdy-view-switcher-bar-private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 Zander Brown <zbrown@gnome.org>
+ * Copyright (C) 2019 Purism SPC
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#pragma once
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include "gtkbin.h"
+#include "gtkstack.h"
+#include "hdy-view-switcher-private.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_HDY_VIEW_SWITCHER_BAR (gtk_hdy_view_switcher_bar_get_type())
+
+G_DECLARE_FINAL_TYPE (GtkHdyViewSwitcherBar, gtk_hdy_view_switcher_bar, GTK, HDY_VIEW_SWITCHER_BAR, GtkBin)
+
+GtkWidget *gtk_hdy_view_switcher_bar_new (void);
+
+GtkHdyViewSwitcherPolicy gtk_hdy_view_switcher_bar_get_policy (GtkHdyViewSwitcherBar *self);
+void gtk_hdy_view_switcher_bar_set_policy (GtkHdyViewSwitcherBar *self,
+ GtkHdyViewSwitcherPolicy policy);
+
+GtkStack *gtk_hdy_view_switcher_bar_get_stack (GtkHdyViewSwitcherBar *self);
+void gtk_hdy_view_switcher_bar_set_stack (GtkHdyViewSwitcherBar *self,
+ GtkStack *stack);
+
+gboolean gtk_hdy_view_switcher_bar_get_reveal (GtkHdyViewSwitcherBar *self);
+void gtk_hdy_view_switcher_bar_set_reveal (GtkHdyViewSwitcherBar *self,
+ gboolean reveal);
+
+G_END_DECLS
diff --git a/gtk/hdy-view-switcher-bar.c b/gtk/hdy-view-switcher-bar.c
new file mode 100644
index 0000000..39d2aa4
--- /dev/null
+++ b/gtk/hdy-view-switcher-bar.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2019 Zander Brown <zbrown@gnome.org>
+ * Copyright (C) 2019 Purism SPC
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#include "gtkactionbar.h"
+#include "gtkrevealer.h"
+#include "gtkprivatetypebuiltins.h"
+#include "hdy-view-switcher-bar-private.h"
+#include "hdy-view-switcher-private.h"
+
+/**
+ * SECTION:hdy-view-switcher-bar
+ * @short_description: A view switcher action bar.
+ * @title: GtkHdyViewSwitcherBar
+ * @See_also: #GtkHdyViewSwitcher, #GtkHdyViewSwitcherTitle
+ *
+ * An action bar letting you switch between multiple views offered by a
+ * #GtkStack, via an #GtkHdyViewSwitcher. It is designed to be put at the bottom of
+ * a window and to be revealed only on really narrow windows e.g. on mobile
+ * phones. It can't be revealed if there are less than two pages.
+ *
+ * You can conveniently bind the #GtkHdyViewSwitcherBar:reveal property to
+ * #GtkHdyViewSwitcherTitle:title-visible to automatically reveal the view switcher
+ * bar when the title label is displayed in place of the view switcher.
+ *
+ * An example of the UI definition for a common use case:
+ * |[
+ * <object class="GtkWindow"/>
+ * <child type="titlebar">
+ * <object class="HdyHeaderBar">
+ * <property name="centering-policy">strict</property>
+ * <child type="title">
+ * <object class="GtkHdyViewSwitcherTitle"
+ * id="view_switcher_title">
+ * <property name="stack">stack</property>
+ * </object>
+ * </child>
+ * </object>
+ * </child>
+ * <child>
+ * <object class="GtkBox">
+ * <child>
+ * <object class="GtkStack" id="stack"/>
+ * </child>
+ * <child>
+ * <object class="GtkHdyViewSwitcherBar">
+ * <property name="stack">stack</property>
+ * <property name="reveal"
+ * bind-source="view_switcher_title"
+ * bind-property="title-visible"
+ * bind-flags="sync-create"/>
+ * </object>
+ * </child>
+ * </object>
+ * </child>
+ * </object>
+ * ]|
+ *
+ * # CSS nodes
+ *
+ * #GtkHdyViewSwitcherBar has a single CSS node with name viewswitcherbar.
+ *
+ * Since: 0.0.10
+ */
+
+enum {
+ PROP_0,
+ PROP_POLICY,
+ PROP_STACK,
+ PROP_REVEAL,
+ LAST_PROP,
+};
+
+struct _GtkHdyViewSwitcherBar
+{
+ GtkBin parent_instance;
+
+ GtkActionBar *action_bar;
+ GtkRevealer *revealer;
+ GtkHdyViewSwitcher *view_switcher;
+
+ GtkHdyViewSwitcherPolicy policy;
+ gboolean reveal;
+};
+
+static GParamSpec *props[LAST_PROP];
+
+G_DEFINE_TYPE (GtkHdyViewSwitcherBar, gtk_hdy_view_switcher_bar, GTK_TYPE_BIN)
+
+static void
+count_children_cb (GtkWidget *widget,
+ gint *count)
+{
+ (*count)++;
+}
+
+static void
+update_bar_revealed (GtkHdyViewSwitcherBar *self)
+{
+ GtkStack *stack = gtk_hdy_view_switcher_get_stack (self->view_switcher);
+ gint count = 0;
+
+ if (self->reveal && stack)
+ gtk_container_foreach (GTK_CONTAINER (stack), (GtkCallback) count_children_cb, &count);
+
+ gtk_revealer_set_reveal_child (self->revealer, count > 1);
+}
+
+static void
+gtk_hdy_view_switcher_bar_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkHdyViewSwitcherBar *self = GTK_HDY_VIEW_SWITCHER_BAR (object);
+
+ switch (prop_id) {
+ case PROP_POLICY:
+ g_value_set_enum (value, gtk_hdy_view_switcher_bar_get_policy (self));
+ break;
+ case PROP_STACK:
+ g_value_set_object (value, gtk_hdy_view_switcher_bar_get_stack (self));
+ break;
+ case PROP_REVEAL:
+ g_value_set_boolean (value, gtk_hdy_view_switcher_bar_get_reveal (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_hdy_view_switcher_bar_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkHdyViewSwitcherBar *self = GTK_HDY_VIEW_SWITCHER_BAR (object);
+
+ switch (prop_id) {
+ case PROP_POLICY:
+ gtk_hdy_view_switcher_bar_set_policy (self, g_value_get_enum (value));
+ break;
+ case PROP_STACK:
+ gtk_hdy_view_switcher_bar_set_stack (self, g_value_get_object (value));
+ break;
+ case PROP_REVEAL:
+ gtk_hdy_view_switcher_bar_set_reveal (self, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_hdy_view_switcher_bar_class_init (GtkHdyViewSwitcherBarClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = gtk_hdy_view_switcher_bar_get_property;
+ object_class->set_property = gtk_hdy_view_switcher_bar_set_property;
+
+ /**
+ * GtkHdyViewSwitcherBar:policy:
+ *
+ * The #GtkHdyViewSwitcherPolicy the #GtkHdyViewSwitcher should use to determine
+ * which mode to use.
+ *
+ * Since: 0.0.10
+ */
+ props[PROP_POLICY] =
+ g_param_spec_enum ("policy",
+ _("Policy"),
+ _("The policy to determine the mode to use"),
+ GTK_TYPE_HDY_VIEW_SWITCHER_POLICY, GTK_HDY_VIEW_SWITCHER_POLICY_NARROW,
+ G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtkHdyViewSwitcherBar:stack:
+ *
+ * The #GtkStack the #GtkHdyViewSwitcher controls.
+ *
+ * Since: 0.0.10
+ */
+ props[PROP_STACK] =
+ g_param_spec_object ("stack",
+ _("Stack"),
+ _("Stack"),
+ GTK_TYPE_STACK,
+ G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtkHdyViewSwitcherBar:reveal:
+ *
+ * Whether the bar should be revealed or hidden.
+ *
+ * Since: 0.0.10
+ */
+ props[PROP_REVEAL] =
+ g_param_spec_boolean ("reveal",
+ _("Reveal"),
+ _("Whether the view switcher is revealed"),
+ FALSE,
+ G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, props);
+
+ gtk_widget_class_set_css_name (widget_class, "viewswitcherbar");
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gtk/libgtk/ui/hdy-view-switcher-bar.ui");
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherBar, action_bar);
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherBar, view_switcher);
+}
+
+static void
+gtk_hdy_view_switcher_bar_init (GtkHdyViewSwitcherBar *self)
+{
+ /* This must be initialized before the template so the embedded view switcher
+ * can pick up the correct default value.
+ */
+ self->policy = GTK_HDY_VIEW_SWITCHER_POLICY_NARROW;
+
+ g_type_ensure (GTK_TYPE_HDY_VIEW_SWITCHER);
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->revealer = GTK_REVEALER (gtk_bin_get_child (GTK_BIN (self->action_bar)));
+ update_bar_revealed (self);
+ gtk_revealer_set_transition_type (self->revealer, GTK_REVEALER_TRANSITION_TYPE_SLIDE_UP);
+}
+
+/**
+ * gtk_hdy_view_switcher_bar_new:
+ *
+ * Creates a new #GtkHdyViewSwitcherBar widget.
+ *
+ * Returns: a new #GtkHdyViewSwitcherBar
+ *
+ * Since: 0.0.10
+ */
+GtkWidget *
+gtk_hdy_view_switcher_bar_new (void)
+{
+ return g_object_new (GTK_TYPE_HDY_VIEW_SWITCHER_BAR, NULL);
+}
+
+/**
+ * gtk_hdy_view_switcher_bar_get_policy:
+ * @self: a #GtkHdyViewSwitcherBar
+ *
+ * Gets the policy of @self.
+ *
+ * Returns: the policy of @self
+ *
+ * Since: 0.0.10
+ */
+GtkHdyViewSwitcherPolicy
+gtk_hdy_view_switcher_bar_get_policy (GtkHdyViewSwitcherBar *self)
+{
+ g_return_val_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BAR (self), GTK_HDY_VIEW_SWITCHER_POLICY_NARROW);
+
+ return self->policy;
+}
+
+/**
+ * gtk_hdy_view_switcher_bar_set_policy:
+ * @self: a #GtkHdyViewSwitcherBar
+ * @policy: the new policy
+ *
+ * Sets the policy of @self.
+ *
+ * Since: 0.0.10
+ */
+void
+gtk_hdy_view_switcher_bar_set_policy (GtkHdyViewSwitcherBar *self,
+ GtkHdyViewSwitcherPolicy policy)
+{
+ g_return_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BAR (self));
+
+ if (self->policy == policy)
+ return;
+
+ self->policy = policy;
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_POLICY]);
+
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+}
+
+/**
+ * gtk_hdy_view_switcher_bar_get_stack:
+ * @self: a #GtkHdyViewSwitcherBar
+ *
+ * Get the #GtkStack being controlled by the #GtkHdyViewSwitcher.
+ *
+ * Returns: (nullable) (transfer none): the #GtkStack, or %NULL if none has been set
+ *
+ * Since: 0.0.10
+ */
+GtkStack *
+gtk_hdy_view_switcher_bar_get_stack (GtkHdyViewSwitcherBar *self)
+{
+ g_return_val_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BAR (self), NULL);
+
+ return gtk_hdy_view_switcher_get_stack (self->view_switcher);
+}
+
+/**
+ * gtk_hdy_view_switcher_bar_set_stack:
+ * @self: a #GtkHdyViewSwitcherBar
+ * @stack: (nullable): a #GtkStack
+ *
+ * Sets the #GtkStack to control.
+ *
+ * Since: 0.0.10
+ */
+void
+gtk_hdy_view_switcher_bar_set_stack (GtkHdyViewSwitcherBar *self,
+ GtkStack *stack)
+{
+ GtkStack *previous_stack;
+
+ g_return_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BAR (self));
+ g_return_if_fail (stack == NULL || GTK_IS_STACK (stack));
+
+ previous_stack = gtk_hdy_view_switcher_get_stack (self->view_switcher);
+
+ if (previous_stack == stack)
+ return;
+
+ if (previous_stack)
+ g_signal_handlers_disconnect_by_func (previous_stack, G_CALLBACK (update_bar_revealed), self);
+
+ gtk_hdy_view_switcher_set_stack (self->view_switcher, stack);
+
+ if (stack) {
+ g_signal_connect_swapped (stack, "add", G_CALLBACK (update_bar_revealed), self);
+ g_signal_connect_swapped (stack, "remove", G_CALLBACK (update_bar_revealed), self);
+ }
+
+ update_bar_revealed (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STACK]);
+}
+
+/**
+ * gtk_hdy_view_switcher_bar_get_reveal:
+ * @self: a #GtkHdyViewSwitcherBar
+ *
+ * Gets whether @self should be revealed or not.
+ *
+ * Returns: %TRUE if @self is revealed, %FALSE if not.
+ *
+ * Since: 0.0.10
+ */
+gboolean
+gtk_hdy_view_switcher_bar_get_reveal (GtkHdyViewSwitcherBar *self)
+{
+ g_return_val_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BAR (self), FALSE);
+
+ return self->reveal;
+}
+
+/**
+ * gtk_hdy_view_switcher_bar_set_reveal:
+ * @self: a #GtkHdyViewSwitcherBar
+ * @reveal: %TRUE to reveal @self
+ *
+ * Sets whether @self should be revealed or not.
+ *
+ * Since: 0.0.10
+ */
+void
+gtk_hdy_view_switcher_bar_set_reveal (GtkHdyViewSwitcherBar *self,
+ gboolean reveal)
+{
+ g_return_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BAR (self));
+
+ reveal = !!reveal;
+
+ if (self->reveal == reveal)
+ return;
+
+ self->reveal = reveal;
+ update_bar_revealed (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REVEAL]);
+}
diff --git a/gtk/meson.build b/gtk/meson.build
index 1054e29..1d35e83 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -384,6 +384,7 @@ gtk_sources = files(
'gtkwin32theme.c',
'gdkpixbufutils.c',
'hdy-css.c',
+ 'hdy-view-switcher-bar.c',
'hdy-view-switcher-button.c',
'hdy-view-switcher.c',
'language-names.c',
@@ -394,6 +395,7 @@ gtk_private_type_headers = files(
'gtkcsstypesprivate.h',
'gtktexthandleprivate.h',
'hdy-css-private.h',
+ 'hdy-view-switcher-bar-private.h',
'hdy-view-switcher-button-private.h',
'hdy-view-switcher-private.h',
)
diff --git a/gtk/ui/hdy-view-switcher-bar.ui b/gtk/ui/hdy-view-switcher-bar.ui
new file mode 100644
index 0000000..42246e8
--- /dev/null
+++ b/gtk/ui/hdy-view-switcher-bar.ui
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <template class="GtkHdyViewSwitcherBar" parent="GtkBin">
+ <child>
+ <object class="GtkActionBar" id="action_bar">
+ <property name="visible">True</property>
+ <child type="center">
+ <object class="GtkHdyViewSwitcher" id="view_switcher">
+ <property name="margin-start">10</property>
+ <property name="margin-end">10</property>
+ <property name="narrow-ellipsize">end</property>
+ <property name="policy" bind-source="GtkHdyViewSwitcherBar" bind-property="policy" bind-flags="sync-create|bidirectional" />
+ <property name="visible">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>