Copyright ╘ 1997 The Open Group
Copyright ╘ 2000, 2001 Перевод Вадим Годунко
. | ||
Предисловие |
Copyright ╘ 1997 The Open Group
Copyright ╘ 2000, 2001 Перевод Вадим Годунко
. | ||
Предисловие |
Motif. Руководство программиста | ||
---|---|---|
. | . |
Этот документ организован следующим образом:
Глава 1 представляет книгу и дает обзор системы X Window, библиотек Xlib, Xt и Motif.
Глава 2 описывает структуру иерархии виджетов Motif и дает общие принципы написания Motif программ.
Глава 3 объясняет структуру и общие элементы Motif приложения. Эта глава также описывает использование многопоточности в приложении.
Глава 4 описывает структуру программ, использующих язык описание интерфейсов пользователя (UIL - User Interface Language) и менеджер ресурсов Motif (MRM - Motif Resource Manager).
Глава 5 описывает большинстро примитывных виджетов, которые являются строительными кирпичиками любого Motif приложения.
Глава 6 рассказывает об использования виджетов RowColumn для создания меню, радиокнопок и check boxes.
Глава 7 описывает виджеты предназначенные для ведения диалога с пользователем.
Глава 8 рассказывает о композитных виджетах, предназначенных для размещения в них других виджетов.
Глава 9 объясняет понятия композитных строк (XmString), таблиц визуализации, списков табуляций, шрифтов, и других аспектов форматированного текста.
Глава 10 описывает виджеты Text и TextField, предоставляющие возможность отображения и редактирования текста.
Глава 11 является руководством по интернационализации приложений и предоставлению текста, шрифтов и другой информации, специфичной для конкретного языкового окружения.
Глава 12 объясняет как Motif использует цвета и пиксельные изображения и как приложение может само их предоставлять.
Глава 13 обсуждает особенности обработки ввода, включающие клавиатурный фокус и его переход, трансляции и действия.
Глава 14 описывает правила работы менеджера расположения для некоторых виджетов Motif.
Глава 15 описывает DrawingArea, виджет общего назначения для отображения графики и обработки ввода пользователя на низком уровне.
Глава 16 описывает как приложения может передавать данные используя Универсальный Метод Передачи (UTM - Universal Transfer Method).
Глава 17 подробно описывает drag-and-drop интерфейс Motif, с помощью которого передаваемые пользователем данные изменяют иконку представления курсора устройства указания.
Глава 18 описывает взаимодействие между приложением и менеджером окон Motif (MWM - Motif Window Manager), посредством ресурсов, выделений, протокола и свойств.
Глава 19 описывает печать из Motif приложений.
Приложение A описывает вызовы XmClipboard.
Приложение B суммирует встроенную поддержку передачи данных для стандартных виджетов Motif.
Motif. Руководство программиста | ||
---|---|---|
. | Предисловие | . |
Для получения дополнительной информации о Motif можно обратиться к следующим документам:
Motif. Справочник программиста. содержит детальную информацию для программистов, создающих Motif программы.
Motif. Руководство по стилю
Motif. Руководство пользователя
Motif. Руководство по написанию виджетов
Дополнительную информацию по Xlib и Xt можно найти в следующих документах системы X Window:
Xlib - Интерфейс языка C с системой X Window
X Toolkit Intrinsics - Интерфейс языка C
Motif. Руководство программиста | ||
---|---|---|
. | Предисловие | . |
Таблица 1. Типографские соглашения
AaBbCc123 | Выделение важного элемента, понятия | |
AaBbCc123 | Кнопка мыши | |
AaBbCc123 | Клавиша клавиатуры | |
AaBbCc123 | Класс виджета | |
AaBbCc123 | Макроопределение | |
AaBbCc123 | Кнопка графического интерфейса пользователя | |
AaBbCc123 | Подпрограмма | |
AaBbCc123 | Параметр подпрограммы | |
AaBbCc123 | Параметр команды | |
AaBbCc123 | Имя файла | |
AaBbCc123 | Команда операционной системы |
Motif. Руководство программиста | ||
---|---|---|
. | . |
Motif является графическим интерфейсом пользователя, с его помощью прикладная программа получет вводимые пользователем данные и производит отображение выходных данных для пользователя приложения. Motif предоставляет промежуточный механизм для взаимодействия между приложением и пользователем. С обоих сторон этом механизм выглядит как набор объектов имеющих графическое представление на экране. Программа создает и отображает объекты разных типов, предоставляемых Motifом, для отображения специфической информации и запроса необходимых видов данных. Пользователь производит ввод манипулированием экранных представлений этих объектов с помощью устройства указания, клавиатуры или обоих.
Эта книга описывает программый интерфейс приложений (API - Application Programming Interface). Это набор средств которые Motif предоставляет разработчику приложения для создания и взаимодействия с Motif для создания приложения. Эта книга не является справочником, она не пытается дать исчерпывающее описание всех деталей Motif. Она фокусирует внимание на обзоре архитектуры Motif, разъясняет концепции и соглашения, необходимые для использования его API и предоставляет некоторые примеры. Эта книга дополняет другие из набора документации на Motif:
Справочник программиста Motif детально определяет каждый элемент интерфейса прикладных программ Motif. Он организован как справочные страницы по одной на каждый элемен интерфейса.
Спецификация окружения приложения - окружение пользователя описывает как каждый элемент интерфейса должно использовать приложение для достижения максимальной совместимости. Все реализации Motif должны поддерживать интерфейсы, описанные в этой книге.
Руководство по стилю Motif описывает как приложение должно использовать интерфейсы для обеспечения максимальной согласованности с другими Motif приложениями.
Руководство пользователя описывает внешний вид и стиль взаимодействия с Motif с точки зрения пользователя.
Иитерфейс прикладных программ Motif реализован на языке C. Motif требует, чтобы приложения написанные на C согласовывались с диалектом ANSI C. Эта книга подразумевает знание ANSI C, также как и остальные справочные и учебные книги. Также возможно написание программ на других языках, включая C++, но эта книга дает объяснения и примеры только для приложений написанных на C.
Motif основан на системе X Window, также сокращенно называемой X. В своей основе система X Window является протоколом с помощью которого приложение генерирует изображение на компьютере имеющем растровый дисплей и получает информацию от устройств связанных с дисплеем.
X основан на клиент-серверной модели вычислений. Прикладная программа является клиентом, взаимодействующим посредством X протокола с сервером, который производит непосредственный ввод и вывод информации на дисплее. Эта модель имеет несколько важных возможностей:
Клиент и сервер могут быть запущены как на одной машине, так и на разных машинах, связанных посредством сети.
Только сервер нуждается в непосредственном доступе к аппаратуре дисплея. X протокол является аппаратно-независимым, т.е. клиент без изменений использует любые возможности дисплея поддерживаемые протоколом.
Сервер может обрабатывать несколько клиентов на одном дисплее в одно время. Эти клиенты могут взаимодействовать друг с другом использую передачу информации через сервер.
Клиент может взаимодействовать с несколькими серверами.
Дисплей является абстракцией, предсавляющей устройства ввода и вывода, контролируемые одним сервером. Типично дисплей состоит из клавиатуры, устройства указания и одного или более экранов. Экран является абстракцией, представляющей одно растровое устройство вывода.
Каждый клиент создает одно или более окно на одном или более экранах данного дисплея. Окно это прямоугольная область экрана на которой клиент производит отображение. Окна организованы в иерархию как родительские и дочерние. Сервер поддерживает дерево окон для каждого экрана. Окно самого верхнего уровня называется корневым окном экрана. Каждый клиент обычно создает зотябы одно окно дочернее к корневому, и любые другие окна клиента являются потомками этого окна. Окна могут перекрываться и сервер поддержывает организованный в виде стэка порядок всех окон на экране. Дочернее окно может выходить за диапазоны своего радителя, но весь вывод будет отсечен или подавлен вне границ родительского окна.
Клиент запрашивает сервер для создания или уничтожения окон, а окна являются ресурсами управляемые сервером. Сервер поддерживает другие ресурсы, включая следующие:
Пиксельные изображения являются прямоугольными внеэкранными областями в которых приложение может производить отрисовку. Совместно окна и пиксельные изображения являются отрисовываемыми элементами или элементами на которых клиент может производить рисование. Единицей измерения высоты и ширины окон и пиксельных изображений является пиксел. Каждый пиксел имеет определеную глубину, представляющую из себя количество бит или плоскостей. Таким образом пиксел имеет суммарное значение, диапазон которого зависит от глубины отрисовываемого элемента. Пиксельные изображения имеющие единичную глубину называются битовыми изображениями. Каждый пиксел в битовом изображении имеет одно из двух возможных значений: 0 или 1.
Цветовая палитра является связью между значениями пикселов и цветами. Каждый цвет представляется тройкой значений красной, зеленой и синей составляющих которая дает конкретный цвет на конкретном экране. Каждое окно имеет связанную с ним палитру которая определяет какие цвета используются для отображения каждого пикселя.
Шрифт это набор битовых образов символов используемых для отображения текста.
Курсор это объект, содержащий информацию необходимую для графического представления положения устройства указания. Он состоит из исходного битового изображения, битового изображения формы, горячей точки или положения представляющего реальную точку положения устройства указания и двух цветов.
Графический контекст или GC является набором атрибутов, определяющих как любые графические операции будут влиять на отрисовываемый элемент. Каждая графическая операция над отрисовываемым элементом выполняется с использованием графического контекста указанного клиентом. Некоторые из атрибутов графического контекста это значения пикселя для фона и изображения, ширина линии и область отсечения.
Свойство это именованная структура данных, связанная с окном. Клиенты часто используют свойства для взаимодействия друг с другом.
Каждый клиент открывает соединения с одним или более сервером. Клиенты и серверы взаимодействуют друг с другом посредством запросов, ответов, ошибок и событий. Клиент отправляет запрос на сервер запрашивая выполнение некоторой операции, типа создания окна или рисования линии в пиксельном изображении. Некоторые запросы, такие как информационные запросы, заставляют сервер сгенерировать ответ для клиента. Запрос, превевший к возникновения ошибочной ситуации, может побудить сервер сгенерировать для клиента ответ об ошибке. Сервер выполняет запросы от каждого клиента в порядке их приема от клиентов, хотя сервер может выполнять запросы от других клиентов в любое время.
Сервер оповещает клиентов об изменении состояния посредством событий. Событие может быть побочным эффектом запроса клиента или иметь полностью асинхронный характер, такой как нажатие пользователем клавиши или перемещение указателя. В дополнение клиент может посредством сервера отправить событие другому клиенту.
Каждый клиент запрашивает сервер посылать ему события отдельных типов происходящие в конкретных окнах. Сервер обычно сообщает о событиях произошедших в некотором окне. Например, клавиатура концептуально подключена к одному из окон, называемых окном фокуса. Когда пользователь нажмет клавишу, сервер обычно сообщает о произошедшем событии окну фокуса. Если клиент запросил сервер отправлять ему события типа \eventtype{KeyPress} происходящие в некотором окне, сервер будет отправлять клиенту событие когда пользователь нажимает клавишу пока это окно имеет фокус.
С точки зрения клиента он читает события от сервера, события являющиеся результатом запросов клиента поступают в последовательности в которой он делал запросы. Несмотря на это, эти события могут идти вперемешку с событиями произошедшими по другим причинам, таким как ввод пользователя или действия других клиентов. Более того, клиент может буферизировать запросы, а сервер может буферизировать события перед их фактической передачей дркгому, т.е. события могут поступить намного позже после того как клиент сделает запрос, который создаст событие.
В большей своей части обработке событий в X свойственна асинхронность. Большая часть клиентских приложений выполняет бесконечный цикл в котором читает событие, обрабатывает его (возможно делая запросы в процессе обработки), а затем читает другое событие. Клиент не предпологает, например, когда данное событие будет сгенерировано после данного запроса клиента поскольку клиент читает событие после того как сделает запрос. Многие события имеют метку времени для обозначения момента когда сервер действительно сгенерировал событие. Клиент который зависит от временной последовательности поступления событий должен анализировать эти метки.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 1. Введение | . |
Приложение не взаимодействует с X сервером напрямую. Вместо этого, оно использует одну или несколько библиотек которые предоставляют высокоуровневый интерфейс к X протоколу. Принципиально для Motif приложений доступны три библиотеки: Xlib, X Toolkit Intrinsics (Xt) и Motif toolkit (Xm).
X клиентам не необходимости взаимодействовать с сервером на уровне X протокола. X имеет интерфейс клиента на языке C к протоколу, называемый Xlib. Среди других Xlib предоставляет следующие возможности:
Подпрограммы для создания и управления основными ресурсами сервера, включающими окна, пиксельные изображения, шрифты, курсоры, графические контексты и свойства.
Подпрограммы для отрисовки текста и графики в отрисовываемых элементах.
Буферизацию запросов к серверу и постановку в очередь событий от сервера.
Структуры данных представляющие события всех типов и подпрограммы для выбора и чтения событий.
Подпрограммы для обслуживания цветовых палитр и для использования аппаратно-независимых цветовых пространств.
Подпрограммы для генерации текстового ввода и вывода в различных локализациях.
Менеджер ресурсов X (Xrm - X resource manager), базу данных параметров указанных пользователем для приложения.
Менеджер ресурсов это ключевой момент в основных принципах X: как прользователь и приложение должны управлять внешним видом, стилем взаимодействия и другими вспомогательными характеристиками клиента. Например, цвета заднего и переднего плана и шрифты, используемые приложением должны быть представлены как ресурсы. Обычно приложение предоставляет значения по умолчанияю для таких ресурсов, но позволяет пользователю перекрывать значения по умолчанию.
Ресурс состоит из трех компонент: имени, класса и значения. Класс может включать набор ресурсов с различными именами. Ресурсы могут быть расположены в виде иерархии; имя и класс могут состоять из компонент, каждый указывая имя или класс некоторого уровня иерархии. Полностью определенное имя или класс ресурса есть список имен или классов на всех уровнях, начиная с имени или класса приложения и заканчивая именем или классом самого ресурса.
Менеджер ресурсов позволяет пользователю или приложению указывать значения в файле, в командной строке при запуске приложения или вызовом подпрограмм Xrm в программе. Спецификация ресурса должна включать имя или класс ресурса, но может быть как полностью так и частично определенным относительно имен, класс или смесь компонентов имен и классов. Результирующая база данных ресурсов может содержать как общие так и конкретные спецификации ресурсов. Когда приложение запрашивает в базе данных значение ресурса, оно предоставляет полностью определенное имя и класс. Менеджер ресурсов использует алгоритм поиска возвращающий значение из наиболее конкретной спецификации которая попадает под запрашиваемые имя и класс.
Поскольку Xlib предоставляет базовые возможности взаимодействия с X серверо, разработка сложного приложения с использованием только Xlib будет очень сложной задачей. Xlib в сущности предоставляет примитивы для X клиента. Сложные приложения нуждаются в объединеии этих примитивов в конструкции, которые позволяют взаимодействовать с сервером более обобщенным способом.
X включает библиотеку X Toolkit Intrinsics (сокращенно Xt) поддерживающую некоторые из таких высокоуровневых интерфейсов. Три наиболее важных возможности Xt следующие:
Объекты, известные как виджеты, используемые для содержания данных и представления интерфейса для пользователя.
Управление геометрией виджетов.
Диспетчеризации и обработки событий.
Ядром Xt является набор абстракций данных построенных в объектной модели. Каждый из этих объектов, называемых виджетами, является комбинацией данных и процедур. Каждый экземпляр виджета является членом класса. Класс виджета объединяет набор процедур и структур данных являющихся общими для всех виджетов класса. Экземпляр виджета содержит процедуры и структуры данных свойственные только к этому виджету. Зкземпляр виджета также содержит ссылку на свой класс.
Каждый виджет обычно предоставляет обобщенное поведение сязанное с специфическим видом взаимодействия с пользователем. Например, Motif содержит класс виджетов предназначенных для предоставления пользователю возможности ввода и редактирования текста. Этот класс предоставляет общие возможности для поддержки ввода и отображения текста, включая редактирование, выделение, удаление и вставку текста в/из буфера обмена. Класс содержит структуры данных связанные не только с содержащимся текстом, но и с внешним видом на экране. Для использования этого класса приложение создает экземпляр этого класса виджетов и предоставляет некоторые свои данные и процедуры для экземпляра виджета.
Xt поддерживает простое наследование классов виджетов. Это значит, что класс виджетов может быть подклассом другого класса, называемого суперклассом. Подкласс часто является специализированным вариантом более общего суперкласса. Подкласс может наследовать, переопределять или добавлять процедуры и структуры данных своего суперкласса. Xt обычно предоставляет классы разработанные для того чтобы быть суперклассами для других классов. Motif предоставляет подклассы из которых приложение создает экземпляры виджетов. Раздел 1.3 содержит полную информацию об иерархии классов виждетов Motif и Xt.
Экземпляры виджетов организованы в другую иерархию. Каждый виджет приложения, кроме виджета (или виджетов) верхнего уровня, имеет родительский виджет. Виджеты некоторых классов, называемых композитными, могут иметь дочерние виджеты. Другие виды виджетов, называемые примитивами и гадгетами, обычно не могут иметь дочерних виджетов. Приложение создает одну или несколько деревьев экземпляров виджетов составляя ее из композитных виджетов, примитивных виджетов и гадгетов. Например, меню может состоять из композитного родителя представляющего меню и некоторого числа примитивных дочерних виджетов представляющих кнопки. Меню и его дочерние компонеты являются одной из ветвей общего дерева виджетов в приложении.
Xt и Motif предоставляют все классы виджетов обычно необходимые для приложений. Любое приложение может доопределить новые классы виджетов, но это требует знания внутреннего устройства которое не будет обсуждаться в этой книге. Типичное приложение создает экземпляры виджетов встроенных классов, предоставляя свои процедуры и данные для этих виджетов.
Xt использует расширение механизма ресурсов для представления данных экземпляров виджетов доступных приложению. Каждый класс виджетов определяет набор ресурсов, применимых к виджетам этого класса. Класс может наследовать или прекрывать ресурсы суперкласса по своему усмотрению.
Класс виджетов определяет имен и класс каждого своего ресурса. Xt и Motif дают имя каждому своему классу виджетов, а приложение дает имя для каждого экземпляра виджета. Наконец, разработчик приложения предоставляет имя и класс для своего приложения. Для получения ресурса данного виджета, поностью определенным именем являетсясписок именначинающийся с имени приложения, затем содержащий имя виджета верхнего уровня и затем, спускаясь вниэ по дереву виджетов до данного виджета, имена виджетов и, наконец, имя самого ресурса. Полностью определенный класс это список классов начиная с класса приложения, затем класса виджета верхнего уровня и затем классов всех виджетов по пути вниз по дереву виджетов до данного виджета, и заканчивающийся классом ресурса.
Пользователь, приложение и классы виджетов совместно предоставляют значения ресурсам и тем самым контроль за внешним видом и другими атрибутами компонентов приложения. Как пользователь, так и разработчик приложения могу предоставлять как конкретные так и общие спецификации для ресурсов виджетов в различных файлах ресурсов или из командной строки. Также возможно предоставление различных спецификаций ресурсов в зависимости от локализации, параметров экрана или других произвольных критериев.
Когда приложение запускается, Xt объединяет эти спецификации с начальной базой данных ресурсов. Когда приложение создает виджет, Xt назначает начальные значения ресурсам виджета с использованием спецификаций из базы данных, значений указываемых приложением во время создания или значений по умолчания определяемых классом виджета. После создания ввиджета приложение использует подпрограмму XtGetValues для получения значения ресурса виджета и XtSetWidget для назначения ресурсу нового значения.
Большинство виджетов или имеют связанное с ним окно или занимают определенную прямоугольную область на окне своего родителя. Каждый виджет имеет высоту, ширину и положение относительно своегжо родителя, выражаемое как x и y координаты верхнего левого угла виджета. Определения положения и размеров виджетов относительно других виджетов составляют раскладку или геометрию приложения.
Геометрия приложения является результатом воздействия следующих факторов:
Пользователь или приложение может предоставить значения для ресурсов, оказывающих влияние на геометрию, например высоту и ширину виджета.
Менеджер окон, специальная клиентская программа которая управляет положением и размерами окно верхнего уровня, запускается на большинстве дисплеев. Motif предоставляет менеджер окон называемый менеджером окон Motif (MWM - Motif Window Manager). Пользователь часто изменяет размер окон верхнего уровня посредством средств менеджера окон.
Дочерний виджет может иметь предпочтения относительно своего размера. Например, виджет отображающий метку может желать имет ширину, достаточную для отображения всего текста метки.
Родительский виджет может иметь предпочтения о своем размере и положении сових дочерних виджетов. Например, виджет меню может желать расположить свои дочерние кнопки расположив их в несколько строк или рядов.
Процесс учета всех этих факторов и определения расположения виджетов называют управлением геометрией. Xt предоставляет существенные возможности для управления геометрией:
Все виджеты имеют ресуры указывающие, как непосредственно так и косвено, геометрию подразумеваемую пользователем или приложением.
Xt имеет специальные виджеты, называемые оболочками, чьи функции в основном предназначены для взаимодействия между приложением и внешними агентами типа менеджеров окон.
Процедуры классов виджетов могут запросить родительский виджет изменить геометрию виджета, могут вычислить предпочтительный размер и могут пересчитать раскладку виджета когда виджет получит новый размер.
Родительские виджеты имеют абсолютный контроль над геометрией своих детей. Процедуры класса родительского виджета могу принять или отвергнуть запрос дочернего виджета на изменение его геометрии. В общем случае родительский виджет может изменить геометрию дочернего виджета в любой момент.
Виджет считается управляемым если он и его родитель готовы к согласованию геометрии. В общем, виджет может быть отображен на экране только после того, как он взят на управление.
Смотрите Главу 14 для дополнительной информации об управлении геометрией и специфических правилах управления Motif виджетов.
Xt содержит процедуру обработки событий которая читает события из сервера и распределяет их сообветствующим виджетам. Каждый виджет который имеет связанное с ним окно может также иметь таблицу транстляции. Эта таблица отображает определения событий на имена процедур, называемые действиями. Когда Xt читает событие связанное с виджетом, он ищет описание события в таблице трансляции и распределяет событие соответствующей подпрограмме-действию.
Приложение может предоставлять свои собственные подпрограммы действий, но\ многие такие подпрограммы содержатся в классах виджетов. Подпрограмма действия часто производит некоторые действия над ее владельцем и затем оповещает приложение посредством вызова процедур приложения, называемых процедурами обратного вызова. Многие виджеты содержат ресурсы, чьими значениями являются списки процедур обратного вызова. Виджет вызывает процедуры этих списков в определенном случае, обычно когда виджет принимает некоторые виды событий. Xt предоставляет и другие возможности для приема и ответа на события, но многим приложениям необходимо только добавить соответствующие процедуры обратного вызова. Эти процедуры обратного вызова выполняют большую часть работы приложения в части проведения диалога с пользователем.
Механизм обработки событий в Xt естественно приводит к событийно-управляемой структуре прикладной программы. Большинство приложений имеют сходный общий вид:
Инициализация приложения.
Создание в взятие на управление виджетов.
Предоставление процедур обратного вызова вызываемых виджетами.
Вызов цикла обработки событий в Xt, который обычно никогда не завершается.
Xt предоставляет фундамент для создания наборов виджет, ответственных за специфические возможности прользовательского интерфейса. Motif использует фундамент Xt для построения как базовых классовтак и различных специализированных подклассов виджетов. Раздел 1.3 содержит описание набора виджетов Motif.
В дополнение к предоставляемым виджетам, Motif добавляет некоторые возможности которые обычно используются приложением и пользователем. Этот раздел содержит описание некоторых из этих возможностей.
Виджеты Motif имеют характерные визуальные стили. Многие виджеты имеют тень c трехмерным видом что делает изобржения виджетов выступающими из или погруженными в задний фон. Виджеты, содержащие клавиатурных фокус могут иметь прямоугольную рамку подсветки. Когда пользователь нажимает кнопку Btn1 мыши и фокус находится в кнопке цвет изображения кнопки изменчяется для индикации того, что пользователь выбрал или "нажал" кнопку.
Motif автоматически создает цвета по умолчанию для изображения, теней, подсветки и выделения виджета. Пользователь или приложение могут предоставить свои собственные цвета или пиксельные изображения как значения ресурсов виджета.
Глава 12 предоставляет дополнительную информацию по использованию цветов и пиксельных изображений в Motif.
Система X Window устанавливает соглашения для своих клиентов которые позволяют пользователю переносить данные из одного приложения в другое. Такой перенос работает посредством выделений нескольких видов включая первичное, вторичное и выделение области обмена. Выделение это совместно используемый ресурс, которым может владеть только один клиент в один момент времени на данном дисплее. Когда пользователь запрашивает перенос данных из одного приложения в другое, принимающий клиент просит владельца выделения преобразовать данные в вид известный клиенту, и затем приемник вставляет данные. Этот механизм также позволяет переносить данные виджетами одного и того же приложения.
Виджеты Text и TextField поддерживают первичное, вторичное выделения и выделение буфера обмена. Motif также содержит подпрограммы обрабатывающие выделение буфера обмена, позволяя приложениям проще копировать данные в и из буфера обмена. Xt предоставляет более общие подпрограммы для переноса данных посредством выделений.
Motif содержит обширный механизм drag and drop для переноса данных. Пользователь начинает перенос нажатием кнопки мыши, назначенной для функции переноса (обычно Btn2) когда указатель находится над источником данных. Пользователь перетаскивает иконку представления данных в точку которая принимает данные, называемой \{drop site местом выброса}. Когда пользователь отпускает кнопку мыши данные перемещаются, копируются или связываются с местом выброса.
Подклассы виджетов Text, TextField, List и Label автоматически поддерживают drag and drop перенос данных в текстовом и некоторых пиксельных форматах. Motif включает обширный программный интерфейс объектов и подпрограмм которые позволяют приложению устанавливать свои источники перетаскивания и места выброса, контролировать договоренность между отправителем и приемноком, настраивать визуальные элементы и преобразовывать различные виды данных.
Дополнительную информацию о переносе данных можно найти в Главе 13.
Motif предоставляет два стиля переноса клавиатурного фокуса с одного виджета на другой. В одном стиле виджет, содержащий указатель содержит фокус. При другом стиле пользователь нажимает клавишу или кнопку Btn1 для перемещения фокуса на другой виджет, а положение указателя не влияет на фокус.
При втором стиле Motif различает переход на композитный виджет или виджет с внутренней навигацией, называемой табуляционной группой, и навигацию между виджетами или элементами внутри табуляцинной группы. Motif имеет несколько ресурсов и подпрограмм для контроля перехода с использованием этого стиля.
Глава 13 содержит дополнительную информацию о клавиатурных переходах и других возможностях ввода.
Motif представляет большинство текстовых данных с использованием типа данных, называемого композитными строками (Также известного как XmString). Это поток компонентов, представляющих текст, направление отображения и тэги воспроизведения. Эти тэги воспроизведения указывают как текст должен выглядеть при отрисовке, включая следующие параметры:
Шрифт
Цвет
Позиции табуляции (если используются)
Подчеркивание
Другие возможности
Композитная строка состоит из нескольких текстовых сегментов, возможно с различными направлениями и тэгами воспроизведения. Motif использует композитные строки для представления всех текстовых данных за исключением виджетов Text и TextField.
Для каждого виджета который содержит текст Motif поддерживает информацию о шрифтах, цвете, позициях табуляций и других свойствах написания текста использую тип данных называемый таблицей воспроизведения. Таблица воспроизведения является списком входов, каждый из которых состоит из (шрифта или набора шрифтов) и информации воспроизведения. Набор шрифтов это конструкция представляющая группу шрифтов необходимых для отображения текста в локализации приложения.
Когда Motif отображает текст сегмента композитной строки, он сопоставляет тег воспроизведения сегмента строки с таблицей воспроизведения виджета. Затем он использует соответствующий шрифт или набор шрифтов для отображения текста из сегмента. Специальный тэг воспроизведения (называемый _MOTIF_DEFAULT_LOCALE) указывает что текст должен разбираться в кодировке текущей локализации и отображаться с использованием шрифтов, необходимых для этой локализации.
Смотрите Главу 9 для получения дополнительной информации о композитных строках, шрифтах, визуальных воспроизведениях и таблицах воспроизведения. Глава 11 содержит информацию об использовании этих инструментов для подготовки приложения к использованию в различных языковых окружениях.
Менеджер окон Motif (MWM) является клиентской программой, которая способна управлять окнами как Motif так и не Motif приложений. MWM предоставляет декорации для окна и функции перемещения, изменения размера, подъема, опускания, максимизации и минимизации окон. Пользователь может отображать иконки как на корневом окне, так и в icon box. MWM имеет много ресурсов, которые позволяют пользователю устанавливать их внешний вид и предпочтения.
В Главе 18 находится дополнительная информация о интерфейсе приложнения к MWM. Смотрите справочную страницу \textbl{mwm}(1) в Motif. Справочник программиста для получения информации о ресурсах и функциях MWM.
Motif содержит язык описания, называемый Языком Интерфейса Пользователя (User Interface Language - UIL). Разработчики используют UIL для задания виджетов и данных в текстовом файле и затем компиляции этого файла в бинарный формат. Во время выполнения приложение, используя подпрограммы Менеджера Ресурсов Motif (Motif Resource Manager - MRM), извлекают описания виджетов и данных из бинарного файла и MRM создает виджеты и структуры данных по этому описанию.
UIL и MRM работают вместе с набором компонентов Motif. Приложение задает процедуры обратного вызова и общается с используемыми виджетами исключительно через набор компонентов Motif. При использовании UIL для определения иерархии виджетов программы разработчик должен отделить опредение пользовательского интерфейса от кода приложения. Разработчик должен изменять интерфейс посредством редактирования и перекомпиляции текстового файла без перекомпиляции и сборки прикладной программы. Как и с файлами ресурсов пользователь должен использовать различные UIL файлы содержащие текст, таблицы визуализации и другие данные, специфические для конкретной локализации.
Смотрите Главу 4 для получения информации об использовании UIL и MRM в приложениях. Смотрите справочную страницу \textbl{UIL}(5) в книге Motif. Справочник программиста для получения информации о синтаксисе UIL.
Xt создан как надстройка над Xlib, а Motif - как надстройка над Xt. Единственная цель Xt это предоставление приложению набора высокоуровневых интерфейсов и объектов освобождают программу от взаимодействия с большим количеством простых подпрограмм Xlib. Задача Motif - предоставить приложению устойчивый высокоуровневый интерфейс и, в частности, разнообразный набор виджетов для освобождения программы от необходимости определять свои собственные виджеты для большинства задач.
Тем не менее, Xt не стремится заменить все интерфейсы Xlib, а Motif не ставит своей задачей заменить все интерфейсы Xt. Даже простое Motif приложение должно использовать подпрограммы Xt для инициализации набора компонентов, управления виджетами, создания окон для виджетов, получения и установки ресурсов, добавления процедур обратного вызова и входа в цикл обработки событий.
Многие Motif приложения не нуждаются в использовании подпрограмм Xlib. Тем не менее, Motif не содержит своих собственных графических подпрограмм, средств работы с цветовыми пространствами или поддержки управления методами ввода для приложения. Программы которым необходимы эти возможности должны использовать инструментальные средства других производителей или же напрямую вызывать подпрограммы Xlib.
Как общее правило, приложение должно использовать наиболее высокоуровневый интерфейс достаточный для решаемых задач. Это обычно дает не только короткую программу, но также обеспечивает то, что функционирование программы сохранится, когда процедуры высокого уровня будут заменены на процедуры низкого уровня.
Например, Xlib, Xt и Motif все содержат подпрограммы для установки фокуса клавиатуры в окно или виджет. Xt и Motif оба поддерживают внутренне состояние для отслеживания изменения фокуса. Если Motif приложение использует подпрограммы Xt или Xlib, то это может привести Motif или Xt к внутреннему нессответствию.
По соглашению, имена подпрограмм и структур данных Xlib начинаются с "X"; имена подпрограмм и структур данных Xt начинаются с "Xt"; и, наконец, имена подпрограмм и структур данных Motif начинаются с "Xm".
Эта книга не описывает интерфейсов Xlib и Xt. Разработчик Motif приложений должен знать основные интерфейсы прикладных программ Xt и должен иметь общее представление о Xlib. Для дополнительной информации по Xlib смотрите стандарт X Consortium Xlib - Интерфейс с X на языке C. Для дополнительной информации по Xt смотрите документ X Window System X Toolkit Intrinsics - Интерфейс на языке C.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 1. Введение | . |
Этот раздел дает краткий обзор иерархии классов виджетов в Xt и Motif. Глава 2 более детально рассматривает эту иерархию.
Xt опередляет базовые классы для всех виджетов. Core является фундаментальным классом для всех виджетов, которые имеют окна. Этот класс содержит базовые ресурсы геометрии виджетов, цвета фона, трансляций, и чувствительности ввода. Виджетоподобные объекты, которые не имеют окон - называемые в Motif гадгетами - являются подклассами от RectObj. Этот класс содержит реурсы геометрии, но не содержит цветов и трансляций.
Composite является базовым классом для всех виджетов, которые могут иметь дочерние виджеты. Этот класс поддерживает список своих дочерних виджетов и отвечает за управление их геометрией. Constraint является подклассом от Composite который поддерживает дополнительные данные для каждого дочернего виджета, представляющие ограничивающие ресурсы для дочерних виджетов.
Shell является базовам классом для всех виджетов-оболочек. Оболочки обертывают другие виджеты чьи окна являюся дочерними от корневого окна. Оболочки отвечают за взаимодействие с менеджером окон. Shell является подклассом Composite. Xt содержит следующие подклассы Shell:
Окружает виджеты, которые менеджер окон должен игнорировать, такие как меню.
Суперкласс для оболочек которым необходимо особым образом взаимодействовать с менеджером окон.
Подкласс от WMShell реализующий зависимое от набора компонентов поведение.
Подкласс от VendorShell для виджетов типа диалогов которые отображаются ненадолго в интересах других виджетов.
Подкласс от VendorShell для виджет верхнего уровня для компонент приложения.
Подкласс от TopLevelShell для виджетов верхнего уровня представляющих приложение как единое целое.
Motif содержит три обширные группы виджетов: примитивы и гадгеты, менеджеры, оболочки.
Примитивы это виджеты которые не имеют дочерних виджетов. Они обычно являются фундаментальными элементами для ввода и вывода, и они обычно используются как строительные кирпичики для композитных виджетов. XmPrimitive, подкласс от Core, является базовым классом для всех примитивов. XmPrimitive содержит базовые ресурсы цвета и предоставляет возможность клавиатурного перехода.
XmPrimitive используется только как суперкласс для классов с более специализированным поведением. Подклассами примитивов Motif являются следующие:
Используется для разделения других виджетов. Обычно выглядит как линия.
Отображает текст или пиксельное изображение. Является суперклассом для кнопок, предоставляет специфическое поведение, такое как клавиатерный переход внутри меню.
Подклассы XmCascadeButton, XmDrawnButton, XmPushButton и XmToggleButton от XmLabel производят некоторые действия когда активизируются или "нажимаются" пользователем. Подклассы имеют роль активизаторов меню, переключателей, кнопок и маленьких графических областей.
Управляет перемещением прокручиваемого горизонтально или вертикально виджета в фиксированной области просмотра.
Массив текстовых элементов из которого пользователь может выбрать один или более элемент.
Виджет для отображения и, возможно, редактирования текста. XmText может быть многострочным или ограниченным одной строкой. XmTextField является оптимизированным для одной строки вариантом XmText.
Гадгеты являются вариантами примитивов которые не имеют окон. Гадгеты имеют геометрию, но они наследуют цвета от их родителя и зависят от родителя в части распределения событий для них. XmGadget, подкласс RetObj, является базовым классом для гадгетов. Гадгет варианты существуют для сепараторов, меток и большинства кнопок. XmIconGadget, который отображает как текст так и пиксельные изображения в различных комбинациях, манипулируются виджетом XmContainer.
Смотрите Главу 10 для дополнительной информации о виджетах XmText и XmTextField. Смотрите главу 5 для дополнительной информации о других примитивах.
Менеджеры это виджеты которые обычно имеют дочерние виджеты и управляют их геометрией. XmManager, подкласс от Constraint, является базовым классом для менеджеров. Этот класс несет особую ответственность когда содержит дочерние гадгеты. Он предостваляет ресурсы цвета, которые наследуют его дочерние гадгеты, и он распределяет события ввода соответствующим гадгетам. Подклассами менеджеров являютя:
Окружает свой дочерние виджет тенью и свободным полем.
Показывает значение внутри диапазона и дополнительно позволяет пользователю устанавливать новое значение.
Распологает своих потомков, называемых панелями, вертикально или горизонтально (с лева на право или с права на лево, в зависимости от \textbl{XmNorientation}). Может также вставлять управляющий элемент, называемый сэшем, позволяющим пользователю устанавливать размер панелей.
Предоставляет область просмотра дочернего виджета реализую виртуальные скроллинг. Управляет полосам скроллинга для перемещения скроллируемого элемента в области просмотра.
Подкласс от XmScrolledWindow предоставляющий поддержку полосы меню и других специализированных областей.
Используется для реализации меню, групп радиокнопок и кнопос переключателей, обычно в качестве потомков содержащих кнопки. Также используется для расположения произвольных виджетов к строки, колонки или двумерные структуры.
Суперкласс для диалогов, виджетов которые представляют информацию пользователю или получают ее отпользователя. Диалоговым виджетом может быть BulletinBoard, предоставляющий базовое поведение, или специализированный подкласс. Частные подклассы представляют список из которого пользователь может сделать выбор, отображают имена файлов и позволяют пользователю выбратьодин из них, просят пользователя ввести команду и отображают сообщение. Один из подклассов,XmForm, предоставляет обобщенное основанное на ограничениях управление геометнией своих потомков.
Менеджер общего назначения предназначенные для использования в качестве области для выполениения графических операций.
Управляет наборами виджетов определенных видов (обычно IconGadget). Эти дочерние виджеты показываются в нескольких различных форматах расположения, выбираются с использованием различных типов и техники выделения и непосредственно управляются пользователем. Одно из возможных применений Container виджета это построение графического интерфейса пользователя для файловой системы.
Управляет виджетом текстового поля и виджетом списка. Пользователь может выбрать элемент и ComboBox посредством щелчка на нем в списке или набрав его непосредственно в текстовом поле.
Позволяет пользователю выбрать значение из кольцевого набора связанных взаимооднозначных вариантов которые отображаются последовательно. Например, пользователь может использовать SpinBox для выбора месяца в одном элементе и выбора дня месяца посредством другого.
Организовывает своих потомков в страницы, закладки, области состояния и прокрутчики страниц для моделирования настоящей записной книжки. Каждая страница в Notebook может содержит различные виды элементов. Например, первая страница может содержать текст в виджете Text, вторая страница может быть графическим изображением отображаемыми в виджете Label, и наконец третья страница может анкетой управляемой виджетом Form.
Motif содержит три класса оболочек:
Специализированная для Motif реализация соответствующего Xt класса. Среди других возможностей управляет взаимодействием с MWM.
Подкласс от TransientShell который содержит диалоги. Взаимодействует с BulletinBoard при всплытии и позиционировании временных диалогов.
Подкласс от OverrideShell который содержит меню.
Motif использует некоторое кольчество специализированных объектов не предназначенных для использования в создании виджетов. Эти объекты существуют в первую очередь для хранения ресурсов и другой информации которую сложно сделать доступной другим путем. XmDisplay сохраняет ресурсы специфичные для данного дисплея, а XmScreen сохраняет ресурсы специфичные для каждого экрана на котором приложение создает виджеты. Интерфейс drag and drop включает объекты представляющие некоторые аспекты транзакций drag and drop, включая общий контекст, точки выброса, иконки перетаскивания и перенос данных.
В дополнение к объектам Motif предоставляемыми стандартным набором компонентов, ваше приложение может использовать виджеты предоставляемими дркгими производителями. Вы также можете свои собственные виджеты. Смотрите Руководство по написанию виджетов Motif для дополнительной информации.
Xlib, Xt и Motif имеют заголовочные файлы (иниче называемые подключаемыми файлами) которые приложение должно включать в свой код. Однако, заголовочные файлы Motif сами подключают необходимые файлы Xt, которые в свою очередь подключают необходимые файла Xlib. Приложению обычно необходимо подключить только соответствующие файлы Motif.
Все Motif приложения должны подключать файл <Xm/Xm.h>. Этот файл содержит определения, необходимые всем приложениям. Каждый виджет Motif также имеет подключаемый файл. Приложение должно подключить эти заголовочные файлы для всех виджетов, которые оно создает. Дополнительно некоторые группы подпрограмм Motif имеют свои собственные заголовочные файлы. Необходимые подключаемые файлы для каждого виджета и подпрограммы Motif описаны в Справочник программиста Motif.
Вместо использования большого количества заголовочных файлов для конкретных виджетов и подпрограмм приложение может подключить файл <Xm/XmAll.h>. Этот файл объединяет все документированные заголовочные файлы Motif. Подключение <Xm/XmAll.h> может немного замедлить компиляцию; тем не менее его подключение не увеличивает размер результирующего приложения. Другими словами работа редактора связей никак не изменяется в результате подключения <Xm/XmAll.h> вместо подключения индивидуальных заголовочных файлов.
При создании Motif приложения разработчик связать программу с необходимыми библиотеками. Xlib, Xt, набор компонентов Motif и MRM имеют раздельные библиотеки. Приложение которое не использует MRM должно быть связано с библиотеками набора компонентов Motif, Xp, Xext, Xpm, Xt и Xlib. Приложение которое использует MRM должно быть связано с этими библиотеками и дополнительно с библиотекой MRM. Разаработчик также должен связать приложение с дополнительными бибилиотеками, в зависимости от платформы или операционной системы. Проконсультируйтесь у Вашего системного администратора и прочтите документацию производителя для получения дополнительной информации о библиотеках необходимых для Motif приложений.
Motif. Руководство программиста | ||
---|---|---|
. | . |
Motif дает возможность использовать различные стили программирования приложений. Приложение выполняющее большинство задач, таких как обработка некоторых видов ввода пользователя и отображение некоторых видов вывода, может делать это несколькими способами. Пока эта гибкость одна из сильных сторон Motif, набор компонентов разработан с учетом различных принципов программирования. Эта глава объясняет общее назначение используемых Motif виджетов и других возможностей набора компонентов. Следующая глава дает набросок общей структуры Motif программ, и последующие главы описывают возможности набора комполнентов в деталях.
Следующие общие принципы позволяют понять как писать любые Motif программы:
Применяйте ориентированную на пользователя перспективу. В большинстве Motif программ приложение производит свою работу в ответ на команды или другие виды ввода информации от пользователя. Важной частью разработки интерфейсов является предоставление возможности точного принятия решения пользователем на основании команд, параметров и другой информации, предоставленной приложением. Интерфейс в большей части состоит из процедур которые исполняют команда пользователя или иным образом реагируют на вводимые пользователем данные.
Разделяйте разработку ядра приложения от интерфейса пользователя. Ядро приложения не должно зависеть от любого интерфейса пользователя. Хорошей идеей является определение обобщенного набора общих подпрограмм и структур данных для обслуживания ввода и отображения вывода. В последующем разработчик будет иметь возможность реализовать эти подпрограммы различными способами для предоставления различных интерфейсов пользователя для приложения.
Следуйте Руководству по стилю Motif при разработке интерфейсов пользователя. Поскольку приложение может использовать виджеты Motif в различных конфигурациях для пользователя некоторые из них будут более общими, понятными и комфортабельными чем другие. Руководство по стилу Motif содержит требования и рекомендации для удобных приложений, а также дополнительные пояснения в части разработки приложений.
Делайте наброски иерархии виджетов. Однажды Вы остановитесь на нескольких вариантах комбинаций виджетов, тогда Вы сможете найти более удачную реализацию если у Вас будут эскизные наброски дерева всех виджетов, которые использует программа. Конструирование дерева виджетов позволяет раскрывать расхождения и неуклюжесть в разработке. Присоединение диалогов и меню к иерархии может помочь обеспечить соответствие и завершенность в представлении и требованиях к информации.
Используйте наиболее высокоуровневые интерфейсы как только возможно. Motif приложение должно использовать некоторые интерфейсы X Toolkit Intrinsics (Xt) и оно может вызывать другие публичные подпрограммы Xt и Xlib. Для некоторых задач, таких как рисование графики, приложение должно вызывать низкоуровнывые подпрограммы. Тем не менее, Motif предоставляет интерфейсы типа ресурсов, списков процедур обратного вызова и разнообразные удобные подпрограммы для решения большинства задач. Motif также содержит как простые так и сложные виджеты которые выполняют большую часть работы связанной с их специфичными функциями, такими как редактирование текста или основанное на ограничениях управление геометрией. Использование высокоуровневых интерфейсов Motif вместо сравнимой последовательности низкоуровневых вызовов делает код более простым и облегчает его сопровождение.
Используйте файлы ресурсов и язык описания интерфейсов пользователя (User Interface Language - UIL) для определения характеристик интерфейса. Избегайте включения описания и данных интерфейса полизователя в код приложения. Использование ресурсов дает пользователю возможность переопределять предоставляемые приложением значения по умолчанию. UIL предоставляет удобную возможность для отделения иерархии виджетов от приложения. При использовании как ресурсов, так и UIL разработчик получает возможность изменять интерфейс без перекомпиляции кода приложения. Эти механизмы какже предоставляют возможности для приспособления интерфейса и данных для специфических языковых окружений.
Базовым принципом программирования в Motif и Xt является забота приложения о пользователе. За исключением редких случаев программа выполняет действия в ответ на команды или другой вводимые пользователем данные. Как факт, типичная Motif программа проводит большую часть времени в ожидании ввода информации пользователем.
Основным типом объектов в Motif интерфейсах является виджет. Некоторые виджеты отображают выходную информацию, брабатывают входную информацию или выполняют и то и другое. Некоторые виджеты предназначены для содержания других виджетов. Виджет обычно связан с окном или прямоугольной областью экрана. Виджет также имеет атрибуты, называемые ресурсами, которые могут быть установлены пользователем или приложением. Приложение организует виджеты в оду или более иерархий или деревьев родительских виджетов и их потомков.
Motif и Xt определяет набор типов или классов виджетов. Класс видета может быть подклассом другого класса; в этом случае он наследует некоторые атрибуты и поведение от суперкласса. Motif имеет три базовых класса виджетов:
Примитивы являются базовыми элементами для ввода и вывода. Примитивы обычно не содержат потомков. Специализированные примитивы Motif включают метки, разделители, кнопки, полосы прокрутки, списки и текстовые виджеты. Некоторые классы примитивов имеют эквивалентные объекты, называемые гадгетами. Они очень похожи на примитивы за исключением того, что для увеличения производительности они не имеют связанного с ними окна.
Менеджеры сложные виджеты, которые могут содержать примитивы, гадгеты или другие менеджеры. Менеджеры отвечают за геометрическое расположение своих потомков. Они также обрабатывают и распределяют ввод для своих гадгет потомков. Специализированные Motif менеджеры включают рамки, скроллируемые и панельные окна, меню, менеджеры геометрии основанной на ограничениях и различные виды диалогов.
Оболочки это виджеты основное назначение которых заключается во взаимодействии с менеджером окон. Большинство оболочек могут иметь только одного потомка, и они поддерживают такой же размер и расположение как и потомок. Специализированные оболочки Motif существуют для окружения приложения, диалогов и меню.
Определение иерархии виджетов является одной из двух основных задач Motif приложения. Другая задача - определение набора процедур обратного вызова. Процедуры обратного вызова являются основным механизмом посредством которого приложение реагирует на ввод пользователя. Когда пользователь совершает действие типа нажатия на клавишу или кнопку мыши X сервер отправляет приложению событие. Xt распределяет зто событие соответствующему виджету, обычно тому которому пользователь направил ввод. Xt отображает события на одну или более подпрограмм действий виджета. Действие может изменить состояние виджета и, если приложение запросило оповещение об этом действии, может произвести "обратный вызов" программы посредством вызова процедур обратного вызова приложения.
Многие Motif виджеты ресурсы, являющиеся списками процедур обратного вызова. Motif вызывает процедуры из этого списка когда пользователь производит действие некоторого вида. Например, большинство кнопок имеют процедуры обратного вызова вызываемые Motif когда пользователь актвизирует кнопку. Пользователь может активировать кнопку несколькими способами, такими как нажатием клавиши osfSelect или кнопки Btn1 мыши. События, составляющие активизацию и другие значащие действия пользователя определены в общем виде в Руководстве по стилю Motif и описаны для каждого виджета в Справочнике программиста Motif.
Действия пользователя могут заставить Motif изменить состояние и внешний вид виджета. Например, когда пользователь нажимает osfSelect на PushButton, Motif может изменить внешний вид кнопки как будто она была нажата, а затем отпущена, аналогично обычной механической кнопке. Действие может иметь и другой эффект в зависимости от контекста. Например, Motif содержит диалоговый виджет называемый FileSelectionBox, используемый для поиска и выбора файла. Когда пользователь активизирует PushButton кнопку Фильтр в FileSelectionBox, Motif производит поиск и отображает имена файлов которые совпадают с шаблоном отображаемым в другом месте FileSelectionBox.
В общем Motif берет на себя заботу по изменению состояния и внешнего вида виджета в ответ на соответствующие действия пользователя. По умолчания тем не менее эти действия не оказывают никакого эффекта на приложение. Разработчик приложения должен интерпретировать смысл этих действий для приложения предоставляя процедуры обратного вызова, которые Motif будет вызывать когда пользователь выполнит действие. Процедуры обратного вызова могут изменить состояние приложения, например, изменением значения переменной когда пользователь выбирает новое значение с помощью виджета Scale. Процедура обратного вызова может заставить приложение получить действие. Она также может изменить состояние одного или нескольких его виджетов или может создать совершенно новую иерархию виджетов.
Когда Motif и приложение заканчивают обработку действия пользователя, приложение ожидает от пользователя дальнейшего ввода. Xt предоставляет подпрограмму в которой приложение проводит большую часть своего времени. Эта подпрограмма ожидает поступления события, диспетчеризирует его соответствующему виджету и затем ожидает другого события. После инициализации набора компонентов и создания начальной иерархии виджетов большинство приложений входят в этот цикл и выполняют его пока пользователь не остановит программу.
Motif и Xt предоставляют приложению другие способы получения и обработки событий, но для простых программ фактически полный интерфейс между пользователем и приложением состоит из процедур обратного вызова.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 2. Модель программирования на Motif | . |
Широко применяемым принципом разработки приложения является независимость ядра приложения от специфического пользовательского приложения. Отделение приложения от интерфейса пользователя позволяет разработчику независимо аботать над этими двумя компонентами. Это также позволяет программе работать с различными интерфейсами без изменений в ядре приложения. Это упрощает перенос приложения на более чем один интерфейс и экспереманты с различными конфигурациями одного и тогоже интерфейса.
Большинство приложений нуждаются в сборе данных от пользователя и отображения выходной информации в некотором виде. Это может быть упрощено разделением ядра приложения и интерфейса пользователя указанием набора обобщенных подпрограмм ввода и вавода также как и необходимых структур данных. Если эти обобщенные интерфейсы не зависят от конкретного интерфейса пользователя они могут быть реализованы различными способами для различных интерфейсов без изменения ядра приложения. Это есть модули для взаимодействия между ядром приложения и интерфейсом.
Motif реализация интерфейсных модулей состоит из кода выполняющего следующие задачи:
Ининциализацию набора компонентов.
Создание иерархии виджетов.
Определение процедур обратного вызова.
Разрешения отображения виджетов.
Вход в цикл который ожидает и обрабатывает ввод пользователя.
Эти шаги более подробно рассматриваются в главе 3.
Язык описания интерфейсов (UIL - User Interface Language) помогает увеличить разделение интерфейса от ядра приложения. При использовании UIL разработчик определяет виджеты и их характеристики в текстовом файле и затем компилирует текстовый файл в бинарный формат. Во время выполнения приложение использует подпрограммы менеджера ресурсов Motif (MRM - Motif Resource Manager) для извлечения описания виджетов из бинарного файла и MRM создает виджеты по этому описанию. UIL файл также определяет данные, такие как текстовые строки и цвета, а MRM извлекает эти данные во время исполнения.
В этом случае приложение может удалить описание иерархии виджетов из кода программы. В своем исходном коде приложение определяет процедуры обратного вызова и взаимодействут с виджетами также как если бы использовало Motif обычных способом. Если приложение определяет все необходимые ему процедуры обратного вызова, то разработчик может изменить иерархию виджетов редактированием и перекомпиляцией UIL файлов без перекомпиляции и сборки программы.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 2. Модель программирования на Motif | . |
Виджеты-примитивы являются базовыми элементами для ввода и вывода информации в Motif. Примитивы обычно являются завершающими виджетами иерархии виджетов. Это виджеты не имеют потомков для которых являются родителями. Название примитивы не подразумевает простоты; некоторые примитивы, такие как виджет Text, имеют очень сложное поведение. Примитивами они названы в противоположность менеджерам, виджетам, которые обычно имеют потомков. Они также предлагают базовые компоненты из которых строятся сложные виджеты. Примитивы иногда называют управляющими виджетами.
Класс Motif виджетов XmPrimitive является суперклассом для всех примитивов. XmPrimitive является подклассом от базового класса Xt виджетов Core. Core содержит ресурсы описывающие ширину и высоту виджета, а также x и y координаты виджета отностиельно его родителя. Друге ресурсы Core управляют характеристиками окна, такими как цвет фона; должен или нет виджет принимать события; карты, используемые для трансляции событий в подпрограммы действий виджета.
XmPrimitive добавляет две группы возможностей к классу Core. Одна группа состоит из ресурсов для управления дополнительными визуальными характеристиками, включая характеристики трехмерных теней и прямоугольника подсветки который отображается когда виджет является фокусом для клавиатурного ввода. Вторая группа управляет клавиатурным переходом, использованием клавиатуры для перемещения фокуса с одного виджета на другой. Эта группа включает несколько ресурсов и набор трансляций и действий, позволяющих пользователю перемещать фокус клавиатуры на другой виджет нажатием клавиш со стрелками. XmPrimitive также предоставляет процедуры обратного вызова для обеспечения возможности предоставления приложением справочной информации когда пользователь нажимает osfHelf.
Класс виджетов XmGadget является суперклассом для всех гадгетов. XmGadget является подклассом от Xt класса RectObj. Этот класс предоставляет ресурсы для определения размера и положения прямоугольной области гадгета внутри его родителя. XmGadget является эквивалентом XmPrimitive эа двумя исключениями:
Гадгеты содержат ресурсы цвета и пиксельных изображений, но это ресурсы нельзя устанавливать, гадгеты наследуют из значения от своих родителей.
Гадгеты не имеют трансляций и действий. Родитель гадгетов контролирует клавиатурный переход от одного гадгета к другому виджету, и он диспетчеризирует события для гадгета когда необходимо.
XmPrimitive и XmGadget используются только как суперклассы для других классов виджетов. Приложкение не может создавать фактические виджеты как экземпляры этих классов. Motif имеет несколько специализированных подклассов от примитивов и гадгетов, общее описание которых приведено в последующих разделах.
Метки (Label и LabelGadget) предоставляют возможность отображения статичного (нередактируемого) текста и пиксельных изображений. Label или LabelGadget обычно используются для отображения сообщений, заголовков или описаний. Label и LabelGadget также являются суперклассами для кнопок используемых как элементы меню, переключатели и управляющие элементы.
Метки отображают как текст так и пиксельные изображения. Когда метка отображает текст она использует специальную конструкцию, называемую композитной строкой. Это поток, компоненты которого представляют нуль или более частей текста, каждая с соответствующими тегами воспроизведения и направления отображения. Когда Motif отображает композитные строки он сопоставляет каждый тег с тэгом в таблице воспроизведения виджета и исапользует соответствующий шрифт или шрифты, цвета и другие возможности.
Разделители Separator или SeparatorGadget разделяют управляющие элементы или их группы. Он обычно выглядит как горизонтальная или вертикальная линия и поддерживает различные стили рисования линии.
Метки и разделители более подробно описаны в главе 5.
Кнопка представляет основной управляющий элемент который позволяет производить действия при его активизации пользователем. Кнопки обычно используются в меню, группах кнопок RadioBoxes и CheckBoxes, диалоговых формах SelectionBoxes и MessageBoxes. Motif имеет следующие классы кнопок:
Кнопки CascadeButton и CascadeButtonGadget используются внутри меню и когда активизируются обычно отображают выпадающие меню (PulldownMenu).
Кнопки PushButton и PushButtonGadget могут использоваться как внутри меню так и вне его. Они позволяют выполнять некоторые действия определяемые приложением. Когда кнопка PushButton нажимается или становится готовой к активизации она изменяет свой внешний вид так что пользователь видит что нажал ее. Когда она отпускается, она возвращает внешний вид как будто отжата.
Кнопки-переключатели ToggleButton и ToggleButtonGadget имеют различные состояния: аналогично переключателям они бывают либо включенными либо выключенными. Они используются в меню или в режимах WorkArea менеджера RowColumn, включая RadioBoxes и CheckBoxes. Они также могут иметь неопределенное состояние.
Кнопка DrawnButton является пустой кнопкой, окруженной рамкой тени. Она предназначена для использования как кнопка PushButton но с изображением, отрисовываемым приложением.
С большими подробностями кнопки описаны в главе 5.
Виджет может действовать как окно просмотра в прокручиваемый элемент. Прокручиваемый элемент это плоскость с текстом, графикой, списком элементов или другим содержимым. Окно просмотра это фиксированного размера окно в котором видно часть прокручиваемого элемента.
Полоса прокрутки (ScrollBar) является управляющим элементом, который перемещает область просмотра горизонтально или вертикально относительно прокручиваемого элемента. Полоса прокрутки состоит из прямоугольнока, называемого прокручиваемой областью, представляющей полный размер прокручиваемого элемента. Она имеет маленький прямоугольник, называемый бегунком, внутри прокручиваемой области, представляющий положение и размер области просмотра относительно полного размера прокручиваемого элемента. Полоса прокрутки обычно содержит изображения стрелок на обоих концах большего прямоугольника.
Более детально полосы прокрутки описаны в главе 5.
Список (List) это массив текстовых элементов из которого пользователь может выделить один или несколько. Каждый элемент является композитной строкой. Список имеет четыре режима выделения: два из них позволяют пользователю выделять единовременно только один элемент, и оставшихся два позволяют пользователю выделить одновременно более одного элемента как в непрерывном так и в разрывном диапазоне.
Подробнее списки обсуждаются в главе 5.
Текстовый виджет (Text) предназначен для отображения и, возможно, редактирования текста. Он представляет текст как многобайтные или широкосимвольные строки. Когда виджет является редактируемым и пользователь нажимает клавишу, представляющую текстовый символ, этот символ вставляется в текст. Другие трансляции и действия позволяют пользователю перемещаться или выделять, вырезать, копировать, вставлять или прокручивать текст.
Текст может быть многострочным или ограниченными одной строкой. В однострочном текстовом виджете действия, перемещающие вверх и вниз на одну строку в многострочном виджете, производят переход фокуса на другой виджет, а нажатие osfTab перемещает клавиатурный фокус на другую группу виджетов вместо вставки символа табуляции /textit{Tab}.
Виджет TextField абсолютно аналогичен виджету Text в однострочном режиме, за исключением токо, что он оптимизирован по производительности для выполнения однострочных операций.
Дополнительно текстовые виджеты описаны в главах 5 и 10.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 2. Модель программирования на Motif | . |
Менеджеры это виджеты которые обычно содержат другие виджеты, как примитивы так и другие менеджеры. С одной стороны менеджеры отвечают за расположение и форму их потомков в соответствии с конфигурацией потомков и в зависимости от специализированного назначения менеджера. С другой стороны они отвечают да определение когда их гадгет потомок должен обработать событие ввода и если должен то диспетчеризовать событие этому потомку.
Класс Motif виджетов XmManager является суперклассом для всех менеджеров. XmManager является подклассом от Core. Аналогично XmPrimitive XmManager содержит ресурсы для управления цветом или пиксельным изображением используемыми для изображения, теней и прямоугольника подсветки. Большинство менеджеров не имеют тени или прямоугольника подсветки, но гадгет потомки наследуют эти параметры. Менеджеры также имеют ресурсы для управления клавиатурным переходом и они предоставляют процедуры обратного вызова для обработки запроса пользователя на помощь. В дополнение они содержат трансляции и действия для диспетчеризации событий ввода для гадгет потомков, обычно для потомки содержащего текущий фокус клавиатурных событий.
XmManager не может использоваться для создания экземпляров в программе, он предназначен только для использования в качестве суперкласса для других классов виджетов. Motif содержит несколько специализированных подклассов менеджеров, обобщаемых в последующих разделах.
Рамка (Frame) это простой менеджер который окружает единственного потомка тенью и свободным полем. Рамка также может иметь другого потомка который отображается как название рамки.
Рамки более подробно описываются в главе 8.
Регуляторы (Scale) это менеджеры, выполняющие функции управляющих элементов. Они отображают значение в пределах некоторого диапазона и дополнительно позволяют пользователю установить новое значение. Их внешний вид и поведение аналогичны полосе прокрутки без стрелочек. Они также имеют заголовок и могут отображать текущее значение рядом с бегунком. Если приложение добавит дополнительные потомки к регулятору, то он расположит их строго напротив прямоугольной области представляющей даипазон значений, и эти потомки могут быть использоваться как щкалы или метки значений.
Подробнее регуляторы рассмотрены в главе 5.
Окна панелей (PanedWindow) распологают своих потомков вертикально сверху вниз или горизонтально и устанавливают всем им одинаковую ширину. Каждый потомок является панелью. Между каждой парой парелей окно панелей вставляет необязательный разделитель и орган управления называемый сэшем. Манипулируя сэшем с помощью мыши или клавиатуры пользователь может увеличить или уменьшить высоту примыкающих панелей. Окно панелей содержит ресурсы для для управления свободых полей, пробелов между панелями и внешним видом сэша. Каждая панель окна панелей содержит ресурсы указывающие максимальную и минимальную высоту и может или нет панель самостоятельно, иначе говоря должно ли окно панелей позволять, изменять размер без вмешательства пользователя.
Дополнительную информацию об окнах пнелей можно найти в главе 8.
Окна прокрутки (ScrolledWindow) управляют окном просмотра и полосами прокрутки для реализации окна в виртуальный прокручиваемый элемент. Пользователь может перемещать окно просмотра для отображения различных частей прокручиваемого элемента с использованием полос прокрутки или клавиатурных команд прокрутки.
Окно прокрутки способно автоматически проиводить операции прокрутки. В этом режиме приложение создает виджет, который представляет прокручиваемый элемент, как потомкаокна прокрутки. Окно прокрутки затем создает окно отсечения для выполнения функций окна просмотра, создает и берет на управление полосы прокрутки и изменяет содержимое окна просмотра в ответ на команды прокрутки выдаваемые пользователем.
Окно прокрутки также может позволять приложению выполнять операции прокрутки. В этом режиме приложени само может создать и взять на управление полосы прокрутки и должно изменять содержимое окна просмотра в ответ на действия пользователя.
Списки и текстовые виджеты обычно используются в качестве прокручиваемых элементов. Motif содержит соответствующие процедуры для создания списков и тескстовых виджетов внутри окна прокрутки, о получающиеся прокручиваемые списки (ScrolledList) и прокручиваемые текстовые (ScrolledText) виджеты выполняющие операции прокрутки без участия приложения.
Главное окно (MainWindow) является подклассом окна прокрутки которое предназначено для использвание как главное окно приложения. В дополнение к окну просмотра и полосам прокрутки главное окно содержит необязательные полосу меню (MenuBar), командное окно и окно сообщений.
Более подробно виджеты Окно Прокрутки и Главное окно описываются в главе 8.
Строки-Столбцы (RowColumn) реализуют как меню так и Рабочие Области (WorkAreas). Меню это виджеты которые позволяют пользователю сделать выбор из действий или состояний. Motif поддерживает четые базовые вида меню:
Полоса меню (MenuBar) обычно используется в Главном Окне приложения и иногда в других компонентах. Чаще всего она состоит из строки Каскадных Кнопок которые, когда активизируются, вызывают появление Выпадающих Меню.
Всплывающие меню (PopupMenu) состоит из набора выборов который применим к некоторой компоненте приложения. Меню не видимы пока пользователь не выполнит действия которые вызовут вывод меню. Оно может содержать кнопки которые непосредственно выполняют действия или Каскадные Кнопки для вызова появления Выпадающих Меню.
Выпадающие меню связываются с Каскадными Кнопками в Полосах Меню, Всплывающих Меню или других Выпадающих Меню. Эти меню также не видны пока пользователь не вызовет их появления активизацией связанной Каскадной Кнопкой. Аналогично Всплывающим Меню, Выпадающие Меню могут содержать кнопки которые выполняют непосредственные действия или Каскадные Кнопки которые вызывают появление других Выпадающих Меню.
Меню Опций позволяют пользователю делать выброр из одного набора выборов, обычно являющихся уникальными атрибутами или состояниями. Оно состоит из метки, Гадгета Каскадной Кнопки чья метка отображает текущую выбранную опцию, и Выпадающего Меню содержащего кнопки которые представляют набор параметров.
Одно из применений режима Рабочей Области виджета Строки-Столбцы состоит в содержании набора кнопок ToggleButton для образования наборов кнопок RadioBox и CheckBox. Когда пользователь выберет кнопку ToggleButton ее состояние изменится с включено на выключено или с выключено на включено. Другим применением является расположение некоторого набора виджетов в строки, колонки и двухмерные структуры.
RowColumn описан более подробно в главе 6.
Диалоги являются контейнерными виджетами которые предоставляют возможности взаимодействия между пользователем и приложением. Диалоговый виджет обычно задает вопрос или представляет некоторую информацию для пользователя. В некоторых случаях приложение останавливает свое выполнение до тех пор, пока пользователь не предоставит ответ.
Обычно суперклассом для диалоговых виджетов является XmBulletinBoard. Диалоговый виджет может быть как непосредственно BulletinBoard, так и одним из более специализированных подклассов. BulletinBoard является контейнером без автоматически создаваемых потомков, он предоставляет обобщенное поведение необходимое для большинства диалогов. Его подклассы предоставляют дочерние виджеты и специфическое поведение специфичное для некоторых типов диалогов:
SelectionBox (Поле Выбора) является подклассом BulletinBoard который позволяет пользователю сделать выбор из списка вариантов. Он обычно содержит список, редактируемое текстовое поле отображающее выбор и три или четыре кнопки для принятия или отмены выбранного варианта и вызова справочной информации.
FileSelectionBox (Поле Выбора Файла) является специализированным подклассом SelectionBox для выбора файла из каталога. Он состоит два текстовых поля, одно из которых содержит шаблон поиска файла, другое содержит имя выбранного файла; два списка, один отображающий имена файлов, а другой - имена подкаталогов; и набор кнопок.
Command (Команда) является специализированным SelectionBox для ввода команд. Его основными составляющими являются текстовое поле для редактирования команд и список представляющий историю введенных команд.
MessageBox (Поле Сообщений) представляет подкласс BulletinBoard для отображения сообщений для пользователя. Он обычно содержит символ сообщения, текст сообщения и до трех кнопок. Motif предоставляет индивидуальные символы для различных видов сообщений: ошибок, предупреждений, информации, вопросов и оповещении о занятости приложения.
TemplateDialog является специализированным MessageBox который позволяет приложению создавать собственные диалоги с дополнительными потомками, такими как полосы меню и дополнительными кнопками.
Form является подклассом BulletinBoard позволяющим производить основанное на ограничениях управление геометрией. Потомки Form имеют ресурсы, представляющие привязку к другим потомкам или самой форме, смещения относительно привязки и относительное положение внутри формы. Form вычисляет положение и размер своих потомков частично основываясь на этих ограничениях. Эта функция расположения потомков делает Form часто применяемым и вне диалогов.
Диалоги описываются более подробно в Главе 7.
DrawingArea является менеджером предназначенным для использования в качестве области, содержащей графические объекты. Приложение должно взаимодействовать с DrawingArea на значительно более низком уровне чем с другими Motif виджетами, но DrawingArea предоставляет приложения более мелкоуровневую информацию о событиях. DrawingArea содержит процедуры обратного вызова для оповещения приложения когда выставляется или изменяет размер и когда он принимает ввод с клавиатуры или от мыши. Приложение обычно должно использовать подпрограммы Xlib для отрисовки в DrawingArea и приложение отвечает за обновление содержимого когда это необходимо. Гибкость DrawingArea делает его часто используемым видетом для реализации как графических так и текстовых возможностей, не предоставляемых другими Motif виджетами.
DrawingArea описывается более подробно в Главе 15.
Виджет ComboBox совмещает возможности виджета TextField и виджета List. Он позволяет пользователю вводить информацию через TextField и также предоставляет список возможных значений через List для завершения ввода в текстовое поле. Приложение предоставляет массив композитных строк которые заполняют этот список и также устанавливет количество видимых элементов списка. Если в списке содержится большее число элементов чем может быть видно (определяется значением ресурса \textbl{XmNvisibleItemCount}), то отображается вертикальная полоса прокрутки позволяющая пользователю прокручивать содержимое списка. Список может отображаться все время, или он может выводиться пользователем посредством нажатия на кнопку вниз при "выпадающем вниз" стиле ComboBox.
Текстовое поле в ComboBox может быть редактируемым или нередактируемым. Если TextField является редактируемым, то пользователь может непосредственно произвести набор в поле для ввода вюбора. Если оно не редактируемо, то печать текста может вызвать алгоритм поиска который позволит сделать выбор из списка используя символы, набранные пользователем. В обоих случаях элемент списка может быть выбран с помощью клавиатуры или мыши. Когда элемент является выбранным, он отображается в реверсных цветах и списке и отображается в текстовом поле ComboBox.
ComboBox более подробно описан в Главе 6.
SpinBox это менеджер, основным назначением которого является управление. Он создает пару стрелок которые могут использоваться для перебора значений из некоторого набора. Значения, которые обычно связаны но взамино исключающи, отображаются последовательно по одной в одно время в единственном текстовом поле. Значения могут быть диапазоном числовых значений или упорядоченным списком композитных строк. Кнопки стрелок позволяют пользователю продвигаться вперед или возвращаться назад между значениями пока не будет выбрано желаемое значение.
SimpleSpinBox является "готовым к использованию" подклассом от SpinBox. Текстовое поле для SimpleSpinBox создается автоматически.
SpinBox и SimpleSpinBox более подробно описаны в Главе 6.
Container является менеджером, который принимает потомков только класса XmIconGadget или его подклассов. Он выстраивает этох потомков в различных форматах и просматривать в зависимости от установок их ресурсов, и позволяющий производить выделение и манипулирование потомками.
Более подробно Container описан в Главе 8.
Notebook является менеджером который отображает только одного потомка в одно время. Каждый потомок имеет назначенный ему номер страницы в Notebook и отображается пользователем посредством нажатия клавиши табуляции или прокрутчиков странжиц в Notebook.
Подробнее Notebook описан в главе 8.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 2. Модель программирования на Motif | . |
Пользователи приложений системы X Window обычно используют менеджер окон, специальное приложение которое может управлять положением, размером и декорациями рамки окон верхнего уровня на дисплее. Motif предоставляет свой собственный менеджер окон, Motif Window Manager (MWM), но Motif приложение может также взаимодействовать с другими менеджерами окон.
Менеджер окон взаимодействует с другими приложениями посредством протокола определенного документом системы X Window Inter Clinet Communication Conventions Manual (ICCCM). Xt и Motif определяют группу виджетов чья основная задача окружение других виджетов и взаимодействие с менеджером окон. Такие виджеты называются оболочками.
Оболочки наиболее невидимы для приложения. Каждая оболочка содержит единственного управляемого потомка, и окно оболочки обычно постоянно совпадает с окном потомка. Приложение должно создавать оболочки когда это необходимо, но многие удобные подпрограммы Motif которые создают виджеты также автоматически создают и оболочки. Однажды создав оболочку приложению может не потребоваться обслуживать ее повторно. Например, приложение может изменить позицию или размер Motif оболочки посредством позиционирования или изменения размера дочернего виджета.
Каждый виджет с окном верхнего уровня -- т.е. окном, чьим предком является корневое окно экрана -- нуждается в заключение в оболочку. Motif предоставляет три класса оболочек: VendorShell, DialogShell и MenuShell.
VendorShell является классом оболочек предоставляющим Motif-специализированное поведение для оболочек кроме тех, которые окружают меню. Он отвечает за взаимодействие между приложением и MWM. VendorShell является суперклассом для других подклассов. TopLevelShell является Xt подклассом VendorShell который окружает виджеты верхнего уровня в приложении. ApplicationShell это другой Xt подкласс от VendorShell который окружает главный виджет в приложении.
Многие приложения создают только один ApplicationShell. Программа должна создать эту оболочку непосредственно или использовать удобную Xt подпрограмму XtAppInitialize для инициализации приложения и автоматического создания ApplicationShell. (От автора перевода: в версии X Window X11R6.3 введена более обобщенная подпрограмма инициализации приложения XtOpenApplication, а подпрограмма XtAppInitialize считается устаревшей.)
DialogShell является подклассом VendorShell который окружает диалоги. Поскольку менеджер окон учитывает обобенности диалогов, которые обычно являются временными; они обычно появляются для предоставления пользователю информации или запроса информации от пользователя, а затем они исчезают. DialogShell является подклассом от Xt класс TransientShell, который отслеживает приложение к которому отностися диалог. Пользователь не может свернуть диалог в иконку отдельно от главного окна приложения.
DialogShell разработан для содержания потомка который является подклассом от BulletinBoard. Большинство удобных подпрограмм Motif которые создают диалоги автоматически создают и DialogShell как предка.
MenuShell является классом оболочек, предназначенным для окружения PopupMenu (Всплывающих меню) и PulldownMenu (Выпадающих Меню). MenuShell является подклассом Xt класса XtOverrideShell. Этот класс позволяет оболочке обходить менеджер окон. Большинство удобных подпрограмм Mofit которые создают PopupMenus и PulldownMenus автоматически создают предка класса MenuShell.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 2. Модель программирования на Motif | . |
Примитивы, менеджеры и оболочки являются компонентами Motif предоставляемыми для построения интерфейса. Разработчик собирает эти компоненты в основные модули программы: диалоги, виджеты верхнего уровня и приложения.
Одним из подходов к этому конструированию является указание соединений между ядром приложения и интерфейсом пользователя. Разработчик определяет какую информацию необходимо получить приложению от пользователя и какую представить пользователю. Проводя такую оценку, разработчик определяет обобщенный интерфейс к приложению, а затем реализует Motif версию интерфейса использую удобные комбинации виджетов.
Другим подходом к разработке пользовательского интерфейса является постепенный спуск с уровня приложения к специфическим виджетам. Разработчик решает какими будут компоненты верхнего уровня приложения и как они будут связаны с другими компонентами. С этой точки зрения разработчик разрабатывает комбинации виджетов которые представляют приложение непосредственно пользователю и получает великолепную возможеность перехода с одной задачи на другую. Разработчик затем окончательно подгоняет визуальное представление интерфейса.
На практике разработчики любят использовать оба, как снизу-вверх, так и сверху-вниз, подхода на различных этапах разработки программы. Подходы сходятся на уровне приложения.
Приложение является высшим уровнем абстракции Motif программы. В одном смысле приложение включает в себя целую программу. В другом смысле приложением является первичный виджет программы. Пользователь может быть причиной появления других виджетов, но приложение является центром активности и обычно это первый появившийся виджет после запуска программы пользователем.
Виджетом, который представляет приложение обычно является MainWindow. Для большинства приложений необходимые операции должны быть доступны из Полосы Меню, находящейся вверху Главного Окна. Посредством просмотра Полосы Меню пользователь быстро определяет какие основные функции предоставляет приложение. Процедуры обратного вызова активации кнопок в меню которые выпадают из Полосы Меню инициируют выполнение операций в приложении. Руководство по стилю Motif содержит описание необходимых и рекомендуемых компонентах для заполнения Полосы Меню приложения и его Выпадающих Меню.
Главное Окно обычно содержит большую прокручиваемую рабочую область. Однокомпонентное приложение обычно производит большую часть своей работы используя эту область. Другие приложения могут потребовать более одной рабочей области.
ApplicationShell заключает главный виджет приложения. Разработчик должен использовать функцию Xt XtAppCreateShell для непосредственного создания ApplicationShell или дать Xt возможность самостоятельно создать оболочку в процессе вызова XtAppInitialize.
Обычно программа содержит только одно приложение, но иногда программа создает несколько логических приложений. В этом случае программа может иметь более одного главного окна, каждое из которых окружается различной ApplicationShell. Множественные ApplicationShell также необходимы для приложений которые используют несколько дисплеев.
Поскольку программы обычно не используют более одного логического приложения, в наиболее общем случае приложениям необходимо иметь несколько виджетов верхнего уровня. Например, программа обработки почты может состоять из компонента для чтения почты и другого компонента для ее составления и отправки.
Каждый важный компонент приложения может распологаться в виджете верхнего уровня. Каждый виджет верхнего уровня должен быть заключен в TopLevelShell или в ApplicationShell. Одним их подходов является наличие только одного ApplicationShell для приложения, для которого каждый TopLevelShell является всплывающим потомком от ApplicationShell. При этом программа не создает окна для ApplicationShell. Другой подход заключается в том, чтобы назначить один виджет верхнего уровня для приложения, заключенный в ApplicationShell, и сделать остальные TopLevelShell выпадающими потомками ApplicationShell. Выпадающий потомок это единственный чье окно является потомком корневого окна и чья геометрия не управляется его родительским виджетом.
Множественные виджеты верхнего уровня описаны более подробно в Главе 3.
Диалоги являются короткоживущими компонентами используемыми для отображения информации о текущем состоянии приложения или для получения специфичной информации от пользователя. Диалоговым виджетом обычно является BulletinBoard или один из его подклассов, заключенный в DialogShell. DialogShell является всплывающим потомков другого видета в иерархии. Его окно является дочерним к корневому окну, но пользователь не может свернуть диалог в иконку отдельно от главного приложения.
Диалог может быть модальным -- т.е. он может предотвращать другие части приложения от обработки ввода пока диалог активен. Также он может быть немодальным когда пользователь может взаимодействовать с остальным приложением пока диалог является видимым. Motif содержит удобные подпрограммы которые создают и диалоговые виджеты и DialogShell для различных видов информации.
Более подробно диалоги описываются в Главе 7.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 2. Модель программирования на Motif | . |
Виджет, класс виджетов и приложение в целом имеют набор атрибутов которые программа может проверять и которые пользователь и программа могут задавать. Эти атрибуты реализованы как X ресурсы. Xlib содержит механизм, называемый менеджером ресурсов X (Xrm - X resource manager) чьим назначением является управление и выполнение запросов к базе данных ресурсов. Xt и Motif построены на основе Xrm для получения репозитория общедоступных атрибутов виджетов также как и приложений.
Xt поддерживает базу данных ресурсов которые применяются на нескольких уровнях:
для приложению в целом
для дисплея на котором запущено приложение
для экрана на котором создана иерархия виджетов
для класса виджета
для индивидуального виджета
Пользователь может определять ресурсы на любом из этих уровней посредством файлов ресурсов или командной строки используемой для запуска программы. Приложение также может определять ресурсы посредством файлов ресурсов.
Каждое приложение имеет имя и класс; каждый виджет внутри приложения имеет имя и класс; и каждый ресурс имеет имя и класс. Когда значения ресурсов предоставляются в файле или командной строке, пользователь или приложение указывают область действия значения ресурса определением ресурса соответственно его имени или класса. Например пользователь может указать что все ресурсы класса Background должны иметь специфичное значение для всех виджетов; или пользователь может указать что только ресурсы имеющие имя background внутри некоторой иерархии именованных виджетов должны иметь специфичное значение. Механиз определения позволяет значениям ресурса быть указанными для любого уровня.
Большинство классов виджетов Motif определяют набор ресурсов, по имени и классу, которые применимы для этих классов. Подклассы наследуют ресурсы суперкласса, кроме случаев, когда подкласс переопределяет определение ресурса суперкласса. Класс виджетов также определяет значения по умолчанию для каждого ресурса, используемые в случае когда пользователь и приложение не предоставили другого значения.
Когда приложение запускается, Xt конструирует и инициализирует базу данных значений ресурсов. Эта база данных получается из комбинации файлов ресурсов пользователя и приложения и значений из командной строки. Некоторые ресурсы в базе данных могу иметь различные значения в зависимости от дисплея или экрана на котором приложение запущено. Когда приложение создает виджет, Xt использует начальную базу данных в комбинации со значениями ресурсов по умолчанию класса виджета для предоставления значений ресурсов создаваемого виджета. Приложение может перекрыть эти значения предоставлением аргументов подпрограмме которая создает виджет. Оно также может установить значения ресурсов после создания виджета используя Xt функцию XtSetValues
Установка ресурсов является первичным методом посредством которого приложение изменяет атрибуты виджета. Тем не менее, приложение должно стараться не переопределять определения пользователя для большого числа ресурсов управляющих такими характеристиками как визуальное представление и правила определения как виджет получает клавиатурный фокус. В общем, приложение должно устанавливать только те ресурсы, которые необходимы для правильного функционирования программы. Приложение должно указывать предпочтения для значений других ресурсов в файле умолчаний приложения. Xt читает этот файл когда приложение запускается, но пользователь может перекрыть значения указанные там.
Процесс создания начальной базы данных ресурсов более подробно обсуждается в Главе 3.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 2. Модель программирования на Motif | . |
X сервер направляет ввод клиенты посредством событий ввода, ассоциированных с окном. В простейшем случае, когда происходят события клавиатуры или указателя, X сервер посылает событие клиенту который явно выражает интерес в событиях этого типа в окне которое содержит указатель. Тем не менее, процесс обработки бывает и более сложным. Клиент может захватить кнопку указателя или клавишу клавиатуры, указатель или клавиатуру, или целиком сервер; клиент при этом принимает соответствующие события. Клиет может установить фокус ввода на некоторое окно, и X сервер затем передает события этому окну даже если указатель находится за пределами этого окна.
Для изоляции приложения от этих сложностей, Xt и Motif содержат средства для низкоуровневой обработки ввода пользователя в приложение:
Ресурс VendorShell, \textbl{XmNkeyboardFocusPolicy}, позволяет пользователю или приложению определять будет ли клавиатурные события доходить до виджета который содержит указатель или же виджета на котором пользователь нажал Btn1 (режим поведения "щелкни для ввода").
При использовании модели "щелкни для ввода", пользователь может также использовать клавиши для перемещения от виджета к виджету или от одной группы виджетов к другой.
Xt предоставляет базовый цикл диспетчеризации событий используемый большинством приложений. Xt берет события вне очереди приложения и распределяет их соответствующему виджету, обычно виджету который имеет фокус клавиатуры. Xt обычно вызывает процедуры действия связанные с определенными событиями посредством таблицы трансляции из спецификации события в процедуры действий. Процедура действия, когда выполняется, обычно вызывает список процедур обратного вызова.
Motif и Xt предоставляют мнемоники и ускорители, которые являются клавиши быстрого вызова для выполнения действий связанных с виджетом когда виджет не имеет фокуса ввода. Мнемоника это клавиатурный символ для клавиши которая активирует видимую кнопку меню. Ускоритель это описание события которое вызывает процедуры действия посредством таблицы трансляции.
Большинство приложений используют эти высокоуровневые интерфейсы, пременяя Xt и Motif для обработки ввода пользователя на низком уровне. Если приложение нуждается в большем контроле, оно может предоставить свой собственный обработчик событий, подпрограмму вызываемую из цикла диспетчеризации Xt когда виджет принимает событие указанного типа. Приложение также может предоставить собственный цикл диспетчеризации событий.
Вопросы ввода, фокуса и клавиатурной навигации обсуждаются более подробно в Главе 13.
Для большинства виджетов Xt и Motif самостоятельно производят обработку вывода. Например, в виджетах Label или Text, когда приложение изменяет отображаемый тектс, Motif автоматически перерисовывает содержимое виджета. Большинство виджетов имеют ресурсы которые управляют внешним видом вывода, таким как шрифт используемый при отображении текста.
Motif предоставляет виджет DrawingArea для приложений которые нуждаются в проведении графического вывода или большем контроле или гибкости при отображении текста. DrawingArea обсуждается более подробно в Главе 15.
Motif. Руководство программиста | ||
---|---|---|
. | . |
Motif использует такую же событийно-управляемую модель программирования как и X Toolkit Intrinsics. В своей основе, Motif приложение ожидает пока пользователь произведет ввод, обычно нажмет клавишу, переместит мышь или щелкнет кнопкой мыши. Подобные действия пользователя заставляют X сервер сгенерировать одно или более событий системы X Window. Xt ожидает эти события и диспетчеризирует их соответствующему Motif виджету, обычно это виджет, которому пользователь направляет свой ввод. Виджет может выполните некоторые действия в результате ввода пользователя.Если приложение запрашивает оповещение об этом действии, виджет вызывает приложение - другими словами, он инициирует выполнение процедуры обратного вызова приложения. Когда и Motif и приложение заканчивают отвечать на ввод пользователя, приложение продолжает ожидать дальнейшего ввода пользователя. Этот из цикл инициированных пользователем событий и ответа приложения, называемый циклом обработки событий, продолжается пока пользователь не остановит приложение.
В простых приложениях X Toolkit и Motif выполняют все необходимое для диспетчеризации ввода пользователя к виджетам. Приложение должно выполнить следующие действия:
Подключить все необходимые заголовочные файлы
Инициализировать X Toolkit Intrinsics
Создать один или более виджетов
Определить процедуры обратного вызова и привязать их к виджетам
Сделать виджеты видимыми
Войти в цикл обработки событий
Эта глава рассказывает о каждом из этих шагов. Последующая таблица обобщает эти шаги и некоторые их процедур, которые необходимо вызвать приложению. Обратите внимание, что некоторые из этих шагов отличаются когда приложение использует UIL и MRM. Смотрите главу 4 для дополнительной информации.
Таблица 3-1. Шаги при написании программы
Шаг | Описание | Соответствующие функции |
---|---|---|
1 | Подключить необходимые заголовочные файлы. | #include <Xm/Xm.h> #include <Xm/widget.h> или <Xm/XmAll.h> |
2 | Инициализировать X Toolkit Intrinsics. Выполнить шаги 3 и 4 для каждого виджета. | XtAppInitialize() |
3 | Создать виджет. | XtSetArg() XtCreateManagedWidget() или XtVaCreateManagedWidget() или XmCreate<WidgetName>() с последующим XtManageChild(widget) |
4 | Добавить процедуры обратного вызова. | XtAddCallback() |
5 | Реализовать виджеты. | XtRealizeWidget(parent) |
6 | Войти в цикл обработки событий. | XtAppMainLoop() |
Все Motif приложения должны подключать файл <Xm/Xm.h>. Этот файл содержит определения необходимые для любого приложения. Он также подключает заголовочные файлы Xt: <X11/Intrinsic.h> и <X11/StringDefs.h>.
Каждый Motif виджет также имеет заголовочный файл. Приложение должно подключать заголовочные файлы для всех создаваемых виджетов. Помимо этого некоторые группы подпрограмм Motif имеют собственные заголовочные файлы. Например, приложение, использующее любые подпрограмм буфера обмена Motif должны подключать файл <Xm/CutPaste.h>. Необходимые заголовочные файлы для каждого Motif виджета или подпрограммы описаны в Motif. Справочник программиста.
Далее следует пример, показывающий подключение заголовочных файлов для приложения, использующего только тектовый виджет.
#include <Xm/Xm.h> #include <Xm/Text.h> |
Вместо использования большого числа заголовочных файлов для конкретных виджетов и подпрограмм приложение может подключить файл <Xm/XmAll.h>. Этот файл объединяет все документированные заголовочные файлы Motif.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 3. Структура Motif программы | . |
Первая задача Motif приложения заключается в инициализации библиотеки компонентов. Большинство приложений выполняют инициализацию с помощью вызова подпрограммы XtAppInitialize. Эта удобная подпрограмма которая совмещает несколько шагов инициализации, каждый из которых приложение может выполнить самостоятельно посредством вызова специализированных подпрограмм Xt:
Инициализация внутренних структур библиотеки компонентов. Приложение может сделать это посредством вызова XtToolkitInitialize.
Создание контекста приложения. Xt использует эту конструкцию для хранения информации связанной с каждым экземпляром приложения. Его назначение - обеспечение возможности запуска нескольких экземпляров приложения в едином адресном пространстве. Большинству приложений требуется только создать контекст приложения и передавать его подпрограммам, которые требуют его указания в качестве параметра. Для контекста приложения используется тип данных XtAppContext. Приложение может самостоятельно создать контекст приложения посредством явного вызова подпрограммы XtCreateApplicationContext.
Открыть соединение с дисплеем и привязать его к контексту приложения. Когда приложение использует XtAppInitialize, спецификация дисплея извлекается из командной строки вызванного приложения или из окружения пользователя. После открытия дисплея Xt строит базу данных ресурсов используя для ее построения значения ресурсов по умолчанию и параметры командной строки вызванного приложения. Процесс создания этой базы данных подробнее описан в следующем разделе. Приложение может выполнить эти шаги непосредственным вызовом подпрограммы XtOpenDisplay. Елси же приложение уже имеет дисплей, открытый посредством XOpenDisplay, то оно может привязать дисплей к контексту приложения и построить начальную базу данных ресурсов посредством вызова XtDisplayInitialize.
Создать видгет оболочки верхнего уровня для приложения. XtAppInitialize создает оболочку приложения (ApplicationShell) и возвращает ее в качестве своего результата. Приложение может создать оболочку верхнего уровня посредством вызова подпрограммы XtAppCreateShell.
Пример 3-1. Этот пример простого вызова XtAppInitialize:
int main (int args, char **argv) { Widget app_shell; XtAppContext app; app_shell = XtAppInitialize (&app, "Example", (XrmOptionDescList) NULL, 0, &argc, argv, (String *) NULL, (ArgList) NULL, 0); } |
Подпрограмма XtDisplayInitialize строит начальную базу данных ресурсов для приложения. Приложению редко требуется производить непосредственный вызов этой подпрограммы; она вызывается из XtOpenDisplay, которая вызывается из XtAppInitialize.
XtDisplayInitialize строит отдельную базу данных ресурсов для каждого дисплейного соединения. Начальная база данных ресурсов комбинирует значения ресурсов полученные из командной строки, дисплея, файла умолчаний класса приложения и файлов умолчаний пользователя, которые могут быть специализированы соответственно для приложения или для компьютера на котором приложение запущено. Значения по умолчанию для класса приложения и пользовательские значения по умолчанию для каждого приложения могут быть еще более специализированны в соответствии с используемым естественным языком и, возможно, в соответствии с ресурсом предпочтений общего назначения. Ресурсы в начальной базе данных могут быть заданы для конкретного виджета или класса виджетов, а также и для приложения в целом. Когда приложение создает виджеты значения, указанные в базе данных, чаще всего являются исходными для начальных значений ресурсов виджета.
В оставшейся части этого раздела описавается последовательность в которой XtDisplayInitialize загружает каждый компонент базы данных и как она определяет расположение этого компонента.
В процессе загрузки значений по умолчанию класса приложения и пользовательских умолчаний для приложения XtDisplayInitialize вызывает XtResolvePathname для определения файлов, которые необходимо прочитать. XtResolvePathname использует пути поиска файлов. Каждый путь является набором шаблонов, которые могут содержать специальные последовательности символов вместо которых при поиске файлов XtResolvePathname подставляет значения времени исполнения. Она использует следующие подстановки при построении пути:
%N заменяется на имя класса приложения, определенное аргументом application_class при вызове XtAppInitialize, XtOpenDisplay или XtDisplayInitialize.
%C заменяется на значение ресурса предпочтений.
%L заменяется на спецификацию используемого для дисплея естественного языка. Она может быть взята из ресурса xnlLanguage, локализации приложения или соответствующей процедуры обратного вызова приложения. Смотрите главу 11 для получения более подробной информации. Формат спецификации языка зависит от реализации, она может содержать компоненты языка, территории и набора знаков.
%l заменяется на компоненту языка из спецификации языка.
%t заменяется на компоненту территории из спецификации языка.
%c заменяется на компоненту набора символов из спецификации языка.
%% заменяется на %.
Если спецификация языка не задана или одна из компонент спецификации отсутствует, соответствующий элемент заменяется на NULL.
Пути состоят из последовательности елементов, разделенных двоеточиями. Каждый элемент рассматривается как имя файла. Элементы просматриваются слева на право пока один из них не укажет на существующий файл. Перед просмотром производятся подстановки.
![]() | Xt использует соглашение X/Open по слиянию нескольких подряд идущих символов '/' в единственный символ '/'. |
Функция XtDisplayInitialize загружает базу данных ресурсов слиянием ресурсов из следующих источников в порядке превосходства (т.е. каждый компонент имеет превосходство перед последующими компонентами):
Командная строка приложения.
Специфичный для компьютера файл ресурсов окружения пользователя на локальном компьютере.
Специфичные для экрана ресурсы для экрана по умолчания на дисплее.
Свойство ресурсов сервера или ресурсный файл предпочтений пользователя на локальном компьютере.
Специфичный для приложения ресурсный файл пользователя на локальном компьютере.
Специфичный для класса приложения ресурсный файл на локальном компьютере.
XtDisplayInitialize вызывает функцию XrmParseCommand менеджера ресурсов X для извлечения значений ресурсов из командной строки посредством которой пользователь запустил приложение. Аргументы командной строки и их количество передаются посредством параметров argv и argc в подрограммы XtAppInitialize, XtOpenDisplay или XtDisplayInitialize. Xt поддерживает стандартный набор аргументов командной строки, таких как -background и -geometry, для задания значений ресурсам. Приложение может указать дополнительные аргументы в параметрах подпрограмм XtAppInitialize, XtOpenDisplay или XtDisplayInitialize. Пользователь может применять аргумент -xrm для установки любого ресурса в базе данных.
Для загрузки специфичных для компьютера ресурсов окружения пользователя XtDisplayInitialize использует имя файла определенное переменной окружения XENVIRONMENT. Если XENVIRONMENT не определена, то XtDisplayInitialize ищет файл $HOME/.Xdefaults-host, где host имя компьютера, на котором запущено приложение (т.е. имя компьютера клиента, а не сервера).
Для загрузки специфичных для экрана ресурсов XtDisplayInitialize просматривает свойство SCREEN_RESOURCES у корневого окна на экране по умолчанию дисплея. Свойство SCREEN_RESOURCES обычно является результатом выполнения команды xrdb когда некоторые ресурсы не задаются для всех экранов.
![]() | Когда Xt требуется получить ресурсы для экрана отличного от используемого по умолчанию на дисплее, например, если приложение создает виджет на другом экране, он использует свойство SCREEN_RESOURCES этого экрана вместо свойства SCREEN_RESOURCES экрана по умолчанию. |
Для загрузки свойства ресурсов сервера или файла ресурсов предпочтений пользователя XtDisplayInitialize просматривает свойство RESOURCE_MANAGER у корневого окна экрана 0 на дисплее. Свойство RESOURCE_MANAGER обычно является результатом выполнения команды xrdb когда некоторые ресурсы задаются для всех экранов. Если это свойство не существует, то XtDisplayInitialize просматривает файл $HOME/.Xdefaults.
Для загрузки пользовательского файла ресурсов приложения XtDisplayInitialize выполняет следующие шаги:
Использует XUSERFILESEARCHPATH для поиска файла, выполняя необходимые подстановки.
Если это не дает результата или же XUSERFILESEARCHPATH не определена и определена XAPPLRESDIR использует зависимый от реализации путь, содержащий по меньшей мере семь элементов, в следующем порядке и с следующими префиксами директорий и подстановками:
$XAPPLRESDIR с %C, %N, %L или с %C, %N, %l, %t, %c
$XAPPLRESDIR с %C, %N, %l
$XAPPLRESDIR с %C, %N
$XAPPLRESDIR с %N, %L или с %N, %l, %t, %c
$XAPPLRESDIR с %N, %l
$XAPPLRESDIR с %N
$HOME с %N
Если XAPPLRESDIR не определена используется определяемые реализацией пути поиска, содержащие по крайней мере шесть элементов в следующей последовательности и со следующими каталогами и подстановками:
$HOME с %C, %N, %L или с %C, %N, %l, %t, %c
$HOME с %C, %N, %l
$HOME с %C, %N
$HOME с %N, %L или с %N, %l, %t, %c
$HOME с %N, %l
$HOME с %N
Для загрузки специфичного для класса приложения файла ресурсов XtDisplayInitialize производит необходимые подстановки в путях определенных переменной окружения XFILESEARCHPATH. Если это не дает результата или XFILESEARCHPATH не определена XtDisplayInitialize использует определяемый реализацией путь поиска, содержащий по крайней мере шесть элементов в следующем порядке и с необходимыми подстановками:
%C, %N, %S, %T, %L или %C, %N, %S, %T, %l, %t, %c
%C, %N, %S, %T, %l
%C, %N, %S, %T
%N, %S, %T, %L или %N, %S, %T, %l, %t, %c
%N, %S, %T, %l
%N, %S, %T
Если специфичный для класса приложения файл ресурсов не найдет, то XtDisplayInitialize просматривает ресурсы отката, которые могут быть заданы при вызове XtAppInitialize или XtAppSetFallbackResources.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 3. Структура Motif программы | . |
Виджет верхнего уровня возвращаемый 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} вместо имени ресурса в списке аргументов. Вмесо значения ресурса приложение указывает четыре аргумента:
Имя ресурса
Строку представляющую тип указываемого значения
Собственно значение (типа XtArgVal)
Целое число представляющее количество байт в значении
Например, следующий вызов производит преобразование предоставленной строки в композитную строку которую 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 | Список табуляций |
Motif. Руководство программиста | ||
---|---|---|
. | Глава 3. Структура Motif программы | . |
Процедуры обратного вызова являются сердцем Motif приложения. Многие классы виджетов имеют ресурсы чьим значением являются списки процедур обратного вызова. Когда пользователь действует на виджет, например, нажимает кнопку PushButton, Motif вызывает процедуры обратного вызова в соответствующем списке. Если приложению необходимо выполнить некоторые действия когда пользователь нажимает кнопку PushButton, оно предоставляет процедуру обратного вызова и добавляет ее в соответствующий список процедур обратного вызова.
Процедуры обратного вызова не единственное средство, которое использует Motif для оповещения приложения о действиях пользователя. Приложение может также поддерживать собственные процедуры действий и обработчики сообщений. Основным отличием между этими видами процедур является уровень абстракции на котором Motif и Xt вызывает процедуры:
Диспетчер событий Xt вызывает обработчик событий всякий раз когда событие некоторого типа возникает в указанном виджете.
Менеджер трансляции Xt вызывает процедуры действий когда последовательность событий совпадает со спецификацией событий в таблице трансляции виджета.
Motif виджет вызывает процедуры обратного вызова когда ввод пользователя означает действие которое выражает виджет, типа активации кнопки PushButton. Очень часто виджет вызывает процедуры обратного вызова из процедур действий. Необязательно только одно действие может вызвать один и тот-же список процедур обратного вызова.
Многие Motif приложения используют только процедуры обратного вызова. Процедуры действий и обработчики событий описываются в главе 13.
Каждая процедура обратного вызова является функцией типа XtCallbackProc. Процедуры принимают три аргумента: виджет и два указателя на данные. Превый указатель является данными которые приложение указало виджету передавать обратно приложению когда вызывается процедура обратного вызова. Второй указатель используется для передачи виджетом данных всем процедурам в списке. Процедуры обратного вызова не возвращают значения.
Аргумент данных приложения предназначен в первую очередь для передачи данных, которые приложение поддерживает отдельно от самого виджета. Аргумент данных виджета для большинства Motif виджетов является указателем на структуру, содержащую которая зависит от класса виджета. Например, когда пользователь изменяет значение кнопки ToggleButton, Motif вызывает процедуры обратного вызова с указателем на структуру типа XmToggleButtonCallbackStruct в качестве третьего аргумента. Эта структура содержит три поля:
Целое число обозначающее причину вызова процедуры обратного вызова. Когда пользователь изменил значение причина будет \const{XmCR_VALUE_CHANGED}. Обычно причины обозначаются именами, начинающимися с символов bold{XmCR}.
Указатель типа XEvent на событие которое послужило причиной вызова процедуры.
Целое число которое обозначает новое состояние кнопки ToggleButton, т.е. выбрана или не выбрана.
Документация на каждый виджет в Motif. Справочник программиста описывает все структуры, которые виджет передает процедурам обратного вызова как данные виджета. Имейте в виду, что процедуры обратного вызова могут изменить значения некоторых полей этих структур. Поскольку порядок вызова процедур в списке процедур обратного вызова не определена, приложение которое использует несколько процедур обратного вызова в одном списке должно соблюдать осторожность при изменении этих значений.
Ниже приводится простейшая процедура обратного вызова, которую приложение использует для изменения состояния клапана когда пользователь изменяет значение кнопки ToggleButton. Данные приложения передаваемые процедуре в этом примере должны быть указателем на объект кланана связянного с кнопкой ToggleButton:
void ToggleValueChangedCB(Widget toggle, XtPointer app_data, XtPointer widget_data) { Valve *valve_p = (Valve *) app_data; XmToggleButtonCallbackStruct *toggle_info = (XmToggleButtonCallbackStruct *) widget_data; ChangeValveState(*valve_p, ((Boolean) toggle_info->set == TRUE) ? VALVE_ON : VALVE_OFF); } |
Для регистрации процедуры обратного вызова у виджета, приложение использует XtAddCallback или XtAddCallbacks после определения процедуры обратного вызова и создания виджета. Следующий фрагмент кода создает кнопку ToggleButton для каждого клапана из глобального списка клапанов:
... char name[20]; Widget toggles[N_VALVES]; int i; Valve *valve_p; for(i = 0; valve_p = valves; i < N_VALVES; i++, valve_p++) { sprintf(name, "valve_state_%d", i); toggles[i] = XmCreateToggleButton(parent, name, (ArgList) NULL, 0); XtAddCallback(toggles[i], XmNvalueChangedCallback, (XtCallbackProc) ToggleValueChangedCB, (XtPointer) valve_p); } |
Для удаления процедур обратного вызова из списков процедур обратного вызова исползуются XtRemoveCallback или XtRemoveCallbacks. Поскольку Motif иногда добавляет списки процедур обратного вызова собственные процедуры, не исльзуйте XtRemoveAllCallbacks для удаления всех процедур из списка.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 3. Структура Motif программы | . |
Создание виджетов само по себе не делает виджет видимым. Виджет становится видимым когда выполняются следующие условия:
Виджет и его родители взяты на управление. Виджет взят на управление когда менеджеры геометрии Xt и Motif получают формуляр виджета при проведении расчета положения и размера виджетов на дисплее.
Виджет и его родители реализованы. Виджет считается релизованным когда он имеет связанное с ним окно.
Виджет и его родители отображены. Виджет является отображенными когда его окно отображено на экране.
Приложение может брать на управление, реализовывать и отображать виджеты отдельными шагами, но каждое из этих действий влияет на другие.
Родительские виджеты являются ответственными за геометрию своих потомков. Потомок может спросить своего родителя принять данные размеры и позицию, а родитель примет решение разрешить или нет этот запрос. Родитель может переместить или изменить размер дочернего окна без разрешения потомка. Поцесс посредством которого родитель и потомок взаимодействуют с целью определения геометрии виджета описывается в главе 14.
Приложение указывает виджету взять на управление геометрию дочерних виджетов посредством вызова XtManageChild или XtManageChildren. Если родительский виджет реализован, то XtManageChild вызывает процедуру change_managed родительского виджета. Эта процедура может изменить размер или положение любого потомка родительского виджета. После вызова процедуры change_managed родительского виджета XtManageChild проводит реализацию потомка и, если ресурс \textbl{XmNmappedWhenManaged} потомка установлен в True, то и отображает его.
Если родительский виджет не реализован, то XtManageChild отмечает, что потомок взят на управление. Xt откладывает вызов процедуры change_managed родительского виджета пока родительский виджет не будет реализован.
Когда берется на управление более одного потомка реализованного родительского виджета приложению более выгодно вызвать XtManageChildren вместо отдельного вызова XtManageChild для каждого отдаваемого на управление виджета. Расположение виджетов может потребовать значительных расчетов, а XtManageChild вызывает процедуру change_managed каждый раз когда вызывается. XtManageChildren вызывает процедуру change_managed только один раз для всех потомков взятых на управление.
Приложение указывает виджету не производить управление геометрией дочерних виджетов посредством вызова XtUnmanageChild или XtUnmanageChildren. С помощью взятия на управление и снятия с управления виджетов приложение может альтернативно отображать более одного набора потомков без применения процедур создания и уничтожения виджетов каждый раз когда изменяется конфигурация приложения. Дополнительно, взятие на управление диалогов и всплывающих меню заставляет виджет появиться на экране, а снятие с управление заставляет исчезнуть с экрана.
Для создания виджета и взятия его на управление в одном вызове приложение может использовать XtCreateManagedWidget или XtVaCreateManagedWidget. Подпрограммы Motif создающие виджеты определенного класса всегда возвращают не взятые на управление виджеты. Когда используются эти подпрограммы приложение должно самостоятельно отдать на управление виджеты используя XtManageChild или XtManageChildren.
Приложение использует XtRealizeWidget для реализации виджета. Эта подпрограмма делает следующее:
В пост-порядке обходит дерево виджетов, чиьм корнем является виджет и вызывает процедуру change_managed класса для каждого виджета в дереве имеющего взятые на управление потомки.
Рекурсивно обходит дерево корнем является виджет и вызывает процедуру realize класса для каждого виджета в дереве который взят на управление. Процедура realize создает окна виджетов.
Отображает вятые на управление потомки виджета у которых \textbl{XmNmappedWhenManaged} установлен в True. Если виджет является виджетом верхнего уровня и ресурс \textbl{XmNmappedWhenManaged} установлен в True, то XtRealizeWidget отображает его.
Имейте в виду следующие:
Согласование геометрии производится снизу вверх, тогда как создание окон производится сверху вниз.
После того, как виджет реализован все его взятые на управление потомки реализованы и, по умолчанию, отображены.
Если в дереве нет реализованных виджетов, то все согласование геометрии между родителями и их взятыми на управление потомками будет проведено перед реализацией любого виджета.
Когда дерево виджетов делается видимым первый раз приложение должно обычно взять на управление все виджеты, а затем реализовать только виджет верхнего уровня. Это приводит к тому, что все начальные размеры и положения потомков и общий размер окна верхнего уровня будет определены пока не существует никаких окон, что уменьшит взаимодействие с X сервером. Это также позволяет приложению реализовать все виджеты одним вызовом XtRealizeWidget.
Большинство приложение не производят непосредственного отображения и снятия с отображения окон виджетов. Отображение обычно имеет место как часть процесс взятия на управление или реализации виджетов. Но имеется возможность предохранить Xt от отображения окон в это время установкой ресурса \textbl{XmNmannedWhenManaged} в False. В этом случае приложение должно непосредственно использовать XtMapWidget для отображения виджета. Приложение может использовать XtUnmapWidget для отмены отображения виджета.
Эффект от взятия виджета на управление с отмененным отображением отличен от снятия виджета с управления. Когда виджет снят с управления его родитель не получает его формуляр при расположении своих потомков. Когда виджет взят на управнение его родитель сохраняет место для расположения виджета. Когда родитель отображен место, выделенное для управляемого, но неотображенного потомка заполняется фоном родительского окна, а не фоном окна потомка.
Приложение может быть запущено более чем на одном экране. В этом случае оно должно использовать XOpenDisplay для установления соединения с каждым дисплем и должно затем выполнить XtDisplayInitlaize отдельно для каждого соединения. Ему необходимо создать собственный контекст приложения для каждого дисплея.
![]() | XtDisplayInitialize изменяет аргументы argv и argv. Если приложению необходимо вызвать XtDisplayInitialize более чем один раз оно должно сохранить эти аргументы перед первым вызовом и использовать копию сохраненных аргументов для каждого вызова. |
Приложение должно использовать XtAppCreateShell для создания хотябы одного виджета верхнего уровня на каждом дисплее на котором производится запуск. Поскольку Xt поддерживает раздельные базы данных ресурсов для каждого дисплея, то дочерний виджет, запущенный на дисплее, отличном от того на котором запущен родительский виджет, будет использовать некорректные начальные значения ресурсов.
Приложение также может быть запущено более чем на одном экране дисплея. Т.к. приложение открывает и инициализирует дисплей только единожды, то не имеет значения насколько много экранов оно использует на дисплее. Тем не менее, приложению также необходим виджет на каждом экране, чье окно является потомком корневого окна этого экрана для использования виджета как корня иерархии виджетов на этом экране.
Одним из подходов к использованию нескольких экранов является создание единственной нереализованной оболочки ApplicationShell для дисплея. Приложение затем создает одну оболочку TopLevelShell для каждого экрана как всплывающего потомка от ApplicationShell. Поскольку оболочка способна нормально содержать только один управляемый виджет, она может иметь более чем одного всплывающего потомка. Приложение использует XtAppCreateShell для создания оболочки ApplicationShell и XtCreatePopupShell для создания каждой оболочки TopLevelShell. Если не указывать экран для ApplicationShell, то XtAppCreateShell установит в ресурсе \textbl{XmNscreen} этого виджета экран по умолчанию на дисплее. В списке параметров передаваемом в XtCreatPopupShell приложение должно указать соответствующее значение для ресурса \textbl{XmNscreen} для каждой оболочки TopLevelShell чтобы эта оболочка создается на необходимом экране.
Приложение не должно брать на управление оболочки TopLevelShell. Для реализации и отображения этих оболочек приложение должно использовать XtPopup с аргументом grab_kind установленным в \textbl{XtGrabNone}.
int main(int argc, char **argv) { Widget app_shell, top_shell; XtAppContext app; Display *display; char name[20]; Arg args[5]; Cardinal n; int i; app_shell = XtAppInitialize(&app, "Example", (XrmOptionDescList) NULL, 0, &argc, argv, (String *) NULL, (ARGList) NULL, 0); display = XtDisplay(app_shell); for (I = 0; i < ScreenCount(display); i++) { sprintf(name, "top_shell_%d", i); n = 0; XtSetArg(args[n], XmNscreen, ScreenOfDisplay(display, i)); n++; top_shell = XtCreatePopupShell(name, topLevelShellWidgetClass, app_shell, args, n); /* создание и взятие на управление потомков оболочки */ ... /* реализация и отображение оболочки */ XtPopup(top_shell, XtGrabNone); } ... } |
Пограмма может иметь несколько логических приложений на одном экране. В этом случае она использует XtAppCreateShell для создания различных виджетов верхнего уровня для каждого логического приложения.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 3. Структура Motif программы | . |
Последним шагом Motif приложения является вход в цикл обработки событий. Большинство приложений просто вызывают XtAppMainLoop. Эта подпрограмма ождает ввода пользователя и диспетчеризирует результирующие события соответствующим процедурам обработки событий, обычно для виджета в котором произведен этот ввод. XtAppMainLoop является бесконечным циклом, управление из него никогда не возвращается. Приложение должно предоставить пользователю возможность выполнить действие чтобы остановить программу и должно завершить свою работу в результате этого действия, обычно в процедуре обратного вызова.
Motif. Руководство программиста | ||
---|---|---|
. | Глава 3. Структура Motif программы | . |
Для написание многонитевых Motif приложений требуется знание следующих вопросов:
Общих принципов параллельного программирования.
Специфичных интерфейсов нитей.
Новых интерфейсов в X11R6 для многонитевых приложений.
Существует два пути реализации параллельности программы: посредством двух и более процессов или же двух и более нитей. Первый подход известен как многопроцессность, а последний как многонитевость. Существует две основных причины выбора многонитевости а не многопроцессности: многопроцессность требует дорогостоящего межпроцессного взаимодействия, когда различные нити могут непосредственно совместно использовать данные. В сравнении с созданием процесса и переключением контекста процесса, создание нити и переключение контекста нити являются недорогиим операциями.
Motif приложение основано на парадигме в которой приложение работает в бесконечном цикле, проверяя наличие ввода и диспетчеризируя ввод в соответствующие места. Ввод состоит из событий X, поступающих от сервера дисплея, ввода из альтернативных источников ввода и значений таймаутов. Код цикла обработки ввода выглядит приблизительно таким образом:
while(TRUE) { XEvent event; XtAppNextEvent(app, &event); XtDispatchEvent(&event); } |
app ссылается на контекст Motif приложения. XtAppNextEvent удаляет и возвращает событие из вершины очереди событий X. Если очередь бобытий X пуста, то XtAppNextEvent ожидает поступления события X, между тем просматривая альтернативные источники ввода и значения таймаутов и вызывая все процедуры обратного вызова активированные ими. После возврата из XtAppNextEvent XtDispatchEvent диспетчеризирует событие X в соответствующее место. Диспетчеризация событий X обычно инициирует вызов некоторых обработчиков событий, процедур действий, процедур обратного вызова ввода и таймеров, совместно называемых "процедурами обратного вызова".
Обычно каждое Motif приложение выполняет свою работу в процедурах обратного вызова. Если работа, выполняемая в процедуре обратного вызова требует длительного времени (и невидима), обработка следующего события в очереди событий X может быть заметно задержана, являясь причиной ухудшения отзывчивости приложения. Многонитевость может помочь преодолеть задержки в процессе обработки событий X и таким образом облегчить проблемму плохой отзывчивости (или интерактивности).
Тем не менее, это не единственная мотивация. Другие состоят в более "естественной" структуре программы присущей параллельному Motif приложению и лучшей производительности такого Motif приложения на многопроцессорных машинах (или на конфигурациях из нескольких машин).
Motif очень тесно связан с X Toolkit. Интерфейсы X11R6 для многонитевых приложений требуются только если многонитевое приложение вызывает интерфейсы Motif/Xt из нескольких нитей. Вполне возможно написать многопоточное Motif приложение в котором интерфейсы Motif/Xt вызываются только из одной нити. В таких приложениях этот интерфейс может не потребоваться. В дополнение к этому интерфейсу X11R6 определяет функции и типы двнных, используемые в многонитевой программе, в файле X11/Xthreads.h. Поскольку нитевый интерфейс зависит от операционной системы, подключение этого файла вместо специфичного для системы файла улучшает переносимость.
Motif приложение которое создает несколько нитей должно произвести вызов XtToolkitThreadInitialize, которая инициализирует Xt для использования в нескольких нитях. XtToolkitThreadInitialize возвращает True если данный Xt поддерживает многопоточность, а иначе возвращает False.
XtToolkitThreadInitialize может быть вызван перед или после XtToolkitInitialize и может вызываться более чем один раз. Тем не менее, он не может быть вызван параллельно из нескольких нитей. Приложение должно вызвать XtToolkitThreadInitialize перед вызовом XtAppInitialize, XtSetLanguageProc, XtOpenApplication или XtCreateApplicationContext.
Параллельность в Motif приложении может быть запрограммирована с использованием модели в которой каждый контекст приложения имеет одну нить. Это означает, что каждый цикл обработки событий в каждом контексте приложения модет работать независимо внутри собственной нити. Это важно в смысле сохранения данных и обработки событий внутри каждого контекста приложения от случайного разрушения.
Для блокировки и разблокировки контекста приложения, всех виджетов и дисплейного соединения приложение должно использовать XtAppLock и XtAppUnlock.
Все функции Motif и Xt, которые принимают контекст приложения, виджет или дисплейное соединение как параметр, непосредственно блокируют связанный с ними контекст приложения на протяжении выполнения функции. Таким образом, за вычетом нескольких исключений, приложению нет необходимости вызывать XtAppLock или XtAppUnlock. Первым исключением является ситуация в которой приложению необходимо атомарно выполнить некоторую последовательность вызовов функций Xt. В этой ситуации приложение должно заключить последовательность вызовов Xt в соответствующую пару из XtAppLock и XtAppUnlock. Например, если приложению хочет атомарно проверить и обнивить высоту виджета, оно должно сделать это следующим образом:
XtAppContext app; Dimension ht = 0; Widget w; ... XtAppLock(app); XtVaGetValues(w, XtNheight, &ht, NULL); if((int)ht < 10) { ht += 10; XtVaSetValues(w, XtNheight, ht, NULL); } XtAppUnlock(app); |
Другим исключением являются ресурсы, которые возвращаются как реальные сегменты памяти внутри экземпляра виджета. Примером таковых являются:
\textbl{XmNchildren}: возвращает указатель на соответствующее поле Composite.
\textbl{XmNselectedItems}: возвращает указатель на соответствующее поле List.
\textbl{XmNsource}: возвращает указатель на соответствующее поле Text.
В этих случаях приложение также должно окружать вызов XtGetValues вызовом XtAppLock и XtAppUnlock, чтобы другая нить выполняющаяся на том же экземпляре виджета не смогла изменить значение ресурса. Приложению также необходимо сделать копию извлеченного ресурса.
Для предоставления полностью эксклюзивного доступа к глобальным структурам приложение должно использовать XtProcessLock и XtProcessUnlock.
Как XtAppLock так и XtProcessLock могут быть вызваны рекурсивно. Для разблокирования верхнего уровня XtAppUnlock и XtProcessUnlock должны быть вызваны такое же количество раз как и XtAppLock и XtProcessUnlock соответственно. Для одновременной блокировки контекста приложения и глобальных данных Xt сначала вызывается XtAppLock, а затем XtProcessLock. Для разблокировки сначала вызывается XtProcessUnlock, а затем XtAppUnlock. Порядок вызова очень важен для предотвращения взаимоблокировок.
Как мы мжем видеть подпрограмма XtAppMainLoop в X11R5 является бесконечным циклом который вызывает XtAppNextEvent, а затем XtDispatchEvent. В многопоточно-безопасном Xt бесконечный цикл в XtAppMainLoop должет предохранять нить обработки ввода от выхода из XtAppMainLoop без одновременного выхода из самой нити. Эта ситуация может привести к следующим проблеммам:
Потерям памяти.
"Повисшим" нитям.
Усложнению синхронизации между нитью обработки ввода и другими нитями.
Для решения этих проблемм Xt версии X11R6 преобразовал XtAppMainLoop. Он стал условным циклом, который вызывает XtAppNextEvent, а затем XtDispatchEvent, но теперь после каждого цикла обработки производит проверку не завершило-ли приложение работу с помощью нового флага выхода в контексте приложения. Если флаг выхода установлен в True, то XtAppMainLoop выходит из цикла обработки ввода. Следующий пример показывает реализацию новой XtAppMainLoop:
XtAppContext app; do { XEvent event; XtAppNextEvent(app, &event); XtDispatchEvent(&event); } while(XtAppGetExitFlag(app) == FALSE); |
Флаг выхода в контексте приложения может быть установлен в True посредством вызова XtAppSetExitFlag. Значение флага выхода может быть получено посредством XtAppGetExitFlag. Новая XtAppMainLoop предоставляет эффективный способ уничтожения контекста приложения без необходимости выхода из нити обработки ввода.
В многонитевых Motif приложениях рекомендуется следующий способ уничтожения контекста приложения: после того как нить обработки ввода выходит из XtAppMainLoop и после того как она определяет, что никакая другая нить не ссылается на соответствующий контекст приложения, она вызывает XtDestroyApplicationContext. Используйте XtAppGetExitFlag для синхронизации между нитью обработки ввода и другити нитями. Вызывайте XtAppSetExitFlag в процедуре обратного вызова, ответственной за выход из приложения. Это заставляет соответствующий XtAppMainLoop вернуть управление, но не завершает нить обработки ввода.
Когда несколько нитей параллельно вызывают функции обработки сообщений, они возвращаются в порядке "последним вошел первым вышел". По другому это выглядит так: если несколько нитей заблокированы для ввода на любой из процедур обработки событий, они помещаются в стек блокированных нитей контекста приложения. Когда же происходит какой-либо ввод, нить извлекается из стека и ей дается возможность обработать ввод.
Например, предположим, что нить A, являющаяся нитью обработки ввода, блокированна для ввода в XtAppMainLoop, т.е. она находится в стеке блокированных нитей контекста приложения. Предположим также, что одна из других нитей, нить B, обнаружила некоторую ошибочную ситуацию и приняла решение отобразить окно сообщения и временно забрать обработку ввода у нити A. Т.к. блокированные нити помещаются в стек, это позволяет нити B достаточно просто перехватить у нити A обработку ввода на себя. Способ, которым нить B делает это заключается в выполнении некторого подобия цикла обработки ввода внутри соответствующей пары XtAppLock и XtAppUnlock как показано ниже:
/* этот код выполняется нитью, отличной от нити обработки ввода */ XtAppContext app; Widget error_dialog; XEvent event; XtAppLock(app); /* Блокировка контекста приложения */ XtPopup(error_dialog, XtGrabExclusive); /* отображение диалога ошибки */ do { /* собственная обработка ввода */ XtAppNextEvent(app, &:event); if(/* некторое условие вызванное событием */) XtDispatchEvent(&event); } while (/* некоторое условие */); XtAppUnlock(app); |
Поскольку нить B вошла в XtAppNextEvent после того, как это сделала нить A, то нить B будет помещена в стек сверху нити A. Впоследствии, когда произойдет ввод, нить B будет извлечена из стека и произведет обработку ввода.
Motif. Руководство программиста | ||
---|---|---|
. |
Композитные строки являются самым простым способом хранения текста независимо от шрифта или цвета, используемого при его отображении. Сопоставляя закодированный текст с одним из элементов таблицы "визуального воспроизведения", Motif предоставляет программисту большую гибкость в отображении текстовой информации. Например, используя визуальные воспроизведения из файла ресурсов, программист может создать одно приложения которое может быть использовано в различных странах без перекомпиляции. Motif использует композитные строки для отображения любого текста, за исключением виджетов Text и TextField.
Эта глава описывает структуру композитные строк и ее компоненты. Обсуждаются типы данных, связанные с композитными строками, а также рассматриваются функции создания, изменения и обработки этих строк. Поскольку эта глава является только введением, в ней не дано полное описание этих типов данных и функций. Полное описание каждой функции и типа данных Вы можете найти в Motif. Справочник программиста.
. | ||
Написание многонитевых приложений |