[gtk/tagged-entry-demo] Add a tagged entry demo



commit f8099586ffd3db03c563e96844ffa6a85b00b846
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Mar 15 10:34:06 2019 -0400

    Add a tagged entry demo

 demos/gtk-demo/demo.gresource.xml |   5 +
 demos/gtk-demo/demotaggedentry.c  | 488 ++++++++++++++++++++++++++++++++++++++
 demos/gtk-demo/demotaggedentry.h  |  88 +++++++
 demos/gtk-demo/meson.build        |   9 +-
 4 files changed, 589 insertions(+), 1 deletion(-)
---
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index fa0c245c87..cd32f1142b 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -207,6 +207,7 @@
     <file>spinbutton.c</file>
     <file>spinner.c</file>
     <file>tabs.c</file>
+    <file>tagged_entry.c</file>
     <file>textview.c</file>
     <file>textscroll.c</file>
     <file>theming_style_classes.c</file>
@@ -262,6 +263,10 @@
   <gresource prefix="/dnd">
     <file>dnd.css</file>
   </gresource>
+  <gresource prefix="/tagged_entry">
+    <file>demotaggedentry.c</file>
+    <file>demotaggedentry.h</file>
+  </gresource>
   <gresource prefix="/org/gtk/Demo">
     <file>icons/16x16/actions/application-exit.png</file>
     <file>icons/16x16/actions/document-new.png</file>
diff --git a/demos/gtk-demo/demotaggedentry.c b/demos/gtk-demo/demotaggedentry.c
new file mode 100644
index 0000000000..792cc4ecca
--- /dev/null
+++ b/demos/gtk-demo/demotaggedentry.c
@@ -0,0 +1,488 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * Authors:
+ * - Matthias Clasen <mclasen redhat com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "demotaggedentry.h"
+
+#include <gtk/gtk.h>
+#include <gtk/gtk-a11y.h>
+
+typedef struct {
+  GtkWidget *box;
+  GtkWidget *entry;
+} DemoTaggedEntryPrivate;
+
+static void demo_tagged_entry_editable_init (GtkEditableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (DemoTaggedEntry, demo_tagged_entry, GTK_TYPE_WIDGET,
+                         G_ADD_PRIVATE (DemoTaggedEntry)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, demo_tagged_entry_editable_init))
+
+static void
+demo_tagged_entry_init (DemoTaggedEntry *entry)
+{
+  DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
+
+  gtk_widget_set_has_surface (GTK_WIDGET (entry), FALSE);
+
+  priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_widget_set_parent (priv->box, GTK_WIDGET (entry));
+
+  priv->entry = gtk_text_new ();
+  gtk_widget_set_hexpand (priv->entry, TRUE);
+  gtk_widget_set_vexpand (priv->entry, TRUE);
+  gtk_widget_set_hexpand (priv->box, FALSE);
+  gtk_widget_set_vexpand (priv->box, FALSE);
+  gtk_container_add (GTK_CONTAINER (priv->box), priv->entry);
+  gtk_editable_init_delegate (GTK_EDITABLE (entry));
+}
+
+static void
+demo_tagged_entry_dispose (GObject *object)
+{
+  DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (object);
+  DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
+
+  if (priv->entry)
+    gtk_editable_finish_delegate (GTK_EDITABLE (entry));
+
+  g_clear_pointer (&priv->entry, gtk_widget_unparent);
+  g_clear_pointer (&priv->box, gtk_widget_unparent);
+
+  G_OBJECT_CLASS (demo_tagged_entry_parent_class)->dispose (object);
+}
+
+static void
+demo_tagged_entry_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (demo_tagged_entry_parent_class)->finalize (object);
+}
+
+static void
+demo_tagged_entry_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  if (gtk_editable_delegate_set_property (object, prop_id, value, pspec))
+    return;
+
+  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+}
+
+static void
+demo_tagged_entry_get_property (GObject    *object,
+                               guint       prop_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  if (gtk_editable_delegate_get_property (object, prop_id, value, pspec))
+    return;
+
+  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+}
+
+static void
+demo_tagged_entry_measure (GtkWidget      *widget,
+                          GtkOrientation  orientation,
+                          int             for_size,
+                          int            *minimum,
+                          int            *natural,
+                          int            *minimum_baseline,
+                          int            *natural_baseline)
+{
+  DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
+  DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
+
+  gtk_widget_measure (priv->box, orientation, for_size,
+                      minimum, natural,
+                      minimum_baseline, natural_baseline);
+}
+
+static void
+demo_tagged_entry_size_allocate (GtkWidget *widget,
+                                int        width,
+                                int        height,
+                                int        baseline)
+{
+  DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
+  DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
+
+  gtk_widget_size_allocate (priv->box,
+                            &(GtkAllocation) { 0, 0, width, height },
+                            baseline);
+}
+
+static void
+demo_tagged_entry_grab_focus (GtkWidget *widget)
+{
+  DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
+  DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
+
+  gtk_widget_grab_focus (priv->entry);
+}
+
+static void
+demo_tagged_entry_class_init (DemoTaggedEntryClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->dispose = demo_tagged_entry_dispose;
+  object_class->finalize = demo_tagged_entry_finalize;
+  object_class->get_property = demo_tagged_entry_get_property;
+  object_class->set_property = demo_tagged_entry_set_property;
+
+  widget_class->measure = demo_tagged_entry_measure;
+  widget_class->size_allocate = demo_tagged_entry_size_allocate;
+  widget_class->grab_focus = demo_tagged_entry_grab_focus;
+ 
+  gtk_editable_install_properties (object_class, 1);
+
+  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE);
+  gtk_widget_class_set_css_name (widget_class, "entry");
+}
+
+static GtkEditable *
+demo_tagged_entry_get_delegate (GtkEditable *editable)
+{
+  DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (editable);
+  DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
+
+  return GTK_EDITABLE (priv->entry);
+}
+
+static void
+demo_tagged_entry_editable_init (GtkEditableInterface *iface)
+{
+  iface->get_delegate = demo_tagged_entry_get_delegate;
+}
+
+/**
+ * demo_tagged_entry_new:
+ *
+ * Creates a #DemoTaggedEntry.
+ *
+ * Returns: a new #DemoTaggedEntry
+ */
+GtkWidget *
+demo_tagged_entry_new (void)
+{
+  return GTK_WIDGET (g_object_new (DEMO_TYPE_TAGGED_ENTRY, NULL));
+}
+
+void
+demo_tagged_entry_add_tag (DemoTaggedEntry *entry,
+                          GtkWidget      *tag)
+{
+  DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
+
+  g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
+
+  gtk_container_add (GTK_CONTAINER (priv->box), tag);
+}
+
+void
+demo_tagged_entry_insert_tag_after (DemoTaggedEntry *entry,
+                                    GtkWidget       *tag,
+                                    GtkWidget       *sibling)
+{
+  DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
+
+  g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
+
+  if (sibling == NULL)
+    gtk_container_add (GTK_CONTAINER (priv->box), tag);
+  else
+    gtk_box_insert_child_after (GTK_BOX (priv->box), tag, sibling); 
+}
+
+void
+demo_tagged_entry_remove_tag (DemoTaggedEntry *entry,
+                             GtkWidget      *tag)
+{
+  DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
+
+  g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
+
+  gtk_container_remove (GTK_CONTAINER (priv->box), tag);
+}
+
+struct _DemoTaggedEntryTag
+{
+  GtkWidget parent;
+  GtkWidget *box;
+  GtkWidget *label;
+  GtkWidget *button;
+
+  gboolean has_close_button;
+  char *style;
+};
+
+struct _DemoTaggedEntryTagClass
+{
+  GtkWidgetClass parent_class;
+};
+
+enum {
+  PROP_0,
+  PROP_LABEL,
+  PROP_HAS_CLOSE_BUTTON,
+};
+
+enum {
+  SIGNAL_CLICKED,
+  SIGNAL_BUTTON_CLICKED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE (DemoTaggedEntryTag, demo_tagged_entry_tag, GTK_TYPE_WIDGET)
+
+static void
+on_released (GtkGestureMultiPress *gesture,
+             int                   n_press,
+             double                x,
+             double                y,
+             DemoTaggedEntryTag          *tag)
+{
+  g_signal_emit (tag, signals[SIGNAL_CLICKED], 0);
+}
+
+static void
+demo_tagged_entry_tag_init (DemoTaggedEntryTag *tag)
+{
+  GtkGesture *gesture;
+
+  gtk_widget_set_has_surface (GTK_WIDGET (tag), FALSE);
+
+  tag->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_widget_set_parent (tag->box, GTK_WIDGET (tag));
+  tag->label = gtk_label_new ("");
+  gtk_container_add (GTK_CONTAINER (tag->box), tag->label);
+
+  gesture = gtk_gesture_multi_press_new ();
+  g_signal_connect (gesture, "released", G_CALLBACK (on_released), tag);
+  gtk_widget_add_controller (GTK_WIDGET (tag), GTK_EVENT_CONTROLLER (gesture));
+}
+
+static void
+demo_tagged_entry_tag_dispose (GObject *object)
+{
+  DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
+
+  g_clear_pointer (&tag->box, gtk_widget_unparent);
+
+  G_OBJECT_CLASS (demo_tagged_entry_tag_parent_class)->dispose (object);
+}
+
+static void
+demo_tagged_entry_tag_finalize (GObject *object)
+{
+  DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
+
+  g_clear_pointer (&tag->box, gtk_widget_unparent);
+  g_clear_pointer (&tag->style, g_free);
+
+  G_OBJECT_CLASS (demo_tagged_entry_tag_parent_class)->finalize (object);
+}
+
+static void
+demo_tagged_entry_tag_set_property (GObject      *object,
+                            guint         prop_id,
+                            const GValue *value,
+                            GParamSpec   *pspec)
+{
+  DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
+
+  switch (prop_id)
+    {
+    case PROP_LABEL:
+      demo_tagged_entry_tag_set_label (tag, g_value_get_string (value));
+      break;
+
+    case PROP_HAS_CLOSE_BUTTON:
+      demo_tagged_entry_tag_set_has_close_button (tag, g_value_get_boolean (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+demo_tagged_entry_tag_get_property (GObject    *object,
+                            guint       prop_id,
+                            GValue     *value,
+                            GParamSpec *pspec)
+{
+  DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
+
+  switch (prop_id)
+    {
+    case PROP_LABEL:
+      g_value_set_string (value, demo_tagged_entry_tag_get_label (tag));
+      break;
+
+    case PROP_HAS_CLOSE_BUTTON:
+      g_value_set_boolean (value, demo_tagged_entry_tag_get_has_close_button (tag));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+demo_tagged_entry_tag_measure (GtkWidget      *widget,
+                       GtkOrientation  orientation,
+                       int             for_size,
+                       int            *minimum,
+                       int            *natural,
+                       int            *minimum_baseline,
+                       int            *natural_baseline)
+{
+  DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (widget);
+
+  gtk_widget_measure (tag->box, orientation, for_size,
+                      minimum, natural,
+                      minimum_baseline, natural_baseline);
+}
+
+static void
+demo_tagged_entry_tag_size_allocate (GtkWidget *widget,
+                             int        width,
+                             int        height,
+                             int        baseline)
+{
+  DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (widget);
+
+  gtk_widget_size_allocate (tag->box,
+                            &(GtkAllocation) { 0, 0, width, height },
+                            baseline);
+}
+
+static void
+demo_tagged_entry_tag_class_init (DemoTaggedEntryTagClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+  object_class->dispose = demo_tagged_entry_tag_dispose;
+  object_class->finalize = demo_tagged_entry_tag_finalize;
+  object_class->set_property = demo_tagged_entry_tag_set_property;
+  object_class->get_property = demo_tagged_entry_tag_get_property;
+
+  widget_class->measure = demo_tagged_entry_tag_measure;
+  widget_class->size_allocate = demo_tagged_entry_tag_size_allocate;
+
+  signals[SIGNAL_CLICKED] =
+    g_signal_new ("clicked",
+                  DEMO_TYPE_TAGGED_ENTRY_TAG,
+                  G_SIGNAL_RUN_FIRST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+  signals[SIGNAL_BUTTON_CLICKED] =
+    g_signal_new ("button-clicked",
+                  DEMO_TYPE_TAGGED_ENTRY_TAG,
+                  G_SIGNAL_RUN_FIRST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+
+  g_object_class_install_property (object_class, PROP_LABEL,
+      g_param_spec_string ("label", "Label", "Label",
+                           NULL, G_PARAM_READWRITE));
+  g_object_class_install_property (object_class, PROP_HAS_CLOSE_BUTTON,
+      g_param_spec_boolean ("has-close-button", "Has close button", "Whether this tag has a close button",
+                            FALSE, G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
+  gtk_widget_class_set_css_name (widget_class, "tag");
+}
+
+DemoTaggedEntryTag *
+demo_tagged_entry_tag_new (const char *label)
+{
+  return DEMO_TAGGED_ENTRY_TAG (g_object_new (DEMO_TYPE_TAGGED_ENTRY_TAG, "label", label, NULL));
+}
+
+const char *
+demo_tagged_entry_tag_get_label (DemoTaggedEntryTag *tag)
+{
+  g_return_val_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag), NULL);
+
+  return gtk_label_get_label (GTK_LABEL (tag->label));
+}
+
+void
+demo_tagged_entry_tag_set_label (DemoTaggedEntryTag *tag,
+                         const char  *label)
+{
+  g_return_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag));
+
+  gtk_label_set_label (GTK_LABEL (tag->label), label);
+}
+
+static void
+on_button_clicked (GtkButton *button, DemoTaggedEntryTag *tag)
+{
+  g_signal_emit (tag, signals[SIGNAL_BUTTON_CLICKED], 0);
+}
+
+void
+demo_tagged_entry_tag_set_has_close_button (DemoTaggedEntryTag *tag,
+                                    gboolean     has_close_button)
+{
+  g_return_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag));
+
+  if ((tag->button != NULL) == has_close_button)
+    return;
+
+  if (!has_close_button && tag->button)
+    {
+      gtk_container_remove (GTK_CONTAINER (tag->box), tag->button);
+      tag->button = NULL;
+    }
+  else if (has_close_button && tag->button == NULL)
+    {
+      GtkWidget *image;
+
+      image = gtk_image_new_from_icon_name ("window-close-symbolic");
+      gtk_image_set_pixel_size (GTK_IMAGE (image), 16);
+      tag->button = gtk_button_new ();
+      gtk_container_add (GTK_CONTAINER (tag->button), image);
+      gtk_button_set_relief (GTK_BUTTON (tag->button), GTK_RELIEF_NONE);
+      gtk_container_add (GTK_CONTAINER (tag->box), tag->button);
+      g_signal_connect (tag->button, "clicked", G_CALLBACK (on_button_clicked), tag);
+    }
+
+  g_object_notify (G_OBJECT (tag), "has-close-button");
+}
+
+gboolean
+demo_tagged_entry_tag_get_has_close_button (DemoTaggedEntryTag *tag)
+{
+  g_return_val_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag), FALSE);
+
+  return tag->button != NULL;
+}
diff --git a/demos/gtk-demo/demotaggedentry.h b/demos/gtk-demo/demotaggedentry.h
new file mode 100644
index 0000000000..70152ac6fa
--- /dev/null
+++ b/demos/gtk-demo/demotaggedentry.h
@@ -0,0 +1,88 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * Authors:
+ * - Matthias Clasen <mclasen redhat com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DEMO_TAGGED_ENTRY_H__
+#define __DEMO_TAGGED_ENTRY_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define DEMO_TYPE_TAGGED_ENTRY                 (demo_tagged_entry_get_type ())
+#define DEMO_TAGGED_ENTRY(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEMO_TYPE_TAGGED_ENTRY, 
DemoTaggedEntry))
+#define DEMO_TAGGED_ENTRY_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), DEMO_TYPE_TAGGED_ENTRY, 
DemoTaggedEntryClass))
+#define DEMO_IS_TAGGED_ENTRY(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEMO_TYPE_TAGGED_ENTRY))
+#define DEMO_IS_TAGGED_ENTRY_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), DEMO_TYPE_TAGGED_ENTRY))
+#define DEMO_TAGGED_ENTRY_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), DEMO_TYPE_TAGGED_ENTRY, 
DemoTaggedEntryClass))
+
+typedef struct _DemoTaggedEntry       DemoTaggedEntry;
+typedef struct _DemoTaggedEntryClass  DemoTaggedEntryClass;
+
+struct _DemoTaggedEntry
+{
+  GtkWidget parent;
+};
+
+struct _DemoTaggedEntryClass
+{
+  GtkWidgetClass parent_class;
+};
+
+#define DEMO_TYPE_TAGGED_ENTRY_TAG                (demo_tagged_entry_tag_get_type ())
+#define DEMO_TAGGED_ENTRY_TAG(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTag))
+#define DEMO_TAGGED_ENTRY_TAG_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), 
DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTag))
+#define DEMO_IS_TAGGED_ENTRY_TAG(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
DEMO_TYPE_TAGGED_ENTRY_TAG))
+#define DEMO_IS_TAGGED_ENTRY_TAG_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), 
DEMO_TYPE_TAGGED_ENTRY_TAG))
+#define DEMO_TAGGED_ENTRY_TAG_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), 
DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTagClass))
+
+typedef struct _DemoTaggedEntryTag       DemoTaggedEntryTag;
+typedef struct _DemoTaggedEntryTagClass  DemoTaggedEntryTagClass;
+
+
+GType           demo_tagged_entry_get_type (void) G_GNUC_CONST;
+GType           demo_tagged_entry_tag_get_type (void) G_GNUC_CONST;
+
+GtkWidget *     demo_tagged_entry_new      (void);
+
+void            demo_tagged_entry_add_tag (DemoTaggedEntry *entry,
+                                           GtkWidget      *tag);
+
+void            demo_tagged_entry_insert_tag_after (DemoTaggedEntry *entry,
+                                                    GtkWidget       *tag,
+                                                    GtkWidget       *sibling);
+
+void            demo_tagged_entry_remove_tag (DemoTaggedEntry *entry,
+                                              GtkWidget      *tag);
+
+DemoTaggedEntryTag * demo_tagged_entry_tag_new (const char *label);
+
+const char *    demo_tagged_entry_tag_get_label (DemoTaggedEntryTag *tag);
+
+void            demo_tagged_entry_tag_set_label (DemoTaggedEntryTag *tag,
+                                         const char  *label);
+
+gboolean        demo_tagged_entry_tag_get_has_close_button (DemoTaggedEntryTag *tag);
+
+void            demo_tagged_entry_tag_set_has_close_button (DemoTaggedEntryTag *tag,
+                                                    gboolean     has_close_button);
+
+G_END_DECLS
+
+#endif /* __DEMO_TAGGED_ENTRY_H__ */
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index e331001abb..86fd6d6b80 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -65,6 +65,7 @@ demos = files([
   'spinner.c',
   'stack.c',
   'tabs.c',
+  'tagged_entry.c',
   'textmask.c',
   'textview.c',
   'textscroll.c',
@@ -76,7 +77,13 @@ demos = files([
 
 gtkdemo_deps = [ libgtk_dep, ]
 
-extra_demo_sources = files(['main.c', 'gtkfishbowl.c', 'fontplane.c', 'gtkgears.c', 'puzzlepiece.c', 
'bluroverlay.c'])
+extra_demo_sources = files(['main.c',
+                            'gtkfishbowl.c',
+                            'fontplane.c',
+                            'gtkgears.c',
+                            'puzzlepiece.c',
+                            'bluroverlay.c',
+                            'demotaggedentry.c'])
 
 if harfbuzz_dep.found() and pangoft_dep.found()
   demos += files('font_features.c')


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]