[libadwaita/wip/exalm/borderless: 1/13] Add AdwButtonContent
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libadwaita/wip/exalm/borderless: 1/13] Add AdwButtonContent
- Date: Wed, 8 Sep 2021 12:03:17 +0000 (UTC)
commit e5d3c058e4c9f5bdf65292bb6da0bdff508ae602
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Fri Sep 3 15:28:46 2021 +0500
Add AdwButtonContent
We're going to use buttons that use icon+label more commonly, so we need
a nice way to create them.
Unfortunately for technical reasons we can't reuse .icon-button.text-button
style classes, so we'll have to roll our own .image-text-button. We also
still have to add a style class on a button so that later we can know to
flatten these buttons.
Update the existing .icon-button.text-button style as well.
src/adw-button-content.c | 433 +++++++++++++++++++++++++++++++++++
src/adw-button-content.h | 47 ++++
src/adwaita.h | 1 +
src/meson.build | 2 +
src/stylesheet/widgets/_buttons.scss | 46 +++-
tests/meson.build | 1 +
tests/test-button-content.c | 165 +++++++++++++
7 files changed, 686 insertions(+), 9 deletions(-)
---
diff --git a/src/adw-button-content.c b/src/adw-button-content.c
new file mode 100644
index 00000000..828992ea
--- /dev/null
+++ b/src/adw-button-content.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2021 Purism SPC
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Author: Alexander Mikhaylenko <alexander mikhaylenko puri sm>
+ */
+
+#include "config.h"
+#include "adw-button-content.h"
+
+#include "adw-split-button.h"
+
+/**
+ * AdwButtonContent:
+ *
+ * A helper widget for creating buttons.
+ *
+ * `AdwButtonContent` is a box-like widget with an icon and a label.
+ *
+ * It's intended to be used as a direct child of [class@Gtk.Button],
+ * [class@Gtk.MenuButton] or [class@Adw.SplitButton], when they need to habe
+ * both an icon and a label, as follows:
+ *
+ * ```xml
+ * <object class="GtkButton">
+ * <property name="child">
+ * <object class="AdwButtonContent">
+ * <property name="icon-name">document-open-symbolic</property>
+ * <property name="label" translatable="yes">_Open</property>
+ * <property name="use-underline">True</property>
+ * </object>
+ * </property>
+ * </object>
+ * ```
+ *
+ * `AdwButtonContent` handles style classes and connecting the mnemonic to the
+ * button automatically.
+ *
+ * ## CSS nodes
+ *
+ * ```
+ * buttoncontent
+ * ├── image
+ * ╰── label
+ * ```
+ *
+ * `AdwSplitButton`'s CSS node is called `buttoncontent`. It contains the
+ * subnodes `image` and `label`.
+ *
+ * When inside a `GtkButton` or `AdwSplitButton`, the button will receive the
+ * `.image-text-button` style class. When inside a `GtkMenuButton`, the
+ * internal `GtkButton` will receive it instead.
+ *
+ * ## Accessibility
+ *
+ * `AdwSplitButton` uses the `GTK_ACCESSIBLE_ROLE_GROUP` role.
+ *
+ * Since: 1.0
+ */
+
+struct _AdwButtonContent {
+ GtkWidget parent_instance;
+
+ GtkWidget *icon;
+ GtkWidget *label;
+
+ char *icon_name;
+
+ GtkWidget *button;
+};
+
+G_DEFINE_TYPE (AdwButtonContent, adw_button_content, GTK_TYPE_WIDGET)
+
+enum {
+ PROP_0,
+ PROP_ICON_NAME,
+ PROP_LABEL,
+ PROP_USE_UNDERLINE,
+ LAST_PROP
+};
+
+static GParamSpec *props[LAST_PROP];
+
+static inline GtkWidget *
+find_parent_button (AdwButtonContent *self)
+{
+ return gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_BUTTON);
+}
+
+static void
+adw_button_content_root (GtkWidget *widget)
+{
+ AdwButtonContent *self = ADW_BUTTON_CONTENT (widget);
+
+ GTK_WIDGET_CLASS (adw_button_content_parent_class)->root (widget);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (self->label),
+ find_parent_button (self));
+
+ self->button = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_BUTTON);
+
+ /* For AdwSplitButton we want to style the split button widget and not the
+ * button inside. */
+ if (ADW_IS_SPLIT_BUTTON (gtk_widget_get_parent (self->button)))
+ self->button = gtk_widget_get_parent (self->button);
+
+ gtk_widget_add_css_class (self->button, "image-text-button");
+}
+
+static void
+adw_button_content_unroot (GtkWidget *widget)
+{
+ AdwButtonContent *self = ADW_BUTTON_CONTENT (widget);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (self->label), NULL);
+
+ if (self->button) {
+ gtk_widget_remove_css_class (self->button, "image-text-button");
+
+ self->button = NULL;
+ }
+
+ GTK_WIDGET_CLASS (adw_button_content_parent_class)->unroot (widget);
+}
+
+static void
+adw_button_content_dispose (GObject *object)
+{
+ AdwButtonContent *self = ADW_BUTTON_CONTENT (object);
+
+ g_clear_pointer (&self->icon, gtk_widget_unparent);
+ g_clear_pointer (&self->label, gtk_widget_unparent);
+
+ G_OBJECT_CLASS (adw_button_content_parent_class)->dispose (object);
+}
+
+static void
+adw_button_content_finalize (GObject *object)
+{
+ AdwButtonContent *self = ADW_BUTTON_CONTENT (object);
+
+ g_clear_pointer (&self->icon_name, g_free);
+
+ G_OBJECT_CLASS (adw_button_content_parent_class)->finalize (object);
+}
+
+static void
+adw_button_content_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AdwButtonContent *self = ADW_BUTTON_CONTENT (object);
+
+ switch (prop_id) {
+ case PROP_ICON_NAME:
+ g_value_set_string (value, adw_button_content_get_icon_name (self));
+ break;
+ case PROP_LABEL:
+ g_value_set_string (value, adw_button_content_get_label (self));
+ break;
+ case PROP_USE_UNDERLINE:
+ g_value_set_boolean (value, adw_button_content_get_use_underline (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+adw_button_content_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AdwButtonContent *self = ADW_BUTTON_CONTENT (object);
+
+ switch (prop_id) {
+ case PROP_ICON_NAME:
+ adw_button_content_set_icon_name (self, g_value_get_string (value));
+ break;
+ case PROP_LABEL:
+ adw_button_content_set_label (self, g_value_get_string (value));
+ break;
+ case PROP_USE_UNDERLINE:
+ adw_button_content_set_use_underline (self, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+adw_button_content_class_init (AdwButtonContentClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = adw_button_content_dispose;
+ object_class->finalize = adw_button_content_finalize;
+ object_class->get_property = adw_button_content_get_property;
+ object_class->set_property = adw_button_content_set_property;
+
+ widget_class->root = adw_button_content_root;
+ widget_class->unroot = adw_button_content_unroot;
+
+ /**
+ * AdwButtonContent:icon-name: (attributes org.gtk.Property.get=adw_button_content_get_icon_name
org.gtk.Property.set=adw_button_content_set_icon_name)
+ *
+ * The name of the displayed icon.
+ *
+ * If empty, the icon is not shown.
+ *
+ * Since: 1.0
+ */
+ props[PROP_ICON_NAME] =
+ g_param_spec_string ("icon-name",
+ "Icon name",
+ "The name of the displayed icon",
+ "",
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * AdwButtonContent:label: (attributes org.gtk.Property.get=adw_button_content_get_label
org.gtk.Property.set=adw_button_content_set_label)
+ *
+ * The displayed label.
+ *
+ * Since: 1.0
+ */
+ props[PROP_LABEL] =
+ g_param_spec_string ("label",
+ "Label",
+ "The displayed label",
+ "",
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * AdwButtonContent:use-underline: (attributes org.gtk.Property.get=adw_button_content_get_use_underline
org.gtk.Property.set=adw_button_content_set_use_underline)
+ *
+ * Whether an underline in the text indicates a mnemonic.
+ *
+ * The mnemonic can be used to activate the parent button.
+ *
+ * See [property@Adw.ButtonContent:label].
+ *
+ * Since: 1.0
+ */
+ props[PROP_USE_UNDERLINE] =
+ g_param_spec_boolean ("use-underline",
+ "Use underline",
+ "Whether an underline in the text indicates a mnemonic",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties (object_class, LAST_PROP, props);
+
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
+ gtk_widget_class_set_css_name (widget_class, "buttoncontent");
+ gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GROUP);
+}
+
+static void
+adw_button_content_init (AdwButtonContent *self)
+{
+ self->icon_name = g_strdup ("");
+
+ gtk_widget_set_hexpand (GTK_WIDGET (self), FALSE);
+
+ self->icon = g_object_new (GTK_TYPE_IMAGE,
+ "accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION,
+ NULL);
+ gtk_image_set_from_icon_name (GTK_IMAGE (self->icon), "image-missing");
+ gtk_widget_set_valign (self->icon, GTK_ALIGN_CENTER);
+ gtk_widget_set_hexpand (self->icon, TRUE);
+
+ self->label = gtk_label_new (NULL);
+ gtk_widget_set_hexpand (self->label, TRUE);
+ gtk_widget_hide (self->label);
+
+ gtk_widget_set_parent (self->icon, GTK_WIDGET (self));
+ gtk_widget_set_parent (self->label, GTK_WIDGET (self));
+}
+
+/**
+ * adw_button_content_new:
+ *
+ * Creates a new `AdwButtonContent`.
+ *
+ * Returns: the new created `AdwButtonContent`
+ *
+ * Since: 1.0
+ */
+GtkWidget *
+adw_button_content_new (void)
+{
+ return g_object_new (ADW_TYPE_BUTTON_CONTENT, NULL);
+}
+
+/**
+ * adw_button_content_get_icon_name: (attributes org.gtk.Method.get_property=icon-name)
+ * @self: a `AdwButtonContent`
+ *
+ * Gets the name of the displayed icon.
+ *
+ * Returns: the icon name
+ *
+ * Since: 1.0
+ */
+const char *
+adw_button_content_get_icon_name (AdwButtonContent *self)
+{
+ g_return_val_if_fail (ADW_IS_BUTTON_CONTENT (self), NULL);
+
+ return self->icon_name;
+}
+
+/**
+ * adw_button_content_set_icon_name: (attributes org.gtk.Method.set_property=icon-name)
+ * @self: a `AdwButtonContent`
+ * @icon_name: the new icon name
+ *
+ * Sets the name of the displayed icon.
+ *
+ * Since: 1.0
+ */
+void
+adw_button_content_set_icon_name (AdwButtonContent *self,
+ const char *icon_name)
+{
+ g_return_if_fail (ADW_IS_BUTTON_CONTENT (self));
+ g_return_if_fail (icon_name != NULL);
+
+ if (!g_strcmp0 (icon_name, adw_button_content_get_icon_name (self)))
+ return;
+
+ g_free (self->icon_name);
+ icon_name = g_strdup (icon_name);
+
+ if (!icon_name[0])
+ icon_name = "image-missing";
+
+ gtk_image_set_from_icon_name (GTK_IMAGE (self->icon), icon_name);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_NAME]);
+}
+
+/**
+ * adw_button_content_get_label: (attributes org.gtk.Method.get_property=label)
+ * @self: a `AdwButtonContent`
+ *
+ * Gets the displayed label.
+ *
+ * Returns: the label
+ *
+ * Since: 1.0
+ */
+const char *
+adw_button_content_get_label (AdwButtonContent *self)
+{
+ g_return_val_if_fail (ADW_IS_BUTTON_CONTENT (self), NULL);
+
+ return gtk_label_get_label (GTK_LABEL (self->label));
+}
+
+/**
+ * adw_button_content_set_label: (attributes org.gtk.Method.set_property=label)
+ * @self: a `AdwButtonContent`
+ * @label: the new label
+ *
+ * Sets the displayed label.
+ *
+ * Since: 1.0
+ */
+void
+adw_button_content_set_label (AdwButtonContent *self,
+ const char *label)
+{
+ g_return_if_fail (ADW_IS_BUTTON_CONTENT (self));
+ g_return_if_fail (label != NULL);
+
+ if (!g_strcmp0 (label, adw_button_content_get_label (self)))
+ return;
+
+ gtk_label_set_label (GTK_LABEL (self->label), label);
+
+ gtk_widget_set_visible (self->label, label[0]);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LABEL]);
+}
+
+/**
+ * adw_button_content_get_use_underline: (attributes org.gtk.Method.get_property=use-underline)
+ * @self: a `AdwButtonContent`
+ *
+ * Gets whether an underline in the text indicates a mnemonic.
+ *
+ * Returns: whether an underline in the text indicates a mnemonic
+ *
+ * Since: 1.0
+ */
+gboolean
+adw_button_content_get_use_underline (AdwButtonContent *self)
+{
+ g_return_val_if_fail (ADW_IS_BUTTON_CONTENT (self), FALSE);
+
+ return gtk_label_get_use_underline (GTK_LABEL (self->label));
+}
+
+/**
+ * adw_button_content_set_use_underline: (attributes org.gtk.Method.set_property=use-underline)
+ * @self: a `AdwButtonContent`
+ * @use_underline: whether an underline in the text indicates a mnemonic
+ *
+ * Sets whether an underline in the text indicates a mnemonic.
+ *
+ * Since: 1.0
+ */
+void
+adw_button_content_set_use_underline (AdwButtonContent *self,
+ gboolean use_underline)
+{
+ g_return_if_fail (ADW_IS_BUTTON_CONTENT (self));
+
+ use_underline = !!use_underline;
+
+ if (use_underline == adw_button_content_get_use_underline (self))
+ return;
+
+ gtk_label_set_use_underline (GTK_LABEL (self->label), use_underline);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_UNDERLINE]);
+}
diff --git a/src/adw-button-content.h b/src/adw-button-content.h
new file mode 100644
index 00000000..639c2c14
--- /dev/null
+++ b/src/adw-button-content.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 Purism SPC
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Author: Alexander Mikhaylenko <alexander mikhaylenko puri sm>
+ */
+
+#pragma once
+
+#if !defined(_ADWAITA_INSIDE) && !defined(ADWAITA_COMPILATION)
+#error "Only <adwaita.h> can be included directly."
+#endif
+
+#include "adw-version.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_BUTTON_CONTENT (adw_button_content_get_type())
+
+ADW_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (AdwButtonContent, adw_button_content, ADW, BUTTON_CONTENT, GtkWidget)
+
+ADW_AVAILABLE_IN_ALL
+GtkWidget *adw_button_content_new (void) G_GNUC_WARN_UNUSED_RESULT;
+
+ADW_AVAILABLE_IN_ALL
+const char *adw_button_content_get_label (AdwButtonContent *self);
+ADW_AVAILABLE_IN_ALL
+void adw_button_content_set_label (AdwButtonContent *self,
+ const char *label);
+
+ADW_AVAILABLE_IN_ALL
+const char *adw_button_content_get_icon_name (AdwButtonContent *self);
+ADW_AVAILABLE_IN_ALL
+void adw_button_content_set_icon_name (AdwButtonContent *self,
+ const char *icon_name);
+
+ADW_AVAILABLE_IN_ALL
+gboolean adw_button_content_get_use_underline (AdwButtonContent *self);
+ADW_AVAILABLE_IN_ALL
+void adw_button_content_set_use_underline (AdwButtonContent *self,
+ gboolean use_underline);
+
+G_END_DECLS
diff --git a/src/adwaita.h b/src/adwaita.h
index 82a55c48..2de16a19 100644
--- a/src/adwaita.h
+++ b/src/adwaita.h
@@ -27,6 +27,7 @@ G_BEGIN_DECLS
#include "adw-application-window.h"
#include "adw-avatar.h"
#include "adw-bin.h"
+#include "adw-button-content.h"
#include "adw-carousel.h"
#include "adw-carousel-indicator-dots.h"
#include "adw-carousel-indicator-lines.h"
diff --git a/src/meson.build b/src/meson.build
index f32a00d8..9feba8bf 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -74,6 +74,7 @@ src_headers = [
'adw-application-window.h',
'adw-avatar.h',
'adw-bin.h',
+ 'adw-button-content.h',
'adw-carousel.h',
'adw-carousel-indicator-dots.h',
'adw-carousel-indicator-lines.h',
@@ -129,6 +130,7 @@ src_sources = [
'adw-avatar.c',
'adw-bidi.c',
'adw-bin.c',
+ 'adw-button-content.c',
'adw-carousel.c',
'adw-carousel-indicator-dots.c',
'adw-carousel-indicator-lines.c',
diff --git a/src/stylesheet/widgets/_buttons.scss b/src/stylesheet/widgets/_buttons.scss
index 6a8aa894..473fb4de 100644
--- a/src/stylesheet/widgets/_buttons.scss
+++ b/src/stylesheet/widgets/_buttons.scss
@@ -62,13 +62,19 @@ button {
padding-right: 17px;
}
- &.text-button.image-button {
- padding-left: 9px;
- padding-right: 9px;
+ &.text-button.image-button,
+ &.image-text-button {
+ padding-left: 10px;
+ padding-right: 10px;
- label {
- padding-left: 8px;
- padding-right: 8px;
+ > box,
+ > box > box {
+ border-spacing: 4px;
+
+ > label {
+ padding-left: 2px;
+ padding-right: 2px;
+ }
}
}
@@ -76,8 +82,10 @@ button {
padding-left: 10px;
padding-right: 10px;
- > box {
- border-spacing: 4px;
+ > box { border-spacing: 4px; }
+
+ &.text-button {
+ > box { border-spacing: 4px; }
}
}
@@ -408,7 +416,8 @@ splitbutton {
padding-right: 5px;
}
- &.text-button.image-button > button {
+ &.text-button.image-button > button,
+ &.image-text-button > button {
padding-left: 10px;
padding-right: 10px;
@@ -503,3 +512,22 @@ splitbutton {
-gtk-icon-source: -gtk-icontheme('pan-down-symbolic');
}
}
+
+buttoncontent {
+ border-spacing: 6px;
+
+ > label {
+ font-weight: bold;
+
+ &:dir(ltr) { padding-right: 2px; }
+ &:dir(rtl) { padding-left: 2px; }
+ }
+
+ .arrow-button > box > &,
+ splitbutton > button > & {
+ > label {
+ &:dir(ltr) { padding-right: 0; }
+ &:dir(rtl) { padding-left: 0; }
+ }
+ }
+}
diff --git a/tests/meson.build b/tests/meson.build
index 895d13a0..43f908b8 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -24,6 +24,7 @@ test_names = [
'test-application-window',
'test-avatar',
'test-bin',
+ 'test-button-content',
'test-carousel',
'test-carousel-indicator-dots',
'test-carousel-indicator-lines',
diff --git a/tests/test-button-content.c b/tests/test-button-content.c
new file mode 100644
index 00000000..0a8fecad
--- /dev/null
+++ b/tests/test-button-content.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2021 Purism SPC
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Author: Alexander Mikhaylenko <alexander mikhaylenko puri sm>
+ */
+
+#include <adwaita.h>
+
+int notified;
+
+static void
+notify_cb (GtkWidget *widget, gpointer data)
+{
+ notified++;
+}
+
+static void
+test_adw_button_content_icon_name (void)
+{
+ g_autoptr (AdwButtonContent) content = NULL;
+ const char *icon_name;
+
+ content = g_object_ref_sink (ADW_BUTTON_CONTENT (adw_button_content_new ()));
+ g_assert_nonnull (content);
+
+ notified = 0;
+ g_signal_connect (content, "notify::icon-name", G_CALLBACK (notify_cb), NULL);
+
+ g_object_get (content, "icon-name", &icon_name, NULL);
+ g_assert_cmpstr (icon_name, ==, "");
+
+ adw_button_content_set_icon_name (content, "");
+ g_assert_cmpint (notified, ==, 0);
+
+
+ adw_button_content_set_icon_name (content, "document-open-symbolic");
+ g_assert_cmpstr (adw_button_content_get_icon_name (content), ==, "document-open-symbolic");
+ g_assert_cmpint (notified, ==, 1);
+
+ g_object_set (content, "icon-name", "", NULL);
+ g_assert_cmpstr (adw_button_content_get_icon_name (content), ==, "");
+ g_assert_cmpint (notified, ==, 2);
+}
+
+static void
+test_adw_button_content_label (void)
+{
+ g_autoptr (AdwButtonContent) content = NULL;
+ const char *label;
+
+ content = g_object_ref_sink (ADW_BUTTON_CONTENT (adw_button_content_new ()));
+ g_assert_nonnull (content);
+
+ notified = 0;
+ g_signal_connect (content, "notify::label", G_CALLBACK (notify_cb), NULL);
+
+ g_object_get (content, "label", &label, NULL);
+ g_assert_cmpstr (label, ==, "");
+
+ adw_button_content_set_label (content, "");
+ g_assert_cmpint (notified, ==, 0);
+
+
+ adw_button_content_set_label (content, "Open");
+ g_assert_cmpstr (adw_button_content_get_label (content), ==, "Open");
+ g_assert_cmpint (notified, ==, 1);
+
+ g_object_set (content, "label", "", NULL);
+ g_assert_cmpstr (adw_button_content_get_label (content), ==, "");
+ g_assert_cmpint (notified, ==, 2);
+}
+
+static void
+test_adw_button_content_use_underline (void)
+{
+ g_autoptr (AdwButtonContent) content = NULL;
+ gboolean use_underline;
+
+ content = g_object_ref_sink (ADW_BUTTON_CONTENT (adw_button_content_new ()));
+ g_assert_nonnull (content);
+
+ notified = 0;
+ g_signal_connect (content, "notify::use-underline", G_CALLBACK (notify_cb), NULL);
+
+ g_object_get (content, "use-underline", &use_underline, NULL);
+ g_assert_false (use_underline);
+
+ adw_button_content_set_use_underline (content, FALSE);
+ g_assert_cmpint (notified, ==, 0);
+
+
+ adw_button_content_set_use_underline (content, TRUE);
+ g_assert_true (adw_button_content_get_use_underline (content));
+ g_assert_cmpint (notified, ==, 1);
+
+ g_object_set (content, "use-underline", FALSE, NULL);
+ g_assert_false (adw_button_content_get_use_underline (content));
+ g_assert_cmpint (notified, ==, 2);
+}
+
+static void
+test_adw_button_content_style_class_button (void)
+{
+ g_autoptr (GtkWidget) window = NULL;
+ GtkWidget *button;
+ AdwButtonContent *content;
+
+ window = g_object_ref_sink (gtk_window_new ());
+
+ button = gtk_button_new ();
+ gtk_window_set_child (GTK_WINDOW (window), button);
+
+ gtk_window_present (GTK_WINDOW (window));
+
+ content = ADW_BUTTON_CONTENT (adw_button_content_new ());
+ g_assert_nonnull (content);
+
+ gtk_button_set_child (GTK_BUTTON (button), GTK_WIDGET (content));
+ g_assert_true (gtk_widget_has_css_class (button, "image-text-button"));
+
+ gtk_button_set_child (GTK_BUTTON (button), NULL);
+ g_assert_false (gtk_widget_has_css_class (button, "image-text-button"));
+}
+
+static void
+test_adw_button_content_style_class_split_button (void)
+{
+ g_autoptr (GtkWidget) window = NULL;
+ GtkWidget *button;
+ AdwButtonContent *content;
+
+ window = g_object_ref_sink (gtk_window_new ());
+
+ button = adw_split_button_new ();
+ gtk_window_set_child (GTK_WINDOW (window), button);
+
+ gtk_window_present (GTK_WINDOW (window));
+
+ content = ADW_BUTTON_CONTENT (adw_button_content_new ());
+ g_assert_nonnull (content);
+
+ adw_split_button_set_child (ADW_SPLIT_BUTTON (button), GTK_WIDGET (content));
+ g_assert_true (gtk_widget_has_css_class (button, "image-text-button"));
+
+ adw_split_button_set_child (ADW_SPLIT_BUTTON (button), NULL);
+ g_assert_false (gtk_widget_has_css_class (button, "image-text-button"));
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ gtk_test_init (&argc, &argv, NULL);
+ adw_init ();
+
+ g_test_add_func ("/Adwaita/ButtonContent/icon_name", test_adw_button_content_icon_name);
+ g_test_add_func ("/Adwaita/ButtonContent/label", test_adw_button_content_label);
+ g_test_add_func ("/Adwaita/ButtonContent/use_underline", test_adw_button_content_use_underline);
+ g_test_add_func ("/Adwaita/ButtonContent/style_class_button", test_adw_button_content_style_class_button);
+ g_test_add_func ("/Adwaita/ButtonContent/style_class_split_button",
test_adw_button_content_style_class_split_button);
+
+ return g_test_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]