Prev

Up

Home

GTK+ Reference Manual

Next

Text Widget Overview

Text Widget Overview Краткий обзор GtkTextBuffer, GtkTextView и аналогичных

Концептуальный краткий обзор

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

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

Текст в буфере может быть помечен с помощью tags. Тэг это атрибут который может быть применен к некоторой области текста. Например, тэг может быть назван "bold" и создать текст жирным внутри тэга. Однако, концепция тэга более общая чем это; тэги не затрагивают вид. Вместо этого они могут затронуть поведение нажатия мыши и клавиш, "блокировать" диапазон текста так что пользователь не сможет его редактировать, или многое другое. Тэги представляются объектами GtkTextTag. Один GtkTextTag может быть применён к любому числу областей текста в любом количестве буферов.

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

Тэги могут иметь имена, которые иногда удобны (например, вы можете назвать тэг делающий текст полужирным "bold"), но они могут также быть безымянными (что очень удобно если вы создаёте тэг на лету).

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

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

Как и тэги, маркеры могут быть именованными или анонимными. Есть два маркера созданных для GtkTextBuffer; их названия "insert" и "selection_bound" и они относятся к точке вставки и границе выделения соответственно. Если нет выделенного текста, эти два маркера будут в одной позиции. Вы можете управлять выделением и появлением курсора, перемещая эти маркеры. [2]

Текстовый буфер всегда содержит по крайней мере одну строку, но могут быть и пустыми (то есть, буфер может содержать нулевые символы). Последняя строка никогда не заканчивается разделителем строк (таким как новая строка); разные строки всегда заканчиваются разделителем строк. Разделитель строк считается символом когда подсчитывается число символов и смещение символов. Помните, некоторые разделители строк Unicode представляются в много-байтной UTF-8, и двух-символьная последовательность "\r\n" тоже рассматривается как разделитель строки.

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

Самое простое использование 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, "Привет, это какой-то текст", -1); /* Теперь вы можете поместить view в контейнер и показать его на * экране; когда пользователь редактирует текст,в буфере будут * издаваться сигналы, такие как "changed", "insert_text", и так далее. */

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

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

Есть два способа изменения текстовых атрибутов в GtkTextView. Вы можете изменить атрибуты по умолчанию для данного GtkTextView, и вы можете применить тэги которые изменяют атрибуты для областей текста. Для особенностей текста которые идут из темы такие как шрифт и цвет фона используются стандартные GtkWidget функции, такие как gtk_widget_modify_font() или gtk_widget_modify_text(). Для других атрибутов есть специализированные методы GtkTextView, такие как gtk_text_view_set_tabs().

GtkWidget *view; GtkTextBuffer *buffer; GtkTextIter start, end; PangoFontDescription *font_desc; GdkColor color; GtkTextTag *tag; 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); /* Изменяем шрифт по умолчанию для всего виджета */ font_desc = pango_font_description_from_string ("Serif 15"); gtk_widget_modify_font (view, font_desc); pango_font_description_free (font_desc); /* Изменяем цвет по умолчанию для всего виджета */ gdk_color_parse ("green", &color); gtk_widget_modify_text (view, GTK_STATE_NORMAL, &color); /* Изменяем левое поле для всего виджета */ gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 30); /* Используем тэг для изменения цвета только для одной части виджета */ 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);

В gtk-demo приложении которое идёт вместе с GTK+ содержится много примеров кода для GtkTextView.



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