*
* The #GtkLabel widget displays a small amount of text. As the name
* implies, most labels are used to label another widget such as a
- * #GtkButton, a #GtkMenuItem, or a #GtkOptionMenu.
+ * #GtkButton, a #GtkMenuItem, or a #GtkComboBox.
*
* <refsect2 id="GtkLabel-BUILDER-UI">
* <title>GtkLabel as GtkBuildable</title>
GtkAllocation *allocation);
static void gtk_label_state_flags_changed (GtkWidget *widget,
GtkStateFlags prev_state);
-static void gtk_label_style_updated (GtkWidget *widget);
-static void gtk_label_direction_changed (GtkWidget *widget,
- GtkTextDirection previous_dir);
static gint gtk_label_draw (GtkWidget *widget,
cairo_t *cr);
static gboolean gtk_label_focus (GtkWidget *widget,
widget_class->destroy = gtk_label_destroy;
widget_class->size_allocate = gtk_label_size_allocate;
widget_class->state_flags_changed = gtk_label_state_flags_changed;
- widget_class->style_updated = gtk_label_style_updated;
widget_class->query_tooltip = gtk_label_query_tooltip;
- widget_class->direction_changed = gtk_label_direction_changed;
widget_class->draw = gtk_label_draw;
widget_class->realize = gtk_label_realize;
widget_class->unrealize = gtk_label_unrealize;
*
* The preferred place to ellipsize the string, if the label does
* not have enough room to display the entire string, specified as a
- * #PangoEllisizeMode.
+ * #PangoEllipsizeMode.
*
* Note that setting this property to a value other than
* %PANGO_ELLIPSIZE_NONE has the side-effect that the label requests
GtkSettings *settings;
gboolean shortcuts_connected;
+ /* The PangoContext is replaced when the screen changes, so clear the layouts */
+ gtk_label_clear_layout (GTK_LABEL (widget));
+
if (!gtk_widget_has_screen (widget))
return;
*
* If the label has been set so that it has an mnemonic key this function
* returns the keyval used for the mnemonic accelerator. If there is no
- * mnemonic set up it returns #GDK_VoidSymbol.
+ * mnemonic set up it returns #GDK_KEY_VoidSymbol.
*
- * Returns: GDK keyval usable for accelerators, or #GDK_VoidSymbol
+ * Returns: GDK keyval usable for accelerators, or #GDK_KEY_VoidSymbol
**/
guint
gtk_label_get_mnemonic_keyval (GtkLabel *label)
}
}
-static PangoFontMetrics *
-get_font_metrics (PangoContext *context, GtkWidget *widget)
-{
- GtkStyleContext *style_context;
- const PangoFontDescription *font;
- PangoFontMetrics *retval;
-
- style_context = gtk_widget_get_style_context (widget);
- font = gtk_style_context_get_font (style_context, GTK_STATE_FLAG_NORMAL);
-
- retval = pango_context_get_metrics (context,
- font,
- pango_context_get_language (context));
-
- return retval;
-}
-
/**
* gtk_label_get_measuring_layout:
* @label: the label
* @existing_layout: %NULL or an existing layout already in use.
* @width: the width to measure with in pango units, or -1 for infinite
- * @height: the height to measure with in pango units, or -1 for infinite
*
* Gets a layout that can be used for measuring sizes. The returned
* layout will be identical to the label's layout except for the
static PangoLayout *
gtk_label_get_measuring_layout (GtkLabel * label,
PangoLayout *existing_layout,
- int width,
- int height)
+ int width)
{
GtkLabelPrivate *priv = label->priv;
PangoRectangle rect;
if (existing_layout != priv->layout)
{
pango_layout_set_width (existing_layout, width);
- pango_layout_set_height (existing_layout, height);
return existing_layout;
}
gtk_label_ensure_layout (label);
- if (pango_layout_get_width (priv->layout) == width &&
- pango_layout_get_height (priv->layout) == height)
+ if (pango_layout_get_width (priv->layout) == width)
{
g_object_ref (priv->layout);
return priv->layout;
{
g_object_ref (priv->layout);
pango_layout_set_width (priv->layout, width);
- pango_layout_set_height (priv->layout, height);
return priv->layout;
}
*/
pango_layout_get_extents (priv->layout, NULL, &rect);
if ((width == -1 || rect.width <= width) &&
- (height == -1 || rect.height <= height) &&
!pango_layout_is_wrapped (priv->layout) &&
!pango_layout_is_ellipsized (priv->layout))
{
copy = pango_layout_copy (priv->layout);
pango_layout_set_width (copy, width);
- pango_layout_set_height (copy, height);
return copy;
}
const gdouble dy = matrix->xy; /* sin (M_PI * angle / 180) */
pango_layout_set_width (priv->layout, -1);
- pango_layout_set_height (priv->layout, -1);
pango_layout_get_pixel_extents (priv->layout, NULL, &logical);
if (fabs (dy) < 0.01)
else
{
pango_layout_set_width (priv->layout, width * PANGO_SCALE);
- pango_layout_set_height (priv->layout, priv->ellipsize ? height * PANGO_SCALE : -1);
}
}
else
{
pango_layout_set_width (priv->layout, -1);
- pango_layout_set_height (priv->layout, -1);
}
}
pango_attr_list_insert (attrs, attribute);
}
}
- else if (priv->markup_attrs && priv->markup_attrs)
+ else if (priv->markup_attrs || priv->attrs)
attrs = pango_attr_list_new ();
else
attrs = NULL;
}
}
-static gint
-get_single_line_height (GtkWidget *widget,
- PangoLayout *layout)
-{
- PangoContext *context;
- PangoFontMetrics *metrics;
- gint ascent, descent;
-
- context = pango_layout_get_context (layout);
- metrics = get_font_metrics (context, widget);
- ascent = pango_font_metrics_get_ascent (metrics);
- descent = pango_font_metrics_get_descent (metrics);
- pango_font_metrics_unref (metrics);
-
- return ascent + descent;
-}
-
static GtkSizeRequestMode
gtk_label_get_request_mode (GtkWidget *widget)
{
gint *minimum_size,
gint *natural_size)
{
- GtkLabelPrivate *priv = label->priv;
PangoLayout *layout;
gint text_height;
- layout = gtk_label_get_measuring_layout (label, NULL, allocation * PANGO_SCALE, -1);
+ layout = gtk_label_get_measuring_layout (label, NULL, allocation * PANGO_SCALE);
pango_layout_get_pixel_size (layout, NULL, &text_height);
*minimum_size = text_height;
if (natural_size)
- {
- if (priv->ellipsize && priv->wrap)
- {
- layout = gtk_label_get_measuring_layout (label, layout, allocation * PANGO_SCALE, G_MAXINT);
- pango_layout_get_pixel_size (layout, NULL, &text_height);
- }
-
- *natural_size = text_height;
- }
+ *natural_size = text_height;
g_object_unref (layout);
}
gint char_width, digit_width;
context = pango_layout_get_context (layout);
- metrics = get_font_metrics (context, GTK_WIDGET (label));
+ metrics = pango_context_get_metrics (context,
+ pango_context_get_font_description (context),
+ pango_context_get_language (context));
char_width = pango_font_metrics_get_approximate_char_width (metrics);
digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
pango_font_metrics_unref (metrics);
static void
gtk_label_get_preferred_layout_size (GtkLabel *label,
- PangoRectangle *required,
- PangoRectangle *natural)
+ PangoRectangle *smallest,
+ PangoRectangle *widest)
{
GtkLabelPrivate *priv = label->priv;
PangoLayout *layout;
+ gint char_pixels;
/* "width-chars" Hard-coded minimum width:
* - minimum size should be MAX (width-chars, strlen ("..."));
*/
/* Start off with the pixel extents of an as-wide-as-possible layout */
- layout = gtk_label_get_measuring_layout (label, NULL, -1, -1);
-
- pango_layout_get_extents (layout, NULL, natural);
- natural->x = natural->y = 0;
+ layout = gtk_label_get_measuring_layout (label, NULL, -1);
- if (priv->wrap)
- natural->height = get_single_line_height (GTK_WIDGET (label), layout);
+ if (priv->width_chars > -1 || priv->max_width_chars > -1)
+ char_pixels = get_char_pixels (GTK_WIDGET (label), layout);
+ else
+ char_pixels = 0;
+
+ pango_layout_get_extents (layout, NULL, widest);
+ widest->width = MAX (widest->width, char_pixels * priv->width_chars);
+ widest->x = widest->y = 0;
if (priv->ellipsize || priv->wrap)
{
/* a layout with width 0 will be as small as humanly possible */
- layout = gtk_label_get_measuring_layout (label, layout, 0, -1);
-
- pango_layout_get_extents (layout, NULL, required);
+ layout = gtk_label_get_measuring_layout (label,
+ layout,
+ priv->width_chars > -1 ? char_pixels * priv->width_chars
+ : 0);
- /* can happen when Pango decides to ellipsize text */
- if (required->width > natural->width)
- required->width = natural->width;
+ pango_layout_get_extents (layout, NULL, smallest);
+ smallest->width = MAX (smallest->width, char_pixels * priv->width_chars);
+ smallest->x = smallest->y = 0;
- required->x = required->y = 0;
- required->height = natural->height;
+ if (priv->max_width_chars > -1 && widest->width > char_pixels * priv->max_width_chars)
+ {
+ layout = gtk_label_get_measuring_layout (label,
+ layout,
+ MAX (smallest->width, char_pixels * priv->max_width_chars));
+ pango_layout_get_extents (layout, NULL, widest);
+ widest->width = MAX (widest->width, char_pixels * priv->width_chars);
+ widest->x = widest->y = 0;
+ }
}
else
{
- *required = *natural;
+ *smallest = *widest;
}
- if (priv->width_chars > -1 || priv->max_width_chars > -1)
- {
- gint char_pixels;
-
- char_pixels = get_char_pixels (GTK_WIDGET (label), layout);
-
- if (priv->width_chars > -1)
- required->width = MAX (required->width, char_pixels * priv->width_chars);
-
- if (priv->max_width_chars > -1)
- natural->width = MIN (natural->width, priv->max_width_chars * char_pixels);
- natural->width = MAX (natural->width, required->width);
- }
+ if (widest->width < smallest->width)
+ *smallest = *widest;
g_object_unref (layout);
}
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = label->priv;
- PangoRectangle required_rect;
- PangoRectangle natural_rect;
+ PangoRectangle widest_rect;
+ PangoRectangle smallest_rect;
GtkBorder border;
- gtk_label_get_preferred_layout_size (label, &required_rect, &natural_rect);
+ gtk_label_get_preferred_layout_size (label, &smallest_rect, &widest_rect);
/* Now that we have minimum and natural sizes in pango extents, apply a possible transform */
if (priv->have_transform)
{
- PangoLayout *copy;
PangoContext *context;
const PangoMatrix *matrix;
- copy = pango_layout_copy (priv->layout);
- context = pango_layout_get_context (copy);
+ context = pango_layout_get_context (priv->layout);
matrix = pango_context_get_matrix (context);
- pango_layout_set_width (copy, -1);
- pango_layout_set_ellipsize (copy, PANGO_ELLIPSIZE_NONE);
+ pango_matrix_transform_rectangle (matrix, &widest_rect);
+ pango_matrix_transform_rectangle (matrix, &smallest_rect);
- pango_layout_get_extents (copy, NULL, &natural_rect);
- g_object_unref (copy);
-
- pango_matrix_transform_rectangle (matrix, &required_rect);
- pango_matrix_transform_rectangle (matrix, &natural_rect);
-
- /* Bump the natural size in case of ellipsize to ensure pango has
+ /* Bump the size in case of ellipsize to ensure pango has
* enough space in the angles (note, we could alternatively set the
* layout to not ellipsize when we know we have been allocated our
- * full natural size, or it may be that pango needs a fix here).
+ * full size, or it may be that pango needs a fix here).
*/
if (priv->ellipsize && priv->angle != 0 && priv->angle != 90 &&
priv->angle != 180 && priv->angle != 270 && priv->angle != 360)
/* For some reason we only need this at about 110 degrees, and only
* when gaining in height
*/
- natural_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
- natural_rect.width += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
+ widest_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
+ widest_rect.width += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
+ smallest_rect.height += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
+ smallest_rect.width += ROTATION_ELLIPSIZE_PADDING * 2 * PANGO_SCALE;
}
}
- required_rect.width = PANGO_PIXELS_CEIL (required_rect.width);
- required_rect.height = PANGO_PIXELS_CEIL (required_rect.height);
+ widest_rect.width = PANGO_PIXELS_CEIL (widest_rect.width);
+ widest_rect.height = PANGO_PIXELS_CEIL (widest_rect.height);
- natural_rect.width = PANGO_PIXELS_CEIL (natural_rect.width);
- natural_rect.height = PANGO_PIXELS_CEIL (natural_rect.height);
+ smallest_rect.width = PANGO_PIXELS_CEIL (smallest_rect.width);
+ smallest_rect.height = PANGO_PIXELS_CEIL (smallest_rect.height);
_gtk_misc_get_padding_and_border (GTK_MISC (label), &border);
*/
get_size_for_allocation (label,
GTK_ORIENTATION_VERTICAL,
- required_rect.height,
+ smallest_rect.height,
minimum_size, natural_size);
}
else
{
/* Normal desired width */
- *minimum_size = required_rect.width;
- *natural_size = natural_rect.width;
+ *minimum_size = smallest_rect.width;
+ *natural_size = widest_rect.width;
}
*minimum_size += border.left + border.right;
*/
get_size_for_allocation (label,
GTK_ORIENTATION_HORIZONTAL,
- required_rect.width,
+ widest_rect.width,
minimum_size, natural_size);
}
else
/* A vertically rotated label does w4h, so return the base
* desired height (text length)
*/
- *minimum_size = required_rect.height;
- *natural_size = natural_rect.height;
+ *minimum_size = MIN (smallest_rect.height, widest_rect.height);
+ *natural_size = MAX (smallest_rect.height, widest_rect.height);
}
*minimum_size += border.top + border.bottom;
gtk_label_update_cursor (label);
}
- /* We have to clear the layout, fonts etc. may have changed */
- gtk_label_clear_layout (label);
-
if (GTK_WIDGET_CLASS (gtk_label_parent_class)->state_flags_changed)
GTK_WIDGET_CLASS (gtk_label_parent_class)->state_flags_changed (widget, prev_state);
}
-static void
-gtk_label_style_updated (GtkWidget *widget)
-{
- GtkLabel *label = GTK_LABEL (widget);
-
- GTK_WIDGET_CLASS (gtk_label_parent_class)->style_updated (widget);
-
- /* We have to clear the layout, fonts etc. may have changed */
- gtk_label_clear_layout (label);
-}
-
-static void
-gtk_label_direction_changed (GtkWidget *widget,
- GtkTextDirection previous_dir)
-{
- GtkLabel *label = GTK_LABEL (widget);
- GtkLabelPrivate *priv = label->priv;
-
- if (priv->layout)
- pango_layout_context_changed (priv->layout);
-
- GTK_WIDGET_CLASS (gtk_label_parent_class)->direction_changed (widget, previous_dir);
-}
-
static void
get_layout_location (GtkLabel *label,
gint *xp,
priv->select_info->window = gdk_window_new (gtk_widget_get_window (widget),
&attributes, attributes_mask);
- gdk_window_set_user_data (priv->select_info->window, widget);
+ gtk_widget_register_window (widget, priv->select_info->window);
if (attributes_mask & GDK_WA_CURSOR)
g_object_unref (attributes.cursor);
if (priv->select_info->window == NULL)
return;
- gdk_window_set_user_data (priv->select_info->window, NULL);
+ gtk_widget_unregister_window (GTK_WIDGET (label), priv->select_info->window);
gdk_window_destroy (priv->select_info->window);
priv->select_info->window = NULL;
}