Руководство программиста в Photon (953920), страница 36
Текст из файла (страница 36)
Текущая запись геометрии поверхности – это просто вопрос прямой модификации массива указателя поверхностей. Убедитесь, что Вы знаете, как этот массив организован, перед тем как обрабатывать его. Эта организация подробно рассмотрена в документации к функции PtCreateSurface().
Эти функции имеют дело с геометрией поверхностей управления:
PtCalcSurface() | Вынуждает поверхность вычислить свою геометрию | |
PtCalcSurfaceByAction() | Вынуждает все поверхности, связанные с действием, вычислить свою геометрию | |
PtCalcSurfaceById() | Вынуждает поверхность управления с заданным идентификатором вычислить свою геометрию | |
PtSurfaceCalcBoundingBox(), PtSurfaceCalcBoundingBoxById() | Вычисляет окаймляющий прямоугольник для поверхности управления | |
PtSurfaceExtent(), PtSurfaceExtentById() | Вычисляет пределы поверхности управления | |
PtSurfaceHit() | Находит поверхность управления для заданной точки | |
PtSurfaceRect(), PtSurfaceRectById() | Получает ограничивающий прямоугольник для поверхности управления | |
PtSurfaceTestPoint() | Проверяет, находится ли точка на поверхности управления |
Прорисовка поверхностей управления
Поверхности управления опрашиваются на самопрорисовку от заднего плана вперёд, после того как виджет перерисовал себя. Никакого отсечения для Вас не производится. Если Вы хотите отсечения, Вы осуществляете необходимую логику подгонки списка отсечений по ходу прохождения поверхностей, и затем восстанавливаете стек отсечений после того, как прорисована последняя поверхность. В противном случае Вы получите какие-то непредсказуемые результаты.
Следующие функции инициируют перерисовку поверхностей управления:
PtDamageSurface(), PtDamageSurfaceById() | Помечает поверхность как повреждённую, так что она будет перерисована. |
PtDamageSurfaceByAction() | Повреждает все поверхности, связанные с действием. |
Активация поверхностей управления
Эта функция активирует поверхность управления:
PtCheckSurfaces() Сопоставляет событие с поверхностями управления, принадлежащими виджету.
Включение и отключение поверхностей управления
Вы можете включать и отключать поверхности управления, подобно виджетам:
PtDisableSurface(), PtDisableSurfaceById() | Отключает поверхность управления |
PtDisableSurfaceByAction() | Отключает все поверхности управления, связанные с действием |
PtEnableSurface(), PtEnableSurfaceById() | Включает поверхность управления |
PtEnableSurfaceByAction() | Включает все поверхности управления, связанные с действием |
PtSurfaceIsDisabled() | Определяет, отключена ли поверхность управления |
PtSurfaceIsEnabled() | Определяет, включена ли поверхность управления |
Нахождение поверхностей управления
Чтобы найти поверхность управления, используйте эти функции:
PtFindSurface() | Отыскивает поверхность управления с заданным идентификатором |
PtFindSurfaceByAction() | Ищет поверхность управления, связанную с заданным действием |
PtWidgetActiveSurface() | Получает текущую активную в данный момент поверхность управления виджета |
Скрытие и демонстрирование поверхностей управления
Вы можете также скрыть и показать поверхности управления:
PtHideSurface(), PtHideSurfaceById() | Скрывает поверхность управления |
PtHideSurfaceByAction() | Скрывает все поверхности управления, связанные с действием |
PtShowSurface(), PtShowSurfaceById() | Показывает скрытую поверхность управления |
PtShowSurfaceByAction() | Показывает все скрытые поверхности управления, связанные с акцией |
PtSurfaceIsHidden() | Определяет, скрытой ли является поверхность управления |
PtSurfaceIsShown() | Определяет, видна ли поверхность управления |
Установление порядка поверхностей управления
Как и в случае виджетов, Вы можете собирать поверхности управления в стек:
PtInsertSurface(), PtInsertSurfaceById() | Вставляет поверхность управления впереди или позади другой |
PtSurfaceBrotherBehind() | Получает поверхность управления, находящуюся позади данной |
PtSurfaceBrotherInFront() | Получает поверхность управления, находящуюся впереди заданной |
PtSurfaceInBack() | Получает самую заднюю поверхность управления, принадлежащую виджету |
PtSurfaceInFront() | Получает самую переднюю поверхность управления, принадлежащую виджету |
PtSurfaceToBack(), PtSurfaceToBackById() | Перемещает поверхность управления назад за все другие поверхности управления, принадлежащие виджету |
PtSurfaceToFront(), PtSurfaceToFrontById() | Перемещает поверхность управления впереди всех других поверхностей управления, принадлежащих виджету |
Размещение пользовательских данных вместе с поверхностями управления
В функциях, связанных с поверхностями управления, нет данных по ответным реакциям; Вы можете размещать данные пользователя вместе с поверхностями управления, вызывая:
PtSurfaceAddData(), PtSurfaceAddDataById() | Добавляет данные к поверхности управления |
PtSurfaceGetData(), PtSurfaceGetDataById() | Получает данные, связанные с поверхностью управления |
PtSurfaceRemoveData(), PtSurfaceremoveDataById() | Удаляет данные из поверхности управления |
Пример
Вот Вам программа, создающая несколько поверхностей управления:
#include <Pt.h>
/* Это функция, вызываемая, когда для нашей прямоугольной поверхности
управления происходит событие. Когда пользователь щёлкает
на этой поверхности, мы подсчитаем итог и напечатаем, сколько раз это приключилось. */
static int rect_surface_callback( PtWidget_t *widget, PtSurface_t *surface, PhEvent_t *event) {
static int rclicks = 1;
printf("Щелчков по прямоугольнику: %d\n", rclicks++);
return(Pt_END);
}
/* Эта функция, рисующая содержание нашей прямоугольной поверхности
управления. Это очень простой пример; он рисует красный прямоугольник. */
static void rect_surface_draw( PtWidget_t *widget, PtSurface_t *surface, PhTile_t *damage) {
PgSetFillColor(Pg_RED);
PgDrawRect(PtSurfaceRect(surface, NULL), Pg_DRAW_FILL);
}
/* Это функция, синхронизирующая размер поверхности управления с размером виджета.
PtWidgetExtent() возвращает прямоугольник, охватывающий текущий размер виджета.
PtSurfaceRect() является макросом; это означает, что Вы имеете прямой доступ к данным
внутри Вашей поверхности управления. Вам нет нужды вызывать какую-либо функцию,
чтобы изменить её размер. Изменяйте напрямую данные. */
static void rect_surface_calc( PtWidget_t *widget, PtSurface_t *surface, uint8_t post) {
/* Делать это только после того, как виджет расширится. */
if (post) {
/* Прямоугольник занимает верхний левый квадрант окна. */
PhRect_t *extent;
PhRect_t *srect;
extent = PtWidgetExtent(widget, NULL);
srect = PtSurfaceRect(surface, NULL);
srect->ul = extent->ul;
srect->lr.x = (extent->ul.x + extent->lr.x) / 2;
srect->lr.y = (extent->ul.y + extent->lr.y) / 2;
}}
/* Это функция, вызываемая, когда случается событие для нашей эллиптической
поверхности управления. Когда пользователь щёлкает на этой поверхности, мы
подсчитаем итог и напечатаем, сколько раз это приключилось. */
static int ell_surface_callback( PtWidget_t *widget, PtSurface_t *surface, PhEvent_t *event) {
static int eclicks = 1;
printf("Ellipse clicks: %d\n", eclicks++);
return(Pt_END);
}
/* Эта функция, рисующая содержание нашей эллиптической поверхности
управления. Это очень простой пример; он рисует зелёный эллипс. */
static void ell_surface_draw( PtWidget_t *widget, PtSurface_t *surface, PhTile_t *damage) {
PhRect_t *s = PtSurfaceRect(surface, NULL);
PgSetFillColor(Pg_GREEN);
PgDrawEllipse(&(s->ul), &(s->lr), Pg_DRAW_FILL | Pg_EXTENT_BASED);
}
/* Это наша main-функция. Мы создаём окно, инициализируем наше приложение
с сервером Photon и создаём две поверхности управления.
Заметьте, что вторая поверхность не обеспечивает последний параметр, функцию
вычисления занимаемого пространства. Это не нужно, так как пятый параметр,
высота и ширина хранятся в указываемой структуре. Это указатель на реальную
указываемую структуру внутри виджета окна. Поэтому, если объём окна изменился,
изменяя структуру указания пространства, поверхность управления обновляет свои
значения автоматически! */
int main(int argc, char **argv) {
PtArg_t args[1];
PtWidget_t *window;
const PhDim_t dim = { 200, 200 };
PtSetArg(&args[0], Pt_ARG_DIM, &dim, 0);
window = PtAppInit(NULL, &argc, argv, 1, args);
/* Создание прямоугольной поверхности управления. */
PtCreateSurface( window, 0, 0, Pt_SURFACE_RECT, NULL, Ph_EV_BUT_PRESS,
rect_surface_callback, rect_surface_draw, rect_surface_calc);
/* Создание эллиптической поверхности управления для заполнения окна. */
PtCreateSurface( window, 0, 0, Pt_SURFACE_ELLIPSE,
(PhPoint_t*)PtWidgetExtent(window, NULL),
Ph_EV_BUT_PRESS, ell_surface_callback, ell_surface_draw, NULL);
PtRealizeWidget(window);
PtMainLoop();
return(EXIT_SUCCESS);
}
Глава 13. Доступ к модулям PhAB из программного кода
В этой главе обсуждается:
-
Создание внутренних связей
-
Использование внутренних связей в Вашем коде
-
Базы данных виджетов
Вы можете получить доступ к любому модулю напрямую из программного кода Вашего приложения, создав внутреннюю связь к этому модулю.
Внутренняя связь подобна связи ответной рекции – она позволяет Вам задать тип модуля, функцию предустановки и там, где это присуще, расположение. Но в отличие от связи ответной реакции, которая всегда привязана непосредственно к ответной реакции виджета, внутренняя связь не привязана ни к какому виджету. Вместо этого PhAB сгенерирует описание, которое Вы используете в своём программном коде, чтобы задать, какую внутреннююю связь Вы хотите использовать. PhAB предоставляет несколько функций, помогающих Вам использовать внутренние связи (обсуждаются ниже).
Вы можете использовать внутренние связи, чтобы:
-
Создать модуль PhAB внутри кода приложения. Используя связь ответной реакции, Вы можете напрямую связать виджет с модулем приложения PhAB. Но иногда Вам необходимо вместо этого создавать модуль из Вашего программного кода. Чтобы это сделать, используйте внутреннюю связь. Вот несколько общих ситуаций, когда Вы будете использовать внутреннюю связь для создания модуля:
-
Когда Ваше приложение может отображать один из двух различных модулей, основанных на одном и том же состоянии внутри приложения.
-
Когда Вам надо управлять генеалогией модуля, вместо того чтобы использовать принимаемую в PhAB по умолчанию (по умолчанию новый модуль является потомком базового окна).
-
Когда Вы хотите отобразить меню при нажатии пользователем правой кнопки мыши.
-
Получить доступ и отобразить модули картинок. Вы используете модули картинок главным образом для того, чтобы заменить содержимое существующих контейнерных виджетов, таких как PtWindow или PtPanelGroup.
Заметьте, что когда Вы создаёте модуль картинки, используя ApCreateModule(), Вы должны задать родительский контейнерный виджет.
-
Открыть базы данных виджетов. Более подробно см. "Использование баз данных виджетов".
Создание внутренних связей
Чтобы создать внутреннюю связь:
-
Выберите пункт "Internal Links" в меню "Application" или нажмите <F4>. Вы увидите диалог "Internal Module Links":
Рис. 13-1. Диалог "Internal Module Links"
-
Щёлкните на опции <NEW>, если она ещё не выбрана
-
Выберите требующийся Вам тип модуля
-
Заполните области в разделе информации о связи модуля – см. ниже
-
Щёлкните на "Apply", затем щёлкните на "Done"
Вы можете создавать только по одной внутренней связи для каждого модуля.
Области диалога "Internal Module Links" включают:
-
Name – Содержит имя модуля. Чтобы выбрать имя из списка существующих модулей, щёлкните на кнопке рядом с этой областью.
-
Location – определяет, где появится этот модуль; см. "Позиционирование модуля" в главе "Работа с модулями".
-
Setup Functaion – задаёт функцию, которая будет вызываться, когда модуль реализуется (необязательная). Чтобы редактировать функцию, щёлкните на иконке рядом с этой областью. Более подробно см. в разделе "Установочные функции модуля" в главе "Работа с программным кодом".
-
Called – Определяет, вызывается ли установочная функция перед тем, как модуль реализуется, после того, или – и до и после.
-
Apply – Принимает все изменения
-
Reset – Восстанавливает всю информацию о внутренней связи в её перевоначальном состоянии.
-
Remove – Удаляет выбранную внутреннюю связь из списка связей модулей.
Использование внутренних связей в Вашем программном коде
Декларации
Для каждой внутренней связи, определённой в Вашем приложении, PhAB генерирует декларацию, так чтобы Вы могли идентифицировать и получить доступ к связи.