#include "gtkprivate.h"
#include "gtktypebuiltins.h"
+#include "a11y/gtklabelaccessible.h"
/**
* SECTION:gtklabel
gint anchor_index,
gint end_index);
+
static gboolean gtk_label_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
static void gtk_label_setup_mnemonic (GtkLabel *label,
"activate-current-link", 0);
g_type_class_add_private (class, sizeof (GtkLabelPrivate));
+
+ gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_LABEL_ACCESSIBLE);
}
static void
g_value_set_object (value, (GObject*) priv->mnemonic_widget);
break;
case PROP_CURSOR_POSITION:
- if (priv->select_info && priv->select_info->selectable)
- {
- gint offset = g_utf8_pointer_to_offset (priv->text,
- priv->text + priv->select_info->selection_end);
- g_value_set_int (value, offset);
- }
- else
- g_value_set_int (value, 0);
+ g_value_set_int (value, _gtk_label_get_cursor_position (label));
break;
case PROP_SELECTION_BOUND:
- if (priv->select_info && priv->select_info->selectable)
- {
- gint offset = g_utf8_pointer_to_offset (priv->text,
- priv->text + priv->select_info->selection_anchor);
- g_value_set_int (value, offset);
- }
- else
- g_value_set_int (value, 0);
+ g_value_set_int (value, _gtk_label_get_selection_bound (label));
break;
case PROP_ELLIPSIZE:
g_value_set_enum (value, priv->ellipsize);
attribute = pango_attr_stretch_new (g_value_get_enum (&val));
break;
case PANGO_ATTR_UNDERLINE:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
- attribute = pango_attr_underline_new (g_value_get_boolean (&val));
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_UNDERLINE, value, &val, NULL))
+ attribute = pango_attr_underline_new (g_value_get_enum (&val));
+ else
+ {
+ /* XXX: allow boolean for backwards compat, so ignore error */
+ /* Deprecate this somehow */
+ g_value_unset (&val);
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
+ attribute = pango_attr_underline_new (g_value_get_boolean (&val));
+ }
break;
case PANGO_ATTR_STRIKETHROUGH:
if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
}
attr = attribute_from_text (data->builder, name, value, error);
- attr->start_index = start_val;
- attr->end_index = end_val;
if (attr)
{
+ attr->start_index = start_val;
+ attr->end_index = end_val;
+
if (!data->attrs)
data->attrs = pango_attr_list_new ();
* Return value: the text of the label widget. This string is
* owned by the widget and must not be modified or freed.
**/
-G_CONST_RETURN gchar *
+const gchar *
gtk_label_get_label (GtkLabel *label)
{
g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
* Return value: the text in the label widget. This is the internal
* string used by the label, and must not be modified.
**/
-G_CONST_RETURN gchar *
+const gchar *
gtk_label_get_text (GtkLabel *label)
{
g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
gtk_label_set_pattern (GtkLabel *label,
const gchar *pattern)
{
- GtkLabelPrivate *priv = label->priv;
+ GtkLabelPrivate *priv;
g_return_if_fail (GTK_IS_LABEL (label));
get_font_metrics (PangoContext *context, GtkWidget *widget)
{
GtkStyleContext *style_context;
- PangoFontDescription *font;
+ const PangoFontDescription *font;
PangoFontMetrics *retval;
style_context = gtk_widget_get_style_context (widget);
- gtk_style_context_get (style_context, 0, "font", &font, NULL);
+ font = gtk_style_context_get_font (style_context, GTK_STATE_FLAG_NORMAL);
retval = pango_context_get_metrics (context,
font,
pango_context_get_language (context));
- if (font != NULL)
- pango_font_description_free (font);
-
return retval;
}
layout = gtk_label_get_measuring_layout (label, layout, 0, -1);
pango_layout_get_extents (layout, NULL, required);
+
+ /* can happen when Pango decides to ellipsize text */
+ if (required->width > natural->width)
+ required->width = natural->width;
+
required->x = required->y = 0;
required->height = natural->height;
}
gtk_widget_get_allocation (widget, &allocation);
- x = floor (allocation.x + xpad + xalign * (allocation.width - req_width));
-
- if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
- x = MAX (x, allocation.x + xpad);
- else
- x = MIN (x, allocation.x + allocation.width - xpad);
+ x = floor (allocation.x + xpad + xalign * (allocation.width - req_width) - logical.x);
/* bgo#315462 - For single-line labels, *do* align the requisition with
* middle". You want to read the first line, at least, to get some context.
*/
if (pango_layout_get_line_count (priv->layout) == 1)
- y = floor (allocation.y + ypad + (allocation.height - req_height) * yalign);
+ y = floor (allocation.y + ypad + (allocation.height - req_height) * yalign) - logical.y;
else
- y = floor (allocation.y + ypad + MAX ((allocation.height - req_height) * yalign, 0));
+ y = floor (allocation.y + ypad + MAX ((allocation.height - req_height) * yalign, 0)) - logical.y;
if (xp)
*xp = x;
if (priv->text && (*priv->text != '\0'))
{
- GdkRGBA *bg_color, *fg_color;
+ GdkRGBA bg_color, fg_color;
get_layout_location (label, &x, &y);
if (gtk_widget_has_focus (widget))
state |= GTK_STATE_FLAG_FOCUSED;
- gtk_style_context_get (context, state,
- "background-color", &bg_color,
- "color", &fg_color,
- NULL);
+ gtk_style_context_get_color (context, state, &fg_color);
+ gtk_style_context_get_background_color (context, state, &bg_color);
- gdk_cairo_set_source_rgba (cr, bg_color);
+ gdk_cairo_set_source_rgba (cr, &bg_color);
cairo_paint (cr);
- gdk_cairo_set_source_rgba (cr, fg_color);
+ gdk_cairo_set_source_rgba (cr, &fg_color);
cairo_move_to (cr, x, y);
_gtk_pango_fill_layout (cr, priv->layout);
cairo_restore (cr);
cairo_region_destroy (clip);
-
- gdk_rgba_free (bg_color);
- gdk_rgba_free (fg_color);
}
else if (info)
{
if (active_link)
{
- GdkRGBA *bg_color;
+ GdkRGBA bg_color;
range[0] = active_link->start;
range[1] = active_link->end;
else
state = GTK_STATE_FLAG_PRELIGHT;
- gtk_style_context_get (context, state,
- "background-color", &bg_color,
- NULL);
+ gtk_style_context_get_background_color (context, state, &bg_color);
- gdk_cairo_set_source_rgba (cr, bg_color);
+ gdk_cairo_set_source_rgba (cr, &bg_color);
cairo_paint (cr);
gdk_cairo_set_source_color (cr, text_color);
gdk_color_free (link_color);
gdk_color_free (visited_link_color);
- gdk_rgba_free (bg_color);
cairo_restore (cr);
}
if (event->button == 1)
{
if (!gtk_widget_has_focus (widget))
- {
- priv->in_click = TRUE;
- gtk_widget_grab_focus (widget);
- priv->in_click = FALSE;
- }
+ {
+ priv->in_click = TRUE;
+ gtk_widget_grab_focus (widget);
+ priv->in_click = FALSE;
+ }
if (event->type == GDK_3BUTTON_PRESS)
- {
- gtk_label_select_region_index (label, 0, strlen (priv->text));
- return TRUE;
- }
+ {
+ gtk_label_select_region_index (label, 0, strlen (priv->text));
+ return TRUE;
+ }
if (event->type == GDK_2BUTTON_PRESS)
- {
+ {
info->select_words = TRUE;
- gtk_label_select_word (label);
- return TRUE;
- }
+ gtk_label_select_word (label);
+ return TRUE;
+ }
get_layout_index (label, event->x, event->y, &index);
max = MAX (info->selection_anchor, info->selection_end);
if ((info->selection_anchor != info->selection_end) &&
- (event->state & GDK_SHIFT_MASK))
- {
- /* extend (same as motion) */
- min = MIN (min, index);
- max = MAX (max, index);
+ (event->state & GDK_SHIFT_MASK))
+ {
+ if (index > min && index < max)
+ {
+ /* truncate selection, but keep it as big as possible */
+ if (index - min > max - index)
+ max = index;
+ else
+ min = index;
+ }
+ else
+ {
+ /* extend (same as motion) */
+ min = MIN (min, index);
+ max = MAX (max, index);
+ }
- /* ensure the anchor is opposite index */
- if (index == min)
- {
- gint tmp = min;
- min = max;
- max = tmp;
- }
+ /* ensure the anchor is opposite index */
+ if (index == min)
+ {
+ gint tmp = min;
+ min = max;
+ max = tmp;
+ }
- gtk_label_select_region_index (label, min, max);
- }
+ gtk_label_select_region_index (label, min, max);
+ }
else
- {
- if (event->type == GDK_3BUTTON_PRESS)
- gtk_label_select_region_index (label, 0, strlen (priv->text));
- else if (event->type == GDK_2BUTTON_PRESS)
- gtk_label_select_word (label);
- else if (min < max && min <= index && index <= max)
- {
- info->in_drag = TRUE;
- info->drag_start_x = event->x;
- info->drag_start_y = event->y;
- }
- else
- /* start a replacement */
- gtk_label_select_region_index (label, index, index);
- }
+ {
+ if (event->type == GDK_3BUTTON_PRESS)
+ gtk_label_select_region_index (label, 0, strlen (priv->text));
+ else if (event->type == GDK_2BUTTON_PRESS)
+ gtk_label_select_word (label);
+ else if (min < max && min <= index && index <= max)
+ {
+ info->in_drag = TRUE;
+ info->drag_start_x = event->x;
+ info->drag_start_y = event->y;
+ }
+ else
+ /* start a replacement */
+ gtk_label_select_region_index (label, index, index);
+ }
return TRUE;
}
GtkClipboard *clipboard;
if (priv->select_info->selection_anchor == anchor_index &&
- priv->select_info->selection_end == end_index)
- return;
+ priv->select_info->selection_end == end_index)
+ return;
+
+ g_object_freeze_notify (G_OBJECT (label));
+
+ if (priv->select_info->selection_anchor != anchor_index)
+ g_object_notify (G_OBJECT (label), "selection-bound");
+ if (priv->select_info->selection_end != end_index)
+ g_object_notify (G_OBJECT (label), "cursor-position");
priv->select_info->selection_anchor = anchor_index;
priv->select_info->selection_end = end_index;
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (label),
- GDK_SELECTION_PRIMARY);
+ if (gtk_widget_has_screen (GTK_WIDGET (label)))
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (label),
+ GDK_SELECTION_PRIMARY);
+ else
+ clipboard = NULL;
if (anchor_index != end_index)
{
gtk_target_list_add_text_targets (list, 0);
targets = gtk_target_table_new_from_list (list, &n_targets);
- gtk_clipboard_set_with_owner (clipboard,
- targets, n_targets,
- get_text_callback,
- clear_text_callback,
- G_OBJECT (label));
+ if (clipboard)
+ gtk_clipboard_set_with_owner (clipboard,
+ targets, n_targets,
+ get_text_callback,
+ clear_text_callback,
+ G_OBJECT (label));
gtk_target_table_free (targets, n_targets);
gtk_target_list_unref (list);
}
else
{
- if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (label))
+ if (clipboard &&
+ gtk_clipboard_get_owner (clipboard) == G_OBJECT (label))
gtk_clipboard_clear (clipboard);
}
gtk_widget_queue_draw (GTK_WIDGET (label));
- g_object_freeze_notify (G_OBJECT (label));
- g_object_notify (G_OBJECT (label), "cursor-position");
- g_object_notify (G_OBJECT (label), "selection-bound");
g_object_thaw_notify (G_OBJECT (label));
}
}
{
g_return_if_fail (GTK_IS_LABEL (label));
+ g_object_freeze_notify (G_OBJECT (label));
+
gtk_label_set_use_markup_internal (label, setting);
gtk_label_recalculate (label);
+
+ g_object_thaw_notify (G_OBJECT (label));
}
/**
{
g_return_if_fail (GTK_IS_LABEL (label));
+ g_object_freeze_notify (G_OBJECT (label));
+
gtk_label_set_use_underline_internal (label, setting);
gtk_label_recalculate (label);
+
+ g_object_thaw_notify (G_OBJECT (label));
}
/**
static void
gtk_label_move_cursor (GtkLabel *label,
- GtkMovementStep step,
- gint count,
- gboolean extend_selection)
+ GtkMovementStep step,
+ gint count,
+ gboolean extend_selection)
{
GtkLabelPrivate *priv = label->priv;
gint old_pos;
* start/or end of the selection as appropriate
*/
switch (step)
- {
- case GTK_MOVEMENT_VISUAL_POSITIONS:
- {
- gint end_x, end_y;
- gint anchor_x, anchor_y;
- gboolean end_is_left;
-
- get_better_cursor (label, priv->select_info->selection_end, &end_x, &end_y);
- get_better_cursor (label, priv->select_info->selection_anchor, &anchor_x, &anchor_y);
-
- end_is_left = (end_y < anchor_y) || (end_y == anchor_y && end_x < anchor_x);
-
- if (count < 0)
- new_pos = end_is_left ? priv->select_info->selection_end : priv->select_info->selection_anchor;
- else
- new_pos = !end_is_left ? priv->select_info->selection_end : priv->select_info->selection_anchor;
- break;
- }
- case GTK_MOVEMENT_LOGICAL_POSITIONS:
- case GTK_MOVEMENT_WORDS:
- if (count < 0)
- new_pos = MIN (priv->select_info->selection_end, priv->select_info->selection_anchor);
- else
- new_pos = MAX (priv->select_info->selection_end, priv->select_info->selection_anchor);
- break;
- case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
- case GTK_MOVEMENT_PARAGRAPH_ENDS:
- case GTK_MOVEMENT_BUFFER_ENDS:
- /* FIXME: Can do better here */
- new_pos = count < 0 ? 0 : strlen (priv->text);
- break;
- case GTK_MOVEMENT_DISPLAY_LINES:
- case GTK_MOVEMENT_PARAGRAPHS:
- case GTK_MOVEMENT_PAGES:
- case GTK_MOVEMENT_HORIZONTAL_PAGES:
- break;
- }
+ {
+ case GTK_MOVEMENT_VISUAL_POSITIONS:
+ {
+ gint end_x, end_y;
+ gint anchor_x, anchor_y;
+ gboolean end_is_left;
+
+ get_better_cursor (label, priv->select_info->selection_end, &end_x, &end_y);
+ get_better_cursor (label, priv->select_info->selection_anchor, &anchor_x, &anchor_y);
+
+ end_is_left = (end_y < anchor_y) || (end_y == anchor_y && end_x < anchor_x);
+
+ if (count < 0)
+ new_pos = end_is_left ? priv->select_info->selection_end : priv->select_info->selection_anchor;
+ else
+ new_pos = !end_is_left ? priv->select_info->selection_end : priv->select_info->selection_anchor;
+ break;
+ }
+ case GTK_MOVEMENT_LOGICAL_POSITIONS:
+ case GTK_MOVEMENT_WORDS:
+ if (count < 0)
+ new_pos = MIN (priv->select_info->selection_end, priv->select_info->selection_anchor);
+ else
+ new_pos = MAX (priv->select_info->selection_end, priv->select_info->selection_anchor);
+ break;
+ case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
+ case GTK_MOVEMENT_PARAGRAPH_ENDS:
+ case GTK_MOVEMENT_BUFFER_ENDS:
+ /* FIXME: Can do better here */
+ new_pos = count < 0 ? 0 : strlen (priv->text);
+ break;
+ case GTK_MOVEMENT_DISPLAY_LINES:
+ case GTK_MOVEMENT_PARAGRAPHS:
+ case GTK_MOVEMENT_PAGES:
+ case GTK_MOVEMENT_HORIZONTAL_PAGES:
+ break;
+ }
}
else
{
switch (step)
- {
- case GTK_MOVEMENT_LOGICAL_POSITIONS:
- new_pos = gtk_label_move_logically (label, new_pos, count);
- break;
- case GTK_MOVEMENT_VISUAL_POSITIONS:
- new_pos = gtk_label_move_visually (label, new_pos, count);
+ {
+ case GTK_MOVEMENT_LOGICAL_POSITIONS:
+ new_pos = gtk_label_move_logically (label, new_pos, count);
+ break;
+ case GTK_MOVEMENT_VISUAL_POSITIONS:
+ new_pos = gtk_label_move_visually (label, new_pos, count);
if (new_pos == old_pos)
{
if (!extend_selection)
gtk_widget_error_bell (GTK_WIDGET (label));
}
}
- break;
- case GTK_MOVEMENT_WORDS:
- while (count > 0)
- {
- new_pos = gtk_label_move_forward_word (label, new_pos);
- count--;
- }
- while (count < 0)
- {
- new_pos = gtk_label_move_backward_word (label, new_pos);
- count++;
- }
+ break;
+ case GTK_MOVEMENT_WORDS:
+ while (count > 0)
+ {
+ new_pos = gtk_label_move_forward_word (label, new_pos);
+ count--;
+ }
+ while (count < 0)
+ {
+ new_pos = gtk_label_move_backward_word (label, new_pos);
+ count++;
+ }
if (new_pos == old_pos)
gtk_widget_error_bell (GTK_WIDGET (label));
- break;
- case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
- case GTK_MOVEMENT_PARAGRAPH_ENDS:
- case GTK_MOVEMENT_BUFFER_ENDS:
- /* FIXME: Can do better here */
- new_pos = count < 0 ? 0 : strlen (priv->text);
+ break;
+ case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
+ case GTK_MOVEMENT_PARAGRAPH_ENDS:
+ case GTK_MOVEMENT_BUFFER_ENDS:
+ /* FIXME: Can do better here */
+ new_pos = count < 0 ? 0 : strlen (priv->text);
if (new_pos == old_pos)
gtk_widget_error_bell (GTK_WIDGET (label));
- break;
- case GTK_MOVEMENT_DISPLAY_LINES:
- case GTK_MOVEMENT_PARAGRAPHS:
- case GTK_MOVEMENT_PAGES:
- case GTK_MOVEMENT_HORIZONTAL_PAGES:
- break;
- }
+ break;
+ case GTK_MOVEMENT_DISPLAY_LINES:
+ case GTK_MOVEMENT_PARAGRAPHS:
+ case GTK_MOVEMENT_PAGES:
+ case GTK_MOVEMENT_HORIZONTAL_PAGES:
+ break;
+ }
}
if (extend_selection)
gtk_label_select_region_index (label,
- priv->select_info->selection_anchor,
- new_pos);
+ priv->select_info->selection_anchor,
+ new_pos);
else
gtk_label_select_region_index (label, new_pos, new_pos);
}
*
* Since: 2.18
*/
-G_CONST_RETURN gchar *
+const gchar *
gtk_label_get_current_uri (GtkLabel *label)
{
GtkLabelLink *link;
keyboard_tip,
tooltip);
}
+
+gint
+_gtk_label_get_cursor_position (GtkLabel *label)
+{
+ GtkLabelPrivate *priv = label->priv;
+
+ if (priv->select_info && priv->select_info->selectable)
+ return g_utf8_pointer_to_offset (priv->text,
+ priv->text + priv->select_info->selection_end);
+
+ return 0;
+}
+
+gint
+_gtk_label_get_selection_bound (GtkLabel *label)
+{
+ GtkLabelPrivate *priv = label->priv;
+
+ if (priv->select_info && priv->select_info->selectable)
+ return g_utf8_pointer_to_offset (priv->text,
+ priv->text + priv->select_info->selection_anchor);
+
+ return 0;
+}