Создание виджетов

Виджет верхнего уровня возвращаемый XtAppInitialize или XtAppCreateShell является корнем иерархии виджетов программы для данного дисплея или логического приложения. После инициализации Intrinsics, приложение должно провести создание остальной части иерархии виджетов которые ему необходимы для записка программы.

Создание виджетов является двухэтапным процессом. На первом этапе приложение создает иерархию виджетов, но не назначает виджетам окна. На втором этапе приложение назначает виджетам окна и делает их видимыми. Эти этапы разделяются потому, что иначе геометрия окон будет перерасчитываться каждый раз когда добавляется новый потомок. Эти вычисления требуют интенсивного взаимодействия с X сервером и занимают моного времени. Вместо этого начальная геометрия окон вычисляется только один раз. Для получения дополнительной информации смотрите раздел 3.5.

Обобщенной подпрограммой для создания виджетов является XtCreateWidget. Неободимыми аргументами для этой подпрограммы являются имя создаваемого виджета, его класс и родительский виджет. Вы также можете предоставить начальные значения ресурсов для виджета, что будет описано в следующем разделе. XtVaCreateWidget является версией XtCreateWidget которая использует список аргументов переменной длинны.

Motif содержит удобные подпрограммы для создания виджета кажного класса, входящего в Motif. Имя таких подпрограмм обычно выглядит как XmCreate<widget>, где widget является именем класса виджетов. Например, для создания текстового виджета удобно использовать XmCreateText. Эти подпрограммы не требуют аргумента, указывающего класс виджета.

Некоторые удобные подпрограммы типа XmCreateMenuBar создают специализированные виджеты. Такие подпрограммы обычно устанавливают начальные значения некоторых ресурсов для настройки виджета для конкретного использования, например, для настройки виджета RowColumn для использования как полосы меню. Документация на каждую удобную подпрограмму в Motif. Справочник программиста объясняют что делают эти подпрограммы.

Использование подпрограмм создания виджетов из Motif обычно предпочтительнее вызовов XtCreateWidget. В дополнение к созданию нескольких виджетов и установки начальных значений эти подпрограммы иногда производят оптимизацию. Например, некоторые удобные подпрограммы добавляют процедуры /textbl{XmNdestroyCallback} для освобождения памяти при уничтожении виджета.

Замечание

Каждый виджет кроме виджета верхнего уровня в момент создания должет иметь родительский виджет.

Приложение может использовать XtDestroyWidget для уничтожения виджета. Приложение может задавать значения ресурсов как во время создания виджета так и в любое время после этого. Имейте ввиду что жестко запрограммированные значения ресурсов виджета снижает возможности пользователя по настройке виджетов. Он может восстановить значения ресурсов после создания виджета.

Установка ресурсов в процессе инициализации виджета

Когда приложение создает виджет, подпрограмма создания устанавливает начальные значения ресурсов используя следующие источники в порядке возрастания приоритета (т.е. каждый последующий компонент имеет приоритет перед предыдущими):

Каждый класс виджетов имеет собственную процедуру инициализации initialize. После установки начальных значений ресурсов, подпрограмма создания виджета вызывает процедуру initialize для каждого класса в иерархии классов виджета в очередности от суперкласса к подклассу. Процедура initialize может установить новые значения для ресурсов, возможно на основании значений других ресурсов виджета или его родителей. В некоторых случаях процедура initialize принуждает ресурс иметь конкретное значение не обращая внимания на то, что пользователь либо приложение желают установить другое значение. В других случаях процедура initialize может установить значение только если пользователь или приложение не указали другого значения.

Документация на каждый класс виджетов в Motif. Справочник программиста приводит список типов данных и значений по умолчанию для каждого ресурса. Для ресурсов чьи значения по умолчанию вычисляются динамически документация описывает как определяются эти значения.

Аргументы для задания значений ресурсов

Для указания начальных значений ресурсов при вызове подпрограммы создания виджета приложение предоставляет два аргумента: список элементов, представляющих значения ресурсов и целое число указывающее количество элементов в списке. Каждый элемент списка представляет структуру типа Arg. Эта структура состоит из двух полей: строки, определяющей имя ресурса и значения определяющего необходимое значение ресурса. Указываемое значение имеет тип XtArgVal. Этот тип данных имеет размер, достаточные для сохранения значений длинного целого типа или одного из различных типов указателей на данные. Если значение ресурса является типом меньшим чем может быть задано в XtArgVal, то заносится непосредственное значение ресурса, а иначе заносится указатель на необходимое значение. Для большинства ресурсов приложение определяет целочисленные значения (включая тикие типы как Position и Dimension) прямо в поле, определяющем значение ресурса, а иначе в это поле приложение заносит указатель на занчение.

Наиболее общий способ заполнения спецификаций ресурсов заключается в определении списка элементов типа Arg, с достаточным для сохранения всех необходимых спецификаций размером, а затем использовать XtSetArg для вставки каждой спецификации в список. Приложение всегда должно использовать последовательность вызова XtSetArg следующим образом для предотвращения ошибок при построении списка:

    ...
    Widget    text;
    Arg       args[10];
    Cardinal  n;

    n = 0;
    XtSetArg(args[n], XmNrows, 10);    n++;
    XtSetArg(args[n], XmNcolumns, 80); n++;
    text = XmCreateText("text", parent, args, n);

Вместо использования списка Arg, подпрограммы с переменным списком аргументов позволяют определять значения ресурсов как переменное число пар из имени ресурса и его значения. Значения ресурса в каждой паре имеет тип XtSetArg с тем же смыслом что и значение в структуре Arg. Приложение может указать две специальные строки вместо имени ресурса. Если указывается имя \textbl{XtVaNestedList}, то следующий аргумент интерпретируется как вложенный список пар имя-значение. Если же указано имя \textbl{XtVaTypedArg}, то последующие четыре аргумента предоставляют значение ресурса и указывает на необходимость произвести преобразование одного типа данных в другой, как это описано в следующем разделе.

Установка значений ресурсов

Для установки значений ресурсов после того, как виджет был создан, приложение может использовать XtSetValues или XtVaSetValues. XtSetValues принимает список спецификаций ресурсов в формате, аналогичном формату который используется при создании виджета:

    ...
    Arg       args[10];
    Cardinal  n;
   
    n = 0;
    XtSetArg(args[n], XmNrows, 10);    n++;
    XtSetArg(args[n], XmNcolumns, 80); n++;
    XtSetValues(text, args, n);

Каждый класс виджетов имеет собственную процедуру установки значений set_values. После установки значений из указанного списка аргументов, XtSetValues вызывает процедуру set_values для каждого класса в иерархии классов виджета в очередности от суперкласса к подклассу. Процедура set_values может установить новые значения ресурсов отличных от указанных аргументами XtSetValues. Это обычно происходит когда значение одного ресурса зависит от другого. Установка новых значений для ресурсов которые влияют на геометрию виджета может также заставить Motif перерасчитать расположение виджета. В некоторых случаях процедура set_values принуждает ресурс иметь определенное значение не обращая внимание на то, что приложение желает указать другое значение.

Извлечение значений ресурсов

Для извлечения значений ресурсов приложение может использовать XtGetValues или XtVaGetValues. Их аргументы аналогичны аргументам XtSetValues за исключением того, что вместо значения каждого ресурса указывается адрес по которому Motif сохраняет запрашиваемые значения:

    ...
    Arg      args[10];
    Cardinal n;
    short    nrows, ncolumns;
    
    n = 0;
    XtSetArg(args[n], XmNrows, &nrows);  n++;
    XtSetArg(args[n], XmNcolumns, &ncolumns); n++;
    XtGetValues(text, args, n);

Типы данных значений ресурсов

Документация на каждый класс виджетов в Motif. Справочник программиста перечисляет типы двнных, используемые при установке и извлечении значений ресурсов. Пользователь или приложение не всегда имеют возможность предоставить данные в необходимого типа. Motif содержит подпрограммы,называемые конверторами, которые производят преобразование значений ресурсов из одного типа в другой. например, когда значение для базы данных ресурсов извлекается из файла или командной строки, Motif обрабатывает значение как строку. Motif и Xt содержат подпрограммы для преобразования строк в часто используемые типы ресурсов, включая Boolean, Dimension, Position, Pixel и XmFontList.

Когда используются стандартные подпрограммы создания виджетов, XtSetValues и XtGetValues, приложение должно предоставлять значения ресурсов или адреса на значения тех типов, которые ожидает виджет. Но когда используется версии этих процедур с переменными аргументами, приложение может предоставить значения любого типа для которого имеются подпрограммы преобразования из этого типа в значение ожидаемого типа. Для проведения преобразования типа приложение должно указать \textbl{XtVaTypedArg} вместо имени ресурса в списке аргументов. Вмесо значения ресурса приложение указывает четыре аргумента:

Например, следующий вызов производит преобразование предоставленной строки в композитную строку которую Motif ожидает в качестве метки для PushButton:

    ...
    char *label = "Button";
    
    XtVaSetValues(button, XtVaTypedArg, XmNlabelString,
                  XmRString, label, strlen(label) + 1, NULL);

Не забывайте, что установка значений ресурсов с использованием \textbl{XtVaTypedArg} для некоторых ресурсов гаджетов, текстовых полей и VendorShell работает не корректно.

Значения ресурсов и управление памятью

Приложение отвечает за выделение и освобождение памяти, необходимой для значений ресурсов которые оно предоставляет когда инициализирует виджет или устанавливает нове значения. Для большинства ресурсов значения которых не являются непосредственными данными, включая строки, композитные строки и списки шрифтов, Motif делает копию значений предоставленных приложением при создании виджета или вызове XtSetValues. приложение должно освободить выделенную память в любое время после выполнения подпрограммы создания виджета или XtSetValues:

    ...
    char     *label = "Button";
    XmString label_cs;
    
    label_cs = XmStringCreateLocalized(label);
    XtVaSetValues(button, XmNlabelString, label_cs, NULL);
    XmStringFree(label_cs);

Для ресурсов чьи значения не являются непосредственно данными, XtGetValues иногда делает копию значений, а иногда не делает. Например, Motif всегда делает копию композитной строки извлекаемой посредством XtGetValues, но он не делает копии списка композитных строк (тип данных XmStringTable). приложение должно освободить композитную строку, полученную посредством XtGetValues, но в общем не должно освобождать значения других типов за исключением конкретных ресурсов для которых Motif. Справочник программиста не говорит о том, что приложение должно освободить это значение.

Стандартными подпрограммами, которые приложение должно использовать для выделения памяти, являются XtMalloc и XtNew. Стандартной подпрограммой освобождения памяти является XtFree. Некоторые типы данных Motif имеют собственные подпрограммы управления памятью, которые приложение должно использовать вместо более общих подпрограмм Xt. Например, используйте XmStringFree для освобождения памяти, занимаемой композитной строкой. Таблица 2-3 содержит список подпрограмм освобождения памяти в Motif.

Таблица 3-2. Подпрограммы освобождения памяти в Motif

ПодпрограммаВосстанавливает память, используемую для
XmFontListEntryFreeЭлемент списка шрифтов
XmFontListFreeСписок шрифтов
XmFontListFreeFontContextКонтекст списка шрифтов
XmImFreeXICВиджеты ассоциированные с указанным контекстом ввода X (X Input Context - XIC)
XmParseMappingFreeОтображение парсера
XmParseTableFreeТаблица парсера
XmRenderTableFreeТаблица рендеринга
XmRenditionFree???
XmStringConcatAndFreeДве входные композитные строки
XmStringFreeКомпозитная строка
XmStringFreeContextКонтекст сканирования композитной строки
XmTabFreeТабуляция
XmTabListFreeСписок табуляций