Обзор виджета текста
Обзор виджета текста — Обзор GtkTextBuffer, GtkTextView и родственных элементов
Концептуальный обзор
GTK+ имеет чрезвычайно мощную структуру для многострочного редактирования текста. Основные объекты, участвующие в этом процессе, — GtkTextBuffer, представляющий редактируемый текст, и GtkTextView, виджет, который может отображать GtkTextBuffer. Каждый буфер может отображаться любым количеством представлений.
Важно помнить, что текст в GTK+ использует кодировку UTF-8. Это означает, что один символ может быть закодирован несколькими байтами. Количество символов обычно называется смещениями, а количество байтов — индексами. Если вы перепутаете эти два понятия, всё будет работать нормально с ASCII, но как только в вашем буфере появятся многобайтовые символы, могут возникнуть проблемы.
Текст в буфере может быть помечен тегами. Тег — это атрибут, который может быть применен к определённому диапазону текста. Например, тег может называться «жирный» и делать текст внутри тега жирным. Однако концепция тегов более общая; теги не обязательно влияют на внешний вид. Вместо этого они могут влиять на поведение нажатий мыши и клавиш, «блокировать» диапазон текста, чтобы пользователь не мог его редактировать, или множество других действий. Тег представлен объектом GtkTextTag. Один GtkTextTag может быть применён к любому числу диапазонов текста в любом количестве буферов.
Каждый тег хранится в GtkTextTagTable. Таблица тегов определяет набор тегов, которые могут быть использованы вместе. Каждый буфер имеет одну таблицу тегов, связанную с ним; только теги из этой таблицы тегов могут быть использованы с буфером. Однако одну таблицу тегов можно использовать для нескольких буферов.
Теги могут иметь имена, что бывает удобно (например, вы можете назвать свой тег, который делает текст жирным, «жирный»), но они также могут быть анонимными (что бывает удобно, если вы создаёте теги на лету).
Большинство манипуляций с текстом выполняется с помощью итераторов, представленных объектом GtkTextIter. Итератор представляет позицию между двумя символами в буфере текста. GtkTextIter — это структура, предназначенная для выделения в стеке; она гарантированно копируема по значению и никогда не содержит данных, выделенных в куче. Итераторы не являются действительными бесконечно; всякий раз, когда буфер изменяется таким образом, что влияет на количество символов в буфере, все имеющиеся итераторы становятся недействительными. (Обратите внимание, что удаление 5 символов и последующее вставка 5 символов всё равно делает итераторы недействительными, хотя в итоге вы получаете то же количество символов, что и раньше, но проходите через состояние с другим количеством).
По этой причине итераторы нельзя использовать для сохранения позиций после модификации буфера. Для сохранения позиции идеально подходит объект GtkTextMark. Вы можете представить себе маркер как невидимый курсор или точку вставки; он плавает в буфере, сохраняя позицию. Если текст, окружающий маркер, удаляется, маркер остаётся в позиции, которую этот текст занимал ранее; если текст вставляется в маркер, маркер оказывается либо слева, либо справа от нового текста, в зависимости от его тяжести. Стандартный текстовый курсор в языках слева направо — это маркер с правой тяжестью, поскольку он остаётся справа от вставляемого текста.
Как и теги, маркеры могут быть именованными или анонимными. В GtkTextBuffer есть два встроенных маркера; они называются "insert" и "selection_bound" и относятся к точке вставки и границе выделения, которая не является точкой вставки, соответственно. Если текст не выделен, эти два маркера будут в одной позиции. Вы можете манипулировать выделенным текстом и положением курсора, перемещая эти маркеры.
Буферы текста всегда содержат как минимум одну строку, но могут быть пустыми (то есть буферы могут содержать ноль символов). Последняя строка в буфере текста никогда не заканчивается символом перевода строки (таким как новая строка); остальные строки в буфере всегда заканчиваются символом перевода строки. Разделители строк считаются символами при вычислении количества символов и смещений символов. Обратите внимание, что некоторые разделители строк Unicode представлены несколькими байтами в UTF-8, а последовательность из двух символов «\r\n» также считается разделителем строк.
Простой пример
Самое простое использование GtkTextView может выглядеть так:
Во многих случаях также удобно сначала создать буфер с помощью gtk_text_buffer_new(), а затем создать виджет для этого буфера с помощью gtk_text_view_new_with_buffer(). Или вы можете изменить буфер, отображаемый виджетом, после создания виджета с помощью gtk_text_view_set_buffer().
Пример изменения атрибутов текста
Существует два способа изменения атрибутов текста в GtkTextView. Вы можете изменить атрибуты по умолчанию для данного GtkTextView, и вы можете применить теги, которые изменяют атрибуты для области текста. Для текстовых функций, которые берутся из темы (например, шрифт и цвет переднего плана), используйте стандартные функции GtkWidget, такие как gtk_widget_modify_font() или gtk_widget_override_color(). Для других атрибутов существуют специальные методы в GtkTextView, такие как gtk_text_view_set_tabs().
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-demo, которое поставляется с GTK+, содержит больше примеров кода для GtkTextView.
[2] Если вы хотите разместить курсор в ответ на действие пользователя, обязательно используйте gtk_text_buffer_place_cursor(), который перемещает оба одновременно без создания временного выделения (перемещение одного, а затем другого временно выделяет диапазон между старыми и новыми позициями).
© 2005–2020 The GNOME Project
Licensed under the GNU Lesser General Public License version 2.1 or later.
https://developer.gnome.org/gtk3/3.22/TextWidget.html