Руководство программиста в Photon (1037671), страница 60
Текст из файла (страница 60)
Рис. 22-1. Координатное пространство Photon'а
В отличие от обычной декартовой разметки, квадрантом (+, +) является нижний правый.
Корневой регион имеет те же размеры, что и координатное пространство в целом. Как правило, графические драйверы отображают экран дисплея в местоположение, показанное на вышеприведенном рисунке и размещают начало координат Photon'а в левом верхнем углу экрана дисплея. (Графические драйверы приравнивают единицу координаты Photon'а единице значения пикселей экрана Вашего дисплея).
Координаты региона
Начало координат региона
Когда какое-то приложение задаёт координаты внутри данного региона, они являются относительными – от начала координат региона. Приложение задаёт это начало, когда оно открывает регион.
Начальные размеры и расположение
Начальные размеры региона (т.е. аргумент rect функции PhRegionOpen()) являются относительными от его начала координат. Эти размеры управляют диапазоном кординат, которые приложение может использовать внутри региона. Давайте рассмотрим несколько примеров, чтобы осознать взаимосвязь между началом координат региона и начальными координатами его прямоугольника. Эти примеры демонстрируют, как открытые регионы размещаются относительно корневого региона, имеющего начало координат в центре координатного пространства Photon'а.
Начало координат в (0,0) и начальный прямоугольник в (0,0)
По умолчанию приложение использует для регионов следующий подход (разновидности регионов описаны в разделе "Оконный менеджер Photon'а" приложения "Архитектура Photon'а").
Координаты:
Начальные = (0,0)
Верхний левый угол начального прямоугольника = (0,0)
Нижний правый угол начального прямоугольника = (100,100)
Начало координат в (0,0) и начальный прямоугольник не в (0,0)
Следующий пример показывает подход, обычно используемый для регионов, которые заполняют целиком координатное пространство, например, для региона устройств и региона рабочей области (workspace), верхний левый угол имеет координаты (-32768, -32768) и нижний правый – (32767, 32767).
Координаты:
Начальные = (0,0)
Верхний левый угол начального прямоугольника = (-50,-50)
Нижний правый угол начального прямоугольника = (50,50)
Многие виджеты создают регионы, верхние левые углы которых имеют отрицательные координаты, так что начало координат холста виджета находится в (0,0):
Начало координат не в (0,0) и начальный прямоугольник не в (0,0)
Следующий пример показывает, как начало координат потомка может отличаться от начала координат родителя.
Координаты:
Начальные: = (-50,-50)
Верхний левый угол начального прямоугольника = (0,0)
Нижний правый угол начального прямоугольника = (100,100)
О регионах потомка
Начало координат региона потомка задаётся относительно начала координат родителя. Таким образом, когда регион перемещается, все его потомки автоматически перемещаются вместе с ним. И также, когда регион уничтожается, уничтожаются его потомки.
Если Вы хотите сделать регион большим по размеру, чем какой-либо другой регион Вашего приложения, сделайте его потомком корневого региона, вызвав функцию PhRegionOpen() или PhRegionChange(), задав Ph_ROOT_RID как родительский.
Регионы и отсечение событий
Регион может генерировать или получать события только там, где он перекрывается со своим родителем. Например, на следующем рисунке:
-
Потомок 1 может генерировать или получать события во всём своём регионе
-
Потомок 2 может генерировать или получать события только в той малой серой зоне, которая перекрывается с регионом родителя.
Рис. 22-2. Регионы и отсечение событий
На основании этого свойства регионов, любая часть региона, которая не перекрывается со своими родителями, в действительности является невидимой.
Месторасположение и иерархия
Иерархия регионов:
Рис. 22-3. Иерархия регионов типичной системы Photon'а
В Photon'е каждый регион имеет родительский регион. Эта связь родитель-потомок приводит к появлению иерархии регионов с корневым регионом в вершине. Следующая диаграмма показывает иерархию типичной системы Photon'а:
Родительский регион
Менеджер Photon'а всегда размещает регионы потомков впереди (т.е. в сторону пользователя) своих родителей:
При открытии региона приложение определяет родителя региона. Если приложение открывает регион, не задавая его родителя, родитель региона устанавливается по умолчанию – базовые регионы становятся потомками корневого региона и окна становятся потомками фонового региона оконного менеджера.
Братские регионы
Кроме родителя, регион может иметь "братьев", т.е. другие регионы, имеющие того же родителя. Регион знает только о своих двух братьях – о том, который непосредственно перед ним, и том, который непосредственно за ним.
На следующем рисунке показан родитель с тремя потомками, и взаимосвязи, которые имеются между регионом потомка 2 с его братьями:
Когда приложение открывает регион (напр., регион потомка 2 на вышеприведенном рисунке), оно может либо не задавать ничего, либо задать одного, либо двух непосредственных братьев. В зависимости от того, как приложение задало этих братьев, новый регион может быть размещён в соответствии с принимаемыми по умолчанию правилами (см. ниже) или в определённом месторасположении.
Если приложение открывает регион, задав обоих братьев, и результатом этого является неоднозначные требования по месторасположению, требования отвергаются.
Месторасположение по умолчанию
Если приложение открывает регион, не задавая братьев, менеджер Photon'а размещает этот регион, используя принимаемые по умолчанию правила месторасположения. В большинстве случаев эти правила приводят к тому, что вновь открытый регион располагается впереди своего самого переднего брата, который становится "братом сзади" для нового региона. (Чтобы использовать другие правила месторасположения, Вы можете задать флаг Ph_FORCE_FRONT).
Например, на следующем рисунке регион потомка 1 является самым передним регионом:
Когда приложение открывает регион потомка 2 с принимаемым по умолчанию месторасположением (следующий рисунок), регион 2 размещается впереди региона 1. Регион 1 становится братом сзади региона 2. Регион 2 становится братом спереди региона 1.
Флаг Ph_FORCE_FRONT
Приложение использует флаг Ph_FORCE_FRONT, когда оно хочет, чтобы регион оставался впереди всех последующих братьев, зависящих от принимаемого менеджера Photon'а по умолчанию месторасположения. Как обсуждалось ранее, когда регион открыт с принимаемым по умолчанию месторасположением, он размещается перед своим самым передним братом. Но если какой-либо брат имеет установленный флаг Ph_FORCE_FRONT, новый регион размещается позади самого заднего брата, у которого установлен флаг Ph_FORCE_FROM. Например, давайте посмотрим, что случится в следующем примере, если регион потомка 1 имеет установленный флаг Ph_FORCE_FRONT:
Когда открывается регион потомка 2 с принимаемым по умолчанию месторасположением (следующая диаграмма), он размещается позади региона 1, и регион 1 становится "братом впереди". Поскольку регион 2 был размещён с использованием принимаемых по умолчанию правил, он не наследует установку Ph_FORCE_FRONT региона 1:
Затем, если открывается регион 3 с принимаемым по умолчанию месторасположением, он размещается следующим образом:
Приложение может установить флаг Ph_FORCE_FRONT при открытии региона (или позже), изменив флаги региона. Состояние этих флагов не оказывает влияние на то, как размещается сам регион – они влияют на то, как размещаются последующие братья, если эти братья открываются с использованием принимаемых по умолчанию правил месторасположения. То есть состояние Ph_FORCE_FRONT существующих братьев не оказывает влияние на месторасположение нового региона, если он открывается с заданными связями с братом. См. следующий раздел – "Задаваемое месторасположение".
Помните, что флаг Ph_FORCE_FRONT оказывает влияние только на местоположение регионов своих братьев – регион потомка всегда становится впереди его родителя.
Задаваемое месторасположение
В отличие от месторасположения, принимаемого по умолчанию, если при открытии региона определяется какой-либо из братьев, то это определение управляет месторасположением нового региона. Мы называем это задаваемым месторасположением.
Если определяется брат позади, то новооткрытый регион автоматически размещается перед этим братом.
Если определяется брат впереди, то новооткрытый регион автоматически размещается позади этого брата.
Установка Ph_FORCE_FRONT задаваемого брата наследуется новым регионом. Если приложение открывает регион, задавая обоих братьев, и это приводит к неоднозначным требованиям месторасположения, то открытие не выполняется.
Использование регионов
Открытие региона
Чтобы открыть регион, создайте виджет PtRegion. Виджет PtRegion не включён в палитру PhAB'a; для его реализации:
-
Вызовите в Вашем приложении функцию PtCreateWidget()
или
-
Создайте модуль окна, выберите его и используйте пункт "Change Class" в меню "Edit" PhAB'а, чтобы превратить окно в PtRegion. Для более полной информации см. раздел "Изменение класса виджета" в главе "Создание виджетов в PhAB".
Более полную информацию по виджету PtRegion см. в "Справочнике виджетов".
Размещение регионов
В то время как регион всегда размещается перед своим родителем, местоположение его относительно своих братьев является гибким. См. раздел "Месторасположение и иерархия" для получения более полной информации о местоположении "по умолчанию" и "задаваемом".
Структура PhRegion_t (см. "Справочник библиотечных функций Photon'а") содержит следующие члены. Они указывают на взаимосвязь региона со своими братьями:
-
bro_in_front – указывает на брата непосредственно впереди.
-
bro_behind – указывает на брата непосредственно сзади.
Для получения этой информации Вы можете использовать функцию PhRegionQuery().
Изменение месторасположения региона
Приложение может задать месторасположение региона при его открытии или оно может изменить месторасположение позже. Чтобы изменить месторасположение региона, приложение должно изменить взаимосвязь между регионом и семейством региона. Приложение делает это, выполняя что-либо или всё из нижеследующего:
-
устанавливает члены parent, bro_front и bro_behind в структуре PhRegion_t;
-
устанавливает соответствующие биты в fields для указания на то, какие члены являются действительными (только те члены, которые помечены как валидные, будут оказывать действие);
-
вызывает функцию PhRegionChande().
Поскольку приложение может быть уверенным в позиции только принадлежащих ему регионов, оно не в состоянии изменить позицию каких-либо других регионов. В противном случае, в то время, когда приложение выполняет запрос на изменение позиции региона, ему не принадлежащего, доставленная функцией PhRegionQuery() может не отражать текущую позицию этого региона. То есть запрос на изменение месторасположения региона может не иметь результата, на который расчитывает приложение.
Изменение родителя
Вы можете изменить родительский регион таким способом:
-
Если регион имеет родительский виджет, вызовите функцию PtReparentWidget(), чтобы сделать регион потомком другого виджета. Не переназначайте родителя региона напрямую.
-
Задайте родителя в члене parent структуры PhRegion_t потомка. Регион потомка становится самым передним среди регионов-потомков родителя.
-
Задайте потомка другого родителя как брата данного региона. Это делает регион потомком этого другого родителя, но позволяет Вам задать, где регион потомка размещается в иерархии регионов родителя.
В заголовочном файле <photon/PhT.h> определены следующие константы:
-
Ph_DEV_RID – идентификатор региона устройств
-
Ph_ROOT_RID – идентификатор корневого региона
Задаваемые братья
Если Вы устанавливаете: | То: |
bro_behind | Регион, указанный в члене rid структуры PhRegion_t, перемещается перед регионом bro_behind |
bro_in_front | Регион, указанный в члене rid структуры PhRegion_t, перемещается за регион bro_in_front |
Как обсуждалось в разделе "Изменение родителя", регион наследует родителя какого-либо из задаваемых братьев, которые являются потомками другого родителя.
Системная информация
Вы можете получить о Вашей системе следующую информацию:
-
версию Вашего сервера Photon'а
-
оценку пропускной способности связи между Вашим окном и сервером Photon'а
-
информацию о регионах, перекрывающих Ваше окно:
-
графические регионы
-
регионы клавиатуры
-
регионы указателя мыши
-
регионы группы ввода
Вы не получите информацию о каждом регионе. Вместо этого Вы получаете минимальное значение каждого типа информации. Например, если несколько регионов графического драйвера, перекрывающих Ваше окно, имеют различную пропускную способность, выдаваемая пропускная способность является минимальной из них.
Имеются две функции, которые Вы можете использовать для получения системной информации:
PhQuerySystemInfo() Получение информации о данном регионе
PtQuerySystemInfo() Получение информации о виджете (обычно окно)