X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtklabel.c;h=bc17554a230aeeee329c64124acc5326400e12c4;hb=ca2368dba958d6fecf2fce417307bb9cbbe6eb6b;hp=ae6b755b81db700e661ece19a07dcfb32329a58a;hpb=38d869cb8e8d8527a2870e3cd9ed8ebe547ddd0f;p=~andy%2Fgtk diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index ae6b755b8..bc17554a2 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -12,8 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * License along with this library. If not, see .Free */ /* @@ -67,7 +66,7 @@ * * 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. * * * GtkLabel as GtkBuildable @@ -385,9 +384,6 @@ static void gtk_label_size_allocate (GtkWidget *widget, 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, @@ -567,9 +563,7 @@ gtk_label_class_init (GtkLabelClass *class) 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; @@ -841,7 +835,7 @@ gtk_label_class_init (GtkLabelClass *class) * * 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 @@ -1853,6 +1847,9 @@ gtk_label_screen_changed (GtkWidget *widget, 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; @@ -1966,9 +1963,9 @@ gtk_label_get_mnemonic_widget (GtkLabel *label) * * 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) @@ -1980,15 +1977,18 @@ gtk_label_get_mnemonic_keyval (GtkLabel *label) static void gtk_label_set_text_internal (GtkLabel *label, - gchar *str) + gchar *str) { GtkLabelPrivate *priv = label->priv; + gboolean text_changed; - g_free (priv->text); + text_changed = g_strcmp0 (priv->text, str) != 0; + g_free (priv->text); priv->text = str; - gtk_label_select_region_index (label, 0, 0); + if (text_changed) + gtk_label_select_region_index (label, 0, 0); } static void @@ -3134,29 +3134,11 @@ gtk_label_clear_layout (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 @@ -3168,8 +3150,7 @@ get_font_metrics (PangoContext *context, GtkWidget *widget) static PangoLayout * gtk_label_get_measuring_layout (GtkLabel * label, PangoLayout *existing_layout, - int width, - int height) + int width) { GtkLabelPrivate *priv = label->priv; PangoRectangle rect; @@ -3180,7 +3161,6 @@ gtk_label_get_measuring_layout (GtkLabel * label, if (existing_layout != priv->layout) { pango_layout_set_width (existing_layout, width); - pango_layout_set_height (existing_layout, height); return existing_layout; } @@ -3189,8 +3169,7 @@ gtk_label_get_measuring_layout (GtkLabel * label, 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; @@ -3204,7 +3183,6 @@ gtk_label_get_measuring_layout (GtkLabel * label, { g_object_ref (priv->layout); pango_layout_set_width (priv->layout, width); - pango_layout_set_height (priv->layout, height); return priv->layout; } @@ -3215,7 +3193,6 @@ gtk_label_get_measuring_layout (GtkLabel * label, */ 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)) { @@ -3225,7 +3202,6 @@ gtk_label_get_measuring_layout (GtkLabel * label, copy = pango_layout_copy (priv->layout); pango_layout_set_width (copy, width); - pango_layout_set_height (copy, height); return copy; } @@ -3256,7 +3232,6 @@ gtk_label_update_layout_width (GtkLabel *label) 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) @@ -3310,13 +3285,11 @@ gtk_label_update_layout_width (GtkLabel *label) 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); } } @@ -3392,7 +3365,7 @@ gtk_label_ensure_layout (GtkLabel *label) 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; @@ -3447,23 +3420,6 @@ gtk_label_ensure_layout (GtkLabel *label) } } -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) { @@ -3485,11 +3441,10 @@ get_size_for_allocation (GtkLabel *label, 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); @@ -3497,15 +3452,7 @@ get_size_for_allocation (GtkLabel *label, *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); } @@ -3519,7 +3466,9 @@ get_char_pixels (GtkWidget *label, 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); @@ -3529,11 +3478,12 @@ get_char_pixels (GtkWidget *label, 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 ("...")); @@ -3552,46 +3502,46 @@ gtk_label_get_preferred_layout_size (GtkLabel *label, */ /* 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); } @@ -3604,36 +3554,28 @@ gtk_label_get_preferred_size (GtkWidget *widget, { 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_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); + pango_matrix_transform_rectangle (matrix, &widest_rect); + pango_matrix_transform_rectangle (matrix, &smallest_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) @@ -3641,16 +3583,18 @@ gtk_label_get_preferred_size (GtkWidget *widget, /* 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); @@ -3667,15 +3611,15 @@ gtk_label_get_preferred_size (GtkWidget *widget, */ 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; @@ -3694,7 +3638,7 @@ gtk_label_get_preferred_size (GtkWidget *widget, */ get_size_for_allocation (label, GTK_ORIENTATION_HORIZONTAL, - required_rect.width, + widest_rect.width, minimum_size, natural_size); } else @@ -3702,8 +3646,8 @@ gtk_label_get_preferred_size (GtkWidget *widget, /* 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; @@ -3865,37 +3809,10 @@ gtk_label_state_flags_changed (GtkWidget *widget, 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, @@ -4033,13 +3950,20 @@ gtk_label_draw (GtkWidget *widget, gtk_label_ensure_layout (label); + context = gtk_widget_get_style_context (widget); + gtk_widget_get_allocation (widget, &allocation); + + gtk_render_background (context, cr, + 0, 0, + allocation.width, allocation.height); + gtk_render_frame (context, cr, + 0, 0, + allocation.width, allocation.height); + if (priv->text && (*priv->text != '\0')) { get_layout_location (label, &x, &y); - context = gtk_widget_get_style_context (widget); - gtk_widget_get_allocation (widget, &allocation); - cairo_translate (cr, -allocation.x, -allocation.y); gtk_render_layout (context, cr, @@ -5058,7 +4982,7 @@ gtk_label_create_window (GtkLabel *label) 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); @@ -5074,7 +4998,7 @@ gtk_label_destroy_window (GtkLabel *label) 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; }