LXF94:GTK+
Lockal (обсуждение | вклад) м (восстановление кавычек в коде AWB) |
Lockal (обсуждение | вклад) м («LXF94:GTK+: Буфер обмена и VFS» переименована в «LXF94:GTK+»: унификация) |
Версия 19:43, 27 апреля 2008
|
|
|
Содержание |
Погружение в GNOME
ЧАСТЬ 8 Мы уже успели замочить ножки в океане возможностей, которые предоставляет GNOME – и сейчас самое время зайти поглубже. Андрей Боровский проверяет, теплая ли водичка.
В прошлый раз мы начали работу над демо-приложением GNOME – текстовым редактором. До сих пор в этой программе собственно «гномовского» было не так уж много: только код инициализации. На этот раз мы рассмотрим некоторые функции, относящиеся исключительно к GNOME; но сначала – немного визуального программирования.
Редактирование меню
Заготовка главного меню нашей программы содержит пункт Вид (View), однако само это меню пустое. Добавим в меню Вид новую команду Шрифт..., позволяющую выбрать шрифт для отображения текста. Щелкните правой кнопкой мыши по строке главного меню в окне формы приложения и в открывшемся контекстном меню выберите команду Правка меню...
Список названий пунктов меню отражает существующие между ними иерархические отношения. Сдвиг строки вправо означает переход к следующему уровню вложенности меню. С помощью кнопок Добавить и Добавить подчиненный в меню можно добавить новый пункт. При добавлении нового подчиненного пункта необходимо указать для него родительский пункт меню. Если мы потом передумаем, то с помощью клавиш навигации сможем переместить уже созданный пункт в другую группу или на другой уровень вложенности.
Раскрывающийся список Встроенный элемент позволяет присвоить новому пункту меню свойства одного из стандартных элементов меню (эти встроенные элементы используют пункты меню, созданные автоматически). Строка ввода Метка позволяет указать название пункта меню. Нижний дефис в названии пункта меню отмечает подчеркнутый символ, который нужно вводить в сочетании с Alt для быстрого доступа к этому пункту. Строка ввода имя позволяет указать имя объекта GtkImageMenuItem, соответствующего пункту меню. В строке ввода Обработчик указывается имя функции-обработчика сигнала activate, посылаемого командой меню. Комбинированный раскрывающийся список Иконка позволяет указать пиктограмму, которая будет отображаться рядом с командой меню. Можно загрузить собственную пиктограмму из файла либо использовать одну из стандартных пиктограмм, установленных в системе.
Для создаваемого нами пункта меню Шрифт... выберем стандартную пиктограмму gtk-select-font. Остальные элементы редактора меню нам сейчас не интересны, так что мы их опустим (читателю, как всегда, рекомендуется обратиться к документации). Щелкните кнопку OK. Теперь у нас есть новая команда меню, для которой нужно написать обработчик (функция on_fontselect_activate()). Для выбора шрифта используйте уже знакомое нам диалоговое окно GtkFontSelectionDialog. Полный код обработчика вы найдете на диске, мы на нем останавливаться не будем.
Буфер обмена GTK+ и GNOME
Интерфейс буфера обмена в GTK+ основан на структуре GtkClipboard. Мы получаем доступ к этой структуре с помощью функции gtk_clipboard_get(). Первый вызов gtk_clipboard_get() создает экземпляр структуры, которая переходит под управление GTK+ (так что мы не должны удалять ее явным образом). При последующих вызовах gtk_clipboard_get() возвращает указатель на существующую структуру GtkClipboard.
При работе с X Window следует учесть, что система поддерживает как минимум два буфера обмена (теоретически их может быть и больше). Если вы используете команду меню Правка | Копировать, данные обычно попадают в буфер обмена, связанный с атомом CLIPBOARD. В то же время любые данные, выделенные мышью в окне X-программы, заносятся в буфер обмена, связанный с атомом PRIMARY (вставка данных из этого буфера обычно выполняется с помощью щелчка средней кнопкой мыши). Вообще говоря, X-программы вольны интерпретировать оба буфера так, как им заблагорассудится. На практике это иногда приводит к тому, что результаты вставки данных из буфера обмена оказываются несколько неожиданными.
Интерфейс буфера обмена GTK+ позволяет работать со всеми буферами обмена X. GTK+ поддерживает размещение данных в буферах обмена в нескольких форматах и отложенную запись.
Организовать передачу данных между буфером обмена и экземпляром GtkTextBuffer очень просто. Ниже приводится текст обработчика сигнала меню copy1_activate нашего текстового редактора (этот сигнал генерирует команда Правка | Копировать).
void on_copy1_activate (GtkMenuItem * menuitem, gpointer user_data) { char * atom = gdk_atom_name("CLIPBOARD"); GtkClipboard * cb = gtk_clipboard_get(atom); g_free(atom); gtk_text_buffer_copy_clipboard(textbuffer, cb); }
Вызывая gtk_clipboard_get(), мы передаем этой функции X-атом, идентифицирующий буфер обмена, который мы хотим открыть, и получаем строку с именем атома с помощью функции gdk_atom_name(). Функция gtk_text_buffer_copy_clipboard() копирует в буфер обмена строку текста, выделенную в текстовом буфере GtkTextBuffer (программно или с помощью интерфейса пользователя). Первым параметром функции, копирующей данные, должен быть указатель на объект GtkTextBuffer, вторым параметром – указатель на объект GtkClipboard. Для вставки данных из буфера обмена в текстовый буфер применяется функция gtk_text_buffer_paste_clipboard(), которой, помимо прочего, следует передать итератор, указывающий, где именно в тексте должна быть вставлена строка из буфера обмена (при использовании текстового буфера вместе с GtkTextView вместо итератора функции можно передать NULL).
Разумеется, у буфера обмена есть и собственный API, который можно применять независимо от других компонентов GTK+/GNOME. Для передачи в буфер обмена строки текста в общем случае используется функция gtk_clipboard_set_text(). Первым параметром этой функции должен быть указатель на объект GtkClipboard. Второй и третий параметры, соответственно, строка текста с нулевым конечным символом и длина строки в байтах (напомню, что в GTK+ и GNOME по умолчанию используется кодировка UTF-8). Для передачи в буфер обмена растрового графического объекта служит функция gtk_clipboard_set_image(). У этой функции всего два параметра: указатель на объект GtkClipboard и указатель на объект GdkPixBuf, содержащий данные растрового изображения.
Если вы хотите поместить в буфер обмена данные в нескольких форматах или реализовать отложенную запись, все становится более сложным. В этом случае ваша программа должна объявить системе, что она готова передать в буфер обмена данные в определенных форматах и зарегистрировать функции обратного вызова, которые будут выполнять их фактическую обработку. Когда данные понадобятся, эти функции будут вызваны системой. Рассмотрим пример – фрагмент программы, копирующей в буфер строку текста:
void cb_get_func(GtkClipboard * clipboard, GtkSelectionData * selection_data, guint info, gpointer user_data) { char * str = "Данные для буфера обмена"; gtk_selection_data_set_text(selection_data, str, strlen(str)); } void cb_clear_func(GtkClipboard * clipboard, gpointer user_data) { // Nothing to do } void on_copy1_activate (GtkMenuItem * menuitem, gpointer user_data) { static const GtkTargetEntry targets[] = { { "UTF8_STRING", 0, GDK_TARGET_STRING } }; char * atom = gdk_atom_name("CLIPBOARD"); GtkClipboard * cb = gtk_clipboard_get(atom); g_free(atom); gtk_clipboard_set_with_data(cb, targets, 1, cb_get_func, cb_clear_func, NULL); }