[libadwaita/ebassi/tagged-entry: 1/2] Add AdwTaggedEntry
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libadwaita/ebassi/tagged-entry: 1/2] Add AdwTaggedEntry
- Date: Fri, 4 Feb 2022 14:13:16 +0000 (UTC)
commit 9a8ac6c5fcea2e83b27abaf1a4ef9f3c7efb55c7
Author: Emmanuele Bassi <ebassi gnome org>
Date: Fri Feb 4 14:09:08 2022 +0000
Add AdwTaggedEntry
A "tagged entry" is an entry widget that allows defining additional "tags"
to describe the contents of the entry. It can be used for showing
refinements to a search entry, or for introducing tags in a description
form.
Current existing users of this type of UI component are GNOME Photos,
Nautilus, and Epiphany; these projects use the tagged entry widget provided
by the copy-and-paste library "libgd".
src/adw-tagged-entry.c | 649 +++++++++++++++++++++++++++++++++++++++++++++++++
src/adw-tagged-entry.h | 66 +++++
src/adwaita.h | 1 +
src/meson.build | 2 +
4 files changed, 718 insertions(+)
---
diff --git a/src/adw-tagged-entry.c b/src/adw-tagged-entry.c
new file mode 100644
index 00000000..4f794b09
--- /dev/null
+++ b/src/adw-tagged-entry.c
@@ -0,0 +1,649 @@
+/* adw-tagged-entry.c: Tagged entry widget
+ *
+ * SPDX-FileCopyrightText: 2022 Emmanuele Bassi
+ * SPDX-FileCopyrightText: 2019 Matthias Clasen
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "adw-tagged-entry.h"
+
+/**
+ * AdwTag:
+ *
+ * A tag inside a tagged entry.
+ */
+struct _AdwTag
+{
+ GObject parent_instance;
+
+ AdwTaggedEntry *entry;
+
+ char *name;
+ char *label;
+
+ GtkWidget *tag;
+ GtkWidget *tag_label;
+ GtkWidget *tag_close;
+
+ gboolean show_close;
+};
+
+/**
+ * AdwTaggedEntry:
+ *
+ * An entry that allows you to have tags near the text.
+ *
+ * ## AdwTaggedEntry as GtkBuildable
+ *
+ * You can include tags directly inside the UI definition of a tagged entry
+ * by using the `<child>` element to add objects of type `AdwTag`; for
+ * instance, the following definition:
+ *
+ * ```xml
+ * <object class="AdwTaggedEntry">
+ * <child>
+ * <object class="AdwTag">
+ * <property name="name">first-tag</property>
+ * <property name="label">First Tag</property>
+ * <property name="show-close">False</property>
+ * </object>
+ * </child>
+ * </object>
+ * ```
+ *
+ * while create an `AdwTaggedEntry` with a single tag, whose label is set to
+ * "First Tag"; the tag will not have a "close" button.
+ *
+ * ## CSS nodes
+ *
+ * `AdwTaggedEntry` has a single CSS node with the name `entry` and the
+ * CSS class `tagged`.
+ */
+struct _AdwTaggedEntry
+{
+ GtkWidget parent_instance;
+
+ GtkWidget *text;
+ GtkWidget *tags_box;
+
+ GListModel *tags;
+};
+
+enum
+{
+ PROP_PLACEHOLDER_TEXT = 1,
+ N_PROPS
+};
+
+static void buildable_iface_init (GtkBuildableIface *iface);
+static void editable_iface_init (GtkEditableInterface *iface);
+
+static GtkBuildableIface *parent_buildable_iface;
+
+static GParamSpec *entry_props[N_PROPS];
+
+G_DEFINE_TYPE_WITH_CODE (AdwTaggedEntry, adw_tagged_entry, GTK_TYPE_WIDGET,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_iface_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, editable_iface_init))
+
+static GtkEditable *
+adw_tagged_entry_editable_get_delegate (GtkEditable *editable)
+{
+ AdwTaggedEntry *self = ADW_TAGGED_ENTRY (editable);
+
+ return GTK_EDITABLE (self->text);
+}
+
+static void
+editable_iface_init (GtkEditableInterface *iface)
+{
+ iface->get_delegate = adw_tagged_entry_editable_get_delegate;
+}
+
+static AdwTag *
+adw_tagged_entry_add_tag_internal (AdwTaggedEntry *self,
+ AdwTag *tag,
+ gboolean unref_tag)
+{
+ tag->entry = self;
+
+ g_list_store_append (G_LIST_STORE (self->tags), tag);
+
+ gtk_flow_box_append (GTK_FLOW_BOX (self->tags_box), tag->tag);
+
+ if (unref_tag)
+ g_object_unref (tag);
+
+ return tag;
+}
+
+static void
+adw_tagged_entry_buildable_add_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const char *type)
+{
+ if (ADW_IS_TAG (child)) {
+ adw_tagged_entry_add_tag_internal (ADW_TAGGED_ENTRY (buildable), ADW_TAG (child), FALSE);
+ } else {
+ parent_buildable_iface->add_child (buildable, builder, child, type);
+ }
+}
+
+static void
+buildable_iface_init (GtkBuildableIface *iface)
+{
+ parent_buildable_iface = g_type_interface_peek_parent (iface);
+
+ iface->add_child = adw_tagged_entry_buildable_add_child;
+}
+
+static void
+adw_tagged_entry_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AdwTaggedEntry *self = ADW_TAGGED_ENTRY (gobject);
+
+ if (gtk_editable_delegate_set_property (gobject, prop_id, value, pspec))
+ return;
+
+ switch (prop_id) {
+ case PROP_PLACEHOLDER_TEXT:
+ adw_tagged_entry_set_placeholder_text (self, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+adw_tagged_entry_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AdwTaggedEntry *self = ADW_TAGGED_ENTRY (gobject);
+
+ if (gtk_editable_delegate_get_property (gobject, prop_id, value, pspec))
+ return;
+
+ switch (prop_id) {
+ case PROP_PLACEHOLDER_TEXT:
+ g_value_set_string (value, adw_tagged_entry_get_placeholder_text (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+adw_tagged_entry_dispose (GObject *gobject)
+{
+ AdwTaggedEntry *self = ADW_TAGGED_ENTRY (gobject);
+
+ if (self->text != NULL)
+ gtk_editable_finish_delegate (GTK_EDITABLE (self));
+
+ adw_tagged_entry_remove_all_tags (self);
+
+ g_clear_object (&self->tags);
+
+ g_clear_pointer (&self->text, gtk_widget_unparent);
+ g_clear_pointer (&self->tags_box, gtk_widget_unparent);
+
+ G_OBJECT_CLASS (adw_tagged_entry_parent_class)->dispose (gobject);
+}
+
+static void
+adw_tagged_entry_class_init (AdwTaggedEntryClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gobject_class->set_property = adw_tagged_entry_set_property;
+ gobject_class->get_property = adw_tagged_entry_get_property;
+ gobject_class->dispose = adw_tagged_entry_dispose;
+
+ /**
+ * AdwTaggedEntry:placeholder-text:
+ *
+ * The text that will be displayed in the tagged entry when it is empty
+ * and unfocused.
+ */
+ entry_props[PROP_PLACEHOLDER_TEXT] =
+ g_param_spec_string ("placeholder-text", NULL, NULL,
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class, N_PROPS, entry_props);
+ gtk_editable_install_properties (gobject_class, N_PROPS);
+
+ gtk_widget_class_set_css_name (widget_class, "entry");
+ gtk_widget_class_set_layout_manager_type (GTK_WIDGET_CLASS (klass), GTK_TYPE_BOX_LAYOUT);
+ gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_TEXT_BOX);
+}
+
+static void
+adw_tagged_entry_init (AdwTaggedEntry *self)
+{
+ gtk_widget_add_css_class (GTK_WIDGET (self), "tagged");
+
+ g_type_ensure (ADW_TYPE_TAG);
+
+ self->text = gtk_text_new ();
+ gtk_widget_set_hexpand (self->text, TRUE);
+ gtk_widget_set_vexpand (self->text, TRUE);
+ gtk_widget_set_parent (self->text, GTK_WIDGET (self));
+ gtk_editable_init_delegate (GTK_EDITABLE (self));
+ gtk_editable_set_width_chars (GTK_EDITABLE (self->text), 12);
+ gtk_editable_set_max_width_chars (GTK_EDITABLE (self->text), 12);
+
+ self->tags_box = gtk_flow_box_new ();
+ gtk_flow_box_set_min_children_per_line (GTK_FLOW_BOX (self->tags_box), 4);
+ gtk_widget_set_parent (self->tags_box, GTK_WIDGET (self));
+ gtk_widget_add_css_class (self->tags_box, "tags");
+
+ self->tags = G_LIST_MODEL (g_list_store_new (ADW_TYPE_TAG));
+}
+
+/**
+ * adw_tagged_entry_new:
+ *
+ * Creates a new tagged entry widget.
+ *
+ * Returns: (transfer floating): the new tagged entry widget
+ */
+GtkWidget *
+adw_tagged_entry_new (void)
+{
+ return g_object_new (ADW_TYPE_TAGGED_ENTRY, NULL);
+}
+
+/**
+ * adw_tagged_entry_add_tag:
+ * @self: the tagged entry we want to update
+ * @name: the name of the tag we want to add
+ *
+ * Adds a new tag into the tagged entry for the given @name.
+ *
+ * Returns: (transfer none): the tag object
+ */
+AdwTag *
+adw_tagged_entry_add_tag (AdwTaggedEntry *self,
+ const char *name)
+{
+ g_return_val_if_fail (ADW_IS_TAGGED_ENTRY (self), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ guint n_tags = g_list_model_get_n_items (self->tags);
+ for (guint i = 0; i < n_tags; i++) {
+ g_autoptr(AdwTag) tag = g_list_model_get_item (self->tags, i);
+
+ if (g_str_equal (tag->name, name)) {
+ g_critical ("Tag ā%sā with label ā%sā already exists",
+ tag->name,
+ tag->label);
+ return NULL;
+ }
+ }
+
+ AdwTag *tag = g_object_new (ADW_TYPE_TAG, "name", name, NULL);
+
+ return adw_tagged_entry_add_tag_internal (self, tag, TRUE);
+}
+
+/**
+ * adw_tagged_entry_remove_tag:
+ * @self: the tagged entry we want to update
+ * @name: the name of the tag we want to remove
+ *
+ * Removes the given tag from the tagged entry.
+ */
+void
+adw_tagged_entry_remove_tag (AdwTaggedEntry *self,
+ const char *name)
+{
+ g_return_if_fail (ADW_IS_TAGGED_ENTRY (self));
+ g_return_if_fail (name != NULL);
+
+ guint n_tags = g_list_model_get_n_items (self->tags);
+ for (guint i = 0; i < n_tags; i++) {
+ g_autoptr(AdwTag) tag = g_list_model_get_item (self->tags, i);
+
+ if (g_str_equal (tag->name, name)) {
+ GtkWidget *parent = gtk_widget_get_parent (tag->tag);
+ gtk_flow_box_remove (GTK_FLOW_BOX (self->tags_box), parent);
+ g_list_store_remove (G_LIST_STORE (self->tags), i);
+ break;
+ }
+ }
+}
+
+/**
+ * adw_tagged_entry_get_tags:
+ * @self: the tagged entry we want to query
+ *
+ * Retrieves a list model of all tags inside the tagged entry widget.
+ *
+ * Returns: (transfer full): a list model of all the tags
+ */
+GListModel *
+adw_tagged_entry_get_tags (AdwTaggedEntry *self)
+{
+ g_return_val_if_fail (ADW_IS_TAGGED_ENTRY (self), NULL);
+
+ return self->tags;
+}
+
+/**
+ * adw_tagged_entry_remove_all_tags:
+ * @self: the tagged entry we want to change
+ *
+ * Removes all tags from the tagged entry widget.
+ */
+void
+adw_tagged_entry_remove_all_tags (AdwTaggedEntry *self)
+{
+ g_return_if_fail (ADW_IS_TAGGED_ENTRY (self));
+
+ g_list_store_remove_all (G_LIST_STORE (self->tags));
+}
+
+/**
+ * adw_tagged_entry_set_placeholder_text:
+ * @self: the tagged entry to update
+ * @text: (nullable): the placeholder text
+ *
+ * Sets text to be displayed in the tagged entry when it is empty.
+ */
+void
+adw_tagged_entry_set_placeholder_text (AdwTaggedEntry *self,
+ const char *text)
+{
+ g_return_if_fail (ADW_IS_TAGGED_ENTRY (self));
+
+ gtk_text_set_placeholder_text (GTK_TEXT (self->text), text);
+ gtk_accessible_update_property (GTK_ACCESSIBLE (self),
+ GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER, text,
+ -1);
+
+ g_object_notify_by_pspec (G_OBJECT (self), entry_props[PROP_PLACEHOLDER_TEXT]);
+}
+
+/**
+ * adw_tagged_entry_get_placeholder_text:
+ * @self: the tagged entry to query
+ *
+ * Retrieves the placeholder text of the tagged entry.
+ *
+ * Returns: (transfer none) (nullable): the placeholder text
+ */
+const char *
+adw_tagged_entry_get_placeholder_text (AdwTaggedEntry *self)
+{
+ g_return_val_if_fail (ADW_IS_TAGGED_ENTRY (self), NULL);
+
+ return gtk_text_get_placeholder_text (GTK_TEXT (self->text));
+}
+
+/* }}} */
+
+/* {{{ AdwTag */
+enum
+{
+ PROP_TAG_NAME = 1,
+ PROP_TAG_LABEL,
+ PROP_TAG_SHOW_CLOSE,
+
+ N_TAG_PROPS
+};
+
+static GParamSpec *tag_props[N_TAG_PROPS];
+
+G_DEFINE_TYPE (AdwTag, adw_tag, G_TYPE_OBJECT)
+
+static void
+adw_tag_close_clicked (AdwTag *self)
+{
+ adw_tagged_entry_remove_tag (self->entry, self->name);
+}
+
+static void
+adw_tag_dispose (GObject *gobject)
+{
+ AdwTag *self = ADW_TAG (gobject);
+
+ // Keep a reference, as remove_tag() will release the initial reference
+ g_object_ref (self);
+ adw_tagged_entry_remove_tag (self->entry, self->name);
+
+ g_clear_pointer (&self->label, g_free);
+ g_clear_pointer (&self->name, g_free);
+
+ G_OBJECT_CLASS (adw_tag_parent_class)->dispose (gobject);
+}
+
+static void
+adw_tag_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AdwTag *self = ADW_TAG (gobject);
+
+ switch (prop_id) {
+ case PROP_TAG_NAME:
+ g_free (self->name);
+ self->name = g_value_dup_string (value);
+ break;
+
+ case PROP_TAG_LABEL:
+ adw_tag_set_label (self, g_value_get_string (value));
+ break;
+
+ case PROP_TAG_SHOW_CLOSE:
+ adw_tag_set_show_close (self, g_value_get_boolean (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+adw_tag_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AdwTag *self = ADW_TAG (gobject);
+
+ switch (prop_id) {
+ case PROP_TAG_NAME:
+ g_value_set_string (value, self->name);
+ break;
+
+ case PROP_TAG_LABEL:
+ g_value_set_string (value, self->label);
+ break;
+
+ case PROP_TAG_SHOW_CLOSE:
+ g_value_set_boolean (value, self->show_close);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+adw_tag_class_init (AdwTagClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = adw_tag_dispose;
+ gobject_class->set_property = adw_tag_set_property;
+ gobject_class->get_property = adw_tag_get_property;
+
+ /**
+ * AdwTag:name:
+ *
+ * The name of the tag, used for accessing the tag in a tagged entry
+ * and for styling purposes.
+ */
+ tag_props[PROP_TAG_NAME] =
+ g_param_spec_string ("name", NULL, NULL,
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+ /**
+ * AdwTag:label:
+ *
+ * The user readable name of the tag.
+ */
+ tag_props[PROP_TAG_LABEL] =
+ g_param_spec_string ("label", NULL, NULL,
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * AdwTag:show-close:
+ *
+ * Whether the tag should show a close button to remove itself
+ * from the entry.
+ */
+ tag_props[PROP_TAG_SHOW_CLOSE] =
+ g_param_spec_boolean ("show-close", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties (gobject_class, N_TAG_PROPS, tag_props);
+}
+
+static void
+adw_tag_init (AdwTag *self)
+{
+ self->show_close = TRUE;
+
+ self->tag = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
+
+ self->tag_label = gtk_label_new ("");
+ gtk_box_append (GTK_BOX (self->tag), self->tag_label);
+ g_object_bind_property (self, "label",
+ self->tag_label, "label",
+ G_BINDING_DEFAULT);
+
+ self->tag_close = gtk_button_new_from_icon_name ("window-close-symbolic");
+ gtk_box_append (GTK_BOX (self->tag), self->tag_close);
+ g_object_bind_property (self, "show-close",
+ self->tag_close, "visible",
+ G_BINDING_DEFAULT);
+ g_signal_connect_swapped (self->tag_close, "clicked", G_CALLBACK (adw_tag_close_clicked), self);
+}
+
+/**
+ * adw_tag_get_name:
+ * @self: the tag we want to query
+ *
+ * Retrieves the name of the tag.
+ *
+ * Returns: (transfer none): the name of the tag
+ */
+const char *
+adw_tag_get_name (AdwTag *self)
+{
+ g_return_val_if_fail (ADW_IS_TAG (self), NULL);
+
+ return self->name;
+}
+
+/**
+ * adw_tag_get_label:
+ * @self: the tag we want to query
+ *
+ * Retrieves the user readable label of the tag.
+ *
+ * Returns: (transfer none): the label of the tag
+ */
+const char *
+adw_tag_get_label (AdwTag *self)
+{
+ g_return_val_if_fail (ADW_IS_TAG (self), NULL);
+
+ return self->label;
+}
+
+/**
+ * adw_tag_set_label:
+ * @self: the tag we want to update
+ * @label: (not nullable): the label of the tag
+ *
+ * Sets the user readable label of the tag.
+ */
+void
+adw_tag_set_label (AdwTag *self,
+ const char *label)
+{
+ g_return_if_fail (ADW_IS_TAG (self));
+ g_return_if_fail (label != NULL);
+
+ if (g_strcmp0 (self->label, label) == 0)
+ return;
+
+ g_free (self->label);
+ self->label = g_strdup (label);
+
+ g_object_notify_by_pspec (G_OBJECT (self), tag_props[PROP_TAG_LABEL]);
+}
+
+/**
+ * adw_tag_get_show_close:
+ * @self: the tag we want to query
+ *
+ * Checks whether the tag should show a close button or not.
+ *
+ * Returns: true if the tag has a visible close button
+ */
+gboolean
+adw_tag_get_show_close (AdwTag *self)
+{
+ g_return_val_if_fail (ADW_IS_TAG (self), FALSE);
+
+ return self->show_close;
+}
+
+/**
+ * adw_tag_set_show_close:
+ * @self: the tag we want to update
+ *
+ * Sets whether the tag should show a close button or not.
+ */
+void
+adw_tag_set_show_close (AdwTag *self,
+ gboolean show_close)
+{
+ g_return_if_fail (ADW_IS_TAG (self));
+
+ show_close = !!show_close;
+
+ if (self->show_close != show_close) {
+ self->show_close = show_close;
+
+ g_object_notify_by_pspec (G_OBJECT (self), tag_props[PROP_TAG_SHOW_CLOSE]);
+ }
+}
+
+/* }}} */
diff --git a/src/adw-tagged-entry.h b/src/adw-tagged-entry.h
new file mode 100644
index 00000000..eadbf6f7
--- /dev/null
+++ b/src/adw-tagged-entry.h
@@ -0,0 +1,66 @@
+/* adw-tagged-entry.h: Tagged entry widget
+ *
+ * SPDX-FileCopyrightText: 2022 Emmanuele Bassi
+ * SPDX-FileCopyrightText: 2019 Matthias Clasen
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#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_TAG (adw_tag_get_type())
+
+ADW_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (AdwTag, adw_tag, ADW, TAG, GObject)
+
+ADW_AVAILABLE_IN_ALL
+const char *adw_tag_get_name (AdwTag *self);
+
+ADW_AVAILABLE_IN_ALL
+const char *adw_tag_get_label (AdwTag *self);
+ADW_AVAILABLE_IN_ALL
+void adw_tag_set_label (AdwTag *self,
+ const char *label);
+
+ADW_AVAILABLE_IN_ALL
+gboolean adw_tag_get_show_close (AdwTag *self);
+ADW_AVAILABLE_IN_ALL
+void adw_tag_set_show_close (AdwTag *self,
+ gboolean show_close);
+
+#define ADW_TYPE_TAGGED_ENTRY (adw_tagged_entry_get_type())
+
+ADW_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (AdwTaggedEntry, adw_tagged_entry, ADW, TAGGED_ENTRY, GtkWidget)
+
+ADW_AVAILABLE_IN_ALL
+GtkWidget *adw_tagged_entry_new (void);
+
+ADW_AVAILABLE_IN_ALL
+AdwTag * adw_tagged_entry_add_tag (AdwTaggedEntry *self,
+ const char *name);
+ADW_AVAILABLE_IN_ALL
+void adw_tagged_entry_remove_tag (AdwTaggedEntry *self,
+ const char *name);
+ADW_AVAILABLE_IN_ALL
+void adw_tagged_entry_remove_all_tags (AdwTaggedEntry *self);
+ADW_AVAILABLE_IN_ALL
+GListModel *adw_tagged_entry_get_tags (AdwTaggedEntry *self);
+
+ADW_AVAILABLE_IN_ALL
+const char *adw_tagged_entry_get_placeholder_text (AdwTaggedEntry *self);
+ADW_AVAILABLE_IN_ALL
+void adw_tagged_entry_set_placeholder_text (AdwTaggedEntry *self,
+ const char *text);
+
+G_END_DECLS
diff --git a/src/adwaita.h b/src/adwaita.h
index 3371b1c9..72f0dc96 100644
--- a/src/adwaita.h
+++ b/src/adwaita.h
@@ -61,6 +61,7 @@ G_BEGIN_DECLS
#include "adw-swipeable.h"
#include "adw-tab-bar.h"
#include "adw-tab-view.h"
+#include "adw-tagged-entry.h"
#include "adw-timed-animation.h"
#include "adw-toast-overlay.h"
#include "adw-toast.h"
diff --git a/src/meson.build b/src/meson.build
index cfd52054..edefb398 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -120,6 +120,7 @@ src_headers = [
'adw-swipeable.h',
'adw-tab-bar.h',
'adw-tab-view.h',
+ 'adw-tagged-entry.h',
'adw-timed-animation.h',
'adw-toast.h',
'adw-toast-overlay.h',
@@ -189,6 +190,7 @@ src_sources = [
'adw-tab-bar.c',
'adw-tab-box.c',
'adw-tab-view.c',
+ 'adw-tagged-entry.c',
'adw-timed-animation.c',
'adw-toast.c',
'adw-toast-overlay.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]