[libadwaita] indicator-bin: Add badges



commit a33a02601b7749878b27c560821ea94df522db58
Author: CodedOre <CodedOre>
Date:   Mon Jun 28 17:33:42 2021 +0500

    indicator-bin: Add badges
    
    Allow to put a badge displaying text instead of just a dot indicator.
    
    It can stack with needs-attention, that changes the badge color.

 src/adw-indicator-bin-private.h            |  4 ++
 src/adw-indicator-bin.c                    | 82 ++++++++++++++++++++++++++++--
 src/stylesheet/widgets/_view-switcher.scss | 34 ++++++++++---
 3 files changed, 109 insertions(+), 11 deletions(-)
---
diff --git a/src/adw-indicator-bin-private.h b/src/adw-indicator-bin-private.h
index 556352b3..03eeb921 100644
--- a/src/adw-indicator-bin-private.h
+++ b/src/adw-indicator-bin-private.h
@@ -30,6 +30,10 @@ gboolean adw_indicator_bin_get_needs_attention (AdwIndicatorBin *self);
 void     adw_indicator_bin_set_needs_attention (AdwIndicatorBin *self,
                                                 gboolean         needs_attention);
 
+const char *adw_indicator_bin_get_badge (AdwIndicatorBin *self);
+void        adw_indicator_bin_set_badge (AdwIndicatorBin *self,
+                                         const char      *badge);
+
 gboolean adw_indicator_bin_get_contained (AdwIndicatorBin *self);
 void     adw_indicator_bin_set_contained (AdwIndicatorBin *self,
                                           gboolean         contained);
diff --git a/src/adw-indicator-bin.c b/src/adw-indicator-bin.c
index ba5e85c4..0b75f00e 100644
--- a/src/adw-indicator-bin.c
+++ b/src/adw-indicator-bin.c
@@ -32,6 +32,7 @@ struct _AdwIndicatorBin
 
   GtkWidget *mask;
   GtkWidget *indicator;
+  GtkWidget *label;
 
   GskGLShader *shader;
   gboolean shader_compiled;
@@ -48,6 +49,7 @@ enum {
   PROP_0,
   PROP_CHILD,
   PROP_NEEDS_ATTENTION,
+  PROP_BADGE,
   PROP_CONTAINED,
   LAST_PROP
 };
@@ -80,6 +82,14 @@ ensure_shader (AdwIndicatorBin *self)
   }
 }
 
+static gboolean
+has_badge (AdwIndicatorBin *self)
+{
+  const char *text = gtk_label_get_label (GTK_LABEL (self->label));
+
+  return text && text[0];
+}
+
 static void
 adw_indicator_bin_measure (GtkWidget      *widget,
                            GtkOrientation  orientation,
@@ -132,13 +142,16 @@ adw_indicator_bin_size_allocate (GtkWidget *widget,
     y = 0;
   } else {
     if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
-      x = -size.width / 2.0f;
+      x = -size.height / 2.0f;
     else
-      x = width - size.width / 2.0f;
+      x = width - size.width + size.height / 2.0f;
 
     y = -size.height / 2.0f;
   }
 
+  if (size.width > width * 2)
+    x = (width - size.width) / 2.0f;
+
   gtk_widget_allocate (self->mask, size.width, size.height, baseline,
                        gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (x, y)));
   gtk_widget_allocate (self->indicator, size.width, size.height, baseline,
@@ -151,7 +164,7 @@ adw_indicator_bin_snapshot (GtkWidget   *widget,
 {
   AdwIndicatorBin *self = ADW_INDICATOR_BIN (widget);
 
-  if (!self->needs_attention) {
+  if (!has_badge (self) && !self->needs_attention) {
     if (self->child)
       gtk_widget_snapshot_child (widget, self->child, snapshot);
 
@@ -208,6 +221,10 @@ adw_indicator_bin_get_property (GObject    *object,
     g_value_set_boolean (value, adw_indicator_bin_get_needs_attention (self));
     break;
 
+  case PROP_BADGE:
+    g_value_set_string (value, adw_indicator_bin_get_badge (self));
+    break;
+
   case PROP_CONTAINED:
     g_value_set_boolean (value, adw_indicator_bin_get_contained (self));
     break;
@@ -234,6 +251,10 @@ adw_indicator_bin_set_property (GObject      *object,
     adw_indicator_bin_set_needs_attention (self, g_value_get_boolean (value));
     break;
 
+  case PROP_BADGE:
+    adw_indicator_bin_set_badge (self, g_value_get_string (value));
+    break;
+
   case PROP_CONTAINED:
     adw_indicator_bin_set_contained (self, g_value_get_boolean (value));
     break;
@@ -252,6 +273,7 @@ adw_indicator_bin_dispose (GObject *object)
   g_clear_pointer (&self->child, gtk_widget_unparent);
   g_clear_pointer (&self->mask, gtk_widget_unparent);
   g_clear_pointer (&self->indicator, gtk_widget_unparent);
+  self->label = NULL;
 
   G_OBJECT_CLASS (adw_indicator_bin_parent_class)->dispose (object);
 }
@@ -297,6 +319,20 @@ adw_indicator_bin_class_init (AdwIndicatorBinClass *klass)
                           FALSE,
                           G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
+  /**
+   * AdwIndicatorBin:badge:
+   *
+   * Additional information for the user.
+   *
+   * Since: 1.0
+   */
+  props[PROP_BADGE] =
+    g_param_spec_string ("badge",
+                         "Badge",
+                         "Additional information for the user",
+                         "",
+                         G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
   /**
    * AdwIndicatorBin:contained:
    *
@@ -327,6 +363,11 @@ adw_indicator_bin_init (AdwIndicatorBin *self)
   self->indicator = adw_gizmo_new ("indicator", NULL, NULL, NULL, NULL, NULL, NULL);
   gtk_widget_set_can_target (self->indicator, FALSE);
   gtk_widget_set_parent (self->indicator, GTK_WIDGET (self));
+  gtk_widget_set_layout_manager (self->indicator, gtk_bin_layout_new ());
+
+  self->label = gtk_label_new (NULL);
+  gtk_widget_set_visible (self->label, FALSE);
+  gtk_widget_set_parent (self->label, self->indicator);
 }
 
 static void
@@ -433,11 +474,44 @@ adw_indicator_bin_set_needs_attention (AdwIndicatorBin *self,
 
   self->needs_attention = needs_attention;
 
-  gtk_widget_queue_allocate (GTK_WIDGET (self));
+  if (self->needs_attention)
+    gtk_widget_add_css_class (GTK_WIDGET (self), "needs-attention");
+  else
+    gtk_widget_remove_css_class (GTK_WIDGET (self), "needs-attention");
+
+  gtk_widget_queue_draw (GTK_WIDGET (self));
 
   g_object_notify_by_pspec (G_OBJECT (self), props[PROP_NEEDS_ATTENTION]);
 }
 
+const char *
+adw_indicator_bin_get_badge (AdwIndicatorBin *self)
+{
+  g_return_val_if_fail (ADW_IS_INDICATOR_BIN (self), "");
+
+  return gtk_label_get_label (GTK_LABEL (self->label));
+}
+
+void
+adw_indicator_bin_set_badge (AdwIndicatorBin *self,
+                             const char      *badge)
+{
+  g_return_if_fail (ADW_IS_INDICATOR_BIN (self));
+
+  gtk_label_set_text (GTK_LABEL (self->label), badge);
+
+  if (badge && badge[0])
+    gtk_widget_add_css_class (GTK_WIDGET (self), "badge");
+  else
+    gtk_widget_remove_css_class (GTK_WIDGET (self), "badge");
+
+  gtk_widget_set_visible (self->label, badge && badge[0]);
+
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_BADGE]);
+}
+
 gboolean
 adw_indicator_bin_get_contained (AdwIndicatorBin *self)
 {
diff --git a/src/stylesheet/widgets/_view-switcher.scss b/src/stylesheet/widgets/_view-switcher.scss
index c98c14e1..4c771697 100644
--- a/src/stylesheet/widgets/_view-switcher.scss
+++ b/src/stylesheet/widgets/_view-switcher.scss
@@ -16,7 +16,7 @@ viewswitcher {
         padding-top: 7px;
         padding-bottom: 5px;
 
-        label {
+        > stack > label {
           padding-left: 8px;
           padding-right: 8px;
         }
@@ -25,7 +25,7 @@ viewswitcher {
       &.wide {
         padding: 8px 12px;
 
-        label {
+        > stack > label {
           &:dir(ltr) {
             padding-right: 7px;
           }
@@ -65,13 +65,33 @@ viewswitchertitle viewswitcher {
  *******************/
 
 indicatorbin {
-  > indicator { margin: 1px; }
-  > mask { padding: 1px; }
-
   > indicator, > mask {
-    background: $accent_bg_color;
     min-width: 6px;
     min-height: 6px;
-    border-radius: 100%;
+    border-radius: 100px;
+  }
+
+  > indicator {
+    margin: 1px;
+    background: gtkalpha(currentColor, .4);
+
+    > label {
+      font-size: 0.6rem;
+      font-weight: bold;
+      padding: 1px 4px;
+      color: white;
+      font-feature-settings: "tnum";
+    }
+  }
+
+  > mask {
+    padding: 1px;
+    background: black;
+  }
+
+  &.needs-attention > indicator {
+    background: $accent_bg_color;
+
+    > label { color: $accent_fg_color; }
   }
 }


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