[libadwaita/ebassi/tagged-entry: 13/20] Add AdwTagWidget




commit 7d2e0e501bd757051b55f70651a0625973df5523
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Fri Mar 4 18:47:07 2022 +0000

    Add AdwTagWidget
    
    The AdwTagWidget is a representation of an AdwTag.

 src/adw-tag-widget-private.h |  22 +++++
 src/adw-tag-widget.c         | 226 +++++++++++++++++++++++++++++++++++++++++++
 src/adw-tag-widget.ui        |  31 ++++++
 src/meson.build              |   1 +
 4 files changed, 280 insertions(+)
---
diff --git a/src/adw-tag-widget-private.h b/src/adw-tag-widget-private.h
new file mode 100644
index 00000000..a08880a6
--- /dev/null
+++ b/src/adw-tag-widget-private.h
@@ -0,0 +1,22 @@
+/* adw-tag-widget-private.h
+ *
+ * SPDX-FileCopyrightText: 2022 Emmanuele Bassi
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include "adw-tag.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define ADW_TYPE_TAG_WIDGET (adw_tag_widget_get_type())
+
+G_DECLARE_FINAL_TYPE (AdwTagWidget, adw_tag_widget, ADW, TAG_WIDGET, GtkWidget)
+
+AdwTag *adw_tag_widget_get_tag (AdwTagWidget *self);
+
+G_END_DECLS
diff --git a/src/adw-tag-widget.c b/src/adw-tag-widget.c
new file mode 100644
index 00000000..74006075
--- /dev/null
+++ b/src/adw-tag-widget.c
@@ -0,0 +1,226 @@
+/* adw-tag-widget.c
+ *
+ * SPDX-FileCopyrightText: 2022 Emmanuele Bassi
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "adw-tag-widget-private.h"
+
+#include "adw-tag-private.h"
+
+struct _AdwTagWidget
+{
+  GtkWidget parent_instance;
+
+  AdwTag *tag;
+
+  GtkWidget *icon;
+  GtkWidget *label;
+  GtkWidget *close_button;
+};
+
+struct _AdwTagWidgetClass
+{
+  GtkWidgetClass parent_class;
+};
+
+enum
+{
+  PROP_TAG = 1,
+  N_PROPS
+};
+
+static GParamSpec *obj_props[N_PROPS];
+
+enum
+{
+  CLOSED,
+
+  LAST_SIGNAL
+};
+
+static guint obj_signals[LAST_SIGNAL];
+
+
+G_DEFINE_TYPE (AdwTagWidget, adw_tag_widget, GTK_TYPE_WIDGET)
+
+static void
+adw_tag_widget__close_clicked (AdwTagWidget *self)
+{
+  g_signal_emit (self, obj_signals[CLOSED], 0, self->tag);
+}
+
+static void
+update_tag_icon (AdwTagWidget *self)
+{
+  gtk_widget_set_visible (self->icon, adw_tag_has_icon (self->tag));
+
+  AdwTagIconType icon_type = adw_tag_get_icon_type (self->tag);
+  switch (icon_type) {
+  case ADW_TAG_ICON_GICON:
+    {
+      GIcon *icon = adw_tag_get_gicon (self->tag);
+      gtk_image_set_from_gicon (GTK_IMAGE (self->icon), icon);
+    }
+    break;
+
+  case ADW_TAG_ICON_PAINTABLE:
+    {
+      GdkPaintable *paintable = adw_tag_get_paintable (self->tag);
+      gtk_image_set_from_paintable (GTK_IMAGE (self->icon), paintable);
+    }
+    break;
+
+  case ADW_TAG_ICON_NONE:
+  default:
+    break;
+  }
+}
+
+static void
+adw_tag_widget_set_tag (AdwTagWidget *self,
+                        AdwTag       *tag)
+{
+  if (g_set_object (&self->tag, tag)) {
+    if (self->tag != NULL) {
+      g_object_bind_property (self->tag, "show-close",
+                              self->close_button, "visible",
+                              G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+      g_object_bind_property (self->tag, "label",
+                              self->label, "label",
+                              G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
+
+      update_tag_icon (self);
+    }
+
+    g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_TAG]);
+  }
+}
+
+static void
+adw_tag_widget__click_released (AdwTagWidget *self,
+                                guint         n_press,
+                                double        x,
+                                double        y,
+                                GtkGesture   *gesture)
+{
+  gtk_gesture_set_state (gesture, GTK_EVENT_SEQUENCE_CLAIMED);
+
+  const char *action_name = adw_tag_get_action_name (self->tag);
+  if (action_name == NULL)
+    return;
+
+  gtk_widget_activate_action_variant (GTK_WIDGET (self),
+                                      action_name,
+                                      adw_tag_get_action_target_value (self->tag));
+}
+
+static void
+adw_tag_widget_dispose (GObject *gobject)
+{
+  AdwTagWidget *self = ADW_TAG_WIDGET (gobject);
+
+  g_clear_pointer (&self->icon, gtk_widget_unparent);
+  g_clear_pointer (&self->label, gtk_widget_unparent);
+  g_clear_pointer (&self->close_button, gtk_widget_unparent);
+
+  g_clear_object (&self->tag);
+
+  G_OBJECT_CLASS (adw_tag_widget_parent_class)->dispose (gobject);
+}
+
+static void
+adw_tag_widget_set_property (GObject      *gobject,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  AdwTagWidget *self = ADW_TAG_WIDGET (gobject);
+
+  switch (prop_id) {
+  case PROP_TAG:
+    adw_tag_widget_set_tag (self, g_value_get_object (value));
+    break;
+
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+  }
+}
+
+static void
+adw_tag_widget_get_property (GObject    *gobject,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+  AdwTagWidget *self = ADW_TAG_WIDGET (gobject);
+
+  switch (prop_id) {
+  case PROP_TAG:
+    g_value_set_object (value, self->tag);
+    break;
+
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+  }
+}
+
+static void
+adw_tag_widget_class_init (AdwTagWidgetClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gobject_class->set_property = adw_tag_widget_set_property;
+  gobject_class->get_property = adw_tag_widget_get_property;
+  gobject_class->dispose = adw_tag_widget_dispose;
+
+  obj_props[PROP_TAG] =
+    g_param_spec_object ("tag", NULL, NULL, ADW_TYPE_TAG,
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT |
+                         G_PARAM_STATIC_STRINGS |
+                         G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (gobject_class, N_PROPS, obj_props);
+
+  obj_signals[CLOSED] =
+    g_signal_new ("closed",
+                  ADW_TYPE_TAG_WIDGET,
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL,
+                  NULL,
+                  NULL,
+                  G_TYPE_NONE, 1, ADW_TYPE_TAG);
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Adwaita/ui/adw-tag-widget.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, AdwTagWidget, icon);
+  gtk_widget_class_bind_template_child (widget_class, AdwTagWidget, label);
+  gtk_widget_class_bind_template_child (widget_class, AdwTagWidget, close_button);
+
+  gtk_widget_class_bind_template_callback (widget_class, adw_tag_widget__click_released);
+  gtk_widget_class_bind_template_callback (widget_class, adw_tag_widget__close_clicked);
+
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
+  gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_GROUP);
+  gtk_widget_class_set_css_name (widget_class, "tag");
+}
+
+static void
+adw_tag_widget_init (AdwTagWidget *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+AdwTag *
+adw_tag_widget_get_tag (AdwTagWidget *self)
+{
+  g_return_val_if_fail (ADW_IS_TAG_WIDGET (self), NULL);
+
+  return self->tag;
+}
diff --git a/src/adw-tag-widget.ui b/src/adw-tag-widget.ui
new file mode 100644
index 00000000..2b628c98
--- /dev/null
+++ b/src/adw-tag-widget.ui
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="libadwaita">
+  <requires lib="gtk" version="4.0"/>
+  <template class="AdwTagWidget">
+    <child>
+      <object class="GtkGestureClick">
+        <signal name="released" handler="adw_tag_widget__click_released" swapped="yes"/>
+      </object>
+    </child>
+    <child>
+      <object class="GtkImage" id="icon">
+      </object>
+    </child>
+    <child>
+      <object class="GtkLabel" id="label">
+        <property name="ellipsize">end</property>
+        <property name="max-width-chars">12</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkButton" id="close_button">
+        <property name="icon-name">window-close-symbolic</property>
+        <signal name="clicked" handler="adw_tag_widget__close_clicked" swapped="yes"/>
+        <style>
+          <class name="flat"/>
+          <class name="circular"/>
+        </style>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/meson.build b/src/meson.build
index 6da36a62..6c1e5bee 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -182,6 +182,7 @@ src_sources = [
   'adw-tab-bar.c',
   'adw-tab-view.c',
   'adw-tag.c',
+  'adw-tag-widget.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]