Obx/Docu/ru/Buttons.odc

Описание системы примерами: ObxButtons

Данный пример демонстрирует, как могут быть реализованы новые элементы управления (controls). Элемент управления - визуальный объект, позволяющий управлять поведением некоторой другой части программы. Примерами элементов управления могут быть кнопки, ползунки (sliders), флажки (check boxes) и т.п. В отличие от полностью готовых редакторов, элемент управления имеет смысл только во взаимодействии со своим контейнером и другими элементами управления, которые находятся с ним в одном контейнере. В Блэкюоксе элемент управления является специализированным отображением (view). Блэкбокс поддерживает стандартный набор наиболее важных элементов управления, другие могут быть реализованы самостоятельно. Данный текст описывает пример реализации простейшей кнопки.

Наш пример элемента управления имеет 4 свойства: шрифт, цвет, связь и метка. Связь используется большинством элементов управления Блэкбокса для связи с определёнными элементами программы. В нашем случае этот элемент программы - команда Компонентного Паскаля, т.е. экспортированная процедура. Метка - строка, отображаемая на кнопке.

Свойства элементов управления могут быть просмотрены и изменены с помощью инспектора свойств (модуль DevInspector ). Чтобы его опробовать, выберите элемент управления, затем выберите команду Свойства... в подменю Объект меню Правка (Windows) либо команду Part Info в меню Edit (Mac OS).

Что мы должны реализовать, чтобы заставить работать этот элемент управления? В оставшейся части текста мы пройдёмся по различным аспектам реализации элемента управления, представленной в соответствующем листинге. Мы рассмотрим все процедуры, которые должны быть реализованы для работы контроллера. Как обычно в объектно- и компонентно-ориентированном программировании, предполагается, что эти процедуры будут вызываться средой, а не вами. Это называется Голливудским принципом Объектно-ориентированного программирования: не вызывайте нас, мы сами вас вызовем.

Обычно элемент управления встроен в форму. Когда мы сохраняем форму в файл, она даёт встроенным элементам возможность сохраниться. Когда форма считывается из файла, форма обнаруживает элементы управления и дает им возможность загрузиться. Программисту элемента управления необходимо реализовать две процедуры для этой цели: Externalize и Internalize. В листинге вы можете увидеть, что используются вспомогательные функции Views.WriteFont и Views.ReadFont. Они освобождают вас от обременительной задачи записи и чтения по-отдельности таких параметров как начертание шрифта, размер, стиль и жирность.

Для поддержки операций копирования (таких как Вырезать, Вставить, Копировать) визуальное предсталение должно быть способно копировать своё содержимое в свой пустой клон. Для этой цели процедура CopyFrom копирует состояние существующего контроллера (документ) во вновь определённый, но ещё не инициализированный элемент управления.

Наш элемент управления должен уметь перерисовывать свою структуру и метку, для чего есть процедура Restore. Она рисует метку цветом и шрифтом элемента управления. Метка центрирована по горизонтали. Заметьте, что элементу не нужно рисовать фон: это задача контейнера. Рисуется только передний план, т.е. очертания и метка.

Разумеется, элемент управления должен совершать определённое действие, когда пользователь кликает его. Клики мышью и другие интерактивные действия обрабатываются процедурой HandleCtrlMsg  отображения. В нашем примере эта процедура реагирует только на сообщение (событие) клик мыши. Другие интерактивные действия, такие как нажатие клавиш, не воспринимаются, чтобы сделать пример как можно проще.

В основном реализация процедуры состоит в отслеживании положения мыши, которое прекращается, когда пользователь отпускает (основную) кнопку мыши. Отслеживание реализовано таким образом, что прямоугольник элемента управления инвертируется пока мышь находится над ним, а иначе не инвертируется.

Если кнопка мыши отпущена над отображением, инверсия отменяется и строка в v.link передается в процедуру Dialog.Call. По сути эта процедура реализует интерпретатор команд Компонентного Паскаля, т.е. строки типа "Dialog.Beep" могут быть динамически выполнены.

Блэкбокс предопределяет некоторые стандартные свойства системы и элементов управления. Системные свойства - это те свойства, которые можно изменить с помощью меню Characters (Font, Attributes меню в Mac OS), т.е. шрифт и цвет. Свойства элементов управления - это те свойства, которые определяются в модуле Controls и могут быть изменены с помощью инспектора свойств. В Блэкбокс есть сообщения, для запроса свойств отображения (Properties.PollMsg), и для их установки (Properties.SetMsg). Возврат свойств контроллера производится достаточно просто: определяется подходящий дескриптор свойства (Properties.StdProp и Controls.Prop), устанавливаются значения соответствующих полей, т.е. начертание стиля, размер, жирность шрифта, связь и метка, и сигнализируется, что это действующие свойства, о которых знает контроллер. Для стандартных системных свойств всё это делает вспомогательная процедура GetStdProp. Другая процедура - SetStdProp  немного более сложна по устройству, т.к. для каждого свойства проводится запрос о том, нужно ли его менять или необходимо оставить прежнее значение. Ведь пользователь мог просто изменить цвет элемента, не меняя шрифта.

Управление всеми свойствами находится под контролем процедуры HandlePropMsg, в которой распознаются сообщения PollMsg и SetMsg. Для SetMsg обходятся все элементы его списка свойств и выбираются все существующие системные свойства и свойства элемента управления. Это выполняется потому, что элемент управления, очевидно, не может устанавливать свойств, которых он не знает.

Изменения свойств элемента управления заключены между вызовами Views.BeginModification и Views.EndModification. Эти процедуры говорят Блэкбоксу, что произведена некоторая операция, которая не может быть отменена. Поддержка отмены была бы не очень сложной, но все же для данного примера является излишней.

Вызовы Views.Update сигнализируют о том, что видимая область котроллера должна быть  перерисована как только закончится выполнение текущей команды.

В HandlePropMsg элемент управления отвечает на запросы о предпочтениях. Предпочтения - это сообщения, которые отображение-контейнер (например, диалоговая форма) шлёт содержащимся в ней отображениям (например, элементам управления). Они предназначены для настройки свойств контейнера в соответствии с пожеланиями встроенного объекта. Контейнер не обязан запрашивать у встроенных отображений их предпочтения, но "социально ответственные" контейнеры (как то тексты и формы) делают это. Например, у  отображения, у которого ещё не определены ширина и высота, будут запрошены его предпочтительные размеры (Properties.SizeMsg). С помощью предпочтений Properties.FocusPref, отображение может влиять на то как с ним обращаются, когда в него кликают мышью. Наш элемент управления показывает, что он является "hot focus", т.е. он приобретает фокус только на то время, пока удерживается кнопка мыши.

Наконец, процедура New создаёт новый элемент управления, процедура Deposit помещает такой новый элемент в системную очередь Блэкбокса. Например, следующая последовательность команд может быть использована для добавления нового элемента в эту очередь:

 "ObxButtons.Deposit; StdCmds.PasteView"

Вот мы и закончили обсуждение реализации элемента управления! Несмотря на то, что мы не обращались к некоторым более сложным вопросам, таким как клавиатурные сокращения для элементов управления, и как элементы можно связать с переменными вместо команд, все равно перед нами полная реализация элемента управления.

ObxButtonssources

Текст перевёл Адаменко Оскар, группа 08-302.