509 lines
15 KiB
Diff
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>
|