summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2023-04-29 10:40:20 -0400
committerMatthias Clasen <mclasen@redhat.com>2023-04-29 10:42:29 -0400
commitebd4f55335fdbf0c69fc4492b945f8f4ff007ea9 (patch)
tree8971aebf830c76974bb9f9ee1c4b44eae288ace0
parenta8a0850b64a29ddfbb1798451759ec63d47db301 (diff)
downloadgtk+-label-baseline-row.tar.gz
label: Allow picking a baseline rowlabel-baseline-row
Add a property that specifies which line in a multi-line label to align to the baseline.
-rw-r--r--gtk/gtklabel.c104
-rw-r--r--gtk/gtklabel.h6
2 files changed, 105 insertions, 5 deletions
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index ecb48a8d07..ee8b462aa2 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -284,6 +284,8 @@ struct _GtkLabel
guint mnemonic_keyval;
+ unsigned int baseline_row;
+
int width_chars;
int max_width_chars;
int lines;
@@ -381,6 +383,7 @@ enum {
PROP_0,
PROP_LABEL,
PROP_ATTRIBUTES,
+ PROP_BASELINE_ROW,
PROP_USE_MARKUP,
PROP_USE_UNDERLINE,
PROP_JUSTIFY,
@@ -477,6 +480,9 @@ gtk_label_set_property (GObject *object,
case PROP_ATTRIBUTES:
gtk_label_set_attributes (self, g_value_get_boxed (value));
break;
+ case PROP_BASELINE_ROW:
+ gtk_label_set_baseline_row (self, g_value_get_uint (value));
+ break;
case PROP_USE_MARKUP:
gtk_label_set_use_markup (self, g_value_get_boolean (value));
break;
@@ -550,6 +556,9 @@ gtk_label_get_property (GObject *object,
case PROP_ATTRIBUTES:
g_value_set_boxed (value, self->attrs);
break;
+ case PROP_BASELINE_ROW:
+ g_value_set_uint (value, self->baseline_row);
+ break;
case PROP_USE_MARKUP:
g_value_set_boolean (value, self->use_markup);
break;
@@ -1091,6 +1100,31 @@ get_default_widths (GtkLabel *self,
}
}
+static int
+get_layout_baseline (GtkLabel *self,
+ PangoLayout *layout)
+{
+ PangoLayoutIter *iter;
+ int baseline;
+ unsigned int lineno;
+
+ lineno = 0;
+ iter = pango_layout_get_iter (layout);
+ do
+ {
+ if (lineno == self->baseline_row)
+ break;
+
+ lineno++;
+ }
+ while (pango_layout_iter_next_line (iter));
+
+ baseline = pango_layout_iter_get_baseline (iter);
+ pango_layout_iter_free (iter);
+
+ return baseline;
+}
+
static void
get_static_size (GtkLabel *self,
GtkOrientation orientation,
@@ -1126,7 +1160,7 @@ get_static_size (GtkLabel *self,
else
{
pango_layout_get_size (layout, NULL, minimum);
- *minimum_baseline = pango_layout_get_baseline (layout);
+ *minimum_baseline = get_layout_baseline (self, layout);
*natural = *minimum;
*natural_baseline = *minimum_baseline;
@@ -1151,7 +1185,7 @@ get_height_for_width (GtkLabel *self,
/* Minimum height is assuming infinite width */
layout = gtk_label_get_measuring_layout (self, NULL, -1);
pango_layout_get_size (layout, NULL, minimum_height);
- baseline = pango_layout_get_baseline (layout);
+ baseline = get_layout_baseline (self, layout);
*minimum_baseline = baseline;
/* Natural height is assuming natural width */
@@ -1159,7 +1193,7 @@ get_height_for_width (GtkLabel *self,
layout = gtk_label_get_measuring_layout (self, layout, natural_width);
pango_layout_get_size (layout, NULL, natural_height);
- baseline = pango_layout_get_baseline (layout);
+ baseline = get_layout_baseline (self, layout);
*natural_baseline = baseline;
}
else
@@ -1172,7 +1206,7 @@ get_height_for_width (GtkLabel *self,
*minimum_height = text_height;
*natural_height = text_height;
- baseline = pango_layout_get_baseline (layout);
+ baseline = get_layout_baseline (self, layout);
*minimum_baseline = baseline;
*natural_baseline = baseline;
}
@@ -1338,7 +1372,7 @@ get_layout_location (GtkLabel *self,
baseline = gtk_widget_get_baseline (widget);
if (baseline != -1)
{
- int layout_baseline = pango_layout_get_baseline (self->layout) / PANGO_SCALE;
+ int layout_baseline = get_layout_baseline (self, self->layout) / PANGO_SCALE;
/* yalign is 0 because we can't support yalign while baseline aligning */
y = baseline - layout_baseline;
}
@@ -2597,6 +2631,21 @@ gtk_label_class_init (GtkLabelClass *class)
PANGO_TYPE_TAB_ARRAY,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+ /**
+ * GtkLabel:baseline-row: (attributes org.gtk.Property.get=gtk_label_get_baseline_row org.gtk.Property.set=gtk_label_set_baseline_row)
+ *
+ * The line in the text to which the baseline is aligned.
+ *
+ * If this number is bigger than the the number of lines in the formatted
+ * text, the baseline is aligned to the last line.
+ *
+ * Since: 4.12
+ */
+ label_props[PROP_BASELINE_ROW] =
+ g_param_spec_uint ("baseline-row", NULL, NULL,
+ 0, G_MAXUINT, 0,
+ GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
+
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, label_props);
/**
@@ -6025,3 +6074,48 @@ gtk_label_get_tabs (GtkLabel *self)
return self->tabs ? pango_tab_array_copy (self->tabs) : NULL;
}
+
+/**
+ * gtk_label_set_baseline_row:
+ * @self: a `GtkLabel`
+ * @baseline_row: the row to align with the baseline
+ *
+ * Sets the row to align with the baseline.
+ *
+ * This is only relevant if the label is inside a container
+ * that is doing baseline alignment.
+ *
+ * Since: 4.12
+ */
+void
+gtk_label_set_baseline_row (GtkLabel *self,
+ unsigned int baseline_row)
+{
+ g_return_if_fail (GTK_IS_LABEL (self));
+
+ if (self->baseline_row == baseline_row)
+ return;
+
+ self->baseline_row = baseline_row;
+
+ g_object_notify_by_pspec (G_OBJECT (self), label_props[PROP_BASELINE_ROW]);
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+}
+
+/**
+ * gtk_label_get_baseline_row:
+ * @self: a `GtkLabel`
+ *
+ * Gets the row to align with the baseline.
+ *
+ * Returns: the row to align with the baseline
+ *
+ * Since: 4.12
+ */
+unsigned int
+gtk_label_get_baseline_row (GtkLabel *self)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (self), 0);
+
+ return self->baseline_row;
+}
diff --git a/gtk/gtklabel.h b/gtk/gtklabel.h
index c27b60b5f9..dd182473ff 100644
--- a/gtk/gtklabel.h
+++ b/gtk/gtklabel.h
@@ -183,6 +183,12 @@ void gtk_label_set_tabs (GtkLabel *self,
GDK_AVAILABLE_IN_4_8
PangoTabArray * gtk_label_get_tabs (GtkLabel *self);
+GDK_AVAILABLE_IN_4_12
+void gtk_label_set_baseline_row (GtkLabel *self,
+ unsigned int baseline_row);
+
+GDK_AVAILABLE_IN_4_12
+unsigned int gtk_label_get_baseline_row (GtkLabel *self);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkLabel, g_object_unref)