[libadwaita/wip/exalm/dark-avatar: 2/2] avatar: Add appearance property
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libadwaita/wip/exalm/dark-avatar: 2/2] avatar: Add appearance property
- Date: Mon, 17 Jan 2022 15:01:33 +0000 (UTC)
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]