#include <string.h>
#include "gtklabel.h"
#include "gtkmain.h"
+#include "gtkmarshalers.h"
#include "gtksignal.h"
#include "gtkwindow.h"
#include "gdk/gdkkeysyms.h"
#include "gtkclipboard.h"
-#include "gdk/gdki18n.h"
#include <pango/pango.h>
+#include "gtkimagemenuitem.h"
#include "gtkintl.h"
#include "gtkseparatormenuitem.h"
#include "gtkmenuitem.h"
#include "gtknotebook.h"
+#include "gtkstock.h"
#include "gtkbindings.h"
struct _GtkLabelSelectionInfo
GdkWindow *window;
gint selection_anchor;
gint selection_end;
- GdkGC *cursor_gc;
GtkWidget *popup_menu;
};
PROP_WRAP,
PROP_SELECTABLE,
PROP_MNEMONIC_KEYVAL,
- PROP_MNEMONIC_WIDGET
+ PROP_MNEMONIC_WIDGET,
+ PROP_CURSOR_POSITION,
+ PROP_SELECTION_BOUND
};
static guint signals[LAST_SIGNAL] = { 0 };
static void gtk_label_create_window (GtkLabel *label);
static void gtk_label_destroy_window (GtkLabel *label);
static void gtk_label_clear_layout (GtkLabel *label);
-static void gtk_label_ensure_layout (GtkLabel *label,
- gint *widthp,
- gint *heightp);
+static void gtk_label_ensure_layout (GtkLabel *label);
static void gtk_label_select_region_index (GtkLabel *label,
gint anchor_index,
gint end_index);
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkLabelClass, move_cursor),
- gtk_marshal_VOID__ENUM_INT_BOOLEAN,
+ _gtk_marshal_VOID__ENUM_INT_BOOLEAN,
GTK_TYPE_NONE, 3, GTK_TYPE_MOVEMENT_STEP, GTK_TYPE_INT, GTK_TYPE_BOOL);
signals[COPY_CLIPBOARD] =
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkLabelClass, copy_clipboard),
- gtk_marshal_VOID__VOID,
+ _gtk_marshal_VOID__VOID,
GTK_TYPE_NONE, 0);
signals[POPULATE_POPUP] =
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkLabelClass, populate_popup),
- gtk_marshal_VOID__OBJECT,
+ _gtk_marshal_VOID__OBJECT,
GTK_TYPE_NONE, 1, GTK_TYPE_MENU);
g_object_class_install_property (G_OBJECT_CLASS(object_class),
g_param_spec_boolean ("wrap",
_("Line wrap"),
_("If set, wrap lines if the text becomes too wide."),
- TRUE,
+ FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_SELECTABLE,
GTK_TYPE_WIDGET,
G_PARAM_READWRITE));
- gtk_widget_class_install_style_property (widget_class,
- g_param_spec_boxed ("cursor_color",
- _("Cursor color"),
- _("Color with which to draw insertion cursor"),
- GDK_TYPE_COLOR,
- G_PARAM_READABLE));
+ g_object_class_install_property (gobject_class,
+ PROP_CURSOR_POSITION,
+ g_param_spec_int ("cursor_position",
+ _("Cursor Position"),
+ _("The current position of the insertion cursor in chars."),
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_SELECTION_BOUND,
+ g_param_spec_int ("selection_bound",
+ _("Selection Bound"),
+ _("The position of the opposite end of the selection from the cursor in chars."),
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READABLE));
/*
* Key bindings
case PROP_MNEMONIC_WIDGET:
g_value_set_object (value, (GObject*) label->mnemonic_widget);
break;
+ case PROP_CURSOR_POSITION:
+ if (label->select_info)
+ {
+ gint offset = g_utf8_pointer_to_offset (label->label,
+ label->label + label->select_info->selection_end);
+ g_value_set_int (value, offset);
+ }
+ else
+ g_value_set_int (value, 0);
+ break;
+ case PROP_SELECTION_BOUND:
+ if (label->select_info)
+ {
+ gint offset = g_utf8_pointer_to_offset (label->label,
+ label->label + label->select_info->selection_anchor);
+ g_value_set_int (value, offset);
+ }
+ else
+ g_value_set_int (value, 0);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
label->label = NULL;
- label->jtype = GTK_JUSTIFY_CENTER;
+ label->jtype = GTK_JUSTIFY_LEFT;
label->wrap = FALSE;
label->use_underline = FALSE;
* gtk_label_new:
* @str: The text of the label
*
- * Creates a new #GtkLabel, containing the text in @str.
+ * Creates a new label with the given text inside it. You can
+ * pass %NULL to get an empty label widget.
*
* Return value: the new #GtkLabel
**/
* Creates a new #GtkLabel, containing the text in @str.
*
* If characters in @str are preceded by an underscore, they are
- * underlined indicating that they represent a keyboard accelerator
- * called a mnemonic. The mnemonic key can be used to activate
- * another widget, chosen automatically, or explicitly using
+ * underlined. If you need a literal underscore character in a label, use
+ * '__' (two underscores). The first underlined character represents a
+ * keyboard accelerator called a mnemonic. The mnemonic key can be used
+ * to activate another widget, chosen automatically, or explicitly using
* gtk_label_set_mnemonic_widget().
*
* If gtk_label_set_mnemonic_widget()
* widget's ancestry.
*/
parent = widget->parent;
+
+ if (parent && GTK_IS_NOTEBOOK (parent))
+ return FALSE;
+
while (parent)
{
if (GTK_WIDGET_CAN_FOCUS (parent) ||
/* barf if there was nothing to activate */
g_warning ("Couldn't find a target for a mnemonic activation.");
- gdk_beep ();
+ gdk_display_beep (gtk_widget_get_display (widget));
return FALSE;
}
GtkWidget *old_toplevel)
{
GtkLabel *label = GTK_LABEL (widget);
+
+ /* in case the label has been reparented to another screen */
+ gtk_label_clear_layout (label);
gtk_label_setup_mnemonic (label, label->mnemonic_keyval);
}
label->mnemonic_widget = widget;
if (label->mnemonic_widget)
gtk_widget_ref (label->mnemonic_widget);
+
+ g_object_notify (G_OBJECT (label), "mnemonic_widget");
}
/**
* returns the keyval used for the mnemonic accelerator. If there is no
* mnemonic set up it returns #GDK_VoidSymbol.
*
- * Returns: GDK keyval usable for accelerators, or GDK_VoidSymbol
+ * Returns: GDK keyval usable for accelerators, or #GDK_VoidSymbol
**/
guint
gtk_label_get_mnemonic_keyval (GtkLabel *label)
/**
* gtk_label_set_text:
* @label: a #GtkLabel
- * @str: a string
+ * @str: The text you want to set.
*
- * Sets the text of the label to @str.
+ * Sets the text within the #GtkLabel widget. It overwrites any text that
+ * was there before.
*
* This will also clear any previously set mnemonic accelerators.
**/
{
g_return_if_fail (GTK_IS_LABEL (label));
+ g_object_freeze_notify (G_OBJECT (label));
+
gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
gtk_label_set_use_markup_internal (label, FALSE);
gtk_label_set_use_underline_internal (label, FALSE);
gtk_label_recalculate (label);
+
+ g_object_thaw_notify (G_OBJECT (label));
}
/**
* @label: a #GtkLabel
* @str: a markup string (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
*
- * Parses @str which is marked up with the Pango text markup language,
+ * Parses @str which is marked up with the <link linkend="PangoMarkupFormat">Pango text markup language</link>,
* setting the label's text and attribute list based on the parse results.
**/
void
* @label: a #GtkLabel
* @str: a markup string (see <link linkend="PangoMarkupFormat">Pango markup format</link>)
*
- * Parses @str which is marked up with the Pango text markup language,
+ * Parses @str which is marked up with the <link linkend="PangoMarkupFormat">Pango text markup language</link>,
* setting the label's text and attribute list based on the parse results.
* If characters in @str are preceded by an underscore, they are underlined
* indicating that they represent a keyboard accelerator called a mnemonic.
* @jtype: a #GtkJustification
*
* Sets the alignment of the lines in the text of the label relative to
- * each other.
+ * each other. %GTK_JUSTIFY_LEFT is the default value when the
+ * widget is first created with gtk_label_new(). If you instead want
+ * to set the alignment of the label as a whole, use
+ * gtk_misc_set_alignment() instead. gtk_label_set_justify() has no
+ * effect on labels containing only a single line.
**/
void
gtk_label_set_justify (GtkLabel *label,
* gtk_label_get_justify:
* @label: a #GtkLabel
*
- * Returns the justification of the label. See gtk_label_set_justification ().
+ * Returns the justification of the label. See gtk_label_set_justify ().
*
- * Return value: GtkJustification
+ * Return value: #GtkJustification
**/
GtkJustification
gtk_label_get_justify (GtkLabel *label)
* @label: a #GtkLabel
* @wrap: the setting
*
- * If true, the lines will be wrapped if the text becomes too wide.
- */
+ * Toggles line wrapping within the #GtkLabel widget. %TRUE makes it break
+ * lines if text exceeds the widget's size. %FALSE lets the text get cut off
+ * by the edge of the widget if it exceeds the widget size.
+ **/
void
gtk_label_set_line_wrap (GtkLabel *label,
gboolean wrap)
}
}
+typedef struct _LabelWrapWidth LabelWrapWidth;
+struct _LabelWrapWidth
+{
+ gint width;
+ PangoFontDescription *font_desc;
+};
+
static void
-gtk_label_ensure_layout (GtkLabel *label,
- gint *widthp,
- gint *heightp)
+label_wrap_width_free (gpointer data)
+{
+ LabelWrapWidth *wrap_width = data;
+ pango_font_description_free (wrap_width->font_desc);
+ g_free (wrap_width);
+}
+
+static gint
+get_label_wrap_width (GtkLabel *label)
+{
+ PangoLayout *layout;
+ GtkStyle *style = GTK_WIDGET (label)->style;
+
+ LabelWrapWidth *wrap_width = g_object_get_data (G_OBJECT (style), "gtk-label-wrap-width");
+ if (!wrap_width)
+ {
+ wrap_width = g_new0 (LabelWrapWidth, 1);
+ g_object_set_data_full (G_OBJECT (style), "gtk-label-wrap-width",
+ wrap_width, label_wrap_width_free);
+ }
+
+ if (wrap_width->font_desc && pango_font_description_equal (wrap_width->font_desc, style->font_desc))
+ return wrap_width->width;
+
+ if (wrap_width->font_desc)
+ pango_font_description_free (wrap_width->font_desc);
+
+ wrap_width->font_desc = pango_font_description_copy (style->font_desc);
+
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET (label),
+ "This long string gives a good enough length for any line to have.");
+ pango_layout_get_size (layout, &wrap_width->width, NULL);
+ g_object_unref (layout);
+
+ return wrap_width->width;
+}
+
+static void
+gtk_label_ensure_layout (GtkLabel *label)
{
GtkWidget *widget;
PangoRectangle logical_rect;
widget = GTK_WIDGET (label);
- /*
- * There are a number of conditions which will necessitate re-filling
- * our text:
- *
- * 1. text changed.
- * 2. justification changed either from to to GTK_JUSTIFY_FILL.
- * 3. font changed.
- *
- * These have been detected elsewhere, and label->words will be zero,
- * if one of the above has occured.
- *
- * Additionally, though, if GTK_JUSTIFY_FILL, we need to re-fill if:
- *
- * 4. gtk_widget_set_usize has changed the requested width.
- * 5. gtk_misc_set_padding has changed xpad.
- * 6. maybe others?...
- *
- * Too much of a pain to detect all these case, so always re-fill. I
- * don't think it's really that slow.
- */
-
rwidth = label->misc.xpad * 2;
rheight = label->misc.ypad * 2;
align = PANGO_ALIGN_RIGHT;
break;
case GTK_JUSTIFY_CENTER:
- align = PANGO_ALIGN_LEFT;
+ align = PANGO_ALIGN_CENTER;
break;
case GTK_JUSTIFY_FILL:
/* FIXME: This just doesn't work to do this */
}
pango_layout_set_alignment (label->layout, align);
- }
- if (label->wrap)
- {
- GtkWidgetAuxInfo *aux_info;
- gint longest_paragraph;
- gint width, height;
- gint real_width;
-
- aux_info = _gtk_widget_get_aux_info (widget, FALSE);
- if (aux_info && aux_info->width > 0)
+ if (label->wrap)
{
- pango_layout_set_width (label->layout, aux_info->width * PANGO_SCALE);
- pango_layout_get_extents (label->layout, NULL, &logical_rect);
-
- rwidth += aux_info->width;
- rheight += PANGO_PIXELS (logical_rect.height);
- }
- else
- {
- pango_layout_set_width (label->layout, -1);
- pango_layout_get_extents (label->layout, NULL, &logical_rect);
-
- width = logical_rect.width;
- height = logical_rect.height;
-
- /* Try to guess a reasonable maximum width
- */
- longest_paragraph = width;
-
- width = MIN (width,
- PANGO_SCALE * gdk_string_width (gtk_style_get_font (GTK_WIDGET (label)->style),
- "This long string gives a good enough length for any line to have."));
- width = MIN (width,
- PANGO_SCALE * (gdk_screen_width () + 1) / 2);
-
- pango_layout_set_width (label->layout, width);
- pango_layout_get_extents (label->layout, NULL, &logical_rect);
- real_width = logical_rect.width;
- height = logical_rect.height;
+ GtkWidgetAuxInfo *aux_info;
+ gint longest_paragraph;
+ gint width, height;
- /* Unfortunately, the above may leave us with a very unbalanced looking paragraph,
- * so we try short search for a narrower width that leaves us with the same height
- */
- if (longest_paragraph > 0)
+ aux_info = _gtk_widget_get_aux_info (widget, FALSE);
+ if (aux_info && aux_info->width > 0)
+ pango_layout_set_width (label->layout, aux_info->width * PANGO_SCALE);
+ else
{
- gint nlines, perfect_width;
+ GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (label));
+ gint wrap_width;
+
+ pango_layout_set_width (label->layout, -1);
+ pango_layout_get_extents (label->layout, NULL, &logical_rect);
- nlines = pango_layout_get_line_count (label->layout);
- perfect_width = (longest_paragraph + nlines - 1) / nlines;
+ width = logical_rect.width;
+
+ /* Try to guess a reasonable maximum width */
+ longest_paragraph = width;
+
+ wrap_width = get_label_wrap_width (label);
+ width = MIN (width, wrap_width);
+ width = MIN (width,
+ PANGO_SCALE * (gdk_screen_get_width (screen) + 1) / 2);
+
+ pango_layout_set_width (label->layout, width);
+ pango_layout_get_extents (label->layout, NULL, &logical_rect);
+ width = logical_rect.width;
+ height = logical_rect.height;
- if (perfect_width < width)
+ /* Unfortunately, the above may leave us with a very unbalanced looking paragraph,
+ * so we try short search for a narrower width that leaves us with the same height
+ */
+ if (longest_paragraph > 0)
{
- pango_layout_set_width (label->layout, perfect_width);
- pango_layout_get_extents (label->layout, NULL, &logical_rect);
+ gint nlines, perfect_width;
- if (logical_rect.height <= height)
- {
- width = perfect_width;
- real_width = logical_rect.width;
- height = logical_rect.height;
- }
- else
+ nlines = pango_layout_get_line_count (label->layout);
+ perfect_width = (longest_paragraph + nlines - 1) / nlines;
+
+ if (perfect_width < width)
{
- gint mid_width = (perfect_width + width) / 2;
-
- if (mid_width > perfect_width)
+ pango_layout_set_width (label->layout, perfect_width);
+ pango_layout_get_extents (label->layout, NULL, &logical_rect);
+
+ if (logical_rect.height <= height)
+ width = logical_rect.width;
+ else
{
- pango_layout_set_width (label->layout, mid_width);
- pango_layout_get_extents (label->layout, NULL, &logical_rect);
-
- if (logical_rect.height <= height)
+ gint mid_width = (perfect_width + width) / 2;
+
+ if (mid_width > perfect_width)
{
- width = mid_width;
- real_width = logical_rect.width;
- height = logical_rect.height;
+ pango_layout_set_width (label->layout, mid_width);
+ pango_layout_get_extents (label->layout, NULL, &logical_rect);
+
+ if (logical_rect.height <= height)
+ width = logical_rect.width;
}
}
}
}
+ pango_layout_set_width (label->layout, width);
}
- pango_layout_set_width (label->layout, width);
-
- rwidth += PANGO_PIXELS (real_width);
- rheight += PANGO_PIXELS (height);
}
+ else /* !label->wrap */
+ pango_layout_set_width (label->layout, -1);
}
- else /* !label->wrap */
- {
- pango_layout_set_width (label->layout, -1);
- pango_layout_get_extents (label->layout, NULL, &logical_rect);
-
- rwidth += PANGO_PIXELS (logical_rect.width);
- rheight += PANGO_PIXELS (logical_rect.height);
- }
-
- if (widthp)
- *widthp = rwidth;
-
- if (heightp)
- *heightp = rheight;
}
static void
{
GtkLabel *label;
gint width, height;
+ PangoRectangle logical_rect;
+ GtkWidgetAuxInfo *aux_info;
g_return_if_fail (GTK_IS_LABEL (widget));
g_return_if_fail (requisition != NULL);
label = GTK_LABEL (widget);
- gtk_label_ensure_layout (label, &width, &height);
+ /*
+ * If word wrapping is on, then the height requisition can depend
+ * on:
+ *
+ * - Any width set on the widget via gtk_widget_set_usize().
+ * - The padding of the widget (xpad, set by gtk_misc_set_padding)
+ *
+ * Instead of trying to detect changes to these quantities, if we
+ * are wrapping, we just rewrap for each size request. Since
+ * size requisitions are cached by the GTK+ core, this is not
+ * expensive.
+ */
+
+ if (label->wrap)
+ gtk_label_clear_layout (label);
+
+ gtk_label_ensure_layout (label);
+
+ width = label->misc.xpad * 2;
+ height = label->misc.ypad * 2;
+
+ pango_layout_get_extents (label->layout, NULL, &logical_rect);
+
+ aux_info = _gtk_widget_get_aux_info (widget, FALSE);
+ if (label->wrap && aux_info && aux_info->width > 0)
+ width += aux_info->width;
+ else
+ width += PANGO_PIXELS (logical_rect.width);
+
+ height += PANGO_PIXELS (logical_rect.height);
requisition->width = width;
requisition->height = height;
GtkLabel *label;
label = GTK_LABEL (widget);
-
+
(* GTK_WIDGET_CLASS (parent_class)->size_allocate) (widget, allocation);
if (label->select_info && label->select_info->window)
if (GTK_WIDGET_DRAWABLE (label))
{
GtkWidget *widget = GTK_WIDGET (label);
-
+
GtkTextDirection keymap_direction;
GtkTextDirection widget_direction;
PangoRectangle strong_pos, weak_pos;
gboolean split_cursor;
PangoRectangle *cursor1 = NULL;
PangoRectangle *cursor2 = NULL;
- GdkGC *gc1 = NULL;
- GdkGC *gc2 = NULL;
+ GdkRectangle cursor_location;
+ GtkTextDirection dir1 = GTK_TEXT_DIR_NONE;
+ GtkTextDirection dir2 = GTK_TEXT_DIR_NONE;
+ GdkGC *gc;
keymap_direction =
- (gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ?
+ (gdk_keymap_get_direction (gdk_keymap_get_for_display (gtk_widget_get_display (widget))) == PANGO_DIRECTION_LTR) ?
GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
widget_direction = gtk_widget_get_direction (widget);
- gtk_label_ensure_layout (label, NULL, NULL);
+ gtk_label_ensure_layout (label);
pango_layout_get_cursor_pos (label->layout, label->select_info->selection_end,
&strong_pos, &weak_pos);
"gtk-split-cursor", &split_cursor,
NULL);
+ dir1 = widget_direction;
+
if (split_cursor)
{
- gc1 = label->select_info->cursor_gc;
cursor1 = &strong_pos;
if (strong_pos.x != weak_pos.x ||
strong_pos.y != weak_pos.y)
{
- gc2 = widget->style->black_gc;
+ dir2 = (widget_direction == GTK_TEXT_DIR_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
cursor2 = &weak_pos;
}
}
else
{
- gc1 = label->select_info->cursor_gc;
-
if (keymap_direction == widget_direction)
cursor1 = &strong_pos;
else
cursor1 = &weak_pos;
}
- gdk_draw_line (widget->window, gc1,
- xoffset + PANGO_PIXELS (cursor1->x), yoffset + PANGO_PIXELS (cursor1->y),
- xoffset + PANGO_PIXELS (cursor1->x), yoffset + PANGO_PIXELS (cursor1->y + cursor1->height));
+ cursor_location.x = xoffset + PANGO_PIXELS (cursor1->x);
+ cursor_location.y = yoffset + PANGO_PIXELS (cursor1->y);
+ cursor_location.width = 0;
+ cursor_location.height = PANGO_PIXELS (cursor1->height);
+
+ gc = _gtk_get_insertion_cursor_gc (widget, TRUE);
+ _gtk_draw_insertion_cursor (widget, widget->window, gc,
+ &cursor_location, dir1,
+ dir2 != GTK_TEXT_DIR_NONE);
+ g_object_unref (gc);
- if (gc2)
- gdk_draw_line (widget->window, gc2,
- xoffset + PANGO_PIXELS (cursor2->x), yoffset + PANGO_PIXELS (cursor2->y),
- xoffset + PANGO_PIXELS (cursor2->x), yoffset + PANGO_PIXELS (cursor2->y + cursor2->height));
+ if (dir2 != GTK_TEXT_DIR_NONE)
+ {
+ cursor_location.x = xoffset + PANGO_PIXELS (cursor2->x);
+ cursor_location.y = yoffset + PANGO_PIXELS (cursor2->y);
+ cursor_location.width = 0;
+ cursor_location.height = PANGO_PIXELS (cursor2->height);
+
+ gc = _gtk_get_insertion_cursor_gc (widget, FALSE);
+ _gtk_draw_insertion_cursor (widget, widget->window, gc,
+ &cursor_location, dir2, TRUE);
+ g_object_unref (gc);
+ }
}
}
label = GTK_LABEL (widget);
- gtk_label_ensure_layout (label, NULL, NULL);
+ gtk_label_ensure_layout (label);
if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) &&
label->text && (*label->text != '\0'))
gtk_label_draw_cursor (label, x, y);
}
- return TRUE;
+ return FALSE;
}
-void
+static void
gtk_label_set_uline_text_internal (GtkLabel *label,
const gchar *str)
{
{
*pattern_dest++ = '_';
if (accel_key == GDK_VoidSymbol)
- accel_key = gdk_keyval_to_lower (c);
+ accel_key = gdk_keyval_to_lower (gdk_unicode_to_keyval (c));
}
while (src < next_src)
g_return_val_if_fail (str != NULL, GDK_VoidSymbol);
orig_keyval = label->mnemonic_keyval;
+
+ g_object_freeze_notify (G_OBJECT (label));
gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
gtk_label_set_use_markup_internal (label, FALSE);
gtk_label_setup_mnemonic (label, orig_keyval);
+ g_object_thaw_notify (G_OBJECT (label));
+
return keyval;
}
g_return_if_fail (str != NULL);
last_keyval = label->mnemonic_keyval;
-
+
+ g_object_freeze_notify (G_OBJECT (label));
+
gtk_label_set_label_internal (label, g_strdup (str ? str : ""));
gtk_label_set_use_markup_internal (label, FALSE);
gtk_label_set_use_underline_internal (label, TRUE);
gtk_label_recalculate (label);
gtk_label_setup_mnemonic (label, last_keyval);
-}
-static void
-gtk_label_realize_cursor_gc (GtkLabel *label)
-{
- GdkColor *cursor_color;
- GdkColor red = {0, 0xffff, 0x0000, 0x0000};
-
- if (label->select_info == NULL)
- return;
-
- if (label->select_info->cursor_gc)
- gdk_gc_unref (label->select_info->cursor_gc);
-
- gtk_widget_style_get (GTK_WIDGET (label), "cursor_color", &cursor_color, NULL);
- label->select_info->cursor_gc = gdk_gc_new (GTK_WIDGET (label)->window);
- if (cursor_color)
- gdk_gc_set_rgb_fg_color (label->select_info->cursor_gc, cursor_color);
- else
- gdk_gc_set_rgb_fg_color (label->select_info->cursor_gc, &red);
+ g_object_thaw_notify (G_OBJECT (label));
}
static void
(* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
if (label->select_info)
- {
- gtk_label_create_window (label);
- gtk_label_realize_cursor_gc (label);
- }
-}
-
-static void
-gtk_label_unrealize_cursor_gc (GtkLabel *label)
-{
- if (label->select_info == NULL)
- return;
-
- if (label->select_info->cursor_gc)
- {
- gdk_gc_unref (label->select_info->cursor_gc);
- label->select_info->cursor_gc = NULL;
- }
+ gtk_label_create_window (label);
}
static void
label = GTK_LABEL (widget);
if (label->select_info)
- {
- gtk_label_unrealize_cursor_gc (label);
- gtk_label_destroy_window (label);
- }
+ gtk_label_destroy_window (label);
(* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
}
*index = 0;
- gtk_label_ensure_layout (label, NULL, NULL);
+ gtk_label_ensure_layout (label);
window_to_layout_coords (label, &x, &y);
min = MIN (min, index);
max = MAX (max, index);
- gtk_label_select_region_index (label,
- min,
- max);
-
/* ensure the anchor is opposite index */
- if (index == label->select_info->selection_anchor)
+ if (index == min)
{
- gint tmp = label->select_info->selection_end;
- label->select_info->selection_end = label->select_info->selection_anchor;
- label->select_info->selection_anchor = tmp;
+ gint tmp = min;
+ min = max;
+ max = tmp;
}
+
+ gtk_label_select_region_index (label, min, max);
}
else
{
attributes.window_type = GDK_WINDOW_TEMP;
attributes.wclass = GDK_INPUT_ONLY;
attributes.override_redirect = TRUE;
+ attributes.cursor = gdk_cursor_new_for_screen (gtk_widget_get_screen (widget),
+ GDK_XTERM);
attributes.event_mask = gtk_widget_get_events (widget) |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_BUTTON_MOTION_MASK;
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR | GDK_WA_CURSOR;
label->select_info->window = gdk_window_new (widget->window,
&attributes, attributes_mask);
- gdk_window_set_user_data (label->select_info->window, widget);
+ gdk_window_set_user_data (label->select_info->window, widget);
+
+ gdk_cursor_unref (attributes.cursor);
}
static void
GTK_WIDGET_SET_FLAGS (label, GTK_CAN_FOCUS);
if (GTK_WIDGET_REALIZED (label))
- {
- gtk_label_create_window (label);
- gtk_label_realize_cursor_gc (label);
- }
+ gtk_label_create_window (label);
if (GTK_WIDGET_MAPPED (label))
gdk_window_show (label->select_info->window);
/* unselect, to give up the selection */
gtk_label_select_region (label, 0, 0);
- gtk_label_unrealize_cursor_gc (label);
-
if (label->select_info->window)
{
gtk_label_destroy_window (label);
}
if (setting != old_setting)
{
- g_object_notify (G_OBJECT (label), "selectable");
- gtk_widget_queue_draw (GTK_WIDGET (label));
+ g_object_freeze_notify (G_OBJECT (label));
+ g_object_notify (G_OBJECT (label), "selectable");
+ g_object_notify (G_OBJECT (label), "cursor_position");
+ g_object_notify (G_OBJECT (label), "selection_bound");
+ g_object_thaw_notify (G_OBJECT (label));
+ gtk_widget_queue_draw (GTK_WIDGET (label));
}
}
gpointer user_data_or_owner)
{
GtkLabel *label;
- gchar *str;
label = GTK_LABEL (user_data_or_owner);
if (start > len)
start = len;
- str = g_strndup (label->text + start,
- end - start);
-
- gtk_selection_data_set_text (selection_data,
- str);
-
- g_free (str);
+ gtk_selection_data_set_text (selection_data,
+ label->text + start,
+ end - start);
}
}
{
label->select_info->selection_anchor = label->select_info->selection_end;
- gtk_label_clear_layout (label);
gtk_widget_queue_draw (GTK_WIDGET (label));
}
}
{
GtkClipboard *clipboard;
+ if (label->select_info->selection_anchor == anchor_index &&
+ label->select_info->selection_end == end_index)
+ return;
+
label->select_info->selection_anchor = anchor_index;
label->select_info->selection_end = end_index;
- clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (label),
+ GDK_SELECTION_PRIMARY);
if (anchor_index != end_index)
{
gtk_clipboard_clear (clipboard);
}
- gtk_label_clear_layout (label);
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_val_if_fail (GTK_IS_LABEL (label), NULL);
- gtk_label_ensure_layout (label, NULL, NULL);
+ gtk_label_ensure_layout (label);
return label->layout;
}
* @label: a #GtkLabel
* @setting: %TRUE if the label's text should be parsed for markup.
*
- * Sets whether the text of the label contains markup in Pango's
- * text markup lango. See gtk_label_set_markup().
+ * Sets whether the text of the label contains markup in <link
+ * linkend="PangoMarkupFormat">Pango's text markup
+ * language</link>. See gtk_label_set_markup().
**/
void
gtk_label_set_use_markup (GtkLabel *label,
* gtk_label_get_use_markup:
* @label: a #GtkLabel
*
- * Returns whether the label's text is interpreted as marked up with the
- * Pango text markup language. See gtk_label_set_use_markup ().
+ * Returns whether the label's text is interpreted as marked up with
+ * the <link linkend="PangoMarkupFormat">Pango text markup
+ * language</link>. See gtk_label_set_use_markup ().
*
* Return value: %TRUE if the label's text will be parsed for markup.
**/
gint *x,
gint *y)
{
+ GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (label)));
GtkTextDirection keymap_direction =
- (gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ?
+ (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR) ?
GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
GtkTextDirection widget_direction = gtk_widget_get_direction (GTK_WIDGET (label));
gboolean split_cursor;
"gtk-split-cursor", &split_cursor,
NULL);
- gtk_label_ensure_layout (label, NULL, NULL);
+ gtk_label_ensure_layout (label);
pango_layout_get_cursor_pos (label->layout, index,
&strong_pos, &weak_pos);
gint n_attrs;
gint length;
- gtk_label_ensure_layout (label, NULL, NULL);
+ gtk_label_ensure_layout (label);
length = g_utf8_strlen (label->label, -1);
gboolean split_cursor;
gboolean strong;
- gtk_label_ensure_layout (label, NULL, NULL);
+ gtk_label_ensure_layout (label);
g_object_get (gtk_widget_get_settings (GTK_WIDGET (label)),
"gtk-split-cursor", &split_cursor,
strong = TRUE;
else
{
+ GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (label)));
GtkTextDirection keymap_direction =
- (gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ?
+ (gdk_keymap_get_direction (keymap) == PANGO_DIRECTION_LTR) ?
GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
strong = keymap_direction == gtk_widget_get_direction (GTK_WIDGET (label));
PangoLogAttr *log_attrs;
gint n_attrs;
- gtk_label_ensure_layout (label, NULL, NULL);
+ gtk_label_ensure_layout (label);
pango_layout_get_log_attrs (label->layout, &log_attrs, &n_attrs);
PangoLogAttr *log_attrs;
gint n_attrs;
- gtk_label_ensure_layout (label, NULL, NULL);
+ gtk_label_ensure_layout (label);
pango_layout_get_log_attrs (label->layout, &log_attrs, &n_attrs);
start = len;
if (start != end)
- gtk_clipboard_set_text (gtk_clipboard_get (GDK_NONE),
+ gtk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (label),
+ GDK_SELECTION_CLIPBOARD),
label->text + start, end - start);
}
}
static void
append_action_signal (GtkLabel *label,
GtkWidget *menu,
- const gchar *label_text,
+ const gchar *stock_id,
const gchar *signal,
gboolean sensitive)
{
- GtkWidget *menuitem = gtk_menu_item_new_with_label (label_text);
+ GtkWidget *menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
gtk_object_set_data (GTK_OBJECT (menuitem), "gtk-signal", (char *)signal);
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
GtkLabel *label;
GtkWidget *widget;
GtkRequisition req;
+ GdkScreen *screen;
label = GTK_LABEL (user_data);
widget = GTK_WIDGET (label);
return;
g_return_if_fail (GTK_WIDGET_REALIZED (label));
-
+
+ screen = gtk_widget_get_screen (widget);
gdk_window_get_origin (widget->window, x, y);
gtk_widget_size_request (label->select_info->popup_menu, &req);
*x += widget->allocation.width / 2;
*y += widget->allocation.height;
- *x = CLAMP (*x, 0, MAX (0, gdk_screen_width () - req.width));
- *y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height));
+ *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width));
+ *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height));
}
label->select_info->selection_anchor != label->select_info->selection_end;
- append_action_signal (label, label->select_info->popup_menu, _("Cut"), "cut_clipboard",
+ append_action_signal (label, label->select_info->popup_menu, GTK_STOCK_CUT, "cut_clipboard",
FALSE);
- append_action_signal (label, label->select_info->popup_menu, _("Copy"), "copy_clipboard",
+ append_action_signal (label, label->select_info->popup_menu, GTK_STOCK_COPY, "copy_clipboard",
have_selection);
- append_action_signal (label, label->select_info->popup_menu, _("Paste"), "paste_clipboard",
+ append_action_signal (label, label->select_info->popup_menu, GTK_STOCK_PASTE, "paste_clipboard",
FALSE);
menuitem = gtk_menu_item_new_with_label (_("Select All"));