GTK+ 2.0 Tutorial |
||
---|---|---|
Menu Widget |
После рассмотрения сложного пути создания меню, рассмотрим как это же можно сделать при помощи вызова функции gtk_item_factory.
ItemFactory создаёт меню из массива записей ItemFactory. Это означает, что вы можете определить ваше меню в его самой простой форме и затем создать виджеты (меню/строки) меню с минимумом запросов функции.
В ядре ItemFactory находится ItemFactoryEntry. Эта структура определяет один пункт меню и когда массив этих записей определен, целое меню сформировано. Структура записей ItemFactory выглядит так:
struct _GtkItemFactoryEntry
{
gchar *path;
gchar *accelerator;
GtkItemFactoryCallback callback;
guint callback_action;
gchar *item_type;
};
|
Каждая строка определяет часть пункта меню.
*path - определяет путь и название пункта меню, например: "/File/Open" было бы именем пункта меню который подходит для записи ItemFactory с путём "/File". Однако пункт "/File/Open" был бы показан в меню File как "Open", потому что первые "/" используются для определения пути и не могут присутствовать в имени пункта. Символ, которому предшествует символ подчеркивания, указывает акселератор (сокращенная клавиша) в открытом меню.
*accelerator является строкой, которая указывает ключевую комбинацию клавиш и используется как ярлык к пункту меню. Строка может состоять из единичного символа или комбинации модификаторов и символов.
Модификаторами клавиш могут быть:
"<ALT> - alt
"<CTL>" или "<CTRL>" или "<CONTROL>" - control
"<MOD1>" до "<MOD5>" - modn
"<SHFT>" или "<SHIFT>" - shift
|
"<ConTroL>a"
"<SHFT><ALT><CONTROL>X"
|
callback - функция вызываемая при создании пунктом меню сигнала "activate". Форма обратного вызова описана в разделе Callback Description.
Значение callback_action помещается в функцию обратного вызова. Прототип функции смотрите в разделе Callback Description.
item_type - является строкой, которая определяет тип виджета упакованного в контейнер пунктов меню. Возможные значения:
Отметьте, что <LastBranch> полезен только для одного подменю строки меню.
Обратный вызов для ItemFactory entry может иметь две формы. Если callback_action равен 0 (zero), он имеет следующую форму:
void callback(void)
|
другая форма:
void callback(gpointer callback_data,
guint callback_action,
GtkWidget *widget)
|
callback_data - является указателем на произвольную часть данных и установлен вызовом gtk_item_factory_create_items().
callback_action - некоторое значение callback_action в ItemFactory записях.
*widget - указатель на виджет пункта меню (подробности в Manual Menu Creation).
Создаём простой пункт меню:
GtkItemFactoryEntry entry = {"/_File/_Open...", "<CTRL>O", print_hello,
0, "<Item>"};
|
Здесь создаётся простой пункт меню "/File/Open" (отображается как "Open"), внутри строки меню "/File". Он имеет акселератор (shortcut) control+'O' при нажатии которого вызывается функция print_hello(). print_hello() имеет форму void print_hello(void) так как callback_action имеет значение zero. Если 'O' в "Open" подчеркнута, то при открытом меню и нажатой клавише 'O' пункт будет активизирован. Заметьте, что "File/_Open" может быть использован как путь вместо "/_File/_Open".
Создание входа с более сложным обратным вызовом (callback):
GtkItemFactoryEntry entry = {"/_View/Display _FPS", NULL, print_state,
7,"<CheckItem>"};
|
Это определяет новый пункт меню отображаемый как "Display FPS" в вышестоящем пункте меню "View". При нажатии вызывается функция print_state(). Так как callback_action не равно zero print_state() имеет форму:
void print_state(gpointer callback_data,
guint callback_action,
GtkWidget *widget)
|
с callback_action равным 7.
Создаём установку кнопки выбора:
GtkItemFactoryEntry entry1 = {"/_View/_Low Resolution", NULL, change_resolution,
1, "<RadioButton>"};
GtkItemFactoryEntry entry2 = {"/_View/_High Resolution", NULL, change_resolution,
2, "/View/Low Resolution"};
|
entry1 определяет одиночную кнопку выбора которая переключает вызов функции change_resolution() с параметром callback_action равным 1. change_resolution() имеет форму:
void change_resolution(gpointer callback_data,
guint callback_action,
GtkWidget *widget)
|
entry2 определяет кнопку выбора которая принадлежит группе в которой находится entry1. Она вызывает туже самую функцию при переключении, но параметр callback_action равен 2. Обратите внимание на отсутствие акселераторов. Если бы потребовалась ещё одна кнопка выбора для переключения, то её можно было бы создать таким же образом в этой же группе с item_type равным "/View/Low Resolution".
Массив записей для определения меню. Ниже приведен пример объявления массива:
static GtkItemFactoryEntry entries[] = {
{ "/_File", NULL, NULL, 0, "<Branch>" },
{ "/File/tear1", NULL, NULL, 0, "<Tearoff>" },
{ "/File/_New", "<CTRL>N", new_file, 1, "<Item>" },
{ "/File/_Open...", "<CTRL>O", open_file, 1, "<Item>" },
{ "/File/sep1", NULL, NULL, 0, "<Seperator>" },
{ "/File/_Quit", "<CTRL>Q", quit_program, 0, "<Item>"} };
|
Массив GtkItemFactoryEntry пунктов определяет меню. Функция выглядит так:
GtkItemFactory* gtk_item_factory_new( GtkType container_type,
const gchar *path,
GtkAccelGroup *accel_group );
|
container_type может иметь следующие значения:
GTK_TYPE_MENU
GTK_TYPE_MENU_BAR
GTK_TYPE_OPTION_MENU
|
container_type определяет тип нужного вам меню, например - всплывающее меню, панель меню или меню опций (как поле со списком но с выпавшим меню).
path определяет путь к основному меню. В основном уникальное имя основного меню должно быть заключено в треугольные скобки "<>". Это важно для обозначения акселераторов. Оно должно быть уникальным и для каждого меню и для каждой программы. Например программа с именем 'foo', может иметь главное меню "<FooMain>", а всплывающее меню "<FooImagePopUp>", или нечто похожее. Главное чтобы они были уникальны.
accel_group указатель на gtk_accel_group. Таблицы акселераторов устанавливаются в то время как генерируется меню. Новая группа акселераторов создаётся функцией gtk_accel_group_new().
Но это - только первый шаг. Чтобы преобразовывать массив информации GtkItemFactoryEntry в виджеты, используется следующая функция :
void gtk_item_factory_create_items( GtkItemFactory *ifactory,
guint n_entries,
GtkItemFactoryEntry *entries,
gpointer callback_data );
|
*ifactory - указатель на вышеупомянутое созданное производство пунктов.
n_entries - является числом входов в массив GtkItemFactoryEntry..
*entries - указатель на массив GtkItemFactoryEntry.
callback_data - является тем, что передают во все функции обратного вызова для всех входов с callback_action != 0.
Группа акселераторов создана, теперь нужно прикрепить меню к окну:
void gtk_window_add_accel_group( GtkWindow *window,
GtkAccelGroup *accel_group);
|
Следующая функция извлекает виджеты из ItemFactory:
GtkWidget* gtk_item_factory_get_widget( GtkItemFactory *ifactory,
const gchar *path );
|
Например, если ItemFactory имеет две записи "/File", и "/file/new", используя дорожку "/File" извлечётся виджет menu из ItemFactory. Используя путь "/File/New" извлечётся виджет menu item. Это позволяет установить начальное состояние пунктов меню. Например для установки по умолчанию кнопки выбора в путь "/Shape/Oval", код будет выглядеть так:
gtk_check_menu_item_set_active(
GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory, "/Shape/Oval")),
TRUE);
|
Для извлечения основного меню используется функция gtk_item_factory_get_item() с путем "<main>" (в независимости от использованного пути в gtk_item_factory_new()). В случае ItemFactory, создаваемого с типом GTK_TYPE_MENU_BAR, возвращается виджет панели меню. Если тип GTK_TYPE_MENU возвращается виджет меню. Если тип GTK_TYPE_OPTION_MENU возвращается виджет меню опций.
Помните: вход определенный путем "/_File" фактически путь "/File".
Теперь вы имеете строку меню или меню и можете манипулировать ими как обсуждалось в разделе Manual Menu Creation.
Manual Menu Example |
Item Factory Example |