Руководство программиста в Photon (953920), страница 35
Текст из файла (страница 35)
Pt_STYLE_EXTENT или Pt_STYLE_SIZING Адрес функции, вызываемой всякий раз виджетом, использующим этот стиль, когда происходит перемещение, изменение размеров или модификация такого рода, которая может потребовать перемещения виджета или изменения его размеров (изменение в данных виджета). Эта функция отвечает за установку размеров виджета в соответствующие значения.
Pt_STYLE_ACTIVATE Адрес функции, вызываемой всякий раз виджетом, создаваемым со стилем, принятым по умолчанию, и всякий раз, когда стиль виджета изменяется с одного стили на другой. Эта функция является тем местом, где размещается манипулирование плоскостями управления виджета, дополнения к ответным реакциям или установки ресурсов (для перезаписи принятых для виджета по умолчанию).
Pt_STYLE_CALC_BORDER Адрес функции, отвечающей за оповещение как много пространства требуется для представления отделки и границ краёв виджета.
Pt_STYLE_CALC_OPAQUE Адрес функции, отвечающей за вычисление списка
"черепицы", представляющий затенённые области виджета. Этот список используется для определения того, что должно быть повреждено под этим виджетом, когда он модифицируется.
Pt_STYLE_DEACTIVATE Адрес функции, вызываемой всякий раз виджетом,
использующим этот стиль, когда виджет уничтожается либо переключается на другой стиль.
Pt_STYLE_NAME Имя стиля
Pt_STYLE_DATA Указатель на произвольный блок данных для использования стилем.
Более детально описание этих членов см. в описании библиотечной функции Photon'a PtSetStyleMembor().
Следующие функции позволяют Вам создавать и манипулировать стилями класса виджета:
PtAddClassStyle() | Добавляет стиль к классу виджета |
PtCreateClassStyle() | Создаёт стиль класса |
PtDupClassStyle() | Получает копию стиля класса виджета |
PtFindClassStyle() | Отыскивает стиль с заданным именем |
PtGetStyleMember() | Получает член стиля |
PtGetWidgetStyle() | Получает стиль, который виджет использует в текущий момент |
PtSetStyleMember() | Устанавливает член стиля |
PtSetStyleMembers() | Устанавливает множество членов стиля из списка аргументов переменной длины |
PtSetWidgetStyle() | Устанавливает текущий стиль для виджета |
Некоторые из этих функций требуют или возвращают указатель на структуру PtWidgetClassStyle_t. Не обращайтесь к членам этой структуры напрямую, а используйте для этого функцию PtGetStyleMember().
Вы можете также установить стиль экземпляра виджета, установив его ресурс Pt_ARG_STYLE (см. описание виджета PtBasic в книге "Справочник виджетов"). Установка этого ресурса имеет тот же эффект, что и вызов функции PtSetWidgetStyle().
Этот пример создаёт стиль, названный blue, и несколько кнопок. Заметьте, что Ваши виджеты могут использовать стиль до того, как Вы добавили стиль к классу или даже перед тем, как Вы создали стиль. Когда Вы создаёте стиль и добавляете его, все виджеты, использующие стиль, немедленно обновляются.
#include <Pt.h>
PtWidget_t *win, *but;
PtWidgetClassStyle_t *b;
void blue_draw (PtWidget_t *widget, PhTile_t *damage)
{
/* Это функция прорисовки для стиля blue.
Она рисует голубой прямоугольник (без надписи)
для виджета.
*/
PgSetFillColor( Pg_BLUE);
PgDrawRect( PtWidgetExtent (widget,NULL), Pg_DRAW_FILL);
}
int use_blue_style( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo)
{
/* Эта ответная реакция устанавливает текущий стиль для данного
экземпляра виджета. Если Вы не прикрепили стиль blue
к классу, никаких изменений во внешнем виде виджета нет.
*/
PtSetWidgetStyle (widget, "blue");
return Pt_CONTINUE;
}
int attach_blue_style( PtWidget_t *widget, void *data,
PtCallbackInfo_t *cbinfo)
{
/* Эта ответная реакция добавляет стиль к классу виджета.
Если Вы щёлкнули на одной из кнопок "использование стиля blue",
изменится стильвсех кнопок.
*/
PtAddClassStyle (PtButton, b);
return Pt_CONTINUE;
}
int main()
{
PhArea_t area = {{0,50},{100,100}};
PtArg_t argt[10];
PtStyleMethods_t meth;
PtCallback_t cb = {use_blue_style, NULL};
PtCallback_t cb2 = {attach_blue_style, NULL};
int unsigned n;
/* Инициализация методов для стиля. */
meth.method_index = Pt_STYLE_DRAW;
meth.func = blue_draw;
PtInit(NULL);
/* Создание окна. */
PtSetArg (&argt[0], Pt_ARG_DIM, &area.size, 0);
win = PtCreateWidget (PtWindow, NULL, 1, argt);
/* Создание нескольких кнопок. Когда Вы щёлкаете по одной из этих
кнопок, ответная реакция делает экземпляр виджета
использующим стиль blue. */
n = 0;
PtSetArg (&argt[n++], Pt_ARG_TEXT_STRING, "Use blue style", 0);
PtSetArg (&argt[n++], Pt_CB_ACTIVATE, &cb, 1);
but = PtCreateWidget (PtButton, NULL, n, argt);
PtSetArg (&argt[0], Pt_ARG_TEXT_STRING, "Use blue style also", 0);
PtSetArg (&argt[n++], Pt_ARG_POS, &area.pos, 0);
but = PtCreateWidget (PtButton, NULL, n, argt);
/* Создание другой кнопки. Когда Вы щёлкаете на ней,
ответная реакция прикрепляет стиль blue к классу виджета. */
n = 0;
PtSetArg (&argt[n++], Pt_ARG_TEXT_STRING, "Attach blue style", 0);
PtSetArg (&argt[n++], Pt_CB_ACTIVATE, &cb2, 1);
PtSetArg (&argt[n++], Pt_ARG_POS, &area.pos, 0);
area.pos.y = 85;
but = PtCreateWidget (PtButton, NULL, n, argt);
/* Копирование принимаемого по умолчанию стиля, чтобы создать стиль blue.
Замена рисуемого члена новым стилем. */
b = PtDupClassStyle (PtButton, NULL, "blue");
PtSetClassStyleMethods (b,1,&meth);
PtRealizeWidget (win);
PtMainLoop();
return EXIT_SUCCESS;
}
Глава 12. Поверхности управления
Что такое поверхности управления?
Поверхности управления – это геометрические области внутри виджета, которые могут позиционировать, изменять размеры и перерисовывать сами себя. Кроме того, они могут определять своё собственное поведение. Они делают всё это через ответные реакции и флаги управления событиями, предоставляемыми при создании поверхности.
Поверхности управления позволяют Вам переопределять поведение для любой области внутри рисуемого пространства виджета. Кроме того, они могут перерисовывать себя, равно как и пересчитывать свою собственную геометрию. Концептуально они могут рассматриваться как облегчённые "виджеты внутри виджетов".
Например, рассмотрим линейку протяжки (scroll bar). Вы получаете различные действия в зависимости от того, где Вы щёлкнете на ней: кнопки стрелок выполнят шаг вверх или вниз; щелчок на жёлобе выполнит пролистывание страницы вверх или вниз; перетаскивание каретки выполняет прокрутку при её перемещении. Виджет PtScrollbar выполнен как одиночный виджет с несколькими поверхностями управления на нём. Вы можете также использовать плоскости управления для:
-
эмулирования клавиатуры, напр., добавление Shift-lock к клавише Shift;
-
панелей нажимных кнопок;
-
и прочего.
Важно отметить, что поверхности управления – это свойство виджета; для своего существования им требуется виджет. Вместе с тем виджет может обладать любым числом поверхностей управления, делая возможным при использовании всего одного виджета (напр., PtWindow) обеспечивать целый пользовательский интерфейс на ничтожном размере данных при исполнении (8% является разумной верхней границей) как альтернативу обеспечению несколькими виджетами для использования в пользовательском интерфейсе.
Ограничения
Для поверхностей управления существует несколько ограничений:
-
Библиотека виджетов предоставляет сервис для виджетов, который не может, из соображений экономии, обеспечиваться для поверхностей управления. Например, виджеты обладают понятием затенённости, используемым при прорисовке для снижения мерцания. Поверхности управления просто прорисовываются от тыльной к передней без какой-либо заботы о затенении.
-
Поверхности управления не могут содержать других поверхностей управления и не включают понятие фокуса.
-
Поверхности управления являются крайне необработанными элементами и могут обеспечивать только то поведение, которое Вы заложили при их создании. Нетрудно реализовать кнопку как поверхность управления, но построение виджета PtMultitext как такую поверхность потребует уже больших усилий.
Привязка действий к поверхностям управления
Вы можете привязать поверхности управления к любым предопределённым действиям виджета или к действиям, определённым пользователем.
Типами поверхностей управления являются:
Обычные поверхности | Позволяют Вам определять маску событий и функции ответных реакций для поверхности управления |
Активные поверхности | Позволяют Вам автоматически связывать поверхность управления с одним из предопределённых действий виджета |
Ссылка на поверхности управления
Вы можете ссылаться на поверхности управления через:
-
указатель на структуру поверхности управления (PtSurface_t*)
-
числовой идентификатор (16-битовые PtSurfaceId_t).
Этот идентификатор уникальным образом идентифицирует поверхность управления внутри его соотнесённого виджета. Действительными значениями для идентификатора поверхности являются значения в диапазоне от 1 до 255 включительно.
Хотя метод указателя действует напрямую и потому более быстр, он не настолько безопасен, как метод идентификатора. Чтобы понять почему, обсудим, как поверхности управления организованы и хранятся в памяти.
В отличие от иерархии виджетов, выполненной как связанный список, поверхности управления хранятся как массив структур поверхностей (PtSurface_t). Основными причинами для хранения таким способом являются:
-
Массив обеспечивает быстрое прохождение в обоих направлениях (что требуется, поскольку прорисовка обрабатывается от тыла к переднему плану, а события обрабатываются от переднего плана к заданному).
-
Массив снижает запросы на память в расчёте на одну поверхность. Для удовлетворения требования быстрого прохождения должен быть использован дважды связанный список, что существенно увеличивает требуемый объём памяти.
-
Вам, вероятно, не очень часто понадобится добавлять или удалять поверхности управления, так что использование массива не станет причиной большого ухудшения производительности.
Поскольку Вы физически перемещаете поверхности управления по кругу в стековом порядке, их размещение в массиве изменяется, в результате чего меняются их адреса в памяти. Кроме того, при добавлении или удалении Вами поверхностей управления к виджету, массив необходимо переразмещать, что также станет причиной того, что сам массив в целом будет перемещаться в памяти. Со всеми этими возможностями по перемещению в памяти, цифровые идентификаторы являются единственным реальным способом локализации поверхности.
Если Вы в достаточной степени уверены, что конфигурация поверхностей виджета не будет изменяться, то метод указателя является безопасным (и более быстрым, поскольку метод идентификатора требует исполнения линейной петли обработки в массиве поверхности).
API поверхностей управления
Функции, приведенные ниже, описаны в "Справочнике библиотечных функций Photon'a").
Создание и уничтожение поверхностей управления
Следующие функции создают и уничтожают поверхности управления:
PtCreateActionSurface() | Создаёт поверхность управления внутри виджета, связанную с действием виджета |
PtCreateSurface() | Создаёт обычную поверхность управления внутри виджета |
PtDestroyAllSurface() | Уничтожает все поверхности управления виджета |
PtDestroySurface() | Уничтожает поверхность управления |
PtDestroySurfaceById() | Уничтожает поверхность управления с заданным идентификатором |
Нахождения идентификаторов для поверхностей управления
Чтобы найти идентификатор поверхности и действия, используйте эти функции:
PtSurfaceActionId() | Получает идентификатор действия для поверхности |
PtSurfaceId() | Получает идентификатор поверхности управления |
Вычисление геометрии для поверхностей управления
Вы должны предусмотреть функцию, которая вычисляет геометрию управляющей поверхности. Поверхности управления опрашиваются для вычисления их геометрии дважды, когда виджет, являющийся их владельцем, опрашивается для вычисления его геометрии:
-
непосредственно перед вычислением геометрии виджета (что позволяет виджету изменить свои размеры в соответствии с требованиями своих поверхностей, если виджет заботится об этом – и некоторые виджеты таки делают это);
-
сразу после (позволяя поверхностям позиционировать и задать свои размеры в соответствии с размерами виджета).
Аргумент почтового сообщения, передаваемый функции геометрии, говорит Вам, какой случай обрабатывается.
Поверхность может также вычислять свою геометрию на основании геометрии других поверхностей. Используя функции PtCalcSurface() или PtCalcSurfaceById(), вы можете гарантировать, что поверхности, которыми Вы интересуетесь, вычислили свою геометрию до того, как их рассматривают.