GtkRequisition *requisition);
static void gtk_label_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
+static void gtk_label_state_changed (GtkWidget *widget,
+ GtkStateType state);
static void gtk_label_style_set (GtkWidget *widget,
GtkStyle *previous_style);
static void gtk_label_direction_changed (GtkWidget *widget,
const gchar *str,
gboolean with_uline);
static void gtk_label_recalculate (GtkLabel *label);
-static void gtk_label_hierarchy_changed (GtkWidget *widget);
+static void gtk_label_hierarchy_changed (GtkWidget *widget,
+ GtkWidget *old_toplevel);
static void gtk_label_create_window (GtkLabel *label);
static void gtk_label_destroy_window (GtkLabel *label);
gint anchor_index,
gint end_index);
-static gboolean gtk_label_activate_mnemonic (GtkWidget *widget,
+static gboolean gtk_label_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
+static void gtk_label_setup_mnemonic (GtkLabel *label,
+ guint last_key);
static GtkMiscClass *parent_class = NULL;
widget_class->size_request = gtk_label_size_request;
widget_class->size_allocate = gtk_label_size_allocate;
+ widget_class->state_changed = gtk_label_state_changed;
widget_class->style_set = gtk_label_style_set;
widget_class->direction_changed = gtk_label_direction_changed;
widget_class->expose_event = gtk_label_expose;
widget_class->button_release_event = gtk_label_button_release;
widget_class->motion_notify_event = gtk_label_motion;
widget_class->hierarchy_changed = gtk_label_hierarchy_changed;
- widget_class->activate_mnemonic = gtk_label_activate_mnemonic;
+ widget_class->mnemonic_activate = gtk_label_mnemonic_activate;
g_object_class_install_property (G_OBJECT_CLASS(object_class),
PROP_LABEL,
GParamSpec *pspec)
{
GtkLabel *label;
-
+ guint last_keyval;
+
label = GTK_LABEL (object);
+ last_keyval = label->mnemonic_keyval;
switch (prop_id)
{
case PROP_LABEL:
- gtk_label_set_label_internal (label,
- g_strdup (g_value_get_string (value)));
- gtk_label_recalculate (label);
+ gtk_label_set_label (label, g_value_get_string (value));
break;
case PROP_ATTRIBUTES:
gtk_label_set_attributes (label, g_value_get_boxed (value));
break;
case PROP_USE_MARKUP:
- gtk_label_set_use_markup_internal (label, g_value_get_boolean (value));
- gtk_label_recalculate (label);
+ gtk_label_set_use_markup (label, g_value_get_boolean (value));
break;
case PROP_USE_UNDERLINE:
- gtk_label_set_use_underline_internal (label, g_value_get_boolean (value));
- gtk_label_recalculate (label);
+ gtk_label_set_use_underline (label, g_value_get_boolean (value));
break;
case PROP_JUSTIFY:
gtk_label_set_justify (label, g_value_get_enum (value));
/**
* gtk_label_new:
* @str: The text of the label
- * @returns: a new #GtkLabel
*
* Creates a new #GtkLabel, containing the text in @str.
+ *
+ * Return value: the new #GtkLabel
**/
GtkWidget*
gtk_label_new (const gchar *str)
* gtk_label_new_with_mnemonic:
* @str: The text of the label, with an underscore in front of the
* mnemonic character
- * @returns: a 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 gtk_label_set_mnemonic_widget().
+ * 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
+ * gtk_label_set_mnemonic_widget().
+ *
+ * If gtk_label_set_mnemonic_widget()
+ * is not called, then the first activatable ancestor of the #GtkLabel
+ * will be chosen as the mnemonic widget. For instance, if the
+ * label is inside a button or menu item, the button or menu item will
+ * automatically become the mnemonic widget and be activated by
+ * the mnemonic.
+ *
+ * Return value: the new #GtkLabel
**/
GtkWidget*
gtk_label_new_with_mnemonic (const gchar *str)
}
static gboolean
-gtk_label_activate_mnemonic (GtkWidget *widget,
+gtk_label_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling)
{
GtkWidget *parent;
if (GTK_LABEL (widget)->mnemonic_widget)
- return gtk_widget_activate_mnemonic (GTK_LABEL (widget)->mnemonic_widget, group_cycling);
+ return gtk_widget_mnemonic_activate (GTK_LABEL (widget)->mnemonic_widget, group_cycling);
/* Try to find the widget to activate by traversing the
* widget's ancestry.
(!group_cycling && GTK_WIDGET_GET_CLASS (parent)->activate_signal) ||
(parent->parent && GTK_IS_NOTEBOOK (parent->parent)) ||
(GTK_IS_MENU_ITEM (parent)))
- return gtk_widget_activate_mnemonic (parent, group_cycling);
+ return gtk_widget_mnemonic_activate (parent, group_cycling);
parent = parent->parent;
}
GtkWidget *toplevel;
if (last_key != GDK_VoidSymbol && label->mnemonic_window)
- gtk_window_remove_mnemonic (label->mnemonic_window,
- last_key,
- GTK_WIDGET (label));
+ {
+ gtk_window_remove_mnemonic (label->mnemonic_window,
+ last_key,
+ GTK_WIDGET (label));
+ label->mnemonic_window = NULL;
+ }
if (label->mnemonic_keyval == GDK_VoidSymbol)
return;
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label));
-
- if (GTK_IS_WINDOW (toplevel))
+ if (GTK_WIDGET_TOPLEVEL (toplevel))
{
gtk_window_add_mnemonic (GTK_WINDOW (toplevel),
label->mnemonic_keyval,
}
static void
-gtk_label_hierarchy_changed (GtkWidget *widget)
+gtk_label_hierarchy_changed (GtkWidget *widget,
+ GtkWidget *old_toplevel)
{
GtkLabel *label = GTK_LABEL (widget);
* (i.e. when the target is a #GtkEntry next to the label) you need to
* set it explicitly using this function.
*
- * The target widget will be accelerated by emitting "activate_mnemonic" on it.
+ * The target widget will be accelerated by emitting "mnemonic_activate" on it.
* The default handler for this signal will activate the widget if there are no
* mnemonic collisions and toggle focus between the colliding widgets otherwise.
**/
gtk_widget_ref (label->mnemonic_widget);
}
+/**
+ * gtk_label_get_mnemonic_widget:
+ * @label: a #GtkLabel
+ *
+ * Retrieves the target of the mnemonic (keyboard shortcut) of this
+ * label. See gtk_label_set_mnemonic_widget ().
+ *
+ * Return value: the target of the label's mnemonic, or %NULL if none
+ * has been set and the default algorithm will be used.
+ **/
+GtkWidget *
+gtk_label_get_mnemonic_widget (GtkLabel *label)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
+
+ return label->mnemonic_widget;
+}
/**
* gtk_label_get_mnemonic_keyval:
static void
gtk_label_set_use_markup_internal (GtkLabel *label,
- gboolean val)
+ gboolean val)
{
val = val != FALSE;
if (label->use_markup != val)
- g_object_notify (G_OBJECT (label), "use_markup");
- label->use_markup = val;
+ {
+ g_object_notify (G_OBJECT (label), "use_markup");
+ label->use_markup = val;
+ }
}
static void
{
val = val != FALSE;
if (label->use_underline != val)
- g_object_notify (G_OBJECT (label), "use_underline");
- label->use_underline = val;
+ {
+ g_object_notify (G_OBJECT (label), "use_underline");
+ label->use_underline = val;
+ }
}
static void
-gtk_label_set_attributes_internal (GtkLabel *label,
- PangoAttrList *attrs)
+gtk_label_set_attributes_internal (GtkLabel *label,
+ PangoAttrList *attrs)
{
if (attrs)
pango_attr_list_ref (attrs);
if (label->attrs)
pango_attr_list_unref (label->attrs);
+ if (!label->use_markup && !label->use_underline)
+ {
+ pango_attr_list_ref (attrs);
+ if (label->effective_attrs)
+ pango_attr_list_unref (label->effective_attrs);
+ label->effective_attrs = attrs;
+ }
+
label->attrs = attrs;
g_object_notify (G_OBJECT (label), "attributes");
}
gtk_label_recalculate (GtkLabel *label)
{
if (label->use_markup)
- set_markup (label, label->label, label->use_underline);
+ set_markup (label, label->label, label->use_underline);
else
{
if (label->use_underline)
else
{
gtk_label_set_text_internal (label, g_strdup (label->label));
- gtk_label_set_attributes_internal (label, NULL);
+ if (label->attrs)
+ pango_attr_list_ref (label->attrs);
+ if (label->effective_attrs)
+ pango_attr_list_unref (label->effective_attrs);
+ label->effective_attrs = label->attrs;
}
}
* @attrs: a #PangoAttrList
*
* Sets a #PangoAttrList; the attributes in the list are applied to the
- * label text.
+ * label text. The attributes set with this function will be ignored
+ * if label->use_underline or label->use_markup is %TRUE.
**/
void
gtk_label_set_attributes (GtkLabel *label,
gtk_widget_queue_resize (GTK_WIDGET (label));
}
+/**
+ * gtk_label_get_attributes:
+ * @label: a #GtkLabel
+ *
+ * Gets the attribute list that was set on the label using
+ * gtk_label_set_attributes(), if any. This function does
+ * not reflect attributes that come from the labels markup
+ * (see gtk_label_set_markup()). If you want to get the
+ * effective attributes for the label, use
+ * pango_layout_get_attribute (gtk_label_get_layout (label)).
+ *
+ * Return value: the attribute list, or %NULL if none was set.
+ **/
+PangoAttrList *
+gtk_label_get_attributes (GtkLabel *label)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
+
+ return label->attrs;
+}
+
+/**
+ * gtk_label_set_label:
+ * @label: a #GtkLabel
+ * @str: the new text to set for the label
+ *
+ * Sets the text of the label. The label is interpreted as
+ * including embedded underlines and/or Pango markup depending
+ * on the values of label->use_underline and label->use_markup.
+ **/
+void
+gtk_label_set_label (GtkLabel *label,
+ const gchar *str)
+{
+ guint last_keyval;
+
+ g_return_if_fail (GTK_IS_LABEL (label));
+ g_return_if_fail (str != NULL);
+
+ last_keyval = label->mnemonic_keyval;
+
+ gtk_label_set_label_internal (label, g_strdup (str));
+ gtk_label_recalculate (label);
+ if (last_keyval != label->mnemonic_keyval)
+ gtk_label_setup_mnemonic (label, last_keyval);
+}
+
+/**
+ * gtk_label_get_label:
+ * @label: a #GtkLabel
+ *
+ * Fetches the text from a label widget including any embedded
+ * underlines indicating mnemonics and Pango markup. (See
+ * gtk_label_get_text ()).
+ *
+ * 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 *
+gtk_label_get_label (GtkLabel *label)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
+
+ return label->label;
+}
+
static void
set_markup (GtkLabel *label,
const gchar *str,
if (attrs)
{
- gtk_label_set_attributes_internal (label, attrs);
- pango_attr_list_unref (attrs);
+ if (label->effective_attrs)
+ pango_attr_list_unref (label->effective_attrs);
+ label->effective_attrs = attrs;
}
if (accel_char != 0)
* gtk_label_get_text:
* @label: a #GtkLabel
*
- * Fetches the text from a label widget
+ * Fetches the text from a label widget, as displayed on the
+ * screen. This does not include any embedded underlines
+ * indicating mnemonics or Pango markup. (See gtk_label_get_label())
*
* Return value: the text in the label widget. This is the internal
- * string used by the label, and must not be modified.
+ * string used by the label, and must not be modified.
**/
G_CONST_RETURN gchar *
gtk_label_get_text (GtkLabel *label)
{
- g_return_val_if_fail (label != NULL, NULL);
g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
return label->text;
attrs = gtk_label_pattern_to_attrs (label, pattern);
- gtk_label_set_attributes_internal (label, attrs);
+ if (label->effective_attrs)
+ pango_attr_list_unref (label->effective_attrs);
+ label->effective_attrs = attrs;
}
void
}
+/**
+ * gtk_label_set_justify:
+ * @label: a #GtkLabel
+ * @jtype: a #GtkJustification
+ *
+ * Sets the alignment of the lines in the text of the label relative to
+ * each other.
+ **/
void
gtk_label_set_justify (GtkLabel *label,
GtkJustification jtype)
}
}
+/**
+ * gtk_label_get_justify:
+ * @label: a #GtkLabel
+ *
+ * Returns the justification of the label. See gtk_label_set_justification ().
+ *
+ * Return value: GtkJustification
+ **/
+GtkJustification
+gtk_label_get_justify (GtkLabel *label)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (label), 0);
+
+ return label->jtype;
+}
+
+/**
+ * gtk_label_set_line_wrap:
+ * @label: a #GtkLabel
+ * @wrap: the setting
+ *
+ * If true, the lines will be wrapped if the text becomes too wide.
+ */
void
gtk_label_set_line_wrap (GtkLabel *label,
gboolean wrap)
}
}
+/**
+ * gtk_label_get_line_wrap:
+ * @label: a #GtkLabel
+ *
+ * Returns whether lines in the label are automatically wrapped. See gtk_label_set_line_wrap ().
+ *
+ * Return value: %TRUE if the lines of the label are automatically wrapped.
+ */
+gboolean
+gtk_label_get_line_wrap (GtkLabel *label)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+
+ return label->wrap;
+}
+
void
gtk_label_get (GtkLabel *label,
gchar **str)
{
- g_return_if_fail (label != NULL);
g_return_if_fail (GTK_IS_LABEL (label));
g_return_if_fail (str != NULL);
if (label->attrs)
pango_attr_list_unref (label->attrs);
+ if (label->effective_attrs)
+ pango_attr_list_unref (label->effective_attrs);
+
g_free (label->select_info);
G_OBJECT_CLASS (parent_class)->finalize (object);
label->layout = gtk_widget_create_pango_layout (widget, label->text);
- if (label->attrs)
- pango_layout_set_attributes (label->layout, label->attrs);
+ if (label->effective_attrs)
+ pango_layout_set_attributes (label->layout, label->effective_attrs);
switch (label->jtype)
{
}
}
+static void
+gtk_label_state_changed (GtkWidget *widget,
+ GtkStateType prev_state)
+{
+ GtkLabel *label;
+
+ label = GTK_LABEL (widget);
+
+ if (label->select_info)
+ gtk_label_select_region (label, 0, 0);
+
+ if (GTK_WIDGET_CLASS (parent_class)->state_changed)
+ GTK_WIDGET_CLASS (parent_class)->state_changed (widget, prev_state);
+}
+
static void
gtk_label_style_set (GtkWidget *widget,
GtkStyle *previous_style)
gtk_paint_layout (widget->style,
widget->window,
GTK_WIDGET_STATE (widget),
+ FALSE,
&event->area,
widget,
"label",
label->select_info->window = NULL;
}
+/**
+ * gtk_label_set_selectable:
+ * @label: a #GtkLabel
+ * @setting: %TRUE to allow selecting text in the label
+ *
+ * Selectable labels allow the user to select text from the label, for
+ * copy-and-paste.
+ *
+ **/
void
gtk_label_set_selectable (GtkLabel *label,
gboolean setting)
{
if (label->select_info)
{
+ /* unselect, to give up the selection */
+ gtk_label_select_region (label, 0, 0);
+
if (label->select_info->window)
gtk_label_destroy_window (label);
}
}
+/**
+ * gtk_label_get_selectable:
+ * @label: a #GtkLabel
+ *
+ * Gets the value set by gtk_label_set_selectable().
+ *
+ * Return value: %TRUE if the user can copy text from the label
+ **/
gboolean
gtk_label_get_selectable (GtkLabel *label)
{
label->text)
{
gint start, end;
+ gint len;
start = MIN (label->select_info->selection_anchor,
label->select_info->selection_end);
end = MAX (label->select_info->selection_anchor,
label->select_info->selection_end);
-
+
+ len = strlen (label->text);
+
+ if (end > len)
+ end = len;
+
+ if (start > len)
+ start = len;
+
str = g_strndup (label->text + start,
end - start);
label->select_info->selection_end = end_index;
clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
-
- gtk_clipboard_set_with_owner (clipboard,
- targets,
- G_N_ELEMENTS (targets),
- get_text_callback,
- clear_text_callback,
- G_OBJECT (label));
+
+ if (anchor_index != end_index)
+ {
+ gtk_clipboard_set_with_owner (clipboard,
+ targets,
+ G_N_ELEMENTS (targets),
+ get_text_callback,
+ clear_text_callback,
+ G_OBJECT (label));
+ }
+ else
+ {
+ if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (label))
+ gtk_clipboard_clear (clipboard);
+ }
gtk_label_clear_layout (label);
gtk_widget_queue_draw (GTK_WIDGET (label));
}
}
+/**
+ * gtk_label_select_region:
+ * @label: a #GtkLabel
+ * @start_offset: start offset (in characters not bytes)
+ * @end_offset: end offset (in characters not bytes)
+ *
+ * Selects a range of characters in the label, if the label is selectable.
+ * See gtk_label_set_selectable(). If the label is not selectable,
+ * this function has no effect. If @start_offset or
+ * @end_offset are -1, then the end of the label will be substituted.
+ *
+ **/
void
gtk_label_select_region (GtkLabel *label,
gint start_offset,
if (label->text && label->select_info)
{
if (start_offset < 0)
- start_offset = 0;
-
+ start_offset = g_utf8_strlen (label->text, -1);
+
if (end_offset < 0)
end_offset = g_utf8_strlen (label->text, -1);
}
}
+/**
+ * gtk_label_get_selection_bounds:
+ * @label: a #GtkLabel
+ * @start: return location for start of selection, as a character offset
+ * @end: return location for end of selection, as a character offset
+ *
+ * Gets the selected range of characters in the label, returning %TRUE
+ * if there's a selection.
+ *
+ * Return value: %TRUE if selection is non-empty
+ **/
+gboolean
+gtk_label_get_selection_bounds (GtkLabel *label,
+ gint *start,
+ gint *end)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+
+ if (label->select_info == NULL)
+ {
+ /* not a selectable label */
+ if (start)
+ *start = 0;
+ if (end)
+ *end = 0;
+
+ return FALSE;
+ }
+ else
+ {
+ gint start_index, end_index;
+ gint start_offset, end_offset;
+ gint len;
+
+ start_index = MIN (label->select_info->selection_anchor,
+ label->select_info->selection_end);
+ end_index = MAX (label->select_info->selection_anchor,
+ label->select_info->selection_end);
+
+ len = strlen (label->text);
+
+ if (end_index > len)
+ end_index = len;
+
+ if (start_index > len)
+ start_index = len;
+
+ start_offset = g_utf8_strlen (label->text, start_index);
+ end_offset = g_utf8_strlen (label->text, end_index);
+
+ if (start_offset > end_offset)
+ {
+ gint tmp = start_offset;
+ start_offset = end_offset;
+ end_offset = tmp;
+ }
+
+ if (start)
+ *start = start_offset;
+
+ if (end)
+ *end = end_offset;
+
+ return start_offset != end_offset;
+ }
+}
+
+
+/**
+ * gtk_label_get_layout:
+ * @label: a #GtkLabel
+ *
+ * Gets the #PangoLayout used to display the label.
+ * The layout is useful to e.g. convert text positions to
+ * pixel positions, in combination with gtk_label_get_layout_offsets().
+ * The returned layout is owned by the label so need not be
+ * freed by the caller.
+ *
+ * Return value: the #PangoLayout for this label
+ **/
+PangoLayout*
+gtk_label_get_layout (GtkLabel *label)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (label), NULL);
+
+ gtk_label_ensure_layout (label, NULL, NULL);
+
+ return label->layout;
+}
+
/**
* gtk_label_get_layout_offsets:
* @label: a #GtkLabel
* into coordinates inside the #PangoLayout, e.g. to take some action
* if some part of the label is clicked. Of course you will need to
* create a #GtkEventBox to receive the events, and pack the label
- * inside it, since labels are a #GTK_NO_WINDOW widget.
+ * inside it, since labels are a #GTK_NO_WINDOW widget. Remember
+ * when using the #PangoLayout functions you need to convert to
+ * and from pixels using PANGO_PIXELS() or #PANGO_SCALE.
*
**/
void
get_layout_location (label, x, y);
}
+/**
+ * gtk_label_set_use_markup:
+ * @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().
+ **/
+void
+gtk_label_set_use_markup (GtkLabel *label,
+ gboolean setting)
+{
+ g_return_if_fail (GTK_IS_LABEL (label));
+
+ gtk_label_set_use_markup_internal (label, setting);
+ gtk_label_recalculate (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 ().
+ *
+ * Return value: %TRUE if the label's text will be parsed for markup.
+ **/
+gboolean
+gtk_label_get_use_markup (GtkLabel *label)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+
+ return label->use_markup;
+}
+
+/**
+ * gtk_label_set_use_underline:
+ * @label: a #GtkLabel
+ * @setting: %TRUE if underlines in the text indicate mnemonics
+ *
+ * If true, an underline in the text indicates the next character should be
+ * used for the mnemonic accelerator key.
+ */
+void
+gtk_label_set_use_underline (GtkLabel *label,
+ gboolean setting)
+{
+ g_return_if_fail (GTK_IS_LABEL (label));
+
+ gtk_label_set_use_underline_internal (label, setting);
+ gtk_label_recalculate (label);
+ if (label->use_underline)
+ gtk_label_setup_mnemonic (label, label->mnemonic_keyval);
+}
+
+/**
+ * gtk_label_get_use_underline:
+ * @label: a #GtkLabel
+ *
+ * Returns whether an embedded underline in thef label indicates a
+ * mnemonic. See gtk_label_set_use_underline ().
+ *
+ * Return value: %TRUE whether an embedded underline in the label indicates
+ * the mnemonic accelerator keys.
+ **/
+gboolean
+gtk_label_get_use_underline (GtkLabel *label)
+{
+ g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+
+ return label->use_underline;
+}