Руководство программиста в Photon (1037671), страница 40
Текст из файла (страница 40)
photon.toc
photon/
Файл photon.toc состоит из следующей строки:
1 | Photon micro GUI | ./photon/bookset.html
где:
1 – это уровень иерархии тем;
| – разделитель областей;
Photon micro GUI – название темы.
./photon/bookset.html – унифицированный указатель информационного ресурса (URL) комплекта описания.
Не используйте вертикальную черту ( | ) в названии темы, поскольку она используется в TOC-файлах в качестве разделителя.
Директория photon содержит TOC-файл и директорию для каждой книги. Например, она включает:
prog_guide.toc
prog_guide/
Файл prog_guide.toc похож на файл photon.toc:
2 | Programmer's Guide | ./prog_guide/about.html
Директория prog_guide содержит HTML-файлы и файл book.toc, который определяет названия тем в HTML-файлах:
3 | About This Guide | about.html#ABOUTTHISGUIDE
4 | Assumptions | #id3
4 | Chades and corrections | #ChangesAndCorrections
3 | Introduction | intro.html#id1
4 | Photon Application Builder – PhAB | #PhABApplications
6 | Get immediate results | #id3
.....
Часть URL, следующая за # – это анкер, определённый в HTML.
Ссылки на темы помощи
Просмотровщик помощи понимает два явных способа задания расположения HTML-ского текста помощи, который должен отображаться:
-
Унифицированный указатель информационного ресурса (URL)
-
Маршрут тем
Унифицированный указатель информационного ресурса (URL)
URL задаёт маршрут в файловой системе к файлу текста помощи. Он задаёт этот путь стандартным для HTML способом, за исключением того, что все файлы должны располагаться в локальной сети.
Вот пример URL:
/usr/help/product/photon/prog_guide/window_mgmt.html
URL является чувствительным к регистру букв. Эти URL'ы ограничены рамками файлов помощи; они не могут использоваться для доступа к Всемирной Паутине.
Маршрут тем
Маршрут тем – это группа сцеплённых названий тем, определённых в дереве текущей темы. Например, вот маршрут тем, эквивалентный приведенному выше URL'у:
/Photon microGUI/Programmer's Guide/Window Management
Для просмотровщика помощи маршрут тем является нечувствительным к регистрам букв (в отличие от других просмотровщиков HTML-файлов) и маршрут может содержать групповые символы * или ?, где "*" согласуется со строкой, и "?" согласуется с символом. Выбирается первая тема, удовлетворившая сравнению.
Дерево тем, используемое просмотровщиком помощи, должно иметь по меньшей мере три уровня иерархии: верхний уровень известен как "книжная полка", второй – как "собрание сочинений", и третий – как "книга". Книга может содержать последующие уровни – глав, разделов.
Входы в книжную полку или книгу не могут содержать каких-либо HTML-файлов, а только .toc – входы на следующий уровень; текст помощи должен находиться только в книгах.
Связывание помощи с виджетами
Вы можете отобразить информацию помощи для виджета в просмотровщике помощи либо во всплывающем "баллоне", содержащем текст помощи. Вы можете использовать даже два метода сразу в одном приложении. Например, Вы можете использовать баллон для кратких пояснений и просмотровщик помощи для более детальной помощи.
Независимо от того, какой метод Вы выбрали, Вам необходимо выполнить в каждом окне Вашего приложения следующее:
-
Установить флаг Ph_WM_HELP в ресурсе управления флагов (Pt_ARG_WINDOW_MANAGER_FLAGS).
-
Установить флаг Ph_WM_RENDER_HELP в ресурсе отображения флагов (Pt_ARG_WINDOW_RENDER_FLAGS). Это добавит иконку "?" на рамку окна. Пользователь может щёлкнуть на иконке, затем щёлкнуть на виджете, и отобразится информация с помощью.
Если для Вашего приложения не применимо по каким-либо причинам использование иконки "?", см. раздел "Помощь без иконки "?" ниже в этой главе.
Для более полной информации см. главу "Управление окном".
Отображение помощи в просмотрщике помощи
Чтобы использовать просмотрщик помощи для отображения информации с помощью по виджету, выполните следующее:
-
Необязательно, задайте ресурс корня помощи (Pt_ARG_WINDOW_HELP_ROOT) для каждого окна Вашего приложения. Это позволит Вам задать относительные маршруты тем для виджетов внутри окна.
-
Используйте не URL, а маршруты темы.
Корневая тема должна начинаться с наклонной черты (/) и должна быть вершиной всех тем окна, обычно берётся из TOC-файла в директории /usr/help/product. Например:
/Photon micro GUI/User's Guide
-
Для каждого виджета в окне заполните ресурс темы помощи (Pt_ARG_HELP_TOPIC). Если Вы задали для окна корневую тему, этот маршрут тем может быть относительно корня темы окна. Например:
Introduction
Когда пользователь щёлкнет на иконке "?" и выберет виджет, в просмотрщике помощи отобразится информация помощи.
Если при просьбе о помощи для виджета Вы получите сообщение об ошибке, сообщающее о неверной связи ("bad link"), убедитесь в корректном маршруте тем.
Отображение помощи во всплывающем баллоне
Поместите текст, который Вы хотите отобразить в баллоне, в ресурс виджета Чтобы для отображения помогающей информации для виджета использовать баллон:
-
Поместите текст, который Вы хотите отобразить в баллоне, в ресурс виджета темы помощи (Pt_ARG_HELP_TOPIC).
-
Установите флаг Pt_INTERNAL_HELP в ресурсе расширенных флагов виджета (Pt_ARG_EFLAGS).
Когда пользователь щёлкнет на иконке "?" и затем выберет виджет, в баллоне появится помогающая информация.
Помощь без иконки "?"
Во многих приложениях иконка "?" на рамке окна не применяется. Однако Вы всё равно можете захотеть использовать для отображения помощи Photon'овский просмотровщик помощи.
Например:
-
Для экранов, чувствительных к прикосновению, иконка "?" окна может оказаться слишком маленькой.
-
Вы можете захотеть изменить указатель мыши на указатель помощи при нажатии клавиши.
Чтобы изменить указатель мыши на указатель помощи, перешлите менеджеру окон событие Ph_WM_HELP. Вот такой код должен находиться в ответной реакции, прикреплённый к виджету типа PtButton с надписью "Help":
int help_cb( PtWidget_t *widget, ApInfo_t *apinfo, PtCallbackInfo_t *cbinfo ) {
PhWindowEvent_t winev;
memset( &winev, 0, sizeof(winev) );
winev.event_f = Ph_WM_HELP;
winev.rid = PtWidgetRid( window );
PtForwardWindowEvent( &winev );
return( Pt_CONTINUE );
}
Для окна должен быть установлен флаг Ph_WM_HELP в ресурсе управляемых флагов (Pt_ARG_WINDOW_MANAGER_FLAGS). Вы также должны заполнить ресурс тем помощи (Pt_ARG_HELP_TOPIC) для виджетов, имеющих помощь, как обрисовано выше.
Получение доступа к помощи из Вашего программного кода
Чтобы получить доступ к помощи из кода Вашего приложения, используйте следующие функции (описанные в "Справочнике библиотечных функций Photon'а"). Они Вам не нужны, если Вы используете метод, описанный в разделе "Связывание помощи с виджетами":
PtHelpUrl() | Отображает текст помощи по URL |
PtHelpUrlRoot() | Устанавливает корневой URL |
PtHelpTopic() | Отображает текст помощи по маршруту тем |
PtHelpTopicRoot() | Устанавливает корневую тему |
PtHelpTopicTree() | Отображает текст помощи по дереву тем |
PtHelpSearch() | Ищет строку |
PtHelpQuit() | Закрывает просмотровщик помощи |
Функции PtHelpUrlRoot() и PtHelpTopicRoot() не сохраняют переданную строку, так что не очищайте её, пока не закончили использование корня помощи.
Глава 16. Межпроцессные связи
Приложение Photon'а не сможет всегда работать в изоляции – время от времени ему понадобится связываться с другими процессами.
В этом разделе описано:
-
Коннекция (connections) [Вводим этот термин (для отличия от термина "соединение") как относящийся уже конкретно к механизму, обеспечиваемому библиотекой Photon'а – Прим. пер.]
-
Отсылка QNX-сообщений
-
Получение QNX-сообщений
-
Импульсы Photon'а
-
Обработка сигналов
-
Другие механизмы ввода/вывода
Операционная система QNX поддерживает различные методы межпроцессных связей IPC – interprocess communication), включая:
-
сообщения
-
импульсы
-
сигналы
Эти методы могут быть использованы в приложении Photon, если Вы будете достаточно аккуратны. Хотя лучше всего использовать коннекции Photon'а:
-
Коннекторы (connectors) позволяют двум связывающимся процессам найти друг друга. Поскольку коннекторы регистрируются в Photon'е, отсутствует риск возникновения конфликта между несколькими сессиями Photon'а, запущенных на одной машине.
-
Photon'овские коннекции "знают", как направить сообщение, даже если Вы имеете множество коннекций между одной и той же парой процессов. Если же Вы используете необработанные сообщения, обслуживаемые Neutrino, и процессы ввода, Вам, возможно, понадобится самим выполнять обработку.
Вот когда необработанные сообщения Neutrino [имеются в виду сообщения механизма message passing – Прим. пер.] и/или импульсы иногда могут оказаться лучшим вариантом:
-
Если один из двух связывающихся процессов не является приложением Photon'а, он не может использовать библиотеку Photon'а
-
Если два процесса необязательно принадлежат одной сессии Photon'а, им понадобится несколько иной способ нахождения друг друга
-
Если всё, что Вам надо – это импульсы, применение коннекции является стрельбой из пушки по воробьям.
Главная петля обработки событий Photon'а, вызываемая Вашим приложением, отвечает за обработку событий Photon'а, так что вызываются самообновление виджетов и функции ответных реакций. Такая простая управляемая событиями модель программирования, используемая вместе с библиотекой виджетов Photon'а, в некотором смысле бросает вызов разработчику приложений, поскольку управляемая событиями петля исполняет безоговорочную MsgReceive() для получения событий от Photon'а. Это означает, что Вашему приложению надо быть внимательным, если оно хочет выполнить MsgReceive(), или события Photon'а могут "заблудиться" и пользовательский интерфейс может не обновиться.
Если Вам надо:
-
отвечать на другие сообщения в Вашем приложении;
-
исполнять ввод/вывод, используя другие механизмы (такие как, например, чтение из трубы [Ну не пайпами же это назвать! А слово конвейер – это другое. – Прим.пер.]);
-
обрабатывать сигналы;
-
отвечать на импульсы;
Вам понадобиться способ подцепить Ваш код к петле обработки событий. Аналогично, Вам может понадобиться суметь добавить к Вашему приложению тайм-ауты и присоединить к ним функции ответных реакций.
Коннекции
Процесс, устанавливающий коннекцию, использует объект, называемый коннектором. Коннектор является именем, которое сервер создаёт и которым владеет, и к которому клиент прикрепляет свою коннекцию. Коннектор используется только для установки коннекции.
Коннектор имеет числовой идентификатор и может также иметь имя, с ним связанное. И имя, и идентификатор являются уникальными для своей сессии Photon'а. Вот несколько примеров того, как может быть использовано имя:
-
Когда сервер запускается, он создаёт коннектор с общеизвестным именем (напр., HelpViewer). Клиенты коннектируются к нему, отсылают запросы и затем отконнектируются. Если клиент при поиске имени терпит неудачу, он порождает сервер и повторяет попытку.
-
Сервер создаёт безымянный коннектор и как-то отсылает идентификатор коннектора потенциальному клиенту (эту схему используют события "перетащил-и-бросил"). Этот клиент затем использует идентификатор для коннекта с сервером.
-
Клиенту всегда требуется породить новый сервер для себя, даже если копия этого сервера уже запущена. Клиент создаёт "временное имя коннектора", передаёт его серверу в качестве аргумента командной строки или переменной окружения, и затем коннектится с этим сервером.
Создание коннектора
Со стороны сервера используются следующие функции:
-
PtConnectorCreate()
-
PtConnectorDestroy()
-
PtConnectorGetId()
Со стороны клиента используются такие функции:
-
PtConnectionClientDestroy()
-
PtConnectionFindId()
-
PtConnectionFindName()
-
PtConnectionServerDestroy()
-
PtConnectionTmpName()
Установка объекта коннекции
Эти функции используются для установки объекта коннекции:
-
PtConnectionClientGetUserData()
-
PtConnectionClientSetError()
-
PtConnectionClientSetUserData()
-
PtConnectionServerGetUserData()
-
PtConnectionServerSetError()
-
PtConnectionServerSetUserData()
-
PtConnectionAddMsgHandlers()
-
PtConnectionAddEventHandlers()
-
PtConnectionResizeEventBuffer()
Сообщения
Эти функции используются для получения сообщений между клиентом и сервером
-
PtConnectionSend(), PtConnectionSendmx()
-
PtConnectionReply(), PtConnectionReplymx()
Уведомления
-
PtConnectionFlush()
-
PtConnectionNotify()
Локальные коннекции
Процесс может создавать коннекцию к самому себе. Поведение такой коннекции слегка отличается от поведения нормальной коннекции:
-
В случае нормальной коннекции функции PtConnectionSend(), PtConnectionSendmx() и PtConnectionNotify() просто отсылают сообщение или импульс, и никогда не исполняют никакого пользовательского кода (за исключением случая, когда функция PtConnectinNotify() требует сбросить буфер, что может привести к появлению событий Photon'а, обрабатываемых нормальным образом). Но когда коннекция локальная, функции PtConnectionSend(), PtConnectionSendmx() и PtConnectionNotify() непосредственно вызывают обработчик, и как вызывающий код, так и обработчик должны предусматривать все стороны этого эффекта.
-
Другим отличием является то, что обработчики вызываются из различного контекста. Обычно ответная реакция обработчика событий или обработчика сообщений вызывается из функции ввода. Поскольку функции ввода не вызываются до тех пор, пока Вы или не вернётесь в главную петлю, или не вызовите функцию PtBkgdHandlerProcess() или PtProcessEvent(), зачастую безопасным будет принимать, что обработчик не должен вызываться, пока исполняется ответная реакция. Но если коннекция локальная, обработчик вызывается непосредственно функциями PtConnectionSend(), PtConnectionSendmx() или PtConnectionNotify(), и принятые допущения должны быть соответствующим образом пересмотрены.
-
Ещё одним эффектом этого является то, что если обработчик сообщений вызывает PtConnectionNotify(), клиент получает уведомление перед ответом (перед reply). Иными словами, обработчик событий клиента вызывается до того, как выполнен возврат из функций PtConnectionSend() или PtConnectionSendmx(). Если обработчик снова вызывает функцию PtConnection() или PtConnectionSendmx(), возврат вернётся с ошибкой с errno, установленным в EBUSY (так библиотечная функция защищает себя от бесконечной рекурсии). Простейшим способом обойти это является отказ от посылки уведомлений из обработчика сообщений – вместо этого уведомление можно поместить в ответе (в reply).
Асинхронные клиентские вызовы
-
PtConnectionWaitForId()
-
PtConnectionWaitForName()
Соглашения по именам
Вы можете определить уникальные имена для Ваших коннекторов, следуя таким соглашением по именованию:
-
Имена, не содержащие слэша (/), зарезервированы за QNX Software Systems
-
продукты сторонних разработчиков могут регистрировать только имена, начинающиеся с уникальной строки (напр., адрес электонной почты или имя домена), за которой следует слэш. Например: www.acme.com/dbmanager
Пример
Это приложение использует коннектор для определения того, запущен ли уже другой экземпляр приложения. Программа принимает две опции командной строки: