Reviews / articles about OS/2 |
Operating systems: ArcaOS, eComStation, IBM OS/2 Warp |
|
|
DATE: 2008-04-11 17:35:45 AUTHOR: Eugene Evstigneev
Eugene Evstigneev предлагает разработчикам реализовать скиннинг для рабочего стола eComStation.
1. Аксиомы
2. Промежуточные структуры и API - контекстные переменныеКонтекстные переменные - это переменные, существующие в контексте определенного окна. Особенности переменных:
Работа с контекстными переменными должна быть реализована как базовая возможность системы, не привязанная к скиннингу, но необходимая для этого. При реализации скиннинга в контекстных переменных должны храниться такие данные, как состояние окна (нажата/не нажата для кнопок; активно/не активно для фрейма; курсор на контролом/не над контролом и т.п.) для [A8], так и его визуальные параметры (шрифт, цвет и т.п.). Контекстные переменные должны функционально заменить presparams. Для усовершенствования текущей возможности drag-n-drop цветов и шрифтов на контролы ([A9]) необходимо предопределить 3 контекстных переменных для хранения шрифта, цвета фона и цвета переднего плана. Наличие этих трех предопределенных переменных снимет необходимость в самостоятельной обработке событий при перетаскивании цветов и шрифтов на элемент управления (окно), однако это не должно мешать самостоятельной обработке этих событий окном, если в этом возникнет необходимость. Переменные должны быть доступны для использования в описании скина. Для быстрого сохранения и восстановления состояния окна должно быть предусмотрено API для работы с блоком контекстных переменных, оперативной единицой для которого должен быть блок переменных заданного контекста, определенный парой указатель/размер. Этот блок в зависимости от заданных параметров может включать, а может и не включать переменные всех дочерних окон.
3. Промежуточные структуры и API - XML-парсерПарсер должен быть реализован в соответствии с рекомендацией XML 1.0 W3C. Парсер должен генерировать бинарное дерево в заранее заданном формате для его последующей обработки для обеспечения [A3]. Непосредственно отрисовка должна осуществляться по полученному дереву без дополнительного парсинга и резолвинга.
4. Графические примитивыГрафический примитив - это базовый элемент отображения. В общем понимании - это процедура, которая на основе входных параметров осуществляет некоторый вывод в заданный presentation space. В интерфейсе примитива должна быть определена процедура "Paint", осуществляющая непосредственно отрисовку в presentation space, указатель на который должен передаваться в качестве входного параметра. В параметрах должны также присутствовать некоторые наиболее общеупотребимые переменные для наиболее быстрой обработки входных данных ([A3]). Среди входных параметров должны присутствовать:
Учитывая возможность пользовательского расширения набора примитивов ([A4]), во входных параметрах должен присутствовать указатель на массив структур, содержащих пары "имя"-"значение" для всех прочих параметров, не попавших в число предопределенных, но которые, возможно, присутствуют в описании скина. Кроме "Paint" должна присутствовать процедура "ConfigDlg", которая отображает диалог для визуальной настройки примитива, необходимый в случае реализации расширенного редактора схем. Среди изначально определенных примитивов должны присутствовать:
5. Описание скина5.1. Физическое представление В физическом понимании файл описания должен быть в формате XML ([A1]) и соответствовать требованиям well-formed документа и не быть отдельным документом ("Standalone Document Declaration"), т.е. объявление документа должно быть вида: <?xml version="1.0" standalone="no"?> 5.2. Логическое представление 5.2.1 Визуализация Алгоритм отрисовка каждого элемента определяется последовательностью тегов, описывающих графические примитивы. Формат описания должен быть следующего вида: <primitive name=".."> <parameter name=".." value=".." /> ... </primitive> ..например: <primitive name="text"> <parameter name="x" value="0" /> <parameter name="y" value="0" /> <parameter name="w" value="&cxv_w;" /> <parameter name="h" value="&cxv_h;" /> <parameter name="text" value="&cxv_text;" /> <parameter name="color" value="&cxv_foregroundcolor;" /> <parameter name="font" value="&cxv_font;" /> <parameter name="x_shadow" value="1" /> <parameter name="h_align" value="1" /> </primitive> ..где тег "primitive" определяет вызов к процедуре "paint" примитива, имя которого определяется единственным атрибутом "name". Вложенные атрибуты "parameter" определяют набор значений, передаваемых в качестве входных параметров, где атрибут "name" определяет имя параметра, а "value" - значение. В соответствии с п.4, предопределенные параметры должны передаваться непосредственно в списке параметров, а все прочие в виде массива структур. Значения параметров могут быть заданы в виде констант, так и в виде ссылок на контекстные переменные, определенные в соответствии с форматом описания сущностей ("entity") спецификации XML. Данный механизм снимает необходимость в структурах CCI, поскольку соответствие системного параметра отображения и его местоположения в элементе управления определяется описанием скина. 5.2.2. Идентификация Принадлежность тегов описания примитивов к конкретному классу окна должна определяться тегом верхнего уровня "class" с единственным атрибутом "name", определяющий класс окна ([A5]). Пример: <class name="pushbutton"> <primitive>...</primitive> ... </class> Кроме возможности задания визуализации для класса целиком, необходима возможность описания отображения для конкретного окна, определеямым его идентификатором ([A6]). В случае реализации скиннинга на классической модели PM, идентификатором может быть строка, возвращаемая процедурой окна, а в SOM это может быть имя объекта. Формат описания для конкретного окна должен быть слеующего формата: <window name="closebutton"> <primitive>...</primitive> ... </window> ..где атрибут "name" тега "window" определяет идентификатор визуализируемого окна. Наличие тегов <class> и <window> может порождать неоднозначности при выборе описания, когда для визуализируемого окна имеется как описание <window>, так и <class>. В этом случае приоритет должно иметь описание, содержащееся в теге <window>. В конечном итоге файл описания скина должен содержать последовательность тегов <class> и <window>. 5.2.3. Условные секции Формат скина должен допускать описания визуализации для различных состояний одного и того же элемента ([A8]). Такие состояния должны определяться контекстными переменными, значение которых должно поддерживаться в адекватном состоянии во время работы. Предположительно (данный вариант не является окончательным), для проверки состояния какой-либо контекстной переменной могут быть использованы специальные теги следующего вида: <if-eq name="" value=""> ... </if-eq> ..где атрибут "name" содержит имя (сущность) проверяемой переменной, "value" - значение. Имя тега определяет производимую операцию (в данном случае - равенство). Состоянием элемента (окна) может определяться как его внутренним состоянием (кнопка нажата/отжата), так и действиями пользователя (курсор [не] над окном, hover). Примерное описание скина с условными секциями может выглядеть следующим образом: <class name="pushbutton"> <!-- кнопка нажата --> <if-eq name="&pushed;" value="1"> <primitive>..</primitive> ... </if-eq> <!-- кнопка отжата --> <if-eq name="&pushed;" value="0"> <!-- курсор над кнопкой --> <if-eq name="&hover;" value="1"> <primitive>..</primitive> ... </if-eq> <!-- курсор не над кнопкой --> <if-eq name="&hover;" value="0"> <primitive>..</primitive> ... </if-eq> </if-eq> </class> Открытая проблема - проверка необходимости в перерисовке элемента в зависимости от смены состояния контекстных переменных, используемых в условных секциях. Учитывая, что лишь немногие переменные могут присутствовать в условных секциях, перерисовка окна при изменении значения любой контекстной переменной может привести к значительным потерям производительности.
6. ИерархияУчитывая возможность субклассирования пользователем класса окна для расширения его функциональности, для таких субклассированных окон в скине не будет содержаться никакого описания, соответствующего именно этому классу (кроме случаев, когда для субклассированного окна пользователем определен и скин). В этом случае должно выбираться описание, соответствующее вышестоящему классу в иерархии наследования. Допустим, для иерархии классов: Window Pushbutton MyPushbutton описание визуализации имеется только для класса "Pushbutton". Для визуализации окна класса "MyPushbutton" должно использоваться описание класса "Pushbutton", как наиболее близкого по иерархии, имеющее описание.
7. Составные элементы управленияМногие элементы управления при едином идентификаторе окна имеют несколько активных областей, которые по-разному визуализируются и реагируют на действия пользователя. К таким элементам относятся полосы прокрутки, меню, списки, градусники и т.п. Для решения задачи можно выделить два решения. Первое предполагает фиксацию состояния активных областей в контекстных переменных. Суть второго - в присваивании каждой активной области реального или фиктивного класса окна, описания которых должны присутствовать в скине. На примере полосы прокрутки, для описания всех составных элементов (кнопка вверх, кнопка вниз, движок) можно выделить 4 контекстных переменных - высота кнопок, координата верхней кнопки, координата движка, высота движка. Таким образом, описание визуализации для полосы пркрутки могло бы выглядеть таки образом: <!-- сама полоса --> <primitive name="solidcolor"> <parameter name="x" value="0" /> <parameter name="y" value="0" /> <parameter name="w" value="&cxv_w;" /> <parameter name="h" value="&cxv_h;" /> </primitive> <!-- кнопка вниз --> <primitive name="solidcolor"> <parameter name="x" value="0" /> <parameter name="y" value="0" /> <parameter name="w" value="&cxv_w;" /> <!-- cxv_buttonh - переменная, содержащая высоту кнопки --> <parameter name="h" value="&cxv_buttonh;" /> </primitive> <!-- кнопка вверх --> <primitive name="solidcolor"> <parameter name="x" value="0" /> <!-- cvx_buttony - переменная, содержащая y-координату кнопки "вверх" --> <parameter name="y" value="&cxv_buttony;" /> <parameter name="w" value="&cxv_w;" /> <!-- cvx_buttonh - переменная, содержащая высоту кнопки --> <parameter name="h" value="&cxv_buttonh;" /> </primitive> <!-- движок --> <primitive name="solidcolor"> <parameter name="x" value="0" /> <!-- cvx_slidery - переменная, содержащая y-координату движка --> <parameter name="y" value="&cxv_slidery;" /> <parameter name="w" value="&cxv_w;" /> <!-- cvx_sliderh - переменная, содержащая высоту движка --> <parameter name="h" value="&cxv_sliderh;" /> </primitive> Недостаток метода - его непригодность для визуализации элементов, где количество активных областей непостоянно, например меню. Выделение каждой активной области в отдельное окно со своим классом снимет эти ограничения, но раздует иерархию классов окон, и увеличит затраты опреративной памяти ввиду большого количество таких составных элементов. Как вариант решения последней проблемы - создание окон для активных областей только при непосредственном отображении элемента на экране, и их удаление при его скрытии. Как побочный эффект - уменьшенное время реакции при открытии и закрытии окна (например, меню). Альтернативный вариант предполагает наличие в скине описания визуализации для каждой активной области как для отдельного класса окна, но при фактическом отсутствии такового. При этом отрисовка составного элемента будет состоять из последовательности вызовов к процедуре визуализации для каждой активной области с предварительной установкой контекстных переменных в нужные значения и подстановкой в качестве входного параметра функции визуализации фиктивного класса окна, отсутствующего в системе, но присутствующим в описании скина. Недостаток подхода - его непрозрачность.
8. МаскаНа данный момент в системе имеются элементы, имеющие непрямоугольные активные области, к которым относится спиннер ("WC_SPINBUTTON"). Для их визуализации предлагается или переписать такие классы для ликвидации таких непрямоугольных областей, или введение в описание скина параметра, описывающего бинарную маску.
9. Настраиваемые параметрыПредлагаемая схема визуализация снимает необходимость в фиксированном наборе настраиваемых параметров. Любые цвета, шрифты и прочие параметры могут задаваться как в виде констант, так и в виде ссылок на контекстные переменные. Очевидно, что скин, в котором все визуальные параметры заданы в виде констант, лишен любых настроек, доступных в редакторе схем. В то же время, ничто не мешает задать все параметры в виде переменных, которые могут участвовать как в управлении параметрами визуализации, так и в качестве параметров в условных секциях. Учитывая отсутствие любых требований к таким параметрам со стороны системы, в описании схемы необходимо предусмотреть блок (возможно, отдельным файлом), содержащий описание имеющихся в схеме переменных, пригодное для использования в редакторе схем. Описания должны быть сгруппированы по описываемому классу или идентификатору окна, и содержать все параметры, необходмые для визуализации настройки в редакторе схем. Параметры должны содержать:
Пример предлагаемого описания переменной: <!-- parameters.xml --> <sch:class name="pushbutton"> <sch:name xml:lang="en">Push button</sch:name> <sch:name xml:lang="ru">Кнопка</sch:name> <sch:parameter value="cxv_backgroundcolor"> <sch:name xml:lang="en">Button color</sch:name> <sch:name xml:lang="ru">Цвет кнопки</sch:name> <sch:type value="color" /> <sch:value value="#808080" /> </sch:parameter> <sch:parameter value="cxv_foregroundcolor"> <sch:name xml:lang="en">Text color</sch:name> <sch:name xml:lang="ru">Цвет текста</sch:name> <sch:type value="color" /> <sch:value value="#0" /> </sch:parameter> ... </sch:class> Здесь название переменной (значение атрибута "value" тега "parameter") должно задаваться _не_ в нотации сущности (entity). Описанные таким образом переменные могут быть установлены только для класса, внутри описания которого они были определены. Для описания переменных, используемых в секции "<window>" описания скина предлагается использовать тег "<sch:window>" вместо "<sch:class>". Определенные таким образом переменные по своей сути заменяют переменные SYSCLRs, имеющиеся в текущей модели PM. Для описания переменных вне контекста класса или окна предлагается использовать тег "<sch:section>" с форматом описания, аналогичным приведенному выше. Главное отличие переменных, описанных в секции "<sch:section>" от тех, которые описаны в "<sch:window>" и "<sch:class>" в том, что они существуют вне какого-либо контекста, и имеют силу на всем протяжении описания скина. В случае, когда переменные с одним и тем же именем определены в описаниях класса, окна и общей секции, приоритет распределяется следующим образом:
Предполагаемое применение секции "<sch:section>" - определение общих параметров схемы, не относящихся к определенному классу или окну, хотя формально область применения не ограничена. Таких внеконтекстных секций может быть несколько для возможности визуального разделения разнородных параметров в окне настройки схемы. Определение переменной с одним и тем же именем несколько раз в пределах:
является ошибкой.
10. Схема реализацииОсновную инфраструктуру скиннинга предлагается реализовать в виде функций и методов класса окна верхнего уровня (доступного через функцию WinDefWindowProc текущей версии PM). Стыковку новой инфраструктуры и имеющейся модели PM предлагается сделать в методе Paint (WM_PAINT), переопределенным в классе окна верхнего уровня. Общий алгоритм работы этого метода после переопределения должен выглядеть следующим образом: 1. отрисовка скина для текущего окна 2. если ошибка (например, скин для окна не определен), то 3. отрисовка скина для текущего класса окна 4. если ошибка (например, скин для класса не определен), то 5. если текущий класс окна равен классу верхнего уровня, 5. то возврат с ошибкой 6. определить класс, стоящий выше по иерархии, к п.3 7. успешный возврат Таким образом, алгоритм будет пригоден для использования в любых классах без модификации. Отсутствие непосредственной отрисовки окна объясняется тем, что алгоритм должен быть реализован в классе окна верхнего уровня, который является невизуализируемым. В производных (визуализируемых) классах алгоритм должен быть следующим:
В п.1 произойдет отработка алгоритма, описанного выше, который визуализирует элемент на основе описания скина. Если визуализация прошла с ошибками, происходит прямая отрисовка элемента на экране по имеющимся текущим алгоритмам, не связанных с механизмом скиннинга. Этот алгоритм позволит сохранить работоспособность пользовательского интерфейса даже при критических ошибках в механизме скиннинга, произошедших как из-за ошибок в реализации скиннинга, так и из-за пользовательских ошибок (неправильный скин, отсутствие скинов, эксперименты над системой и т.п.) ([A11]).
Комментарии:
|
|
|||||||||||||||
(C) OS2.GURU 2001-2021