Spec-Zone.ru › GTK 4.0

Редактор многострочного текста

Обзор виджета текста
Простой пример
Пример изменения атрибутов текста
GtkTextIter — Итератор буфера текста
GtkTextMark — Позиция в буфере, сохраняемая при изменениях буфера
GtkTextBuffer — Хранит атрибутированный текст для отображения в GtkTextView
GtkTextTag — Тег, который можно применить к тексту в GtkTextBuffer
GtkTextTagTable — Коллекция тегов, которые могут использоваться вместе
GtkTextView — Виджет, отображающий GtkTextBuffer

GTK имеет чрезвычайно мощный фреймворк для редактирования многострочного текста. Основные объекты, участвующие в этом процессе, — GtkTextBuffer, представляющий текст, который редактируется, и GtkTextView, виджет, который может отображать GtkTextBuffer. Каждый буфер может быть отображен любым количеством представлений.

Необходимо помнить, что текст в GTK закодирован в UTF-8. Это означает, что один символ может быть закодирован несколькими байтами. Количество символов обычно называется смещениями, а количество байтов — индексами. Если вы перепутаете эти два понятия, всё будет работать нормально с ASCII, но как только ваш буфер будет содержать многобайтные символы, произойдут проблемы.

Текст в буфере может быть помечен тегами. Тег — это атрибут, который можно применить к некоторому диапазону текста. Например, тег может называться «“жирный”» и сделать текст внутри тега жирным. Однако концепция тегов более общая; теги не обязательно должны влиять на внешний вид. Они могут вместо этого влиять на поведение нажатий мыши и клавиш, «“заблокировать” диапазон текста, чтобы пользователь не мог его редактировать, или на множество других вещей. Тег представлен объектом GtkTextTag. Один GtkTextTag может быть применён к любому количеству диапазонов текста в любом количестве буферов.

Каждый тег хранится в GtkTextTagTable. Таблица тегов определяет набор тегов, которые могут быть использованы вместе. Каждый буфер имеет связанную с ним таблицу тегов; только теги из этой таблицы могут быть использованы с буфером. Однако одна таблица тегов может быть общей для нескольких буферов.

Теги могут иметь имена, что иногда удобно (например, вы можете назвать свой тег, делающий вещи жирными, «“жирный”»), но они также могут быть анонимными (что удобно, если вы создаёте теги на лету).

Большинство манипуляций с текстом выполняется с помощью итераторов, представленных объектом GtkTextIter. Итератор представляет позицию между двумя символами в буфере текста. GtkTextIter — это структура, предназначенная для выделения в стеке; она гарантированно копируется по значению и никогда не содержит данных, выделенных в куче. Итераторы недействительны неопределённое время; всякий раз, когда буфер изменяется таким образом, что влияет на количество символов в буфере, все активные итераторы становятся недействительными. (Обратите внимание, что удаление 5 символов и последующее повторное вставление 5 по-прежнему делает итераторы недействительными, хотя вы получите то же количество символов, которые вы пройдёте через состояние с другим количеством).

По этой причине итераторы не могут использоваться для сохранения позиций при модификации буфера. Для сохранения позиции идеальным объектом является GtkTextMark. Можно представить маркер как невидимый курсор или точку вставки; он плавает в буфере, сохраняя позицию. Если текст вокруг маркера удаляется, маркер остаётся в позиции, которую занимал текст; если текст вставляется в маркер, маркер оказывается слева или справа от нового текста, в зависимости от его направления. Стандартный курсор текста в языках слева направо — это маркер с направлением вправо, потому что он остаётся справа от вставленного текста.

Как и теги, маркеры могут быть именованными или анонимными. В GtkTextBuffer встроены два маркера; они называются «“вставка”» и «“предел_выделения”» и относятся к точке вставки и границе выделения, которое не является точкой вставки, соответственно. Если текст не выделен, эти два маркера будут находиться в одной позиции. Вы можете манипулировать выделенным текстом и позицией курсора, перемещая эти маркеры.

Если вы хотите поместить курсор в ответ на действие пользователя, убедитесь, что используете gtk_text_buffer_place_cursor(), который перемещает оба одновременно без создания временного выделения (перемещение одного, а затем другого временно выделяет диапазон между старыми и новыми позициями).

Буферы текста всегда содержат хотя бы одну строку, но могут быть пустыми (то есть буферы могут содержать ноль символов). Последняя строка в буфере текста никогда не заканчивается разделителем строк (например, символом новой строки); другие строки в буфере всегда заканчиваются разделителем строк. Разделители строк учитываются при вычислении количества символов и смещений символов. Обратите внимание, что некоторые разделители строк Юникода представлены в UTF-8 несколькими байтами, и последовательность из двух символов «“”» также считается разделителем строк.

Буферы текста поддерживают отмену и повтор, если gtk_text_buffer_set_enable_undo() был установлен в значение TRUE. Используйте gtk_text_buffer_undo() или gtk_text_buffer_redo() для выполнения необходимых действий. Обратите внимание, что эти операции игнорируются, если буфер не редактируется. Разработчики могут захотеть, чтобы некоторые операции не отменялись. Для этого заключите свои изменения в gtk_text_buffer_begin_irreversible_action() и gtk_text_buffer_end_irreversible_action().

Простой пример

Самое простое использование GtkTextView может выглядеть так:

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.
 */

Во многих случаях также удобно сначала создать буфер с помощью gtk_text_buffer_new(), а затем создать виджет для этого буфера с помощью gtk_text_view_new_with_buffer(). Или вы можете изменить буфер, отображаемый виджетом, после создания виджета с помощью gtk_text_view_set_buffer().

Пример изменения атрибутов текста

Способ изменения атрибутов текста в GtkTextView заключается в применении тегов, которые изменяют атрибуты для области текста. Для текстовых функций, которые берутся из темы (таких как шрифт и цвет переднего плана), используйте CSS для переопределения их значений по умолчанию.

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);

Приложение gtk4-demo, поставляемое с GTK, содержит больше примеров кода для GtkTextView.

© 2005–2020 The GNOME Project
Licensed under the GNU Lesser General Public License version 2.1 or later.
https://developer-old.gnome.org/gtk4/4.0/TextWidgetObjects.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API