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

754 lines
26 KiB
Diff

From: Adrien Plazas <kekun.plazas@laposte.net>
Date: Mon, 31 Aug 2020 10:40:01 +0200
Subject: Add GtkHdyViewSwitcherButton
This is imported from HdyViewSwitcherButton from libhandy 1.0.0.
---
gtk/hdy-view-switcher-button-private.h | 51 ++++
gtk/hdy-view-switcher-button.c | 544 +++++++++++++++++++++++++++++++++
gtk/meson.build | 2 +
gtk/ui/hdy-view-switcher-button.ui | 105 +++++++
4 files changed, 702 insertions(+)
create mode 100644 gtk/hdy-view-switcher-button-private.h
create mode 100644 gtk/hdy-view-switcher-button.c
create mode 100644 gtk/ui/hdy-view-switcher-button.ui
diff --git a/gtk/hdy-view-switcher-button-private.h b/gtk/hdy-view-switcher-button-private.h
new file mode 100644
index 0000000..a37add6
--- /dev/null
+++ b/gtk/hdy-view-switcher-button-private.h
@@ -0,0 +1,51 @@
+/*
+ * 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 "gtkradiobutton.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_HDY_VIEW_SWITCHER_BUTTON (gtk_hdy_view_switcher_button_get_type())
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkRadioButton, g_object_unref)
+
+G_DECLARE_FINAL_TYPE (GtkHdyViewSwitcherButton, gtk_hdy_view_switcher_button, GTK, HDY_VIEW_SWITCHER_BUTTON, GtkRadioButton)
+
+GtkWidget *gtk_hdy_view_switcher_button_new (void);
+
+const gchar *gtk_hdy_view_switcher_button_get_icon_name (GtkHdyViewSwitcherButton *self);
+void gtk_hdy_view_switcher_button_set_icon_name (GtkHdyViewSwitcherButton *self,
+ const gchar *icon_name);
+
+GtkIconSize gtk_hdy_view_switcher_button_get_icon_size (GtkHdyViewSwitcherButton *self);
+void gtk_hdy_view_switcher_button_set_icon_size (GtkHdyViewSwitcherButton *self,
+ GtkIconSize icon_size);
+
+gboolean gtk_hdy_view_switcher_button_get_needs_attention (GtkHdyViewSwitcherButton *self);
+void gtk_hdy_view_switcher_button_set_needs_attention (GtkHdyViewSwitcherButton *self,
+ gboolean needs_attention);
+
+const gchar *gtk_hdy_view_switcher_button_get_label (GtkHdyViewSwitcherButton *self);
+void gtk_hdy_view_switcher_button_set_label (GtkHdyViewSwitcherButton *self,
+ const gchar *label);
+
+void gtk_hdy_view_switcher_button_set_narrow_ellipsize (GtkHdyViewSwitcherButton *self,
+ PangoEllipsizeMode mode);
+
+void gtk_hdy_view_switcher_button_get_size (GtkHdyViewSwitcherButton *self,
+ gint *h_min_width,
+ gint *h_nat_width,
+ gint *v_min_width,
+ gint *v_nat_width);
+
+G_END_DECLS
diff --git a/gtk/hdy-view-switcher-button.c b/gtk/hdy-view-switcher-button.c
new file mode 100644
index 0000000..875ca7d
--- /dev/null
+++ b/gtk/hdy-view-switcher-button.c
@@ -0,0 +1,544 @@
+/*
+ * 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 "gtkbox.h"
+#include "gtkimage.h"
+#include "gtklabel.h"
+#include "gtkorientable.h"
+#include "gtkstack.h"
+#include "gtkstylecontext.h"
+#include "gtkstyleprovider.h"
+#include "hdy-view-switcher-button-private.h"
+
+
+/**
+ * PRIVATE:gtk-hdy-view-switcher-button
+ * @short_description: Button used in #GtkHdyViewSwitcher.
+ * @title: GtkHdyViewSwitcherButton
+ * @See_also: #GtkHdyViewSwitcher
+ * @stability: Private
+ *
+ * #GtkHdyViewSwitcherButton represents an application's view. It is designed to be
+ * used exclusively internally by #GtkHdyViewSwitcher.
+ *
+ * Since: 0.0.10
+ */
+
+enum {
+ PROP_0,
+ PROP_ICON_SIZE,
+ PROP_ICON_NAME,
+ PROP_NEEDS_ATTENTION,
+
+ /* Overridden properties */
+ PROP_LABEL,
+ PROP_ORIENTATION,
+
+ LAST_PROP = PROP_NEEDS_ATTENTION + 1,
+};
+
+struct _GtkHdyViewSwitcherButton
+{
+ GtkRadioButton parent_instance;
+
+ GtkBox *horizontal_box;
+ GtkImage *horizontal_image;
+ GtkLabel *horizontal_label_active;
+ GtkLabel *horizontal_label_inactive;
+ GtkStack *horizontal_label_stack;
+ GtkStack *stack;
+ GtkBox *vertical_box;
+ GtkImage *vertical_image;
+ GtkLabel *vertical_label_active;
+ GtkLabel *vertical_label_inactive;
+ GtkStack *vertical_label_stack;
+
+ gchar *icon_name;
+ GtkIconSize icon_size;
+ gchar *label;
+ GtkOrientation orientation;
+};
+
+static GParamSpec *props[LAST_PROP];
+
+G_DEFINE_TYPE_WITH_CODE (GtkHdyViewSwitcherButton, gtk_hdy_view_switcher_button, GTK_TYPE_RADIO_BUTTON,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
+
+static void
+on_active_changed (GtkHdyViewSwitcherButton *self)
+{
+ g_return_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self));
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self))) {
+ gtk_stack_set_visible_child (self->horizontal_label_stack, GTK_WIDGET (self->horizontal_label_active));
+ gtk_stack_set_visible_child (self->vertical_label_stack, GTK_WIDGET (self->vertical_label_active));
+ } else {
+ gtk_stack_set_visible_child (self->horizontal_label_stack, GTK_WIDGET (self->horizontal_label_inactive));
+ gtk_stack_set_visible_child (self->vertical_label_stack, GTK_WIDGET (self->vertical_label_inactive));
+ }
+}
+
+static GtkOrientation
+get_orientation (GtkHdyViewSwitcherButton *self)
+{
+ g_return_val_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self), GTK_ORIENTATION_HORIZONTAL);
+
+ return self->orientation;
+}
+
+static void
+set_orientation (GtkHdyViewSwitcherButton *self,
+ GtkOrientation orientation)
+{
+ g_return_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self));
+
+ if (self->orientation == orientation)
+ return;
+
+ self->orientation = orientation;
+
+ gtk_stack_set_visible_child (self->stack,
+ GTK_WIDGET (self->orientation == GTK_ORIENTATION_VERTICAL ?
+ self->vertical_box :
+ self->horizontal_box));
+}
+
+static void
+gtk_hdy_view_switcher_button_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkHdyViewSwitcherButton *self = GTK_HDY_VIEW_SWITCHER_BUTTON (object);
+
+ switch (prop_id) {
+ case PROP_ICON_NAME:
+ g_value_set_string (value, gtk_hdy_view_switcher_button_get_icon_name (self));
+ break;
+ case PROP_ICON_SIZE:
+ g_value_set_int (value, gtk_hdy_view_switcher_button_get_icon_size (self));
+ break;
+ case PROP_NEEDS_ATTENTION:
+ g_value_set_boolean (value, gtk_hdy_view_switcher_button_get_needs_attention (self));
+ break;
+ case PROP_LABEL:
+ g_value_set_string (value, gtk_hdy_view_switcher_button_get_label (self));
+ break;
+ case PROP_ORIENTATION:
+ g_value_set_enum (value, get_orientation (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_hdy_view_switcher_button_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkHdyViewSwitcherButton *self = GTK_HDY_VIEW_SWITCHER_BUTTON (object);
+
+ switch (prop_id) {
+ case PROP_ICON_NAME:
+ gtk_hdy_view_switcher_button_set_icon_name (self, g_value_get_string (value));
+ break;
+ case PROP_ICON_SIZE:
+ gtk_hdy_view_switcher_button_set_icon_size (self, g_value_get_int (value));
+ break;
+ case PROP_NEEDS_ATTENTION:
+ gtk_hdy_view_switcher_button_set_needs_attention (self, g_value_get_boolean (value));
+ break;
+ case PROP_LABEL:
+ gtk_hdy_view_switcher_button_set_label (self, g_value_get_string (value));
+ break;
+ case PROP_ORIENTATION:
+ set_orientation (self, g_value_get_enum (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_hdy_view_switcher_button_finalize (GObject *object)
+{
+ GtkHdyViewSwitcherButton *self = GTK_HDY_VIEW_SWITCHER_BUTTON (object);
+
+ g_free (self->icon_name);
+ g_free (self->label);
+
+ G_OBJECT_CLASS (gtk_hdy_view_switcher_button_parent_class)->finalize (object);
+}
+
+static void
+gtk_hdy_view_switcher_button_class_init (GtkHdyViewSwitcherButtonClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = gtk_hdy_view_switcher_button_get_property;
+ object_class->set_property = gtk_hdy_view_switcher_button_set_property;
+ object_class->finalize = gtk_hdy_view_switcher_button_finalize;
+
+ g_object_class_override_property (object_class,
+ PROP_LABEL,
+ "label");
+
+ g_object_class_override_property (object_class,
+ PROP_ORIENTATION,
+ "orientation");
+
+ /**
+ * GtkHdyViewSwitcherButton:icon-name:
+ *
+ * The icon name representing the view, or %NULL for no icon.
+ *
+ * Since: 0.0.10
+ */
+ props[PROP_ICON_NAME] =
+ g_param_spec_string ("icon-name",
+ _("Icon Name"),
+ _("Icon name for image"),
+ "text-x-generic-symbolic",
+ G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE);
+
+ /**
+ * GtkHdyViewSwitcherButton:icon-size:
+ *
+ * The icon size.
+ *
+ * Since: 0.0.10
+ */
+ props[PROP_ICON_SIZE] =
+ g_param_spec_int ("icon-size",
+ _("Icon Size"),
+ _("Symbolic size to use for named icon"),
+ 0, G_MAXINT, GTK_ICON_SIZE_BUTTON,
+ G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE);
+
+ /**
+ * GtkHdyViewSwitcherButton:needs-attention:
+ *
+ * Sets a flag specifying whether the view requires the user attention. This
+ * is used by the GtkHdyViewSwitcher to change the appearance of the
+ * corresponding button when a view needs attention and it is not the current
+ * one.
+ *
+ * Since: 0.0.10
+ */
+ props[PROP_NEEDS_ATTENTION] =
+ g_param_spec_boolean ("needs-attention",
+ _("Needs attention"),
+ _("Hint the view needs attention"),
+ FALSE,
+ G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE);
+
+ g_object_class_install_properties (object_class, LAST_PROP, props);
+
+ /* We probably should set the class's CSS name to "viewswitcherbutton"
+ * here, but it doesn't work because GtkCheckButton hardcodes it to "button"
+ * on instantiation, and the functions required to override it are private.
+ * In the meantime, we can use the "viewswitcher > button" CSS selector as
+ * a fairly safe fallback.
+ */
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gtk/libgtk/ui/hdy-view-switcher-button.ui");
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherButton, horizontal_box);
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherButton, horizontal_image);
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherButton, horizontal_label_active);
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherButton, horizontal_label_inactive);
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherButton, horizontal_label_stack);
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherButton, stack);
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherButton, vertical_box);
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherButton, vertical_image);
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherButton, vertical_label_active);
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherButton, vertical_label_inactive);
+ gtk_widget_class_bind_template_child (widget_class, GtkHdyViewSwitcherButton, vertical_label_stack);
+ gtk_widget_class_bind_template_callback (widget_class, on_active_changed);
+}
+
+static void
+gtk_hdy_view_switcher_button_init (GtkHdyViewSwitcherButton *self)
+{
+ self->icon_size = GTK_ICON_SIZE_BUTTON;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_stack_set_visible_child (GTK_STACK (self->stack), GTK_WIDGET (self->horizontal_box));
+
+ gtk_widget_set_focus_on_click (GTK_WIDGET (self), FALSE);
+ /* Make the button look like a regular button and not a radio button. */
+ gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (self), FALSE);
+
+ on_active_changed (self);
+}
+
+/**
+ * gtk_hdy_view_switcher_button_new:
+ *
+ * Creates a new #GtkHdyViewSwitcherButton widget.
+ *
+ * Returns: a new #GtkHdyViewSwitcherButton
+ *
+ * Since: 0.0.10
+ */
+GtkWidget *
+gtk_hdy_view_switcher_button_new (void)
+{
+ return g_object_new (GTK_TYPE_HDY_VIEW_SWITCHER_BUTTON, NULL);
+}
+
+/**
+ * gtk_hdy_view_switcher_button_get_icon_name:
+ * @self: a #GtkHdyViewSwitcherButton
+ *
+ * Gets the icon name representing the view, or %NULL is no icon is set.
+ *
+ * Returns: (transfer none) (nullable): the icon name, or %NULL
+ *
+ * Since: 0.0.10
+ **/
+const gchar *
+gtk_hdy_view_switcher_button_get_icon_name (GtkHdyViewSwitcherButton *self)
+{
+ g_return_val_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self), NULL);
+
+ return self->icon_name;
+}
+
+/**
+ * gtk_hdy_view_switcher_button_set_icon_name:
+ * @self: a #GtkHdyViewSwitcherButton
+ * @icon_name: (nullable): an icon name or %NULL
+ *
+ * Sets the icon name representing the view, or %NULL to disable the icon.
+ *
+ * Since: 0.0.10
+ **/
+void
+gtk_hdy_view_switcher_button_set_icon_name (GtkHdyViewSwitcherButton *self,
+ const gchar *icon_name)
+{
+ g_return_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self));
+
+ if (!g_strcmp0 (self->icon_name, icon_name))
+ return;
+
+ g_free (self->icon_name);
+ self->icon_name = g_strdup (icon_name);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_NAME]);
+}
+
+/**
+ * gtk_hdy_view_switcher_button_get_icon_size:
+ * @self: a #GtkHdyViewSwitcherButton
+ *
+ * Gets the icon size used by @self.
+ *
+ * Returns: the icon size used by @self
+ *
+ * Since: 0.0.10
+ **/
+GtkIconSize
+gtk_hdy_view_switcher_button_get_icon_size (GtkHdyViewSwitcherButton *self)
+{
+ g_return_val_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self), GTK_ICON_SIZE_INVALID);
+
+ return self->icon_size;
+}
+
+/**
+ * gtk_hdy_view_switcher_button_set_icon_size:
+ * @self: a #GtkHdyViewSwitcherButton
+ * @icon_size: the new icon size
+ *
+ * Sets the icon size used by @self.
+ *
+ * Since: 0.0.10
+ */
+void
+gtk_hdy_view_switcher_button_set_icon_size (GtkHdyViewSwitcherButton *self,
+ GtkIconSize icon_size)
+{
+ g_return_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self));
+
+ if (self->icon_size == icon_size)
+ return;
+
+ self->icon_size = icon_size;
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_SIZE]);
+}
+
+/**
+ * gtk_hdy_view_switcher_button_get_needs_attention:
+ * @self: a #GtkHdyViewSwitcherButton
+ *
+ * Gets whether the view represented by @self requires the user attention.
+ *
+ * Returns: %TRUE if the view represented by @self requires the user attention, %FALSE otherwise
+ *
+ * Since: 0.0.10
+ **/
+gboolean
+gtk_hdy_view_switcher_button_get_needs_attention (GtkHdyViewSwitcherButton *self)
+{
+ GtkStyleContext *context;
+
+ g_return_val_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self), FALSE);
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (self));
+
+ return gtk_style_context_has_class (context, GTK_STYLE_CLASS_NEEDS_ATTENTION);
+}
+
+/**
+ * gtk_hdy_view_switcher_button_set_needs_attention:
+ * @self: a #GtkHdyViewSwitcherButton
+ * @needs_attention: the new icon size
+ *
+ * Sets whether the view represented by @self requires the user attention.
+ *
+ * Since: 0.0.10
+ */
+void
+gtk_hdy_view_switcher_button_set_needs_attention (GtkHdyViewSwitcherButton *self,
+ gboolean needs_attention)
+{
+ GtkStyleContext *context;
+
+ g_return_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self));
+
+ needs_attention = !!needs_attention;
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (self));
+ if (gtk_style_context_has_class (context, GTK_STYLE_CLASS_NEEDS_ATTENTION) == needs_attention)
+ return;
+
+ if (needs_attention)
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_NEEDS_ATTENTION);
+ else
+ gtk_style_context_remove_class (context, GTK_STYLE_CLASS_NEEDS_ATTENTION);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_NEEDS_ATTENTION]);
+}
+
+/**
+ * gtk_hdy_view_switcher_button_get_label:
+ * @self: a #GtkHdyViewSwitcherButton
+ *
+ * Gets the label representing the view.
+ *
+ * Returns: (transfer none) (nullable): the label, or %NULL
+ *
+ * Since: 0.0.10
+ **/
+const gchar *
+gtk_hdy_view_switcher_button_get_label (GtkHdyViewSwitcherButton *self)
+{
+ g_return_val_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self), NULL);
+
+ return self->label;
+}
+
+/**
+ * gtk_hdy_view_switcher_button_set_label:
+ * @self: a #GtkHdyViewSwitcherButton
+ * @label: (nullable): a label or %NULL
+ *
+ * Sets the label representing the view.
+ *
+ * Since: 0.0.10
+ **/
+void
+gtk_hdy_view_switcher_button_set_label (GtkHdyViewSwitcherButton *self,
+ const gchar *label)
+{
+ g_return_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self));
+
+ if (!g_strcmp0 (self->label, label))
+ return;
+
+ g_free (self->label);
+ self->label = g_strdup (label);
+
+ g_object_notify (G_OBJECT (self), "label");
+}
+
+/**
+ * gtk_hdy_view_switcher_button_set_narrow_ellipsize:
+ * @self: a #GtkHdyViewSwitcherButton
+ * @mode: a #PangoEllipsizeMode
+ *
+ * Set the mode used to ellipsize the text in narrow mode if there is not
+ * enough space to render the entire string.
+ *
+ * Since: 0.0.10
+ **/
+void
+gtk_hdy_view_switcher_button_set_narrow_ellipsize (GtkHdyViewSwitcherButton *self,
+ PangoEllipsizeMode mode)
+{
+ g_return_if_fail (GTK_IS_HDY_VIEW_SWITCHER_BUTTON (self));
+ g_return_if_fail (mode >= PANGO_ELLIPSIZE_NONE && mode <= PANGO_ELLIPSIZE_END);
+
+ gtk_label_set_ellipsize (self->vertical_label_active, mode);
+ gtk_label_set_ellipsize (self->vertical_label_inactive, mode);
+}
+
+/**
+ * gtk_hdy_view_switcher_button_get_size:
+ * @self: a #GtkHdyViewSwitcherButton
+ * @h_min_width: (out) (nullable): the minimum width when horizontal
+ * @h_nat_width: (out) (nullable): the natural width when horizontal
+ * @v_min_width: (out) (nullable): the minimum width when vertical
+ * @v_nat_width: (out) (nullable): the natural width when vertical
+ *
+ * Measure the size requests in both horizontal and vertical modes.
+ *
+ * Since: 0.0.10
+ */
+void
+gtk_hdy_view_switcher_button_get_size (GtkHdyViewSwitcherButton *self,
+ gint *h_min_width,
+ gint *h_nat_width,
+ gint *v_min_width,
+ gint *v_nat_width)
+{
+ GtkStyleContext *context;
+ GtkStateFlags state;
+ GtkBorder border;
+
+ /* gtk_widget_get_preferred_width() doesn't accept both its out parameters to
+ * be NULL, so we must have guards.
+ */
+ if (h_min_width != NULL || h_nat_width != NULL)
+ gtk_widget_get_preferred_width (GTK_WIDGET (self->horizontal_box), h_min_width, h_nat_width);
+ if (v_min_width != NULL || v_nat_width != NULL)
+ gtk_widget_get_preferred_width (GTK_WIDGET (self->vertical_box), v_min_width, v_nat_width);
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (self));
+ state = gtk_style_context_get_state (context);
+ gtk_style_context_get_border (context, state, &border);
+ if (h_min_width != NULL)
+ *h_min_width += border.left + border.right;
+ if (h_nat_width != NULL)
+ *h_nat_width += border.left + border.right;
+ if (v_min_width != NULL)
+ *v_min_width += border.left + border.right;
+ if (v_nat_width != NULL)
+ *v_nat_width += border.left + border.right;
+}
diff --git a/gtk/meson.build b/gtk/meson.build
index 4b7a453..38b810c 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -383,6 +383,7 @@ gtk_sources = files(
'gtkwin32draw.c',
'gtkwin32theme.c',
'gdkpixbufutils.c',
+ 'hdy-view-switcher-button.c',
'language-names.c',
'script-names.c',
)
@@ -390,6 +391,7 @@ gtk_sources = files(
gtk_private_type_headers = files(
'gtkcsstypesprivate.h',
'gtktexthandleprivate.h',
+ 'hdy-view-switcher-button-private.h',
)
gtk_gir_public_headers = files(
diff --git a/gtk/ui/hdy-view-switcher-button.ui b/gtk/ui/hdy-view-switcher-button.ui
new file mode 100644
index 0000000..6e437dc
--- /dev/null
+++ b/gtk/ui/hdy-view-switcher-button.ui
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <template class="GtkHdyViewSwitcherButton" parent="GtkRadioButton">
+ <signal name="notify::active" handler="on_active_changed" after="yes"/>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hhomogeneous">False</property>
+ <property name="transition-type">crossfade</property>
+ <property name="vhomogeneous">True</property>
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkBox" id="horizontal_box">
+ <property name="halign">center</property>
+ <property name="orientation">horizontal</property>
+ <property name="spacing">8</property>
+ <property name="valign">center</property>
+ <property name="visible">True</property>
+ <style>
+ <class name="wide"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="horizontal_image">
+ <property name="icon-name" bind-source="GtkHdyViewSwitcherButton" bind-property="icon-name" bind-flags="sync-create" />
+ <property name="icon-size" bind-source="GtkHdyViewSwitcherButton" bind-property="icon-size" bind-flags="sync-create" />
+ <property name="visible">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="horizontal_label_stack">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="horizontal_label_inactive">
+ <property name="label" bind-source="GtkHdyViewSwitcherButton" bind-property="label" bind-flags="sync-create|bidirectional" />
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">inactive</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="horizontal_label_active">
+ <property name="label" bind-source="GtkHdyViewSwitcherButton" bind-property="label" bind-flags="sync-create|bidirectional" />
+ <property name="visible">True</property>
+ <style>
+ <class name="active"/>
+ </style>
+ </object>
+ <packing>
+ <property name="name">active</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="vertical_box">
+ <property name="halign">center</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">4</property>
+ <property name="valign">center</property>
+ <property name="visible">True</property>
+ <style>
+ <class name="narrow"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="vertical_image">
+ <property name="icon-name" bind-source="GtkHdyViewSwitcherButton" bind-property="icon-name" bind-flags="sync-create" />
+ <property name="icon-size" bind-source="GtkHdyViewSwitcherButton" bind-property="icon-size" bind-flags="sync-create" />
+ <property name="visible">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="vertical_label_stack">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="vertical_label_inactive">
+ <property name="label" bind-source="GtkHdyViewSwitcherButton" bind-property="label" bind-flags="sync-create|bidirectional" />
+ <property name="visible">True</property>
+ </object>
+ <packing>
+ <property name="name">inactive</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="vertical_label_active">
+ <property name="label" bind-source="GtkHdyViewSwitcherButton" bind-property="label" bind-flags="sync-create|bidirectional" />
+ <property name="visible">True</property>
+ <style>
+ <class name="active"/>
+ </style>
+ </object>
+ <packing>
+ <property name="name">active</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>