forked from AuroraMiddleware/gtk
21570a57f2
Pointed out in https://bugzilla.gnome.org/show_bug.cgi?id=774490
206 lines
7.8 KiB
XML
206 lines
7.8 KiB
XML
<?xml version="1.0"?>
|
|
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
|
|
]>
|
|
<refentry id="TextWidget">
|
|
<refmeta>
|
|
<refentrytitle>Text Widget Overview</refentrytitle>
|
|
<manvolnum>3</manvolnum>
|
|
<refmiscinfo>GTK Library</refmiscinfo>
|
|
</refmeta>
|
|
|
|
<refnamediv>
|
|
<refname>Text Widget Overview</refname>
|
|
<refpurpose>Overview of GtkTextBuffer, GtkTextView, and friends</refpurpose>
|
|
</refnamediv>
|
|
|
|
<refsect1>
|
|
<title>Conceptual Overview</title>
|
|
|
|
<para>
|
|
GTK+ has an extremely powerful framework for multiline text editing. The
|
|
primary objects involved in the process are #GtkTextBuffer, which represents the
|
|
text being edited, and #GtkTextView, a widget which can display a #GtkTextBuffer.
|
|
Each buffer can be displayed by any number of views.
|
|
</para>
|
|
|
|
<para>
|
|
One of the important things to remember about text in GTK+ is that it's in the
|
|
UTF-8 encoding. This means that one character can be encoded as multiple
|
|
bytes. Character counts are usually referred to as
|
|
<firstterm>offsets</firstterm>, while byte counts are called
|
|
<firstterm>indexes</firstterm>. If you confuse these two, things will work fine
|
|
with ASCII, but as soon as your buffer contains multibyte characters, bad
|
|
things will happen.
|
|
</para>
|
|
|
|
<para>
|
|
Text in a buffer can be marked with <firstterm>tags</firstterm>. A tag is an
|
|
attribute that can be applied to some range of text. For example, a tag might
|
|
be called "bold" and make the text inside the tag bold. However, the tag
|
|
concept is more general than that; tags don't have to affect appearance. They
|
|
can instead affect the behavior of mouse and key presses, "lock" a range of
|
|
text so the user can't edit it, or countless other things. A tag is
|
|
represented by a #GtkTextTag object. One #GtkTextTag can be applied to any
|
|
number of text ranges in any number of buffers.
|
|
</para>
|
|
|
|
<para>
|
|
Each tag is stored in a #GtkTextTagTable. A tag table defines a set of
|
|
tags that can be used together. Each buffer has one tag table associated with
|
|
it; only tags from that tag table can be used with the buffer. A single tag
|
|
table can be shared between multiple buffers, however.
|
|
</para>
|
|
|
|
<para>
|
|
Tags can have names, which is convenient sometimes (for example, you can name
|
|
your tag that makes things bold "bold"), but they can also be anonymous (which
|
|
is convenient if you're creating tags on-the-fly).
|
|
</para>
|
|
|
|
<para>
|
|
Most text manipulation is accomplished with <firstterm>iterators</firstterm>,
|
|
represented by a #GtkTextIter. An iterator represents a position between two
|
|
characters in the text buffer. #GtkTextIter is a struct designed to be
|
|
allocated on the stack; it's guaranteed to be copiable by value and never
|
|
contain any heap-allocated data. Iterators are not valid indefinitely;
|
|
whenever the buffer is modified in a way that affects the number of characters
|
|
in the buffer, all outstanding iterators become invalid. (Note that deleting
|
|
5 characters and then reinserting 5 still invalidates iterators, though you
|
|
end up with the same number of characters you pass through a state with a
|
|
different number).
|
|
</para>
|
|
|
|
<para>
|
|
Because of this, iterators can't be used to preserve positions across buffer
|
|
modifications. To preserve a position, the #GtkTextMark object is ideal. You
|
|
can think of a mark as an invisible cursor or insertion point; it floats in
|
|
the buffer, saving a position. If the text surrounding the mark is deleted,
|
|
the mark remains in the position the text once occupied; if text is inserted
|
|
at the mark, the mark ends up either to the left or to the right of the new
|
|
text, depending on its <firstterm>gravity</firstterm>. The standard text
|
|
cursor in left-to-right languages is a mark with right gravity, because it
|
|
stays to the right of inserted text.
|
|
</para>
|
|
|
|
<para>
|
|
Like tags, marks can be either named or anonymous. There are two marks built-in
|
|
to #GtkTextBuffer; these are named <literal>"insert"</literal> and
|
|
<literal>"selection_bound"</literal> and refer to the insertion point and the
|
|
boundary of the selection which is not the insertion point, respectively. If
|
|
no text is selected, these two marks will be in the same position. You can
|
|
manipulate what is selected and where the cursor appears by moving these
|
|
marks around.
|
|
<footnote>
|
|
<para>
|
|
If you want to place the cursor in response to a user action, be sure to use
|
|
gtk_text_buffer_place_cursor(), which moves both at once without causing a
|
|
temporary selection (moving one then the other temporarily selects the range in
|
|
between the old and new positions).
|
|
</para>
|
|
</footnote>
|
|
</para>
|
|
|
|
<para>
|
|
Text buffers always contain at least one line, but may be empty (that
|
|
is, buffers can contain zero characters). The last line in the text
|
|
buffer never ends in a line separator (such as newline); the other
|
|
lines in the buffer always end in a line separator. Line separators
|
|
count as characters when computing character counts and character
|
|
offsets. Note that some Unicode line separators are represented with
|
|
multiple bytes in UTF-8, and the two-character sequence "\r\n" is also
|
|
considered a line separator.
|
|
</para>
|
|
|
|
</refsect1>
|
|
|
|
|
|
<refsect1>
|
|
<title>Simple Example</title>
|
|
|
|
<para>
|
|
The simplest usage of #GtkTextView might look like this:
|
|
<informalexample><programlisting>
|
|
GtkWidget *view;
|
|
GtkTextBuffer *buffer;
|
|
|
|
view = gtk_text_view_new (<!-- -->);
|
|
|
|
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
|
|
|
gtk_text_buffer_set_text (buffer, "Hello, this is some text", -1);
|
|
|
|
/* Now you might put the view in a container and display it on the
|
|
* screen; when the user edits the text, signals on the buffer
|
|
* will be emitted, such as "changed", "insert_text", and so on.
|
|
*/
|
|
</programlisting></informalexample>
|
|
In many cases it's also convenient to first create the buffer with
|
|
gtk_text_buffer_new(), then create a widget for that buffer with
|
|
gtk_text_view_new_with_buffer(). Or you can change the buffer the widget
|
|
displays after the widget is created with gtk_text_view_set_buffer().
|
|
</para>
|
|
|
|
</refsect1>
|
|
|
|
<refsect1>
|
|
<title>Example of Changing Text Attributes</title>
|
|
|
|
<para>
|
|
|
|
The way to affect text attributes in #GtkTextView is to
|
|
apply tags that change the attributes for a region of text.
|
|
For text features that come from the theme — such as font and
|
|
foreground color — use CSS to override their default values.
|
|
|
|
<informalexample><programlisting>
|
|
GtkWidget *view;
|
|
GtkTextBuffer *buffer;
|
|
GtkTextIter start, end;
|
|
PangoFontDescription *font_desc;
|
|
GdkRGBA rgba;
|
|
GtkTextTag *tag;
|
|
GtkCssProvider *provider;
|
|
GtkStyleContext *context;
|
|
|
|
view = gtk_text_view_new (<!-- -->);
|
|
|
|
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
|
|
|
gtk_text_buffer_set_text (buffer, "Hello, this is some text", -1);
|
|
|
|
/* Change default font and color throughout the widget */
|
|
provider = gtk_css_provider_new ();
|
|
gtk_css_provider_load_from_data (provider,
|
|
"textview {"
|
|
" font: 15 serif;"
|
|
" color: green;"
|
|
"}",
|
|
-1);
|
|
context = gtk_widget_get_style_context (view);
|
|
gtk_style_context_add_provider (context,
|
|
GTK_STYLE_PROVIDER (provider),
|
|
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
|
|
|
/* Change left margin throughout the widget */
|
|
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 30);
|
|
|
|
/* Use a tag to change the color for just one part of the widget */
|
|
tag = gtk_text_buffer_create_tag (buffer, "blue_foreground",
|
|
"foreground", "blue", NULL);
|
|
gtk_text_buffer_get_iter_at_offset (buffer, &start, 7);
|
|
gtk_text_buffer_get_iter_at_offset (buffer, &end, 12);
|
|
gtk_text_buffer_apply_tag (buffer, tag, &start, &end);
|
|
</programlisting></informalexample>
|
|
|
|
</para>
|
|
|
|
<para>
|
|
The <application>gtk-demo</application> application that comes with
|
|
GTK+ contains more example code for #GtkTextView.
|
|
</para>
|
|
|
|
</refsect1>
|
|
|
|
</refentry>
|