[libhandy] Add HdyFadingLabel
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libhandy] Add HdyFadingLabel
- Date: Mon, 1 Feb 2021 16:10:23 +0000 (UTC)
commit 19be2f98573ac608f27ab9a57385481d207be8e3
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Tue Jan 26 21:00:05 2021 +0500
Add HdyFadingLabel
Add a helper widget for showing fading ellipsized titles in tabs.
doc/meson.build | 1 +
src/hdy-fading-label-private.h | 31 ++++
src/hdy-fading-label.c | 328 +++++++++++++++++++++++++++++++++++++++++
src/meson.build | 1 +
4 files changed, 361 insertions(+)
---
diff --git a/doc/meson.build b/doc/meson.build
index dd18fca6..622784b1 100644
--- a/doc/meson.build
+++ b/doc/meson.build
@@ -12,6 +12,7 @@ private_headers = [
'hdy-css-private.h',
'hdy-enums.h',
'hdy-enums-private.h',
+ 'hdy-fading-label-private.h',
'hdy-main-private.h',
'hdy-nothing-private.h',
'hdy-keypad-button-private.h',
diff --git a/src/hdy-fading-label-private.h b/src/hdy-fading-label-private.h
new file mode 100644
index 00000000..2ef5d928
--- /dev/null
+++ b/src/hdy-fading-label-private.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 Purism SPC
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ *
+ * Author: Alexander Mikhaylenko <alexander mikhaylenko puri sm>
+ */
+
+#pragma once
+
+#if !defined(_HANDY_INSIDE) && !defined(HANDY_COMPILATION)
+#error "Only <handy.h> can be included directly."
+#endif
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define HDY_TYPE_FADING_LABEL (hdy_fading_label_get_type())
+
+G_DECLARE_FINAL_TYPE (HdyFadingLabel, hdy_fading_label, HDY, FADING_LABEL, GtkBin)
+
+const gchar *hdy_fading_label_get_label (HdyFadingLabel *self);
+void hdy_fading_label_set_label (HdyFadingLabel *self,
+ const gchar *label);
+
+float hdy_fading_label_get_align (HdyFadingLabel *self);
+void hdy_fading_label_set_align (HdyFadingLabel *self,
+ gfloat align);
+
+G_END_DECLS
diff --git a/src/hdy-fading-label.c b/src/hdy-fading-label.c
new file mode 100644
index 00000000..3d1f014b
--- /dev/null
+++ b/src/hdy-fading-label.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2021 Purism SPC
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ *
+ * Author: Alexander Mikhaylenko <alexander mikhaylenko puri sm>
+ */
+
+#include "config.h"
+#include "hdy-fading-label-private.h"
+
+#include <glib/gi18n-lib.h>
+#include "hdy-bidi-private.h"
+
+/**
+ * PRIVATE:hdy-fading-label
+ * @short_description: A helper object for #HdyTab
+ * @title: HdyFadingLabel
+ * @stability: Private
+ *
+ * The HdyFadingLabel widget allows to ellipsize a label with a fading effect.
+ *
+ * Since: 1.1
+ */
+
+#define FADE_WIDTH 18
+
+struct _HdyFadingLabel
+{
+ GtkBin parent_instance;
+
+ GtkWidget *label;
+ gfloat align;
+ cairo_pattern_t *gradient;
+};
+
+G_DEFINE_TYPE (HdyFadingLabel, hdy_fading_label, GTK_TYPE_BIN)
+
+enum {
+ PROP_0,
+ PROP_LABEL,
+ PROP_ALIGN,
+ LAST_PROP
+};
+
+static GParamSpec *props[LAST_PROP];
+
+static gboolean
+is_rtl (HdyFadingLabel *self)
+{
+ PangoDirection pango_direction = PANGO_DIRECTION_NEUTRAL;
+ const gchar *label = hdy_fading_label_get_label (self);
+
+ if (label)
+ pango_direction = hdy_find_base_dir (label, -1);
+
+ if (pango_direction == PANGO_DIRECTION_RTL)
+ return TRUE;
+
+ if (pango_direction == PANGO_DIRECTION_LTR)
+ return FALSE;
+
+ return gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL;
+}
+
+static void
+ensure_gradient (HdyFadingLabel *self)
+{
+ if (self->gradient)
+ return;
+
+ self->gradient = cairo_pattern_create_linear (0, 0, 1, 0);
+ cairo_pattern_add_color_stop_rgba (self->gradient, 0, 1, 1, 1, 0);
+ cairo_pattern_add_color_stop_rgba (self->gradient, 1, 1, 1, 1, 1);
+}
+
+static void
+hdy_fading_label_get_preferred_width (GtkWidget *widget,
+ gint *min,
+ gint *nat)
+{
+ HdyFadingLabel *self = HDY_FADING_LABEL (widget);
+
+ gtk_widget_get_preferred_width (self->label, min, nat);
+
+ if (min)
+ *min = 0;
+}
+
+static void
+hdy_fading_label_get_preferred_width_for_height (GtkWidget *widget,
+ gint for_height,
+ gint *min,
+ gint *nat)
+{
+ hdy_fading_label_get_preferred_width (widget, min, nat);
+}
+
+static void
+hdy_fading_label_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ HdyFadingLabel *self = HDY_FADING_LABEL (widget);
+ gfloat align = is_rtl (self) ? 1 - self->align : self->align;
+ GtkAllocation child_allocation;
+ gint child_width;
+
+ gtk_widget_set_allocation (widget, allocation);
+
+ hdy_fading_label_get_preferred_width (widget, NULL, &child_width);
+
+ child_allocation.x = allocation->x + (gint) ((allocation->width - child_width) * align);
+ child_allocation.y = allocation->y;
+ child_allocation.width = child_width;
+ child_allocation.height = allocation->height;
+
+ gtk_widget_size_allocate (self->label, &child_allocation);
+
+ gtk_widget_get_clip (self->label, &child_allocation);
+ child_allocation.x = allocation->x;
+ child_allocation.width = allocation->width;
+ gtk_widget_set_clip (self->label, &child_allocation);
+}
+
+static gboolean
+hdy_fading_label_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ HdyFadingLabel *self = HDY_FADING_LABEL (widget);
+ gfloat align = is_rtl (self) ? 1 - self->align : self->align;
+ GtkAllocation clip, alloc;
+ int child_width = gtk_widget_get_allocated_width (self->label);
+
+ gtk_widget_get_allocation (widget, &alloc);
+
+ if (child_width <= alloc.width) {
+ gtk_container_propagate_draw (GTK_CONTAINER (widget), self->label, cr);
+
+ return GDK_EVENT_PROPAGATE;
+ }
+
+ ensure_gradient (self);
+
+ gtk_widget_get_clip (self->label, &clip);
+ clip.x = 0;
+ clip.y -= alloc.y;
+ clip.width = alloc.width;
+
+ cairo_save (cr);
+ cairo_rectangle (cr, clip.x, clip.y, clip.width, clip.height);
+ cairo_clip (cr);
+
+ cairo_push_group (cr);
+ gtk_container_propagate_draw (GTK_CONTAINER (widget), self->label, cr);
+
+ if (align > 0) {
+ cairo_save (cr);
+ cairo_translate (cr, clip.x + FADE_WIDTH, clip.y);
+ cairo_scale (cr, -FADE_WIDTH, clip.height);
+ cairo_set_source (cr, self->gradient);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OUT);
+ cairo_fill (cr);
+ cairo_restore (cr);
+ }
+
+ if (align < 1) {
+ cairo_translate (cr, clip.x + clip.width - FADE_WIDTH, clip.y);
+ cairo_scale (cr, FADE_WIDTH, clip.height);
+ cairo_set_source (cr, self->gradient);
+ cairo_rectangle (cr, 0, 0, 1, 1);
+ cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OUT);
+ cairo_fill (cr);
+ }
+
+ cairo_pop_group_to_source (cr);
+ cairo_paint (cr);
+
+ cairo_restore (cr);
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static void
+hdy_fading_label_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ HdyFadingLabel *self = HDY_FADING_LABEL (object);
+
+ switch (prop_id) {
+ case PROP_LABEL:
+ g_value_set_string (value, hdy_fading_label_get_label (self));
+ break;
+
+ case PROP_ALIGN:
+ g_value_set_float (value, hdy_fading_label_get_align (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+hdy_fading_label_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ HdyFadingLabel *self = HDY_FADING_LABEL (object);
+
+ switch (prop_id) {
+ case PROP_LABEL:
+ hdy_fading_label_set_label (self, g_value_get_string (value));
+ break;
+
+ case PROP_ALIGN:
+ hdy_fading_label_set_align (self, g_value_get_float (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+hdy_fading_label_finalize (GObject *object)
+{
+ HdyFadingLabel *self = HDY_FADING_LABEL (object);
+
+ g_clear_pointer (&self->gradient, cairo_pattern_destroy);
+
+ G_OBJECT_CLASS (hdy_fading_label_parent_class)->finalize (object);
+}
+
+static void
+hdy_fading_label_class_init (HdyFadingLabelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = hdy_fading_label_get_property;
+ object_class->set_property = hdy_fading_label_set_property;
+ object_class->finalize = hdy_fading_label_finalize;
+
+ widget_class->get_preferred_width = hdy_fading_label_get_preferred_width;
+ widget_class->get_preferred_width_for_height = hdy_fading_label_get_preferred_width_for_height;
+ widget_class->size_allocate = hdy_fading_label_size_allocate;
+ widget_class->draw = hdy_fading_label_draw;
+
+ props[PROP_LABEL] =
+ g_param_spec_string ("label",
+ _("Label"),
+ _("Label"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+ props[PROP_ALIGN] =
+ g_param_spec_float ("align",
+ _("Align"),
+ _("Align"),
+ 0.0, 1.0, 0.0,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties (object_class, LAST_PROP, props);
+}
+
+static void
+hdy_fading_label_init (HdyFadingLabel *self)
+{
+ gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
+
+ self->label = gtk_label_new (NULL);
+ gtk_widget_show (self->label);
+ gtk_label_set_single_line_mode (GTK_LABEL (self->label), TRUE);
+
+ gtk_container_add (GTK_CONTAINER (self), self->label);
+}
+
+const gchar *
+hdy_fading_label_get_label (HdyFadingLabel *self)
+{
+ g_return_val_if_fail (HDY_IS_FADING_LABEL (self), NULL);
+
+ return gtk_label_get_label (GTK_LABEL (self->label));
+}
+
+void
+hdy_fading_label_set_label (HdyFadingLabel *self,
+ const gchar *label)
+{
+ g_return_if_fail (HDY_IS_FADING_LABEL (self));
+
+ if (!g_strcmp0 (label, hdy_fading_label_get_label (self)))
+ return;
+
+ gtk_label_set_label (GTK_LABEL (self->label), label);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_LABEL]);
+}
+
+float
+hdy_fading_label_get_align (HdyFadingLabel *self)
+{
+ g_return_val_if_fail (HDY_IS_FADING_LABEL (self), 0.0f);
+
+ return self->align;
+}
+
+void
+hdy_fading_label_set_align (HdyFadingLabel *self,
+ gfloat align)
+{
+ g_return_if_fail (HDY_IS_FADING_LABEL (self));
+
+ align = CLAMP (align, 0.0, 1.0);
+
+ if (self->align == align)
+ return;
+
+ self->align = align;
+
+ gtk_widget_queue_allocate (GTK_WIDGET (self));
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALIGN]);
+}
diff --git a/src/meson.build b/src/meson.build
index 7992f72c..f9411a76 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -133,6 +133,7 @@ src_sources = [
'hdy-deck.c',
'hdy-enum-value-object.c',
'hdy-expander-row.c',
+ 'hdy-fading-label.c',
'hdy-flap.c',
'hdy-header-bar.c',
'hdy-header-group.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]