[libadwaita/wip/exalm/dark-avatar: 2/2] avatar: Add appearance property




commit 566f20075ff3296fae072446ae0c48bf8a11c857
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Mon Jan 17 20:01:59 2022 +0500

    avatar: Add appearance property
    
    Fixes https://gitlab.gnome.org/GNOME/libadwaita/-/issues/285

 src/adw-avatar.c                    | 162 ++++++++++++++++++++++++++++++++++++
 src/adw-avatar.h                    |  14 ++++
 src/meson.build                     |   1 +
 src/stylesheet/widgets/_avatar.scss |  22 +++++
 tests/test-avatar.c                 |  13 +++
 5 files changed, 212 insertions(+)
---
diff --git a/src/adw-avatar.c b/src/adw-avatar.c
index dec89921..87496466 100644
--- a/src/adw-avatar.c
+++ b/src/adw-avatar.c
@@ -16,6 +16,7 @@
 #include "adw-avatar.h"
 #include "adw-gizmo-private.h"
 #include "adw-macros-private.h"
+#include "adw-style-manager.h"
 
 #define NUMBER_OF_COLORS 14
 
@@ -64,6 +65,9 @@ struct _AdwAvatar
   gboolean show_initials;
   guint color_class;
   int size;
+  AdwAvatarAppearance appearance;
+
+  AdwStyleManager *style_manager;
 };
 
 G_DEFINE_FINAL_TYPE (AdwAvatar, adw_avatar, GTK_TYPE_WIDGET);
@@ -75,6 +79,7 @@ enum {
   PROP_SHOW_INITIALS,
   PROP_CUSTOM_IMAGE,
   PROP_SIZE,
+  PROP_APPEARANCE,
   PROP_LAST_PROP,
 };
 static GParamSpec *props[PROP_LAST_PROP];
@@ -203,6 +208,69 @@ update_font_size (AdwAvatar *self)
   pango_attr_list_unref (attributes);
 }
 
+static void
+notify_dark_cb (AdwAvatar *self)
+{
+  if (adw_style_manager_get_dark (self->style_manager))
+    gtk_widget_add_css_class (self->gizmo, "dark");
+  else
+    gtk_widget_remove_css_class (self->gizmo, "dark");
+}
+
+static void
+connect_style_manager (AdwAvatar *self)
+{
+  GdkDisplay *display;
+  AdwStyleManager *manager;
+
+  if (self->style_manager)
+    return;
+
+  display = gtk_widget_get_display (GTK_WIDGET (self));
+  manager = adw_style_manager_get_for_display (display);
+
+  self->style_manager = manager;
+  g_signal_connect_swapped (manager, "notify::dark",
+                            G_CALLBACK (notify_dark_cb), self);
+
+  notify_dark_cb (self);
+}
+
+static void
+disconnect_style_manager (AdwAvatar *self)
+{
+  if (!self->style_manager)
+    return;
+
+  g_signal_handlers_disconnect_by_func (self->style_manager,
+                                        G_CALLBACK (notify_dark_cb), self);
+  self->style_manager = NULL;
+
+  gtk_widget_remove_css_class (self->gizmo, "dark");
+}
+
+static void
+adw_avatar_realize (GtkWidget *widget)
+{
+  AdwAvatar *self = ADW_AVATAR (widget);
+
+  GTK_WIDGET_CLASS (adw_avatar_parent_class)->realize (widget);
+
+  if (self->appearance == ADW_AVATAR_AUTO)
+    connect_style_manager (self);
+}
+
+static void
+adw_avatar_unrealize (GtkWidget *widget)
+{
+  AdwAvatar *self = ADW_AVATAR (widget);
+
+  if (self->appearance == ADW_AVATAR_AUTO)
+    disconnect_style_manager (self);
+
+  GTK_WIDGET_CLASS (adw_avatar_parent_class)->unrealize (widget);
+}
+
 static void
 adw_avatar_get_property (GObject    *object,
                          guint       property_id,
@@ -232,6 +300,10 @@ adw_avatar_get_property (GObject    *object,
     g_value_set_int (value, adw_avatar_get_size (self));
     break;
 
+  case PROP_APPEARANCE:
+    g_value_set_enum (value, adw_avatar_get_appearance (self));
+    break;
+
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     break;
@@ -267,6 +339,10 @@ adw_avatar_set_property (GObject      *object,
     adw_avatar_set_size (self, g_value_get_int (value));
     break;
 
+  case PROP_APPEARANCE:
+    adw_avatar_set_appearance (self, g_value_get_enum (value));
+    break;
+
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     break;
@@ -310,6 +386,9 @@ adw_avatar_class_init (AdwAvatarClass *klass)
   object_class->set_property = adw_avatar_set_property;
   object_class->get_property = adw_avatar_get_property;
 
+  widget_class->realize = adw_avatar_realize;
+  widget_class->unrealize = adw_avatar_unrealize;
+
   /**
    * AdwAvatar:icon-name: (attributes org.gtk.Property.get=adw_avatar_get_icon_name 
org.gtk.Property.set=adw_avatar_set_icon_name)
    *
@@ -387,6 +466,29 @@ adw_avatar_class_init (AdwAvatarClass *klass)
                       -1, INT_MAX, -1,
                       G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
+  /**
+   * AdwAvatar:appearance: (attributes org.gtk.Property.get=adw_avatar_get_appearance 
org.gtk.Property.set=adw_avatar_set_appearance)
+   *
+   * The appearance of the avatar.
+   *
+   * Can be used to determine whether the avatar should be light or dark.
+   *
+   * If `ADW_AVATAR_AUTO` appearance is used, the avatar will follow the
+   * application appearance. Use `ADW_AVATAR_LIGHT` or `ADW_AVATAR_DARK` to
+   * override that.
+   *
+   * The default value is `ADW_AVATAR_AUTO`.
+   *
+   * Since: 1.1
+   */
+  props[PROP_APPEARANCE] =
+    g_param_spec_enum ("appearance",
+                       "Appearance",
+                       "The appearance of the avatar",
+                       ADW_TYPE_AVATAR_APPEARANCE,
+                       ADW_AVATAR_AUTO,
+                       G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
   g_object_class_install_properties (object_class, PROP_LAST_PROP, props);
 
   gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
@@ -412,6 +514,7 @@ adw_avatar_init (AdwAvatar *self)
   gtk_widget_set_parent (GTK_WIDGET (self->custom_image), self->gizmo);
 
   self->text = g_strdup ("");
+  self->appearance = ADW_AVATAR_AUTO;
 
   set_class_color (self);
   update_initials (self);
@@ -707,6 +810,65 @@ adw_avatar_set_size (AdwAvatar *self,
   g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SIZE]);
 }
 
+/**
+ * adw_avatar_get_appearance: (attributes org.gtk.Method.get_property=appearance)
+ * @self: a `AdwAvatar`
+ *
+ * Gets the appearance of the avatar.
+ *
+ * Returns: the appearance of the avatar
+ *
+ * Since: 1.1
+ */
+AdwAvatarAppearance
+adw_avatar_get_appearance (AdwAvatar *self)
+{
+  g_return_val_if_fail (ADW_IS_AVATAR (self), ADW_AVATAR_AUTO);
+
+  return self->appearance;
+}
+
+/**
+ * adw_avatar_set_appearance: (attributes org.gtk.Method.set_property=appearance)
+ * @self: a `AdwAvatar`
+ * @appearance: The appearance of the avatar
+ *
+ * Sets the appearance of the avatar.
+ *
+ * Since: 1.1
+ */
+void
+adw_avatar_set_appearance (AdwAvatar           *self,
+                           AdwAvatarAppearance  appearance)
+{
+  g_return_if_fail (ADW_IS_AVATAR (self));
+  g_return_if_fail (appearance <= ADW_AVATAR_DARK);
+
+  if (self->appearance == appearance)
+    return;
+
+  self->appearance = appearance;
+
+  switch (self->appearance) {
+  case ADW_AVATAR_AUTO:
+    gtk_widget_remove_css_class (self->gizmo, "dark");
+    connect_style_manager (self);
+    break;
+  case ADW_AVATAR_LIGHT:
+    disconnect_style_manager (self);
+    gtk_widget_remove_css_class (self->gizmo, "dark");
+    break;
+  case ADW_AVATAR_DARK:
+    disconnect_style_manager (self);
+    gtk_widget_add_css_class (self->gizmo, "dark");
+    break;
+  default:
+    g_assert_not_reached ();
+  }
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_APPEARANCE]);
+}
+
 /**
  * adw_avatar_draw_to_texture:
  * @self: a `AdwAvatar`
diff --git a/src/adw-avatar.h b/src/adw-avatar.h
index 7a0e1fcc..38e4ba29 100644
--- a/src/adw-avatar.h
+++ b/src/adw-avatar.h
@@ -14,10 +14,18 @@
 
 #include <gtk/gtk.h>
 
+#include "adw-enums.h"
+
 G_BEGIN_DECLS
 
 #define ADW_TYPE_AVATAR (adw_avatar_get_type())
 
+typedef enum {
+  ADW_AVATAR_AUTO,
+  ADW_AVATAR_LIGHT,
+  ADW_AVATAR_DARK,
+} AdwAvatarAppearance;
+
 ADW_AVAILABLE_IN_ALL
 G_DECLARE_FINAL_TYPE (AdwAvatar, adw_avatar, ADW, AVATAR, GtkWidget)
 
@@ -56,6 +64,12 @@ ADW_AVAILABLE_IN_ALL
 void adw_avatar_set_size (AdwAvatar *self,
                           int        size);
 
+ADW_AVAILABLE_IN_ALL
+AdwAvatarAppearance adw_avatar_get_appearance (AdwAvatar           *self);
+ADW_AVAILABLE_IN_ALL
+void                adw_avatar_set_appearance (AdwAvatar           *self,
+                                               AdwAvatarAppearance  appearance);
+
 ADW_AVAILABLE_IN_ALL
 GdkTexture *adw_avatar_draw_to_texture (AdwAvatar *self,
                                         int        scale_factor) G_GNUC_WARN_UNUSED_RESULT;
diff --git a/src/meson.build b/src/meson.build
index 1ed528a0..e6fc1256 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -11,6 +11,7 @@ libadwaita_resources = gnome.compile_resources(
 
 adw_public_enum_headers = [
   'adw-animation.h',
+  'adw-avatar.h',
   'adw-flap.h',
   'adw-fold-threshold-policy.h',
   'adw-easing.h',
diff --git a/src/stylesheet/widgets/_avatar.scss b/src/stylesheet/widgets/_avatar.scss
index df8b6134..b0af25ca 100644
--- a/src/stylesheet/widgets/_avatar.scss
+++ b/src/stylesheet/widgets/_avatar.scss
@@ -24,6 +24,22 @@ avatar {
    (#e5d6ca, #be916d, #785336), // brown
    (#d8d7d3, #c0bfbc, #6e6d71), // gray
   );
+  $_colors_dark: (
+   (#8bb6e7, #3b87e3, #154e93), // blue
+   (#86cfe1, #26adcf, #096381), // cyan
+   (#8ae5a0, #2db978, #1a6b45), // green
+   (#bfed9c, #87c662, #268423), // lime
+   (#e4d18b, #e0ae10, #996900), // yellow
+   (#ecc479, #de9612, #995c00), // gold
+   (#fab258, #ed6503, #b23600), // orange
+   (#f0948b, #e8262f, #8f1927), // raspberry
+   (#f689ba, #e75098, #991f63), // magenta
+   (#ce8ad0, #9545b0, #593078), // purple
+   (#b1a8eb, #775ed9, #443a97), // violet
+   (#c7ab80, #a48547, #5e4a27), // beige
+   (#b99274, #805b3d, #563b25), // brown
+   (#b4b2aa, #77767b, #4d4c52), // gray
+  );
 
   @for $i from 1 through length($_colors) {
     &.color#{$i} {
@@ -31,6 +47,12 @@ avatar {
       background-image: linear-gradient(nth($_color, 2), nth($_color, 3));
       color: nth($_color, 1);
     }
+
+    &.dark.color#{$i} {
+      $_color: nth($_colors_dark, $i);
+      background-image: linear-gradient(nth($_color, 2), nth($_color, 3));
+      color: nth($_color, 1);
+    }
   }
 
   &.contrasted { color: white; }
diff --git a/tests/test-avatar.c b/tests/test-avatar.c
index 3d4396b0..7314cbc0 100644
--- a/tests/test-avatar.c
+++ b/tests/test-avatar.c
@@ -47,6 +47,18 @@ test_adw_avatar_size (void)
   g_assert_finalize_object (avatar);
 }
 
+static void
+test_adw_avatar_appearance (void)
+{
+  AdwAvatar *avatar = g_object_ref_sink (ADW_AVATAR (adw_avatar_new (128, NULL, TRUE)));
+
+  g_assert_cmpint (adw_avatar_get_appearance (avatar), ==, ADW_AVATAR_AUTO);
+  adw_avatar_set_appearance (avatar, ADW_AVATAR_DARK);
+  g_assert_cmpint (adw_avatar_get_appearance (avatar), ==, ADW_AVATAR_DARK);
+
+  g_assert_finalize_object (avatar);
+}
+
 int
 main (int   argc,
       char *argv[])
@@ -57,6 +69,7 @@ main (int   argc,
   g_test_add_func ("/Adwaita/Avatar/icon_name", test_adw_avatar_icon_name);
   g_test_add_func ("/Adwaita/Avatar/text", test_adw_avatar_text);
   g_test_add_func ("/Adwaita/Avatar/size", test_adw_avatar_size);
+  g_test_add_func ("/Adwaita/Avatar/appearance", test_adw_avatar_appearance);
 
   return g_test_run ();
 }


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