• Содержание
  • Разработка приложений с помощью Mozilla / автор: Н.Макфарлейн
    4. Глава: Первые элементы управления и темы

    В этой главе объясняется, как пользоваться XUL-кнопками и как менять их внешний вид с помощью системы тем Mozilla. Эта система может использоваться для изменения отображения всех XUL-тегов.

    Приложения Mozilla интерактивны, то есть у них имеются визуальные средства управления, доступные пользователю. Самый простой пример такого средства - скромная кнопочка с надписью "Нажми меня". Кнопки очень удобны, и в Mozilla много различных их видов, но все они создаются с помощью разметки XUL. Простейший пример кнопки можно получить, используя тег <button>, например, вот так:

    <button label="Press Me"/>
    

    Это очень быстрый способ создать готовую к применению кнопку, тем и хорош XUL. Для кнопки также нужен какой-нибудь скрипт, иначе ее нажатие ничего не даст, а такие кнопки вряд ли полезны в практических приложениях. В этой главе мы будем больше уделять внимания собственно кнопкам, а не тому, как реализовывать действия, вызываемые ими.

    Кнопки для нас естественны и привычны. Оглянитесь вокруг: они есть на панелях почти всех современных устройств - на телефоне, CD-проигрывателе, приборной доске и фритюрнице. На сайте "The Really Big Button That Doesn't Do Anything" (http://www.pixelscapes.com/spatulacity/button.htm) можно найти много интересной информации о кнопках, кроме того, он является своеобразным предупреждением разработчикам графических интерфейсов. В Mozilla кнопки - простейший способ разнообразить обычный текст и изображения, используя элементы управления.

    Элемент управления, конечно - маленький кирпичик, только часть приложений с графическим интерфейсом. Самые распространенные элементы управления - те, что создают меню, формы, полосы прокрутки. Некоторые из них можно перемещать, трансформировать, менять или анимировать, другие нельзя. Элементы управления - забота программистов, так как обычно они входят в состав библиотек объектов или языков третьего поколения, например, GTK, Qt, Swing и Win32. При взаимодействии пользователя и элемента управления вид последнего меняется, чтобы пользователь знал, что он что-то сделал. Элементы управления предназначены для упрощения выполнения интерактивных задач. И, кажется, простейший элемент управления - кнопка.

    С точки зрения технологии, некоторые элементы управления (в том числе и кнопки) не так просты, как это может показаться. В мире кнопок много чего происходит. Эта сложность - отличный повод узнать побольше о платформе Mozilla.

    На рисунке в начале главы показаны те части Mozilla, которые тесно связаны с кнопками, а также с темой этой главы. На рисунке видно, что кнопки сильно зависят от набора графических элементов, предоставляемого операционной системой. Это функциональная сторона кнопок. Менее очевидно то, что кнопки зависят и от стилей и тем. Это происходит потому, что внешний вид кнопки так же важен, как и ее функция. Если кнопка не похожа на кнопку, то это не кнопка. До сих пор мы уклонялись от рассуждений о темах, многое делая с помощью стилей. Перед тем, как переходить к более сложным аспектам Mozilla, нужно объяснить работу системы тем. Еще одна особенность кнопок заключается в том, как они взаимодействуют с остальными XUL-тегами. До сих пор единственным наблюдаемым нами взаимодействием между тегами было вкладывание одного в другой. Однако кнопки "общаются" с другими тегами целым рядом способов. В этой главе они также будут описаны, ей даже можно было дать подзаголовок "Тайные отношения между тегами". Полное описание сложной системы XUL-тегов мы оставим на потом. Наша цель в этой главе - показать некоторые из более простых взаимодействий как анонс того, что будет дальше.

    Более пространные рассуждения о создании форм и обработке пользовательского ввода с клавиатуры и мыши приведены в главе 6, "События". В простых же кнопках столько всего, что на эту лекцию нам хватит с лихвой.

    4.1. Что делает кнопку кнопкой?

    Языки разметки вроде HTML и XUL предоставляют много возможностей визуального отображения. Иногда сложно сказать, что из виденного "настоящее", а что - сложная анимация и небольшой скрипт. Беседу о кнопках и элементах управления мы начнем с того, что посмотрим, каковы же на самом деле элементы управления Mozilla. Рассуждая об элементах управления, созданных на XML, можно немного путаться, как в следующем примере.

    На рисунке 4.1 показано простое XUL-приложение, содержащее одну "настоящую" кнопку и две фальшивых. Какая из них настоящая? Хотя по рисунку видно, что самая нижняя из них нажимается, это действие можно проделать со всеми тремя.

    Фальшивые и настоящие кнопки в Mozilla

    Рис. 4.1.  Фальшивые и настоящие кнопки в Mozilla

    На этом рисунке настоящая кнопка самая верхняя. Две другие - просто теги <vbox>, содержащие единственный тег <description>. К тегам <vbox> применены стили, приведенные в листинге 4.1.

    vbox {
      border : solid;
      border-width : 2px; 
      margin : 2px 6px;
      -moz-box-align : center; 
      border-left-color : ButtonHighlight;
      border-top-color : ButtonHighlight;
      border-right-color : ThreeDDarkShadow;
      border-bottom-color : ThreeDDarkShadow; }
    vbox:active {
      border-left-color : ThreeDDarkShadow;
      border-top-color : ThreeDDarkShadow;
      border-right-color : ButtonHighlight;
      border-bottom-color : ButtonHighlight; 
    }
    
    Листинг 4.1. Стили для <box>, имитирующего кнопку

    Эти два стиля заставляют vbox при щелчке на нем вести себя как кнопка. Эти стили границ не идентичны границам, использующимся для настоящей кнопки ("Кнопка 1"). Такой блок со стилями - не настоящий элемент управления Mozilla.

    С другой стороны, даже хотя информация о внешнем виде еще не составляет сам элемент управления, стиль, с точки зрения пользователя, очень важен. На рисунке 4.2 показан снимок консоли JavaScript(), в окне которой есть пара противоречивых кнопок.

    Скрытые кнопки консоли JavaScript

    Рис. 4.2.  Скрытые кнопки консоли JavaScript

    Кто-то может возразить, что слова "Все", "Предупреждения" и т.д. не имеют ничего общего с кнопками. Если навести указатель мыши на любой из этих элементов, появятся границы, характерные для кнопок, но ведь нет никакой подсказки, что нужно сделать именно это. Для нового пользователя это не "нормальные" кнопки, хотя с ними все в порядке. Такие кнопки довольно часто встречаются в программном обеспечении, но даже в этом случае вместо текста там должны быть картинки.

    Очевидно, что есть некоторое несоответствие в том, что некоторые вещи похожи на кнопки, но не ведут себя как кнопки, а также в том, что некоторые вещи ведут себя как кнопки, хотя непохожи на них. Существует широко известный шаблон для проектирования графического интерфейса пользователя под названием MVC (Model-View-Controller, модель-вид- контроллер) - это ключ к пониманию элементов управления Mozilla. Данный шаблон широко применяется для систем с графическим интерфейсом. При его использовании элементы управления разделяются на три части: М, В и К. Внешний вид элемента управления - забота Вида. Хранение данных, нужных элементу управления, - задача Модели. Контроллер - то, что связывает внешний вид с данными, необходимыми элементу управления.

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

    Элементы управления Mozilla определяются их возможностями. В Mozilla можно убрать оформление кнопки (Вид), игнорируя стиль и тривиальное содержимое. Можно также лишить ее эффекта, удалив данные (Модель), с которыми она работает. Останется только то, что кнопка могла бы делать. Все, что она могла бы сделать - и есть ее возможности (и часть Контроллера). Такие возможности и составляют сущность кнопки. Именно на них мы попытаемся сосредоточиться в этой главе.

    Например, у XUL-тега <button> есть несколько простых и несколько сложных возможностей. Простые - состояние кнопки, обработчики событий и специфичные для кнопок атрибуты XML. Более сложные включают в себя дополнительные функции для людей с ограниченными возможностями, а также возможность находиться в списке навигации, использовать кнопки из набора графических элементов ОС и поддерживать собственные темы ОС.

    4.2. Происхождение элементов управления XUL

    Иллюстрация в начале главы дает общий обзор технологий, используемых внутри Mozilla. Прямоугольники на рисунке можно разместить так, чтобы показать анатомию отдельного XUL-элемента управления. XUL содержит большое количество разнообразных тегов, и не все они конструируются одинаковым образом. На рисунке 4.3 показана подсказка, как это делается, которая применима в большинстве случаев.

    Стек составляющих графического элемента управления

    Рис. 4.3.  Стек составляющих графического элемента управления

    В нижней части стека находятся ресурсы, предоставляемые операционной системой, например, Windows, MacOS или UNIX. В верхней части - пользовательский элемент управления в готовом приложении. Между ними низкоуровневая функциональность операционной системы постепенно сменяется более абстрактной и превращается в простой XUL-тег.

    Самый примитивный элемент управления предоставляется системной библиотекой графических элементов, например, GTK или Win32. Такие элементы управления не переносятся на другие операционные системы. Mozilla поддерживает работу с несколькими графическими библиотеками. Очень сложные библиотеки поддерживают работу с темами рабочего стола, так что определение темы может быть применено к системному элементу управления.

    Элементы управления Mozilla скрывают подробности системных элементов управления ОС и предоставляют интерфейс внутри Mozilla, одинаковый для всех платформ и всех графических интерфейсов. Это тонкости реализации, недоступные программисту приложения. Для создания одного элемента управления Mozilla может понадобиться несколько собственных элементов управления ОС.

    Когда элемент управления отображается после загрузки документа в окно, создается фрейм для позиционирования этого элемента управления на экране. Фрейм и все элементы ниже его в стеке написаны на C/C++. Все элементы в стеке, расположенные выше, интерпретируемы и представляют собой XML- или CSS-документы. Как было сказано в главе 2, "Проектирование с XUL", фрейм отвечает за всю информацию о стиле элемента, который он отображает.

    Mozilla поддерживает собственную систему тем, отличную от любой, предоставляемой ОС. Каждая тема Mozilla состоит из набора таблиц стилей. Каждая таблица стилей называется скином и по крайней мере один скин предоставляет набор стилей для элементов управления. Эта информация применяется ко всем фреймам, отвечающим за элементы управления.

    Очень часто у элементов управления есть определение XBL. Такое определение представляет собой XML-документ, определяющий имя тега XUL для элемента управления, атрибуты, свойства и методы его объекта. Это делается с помощью создания связи с XUL-тегом. Наконец, экземпляр элемента управления появится как часть содержимого в документе приложения в виде самостоятельного тега XUL. Этот тег может сам содержать другие теги (возможно, даже элементы управления).

    Хотя рисунок 4.3 выглядит довольно простым и упорядоченным, не все элементы управления Mozilla могут быть представлены так. Имя тега, например, может появиться на любом уровне не ниже "Элемент управления Mozilla", так же, как и где-нибудь еще в платформе. Слои связаны друг с другом; они не могут быть четко разделены.

    Из предыдущего описания неясно, почему внутри Mozilla должно быть несколько мест, где определяется элемент управления. Понятно, что Mozilla использует не зависящие от платформы элементы управления, потому что это способствует переносимости, но зачем нужно еще и XBL- определение? Нельзя ли все это сделать в одном месте? В следующем разделе объясняется стратегия Mozilla.

    4.2.1. Проектирование частей элемента управления

    Реализация множества XUL-элементов управления делится на две части. Тег <button> - типичный тому пример.

    Тег <button> обладает как простыми, специфичными, возможностями, так и более сложными, обобщенными. Некоторые из них, например, атрибут type, специфичны для кнопки. Этот атрибут имеет особое значение только для тега, обозначающего кнопку. Другие возможности, такие как возможность находиться в списке навигации, тесно связаны с общими механизмами платформы Mozilla. Между элементами управления, находящимися в списке навигации, пользователь может переходить по нажатию клавиши Tab. Когда пользователь нажимает ее, фокус ввода перемещается от одного элемента управления к другому автоматически. Эти два типа возможностей реализуются по-разному.

    Особенности тега <button>, в том числе его атрибуты, информация о состоянии и методах - все они определяются в XBL-файле. Эти данные легко менять с развитием и расширением языка XUL, и они достаточно независимы от изменений внутри самой платформы Mozilla. В главе 15, "XBL-связки", описывается, как создавать такие файлы. Программисты приложений, которым нужно сильно изменить Mozilla, могут преобразовать или копировать эти файлы. Изменение XBL-файла приведет к изменению внешних свойств данного элемента управления.

    Более интегрированная часть тега <button> требует сложной логики, которая распространяется на большую часть платформы Mozilla. Она реализуется более эффективным кодом на C/C++ с использованием общих аспектов платформы. Такая функциональность может обновляться только разработчиками платформы Mozilla, так что этот набор функций более низкого уровня для прикладных программистов фиксирован. Внесение изменений на этом уровне меняет всю сущность данного элемента управления.

    Есть некоторое сходство между этим разделением и тем, как реляционные базы хранят данные. В реляционной базе данных каждой таблице присваивается тип хранилища. Согласно этому типу данные могут быть помещены в B-дерево, хэш-таблицу или кучу. Доступны только несколько типов хранилищ, так как они реализуются где-то внутри сервера баз данных. Работа с таблицей с такими типами хранилищ гораздо более гибкая, чем работа с таблицами, чья структура фиксирована. Это происходит потому, что у гибкой версии таблицы может быть сколько угодно столбцов и индексов, что кажется неплохой идеей. Как и такая таблица, элемент управления XUL ограничен функциональностью, реализованной на C/C++, но XBL-определение каждого тега может быть создано отдельно (что обеспечивает гибкость), так что в конце концов элемент управления обладает различными характеристиками.

    4.3. Кнопки XUL

    XUL предоставляет несколько тегов, так или иначе связанных с кнопками. Два из них отвечают большинству требований: <button> и <toolbarbutton>. Для создания кнопок редко требуются какие-то другие теги. Тем не менее, есть еще три тега, достойные упоминания: <autorepeatbutton>, <thumb> и <scrollbarbutton>. Эти пять тегов наиболее похожи на кнопки из всех XUL-тегов. Некоторые из них включают несколько типов кнопок.

    Есть еще большое количество других тегов, имитирующих кнопки. Теги grippy создают элементы, похожие на кнопки и присоединяющиеся к другим элементам управления. У тега <label> тоже есть несколько свойств, присущих кнопкам. <statusbarpanel> рассматривается не здесь, а в главе 8, "Навигация". Наконец, некоторых тегов следует избегать из-за их незавершенности или устаревания.

    4.3.1. Пять основных кнопок

    XUL-теги для создания кнопок определяются, как и любые другие теги, и могут включать любое содержимое:

    <button><description label="Tools"/><button>
    

    Хотя между открывающим и закрывающим тегом может быть помещено любое содержимое, Mozilla не все сочетания кнопок и содержимого отображает корректно. Цель XUL 1.0 - создать функциональный XML-язык для графических интерфейсов. Это значит, что все очевидные сочетания "кнопка-содержимое" будут работать, но поддержка более редких сочетаний - это уж как повезет. Самый простой способ узнать, будет ли конкретное содержимое тега отображаться нормально внутри кнопки - проверить практически.

    На рисунке 4.4 показаны эти пять кнопок, каждая в трех состояниях: обычном, при наведении мышки и в нажатом состоянии. Пустое место означает, что данное состояние не подразумевает смены внешнего вида кнопки.

    Визуальные подсказки, даваемые XUL-кнопками в теме Classic

    Рис. 4.4.  Визуальные подсказки, даваемые XUL-кнопками в теме Classic

    На рисунке 4.4 содержимое каждой кнопки - всего лишь тег <description>, как и в предыдущем примере в одну строчку. Каждая из кнопок выглядит и ведет себя отлично от остальных. Менее очевиден тот факт, что и внутренняя обработка каждой кнопки тоже разная. Немного забегая вперед, скажем только, что каждая из них также поддерживает подмножество событий DOM 2 и, следовательно, набор обработчиков событий JavaScript. Подробнее об этом рассказано в главе 6, "События".

    Получение аналога рисунка 4.4 нетривиально, если пользоваться Mozilla версии 1.2.1 или более поздней. Начиная с этой версии, в теме Classic (и только в ней) реализована особая поддержка элементов управления. Она заключается в том, что такие элементы, как кнопки, будут выглядеть как стандартные кнопки операционной системы, а не как кнопки какой-либо темы Mozilla. Увидеть кнопки Mozilla можно, пользуясь более ранней версией Mozilla или переключившись из Classic в другую тему, либо отредактировав файлы этой темы. В разделе "Темы и скины" настоящей главе описывается, как это все работает.

    4.3.1.1 Тег <button>

    Тег <button> - рабочая лошадка среди всех кнопок Mozilla, он эквивалентен тегу <button> в HTML. Как и положено самой сложной из всех кнопок XUL, ей доступны многие функции, отсутствующие у других кнопок:

    • она может получать фокус ввода. Фокус ввода на рисунке 4.4 показан как пунктирная линия внутри границ кнопки;
    • она может находиться в списке навигации, то есть у нее есть ее пронумерованная позиция в порядке перехода между элементами на странице;
    • все ее содержимое автоматически заключается в невидимый тег <hbox>. На этот внешний блок могут влиять глобальные стили;
    • она поддерживает службы accessibility Mozilla, что гарантирует доступность по нажатию только клавиши Tab или ее эквивалента;
    • она реагирует на действия пользователя как "стандартная" кнопка: она выглядит как кнопка до, во время и после взаимодействия с пользователем.

    У следующих XML-атрибутов внутри тега <button> - особое значение:

    disabled checked group command tabindex image label accesskey crop
    

    Атрибуты disabled и checked могут принимать значение true. Первый из них удаляет кнопку из списка переходов и затеняет ее внешний вид. Второй позволяет кнопке постоянно быть в нажатом состоянии. При этом атрибут checked не играет никакой роли, если значение disabled - true. На рисунке 4.5 показаны кнопки с этими атрибутами. Обратите внимание, что внешний вид кнопки с checked="true" отличен от вида нажатой кнопки на рисунке 4.4.

    Альтернативные представления <button> в теме Classic

    Рис. 4.5.  Альтернативные представления <button> в теме Classic

    Атрибуты image, label, accesskey и crop относятся к содержимому <button>. <button> всегда подразумевает применение <hbox>, но если использовать кнопку без содержимого, <button/>, будет добавлено содержимое по умолчанию, которое эквивалентно во всем, за исключением стилей, листингу 4.2.

    <hbox align="center" pack="center" flex="1"> 	
    <image/> 	
    <label/> 
    </hbox>
    
    Листинг 4.2. Содержимое <button> по умолчанию

    Теги <image> и <label> ничего не будут отображать, потому что у них отсутствуют атрибуты src и value. У тега <button> эту информацию предоставляют атрибуты image и label. accesskey и crop также влияют на значение label содержимого кнопки по умолчанию. Например:

    <button image="green.png" label="Go" dir="rtl"/>
    

    Кнопка, созданная этим кодом, может выглядеть так, как показано на рисунке 4.6.

    Пример <button> с атрибутами, меняющими содержимое по умолчанию

    Рис. 4.6.  Пример <button> с атрибутами, меняющими содержимое по умолчанию

    Части содержимого появляются в обратном порядке потому, что присутствует атрибут dir.

    Для кнопок также будет использоваться содержимое по умолчанию, если внутри присутствуют содержательные теги, но все они особые. К таким особым тегам относятся <observes>, <template>, <menupopup> и <tooltip>. Может показаться, что исключения выбраны случайно, но эти четыре тега часто используются как наполнение для <button>. В главе 15, "XBL-связки", объясняется, как читать XBL-файлы, где указаны эти исключения.

    Стандартные атрибуты размещения вроде align, указанные для <button>, будут относиться к содержимому тега <hbox>. Остальные атрибуты, специфичные для <button>, упомянутые выше, можно применить и к нескольким другим XUL-тегам, а не только к кнопкам, так что они будут обсуждаться ниже, в главе 7, "Формы и меню".

    Как мы увидим далее, тег <button> поддерживает почти все события из стандарта DOM 2, например, onfocus, onclick и onmouseover, а также псевдоселекторы CSS 2 вроде :active, :hover и :focus.

    Что отличает <button> от определенных пользователем XUL-тегов вроде <foo>, так это внутренняя обработка. Когда пользователь нажимает на кнопку, событие нажатия завершается на теге <button>. Это нестандартная модель обработки событий для XML-документа. Стандартная обработка требует прохождения события от <button> ниже, к содержимому тега кнопки, например, к тегам <description> или <image>. В стандартной модели такое событие, несомненно, достигнет любого конкретного тега под указателем мыши, где оно может быть обработано, а затем вернется к <button>. Такого не бывает с <button> в XUL. Внутри Mozilla, в тексте кода для кнопок на C/C++, обработка событий меняется так, как если бы для всех событий тега <button> был вызван метод DOM 2 stopPropagation(). Содержимое <button> "застывает", как насекомое в янтаре - оно не получает событий вообще. Это поведение - суть тега <button>.

    Чтобы увидеть, как работает эта фундаментальная функция <button>, воспользуемся следующим кодом, который реализует две вложенные кнопки:

    <button><button onclick="alert('Hi')" label="B2"/></button>
    

    Внутренняя кнопка внешне никак не будет реагировать на действия пользователя, она даже не будет "знать", что пользователь что-то сделал. Она заморожена во внешней кнопке.

    4.3.1.2 Тег <toolbarbutton>

    <toolbarbutton> - это альтернатива <button>. Следующие атрибуты имеют особое значение внутри <toolbarbutton>:

    disabled checked group command tabindex image label accesskey crop 
    toolbarmode buttonstyle
    

    Почти все они - те же, что и для <button>, так зачем же нужен <toolbarbutton>? Происхождение этого тега - еще одна история о системах с графическим интерфейсом. Самый распространенный способ добавить команды в графическое окно - создать систему меню. Меню часто разрастаются и становятся медленными, потому и возникла идея панели инструментов. Панель инструментов представляет собой набор часто используемых команд, легко доступный пользователю. Самый простой способ добавить команду к панели инструментов - использовать кнопку. Выстраивание кнопок в ряд друг за другом выглядит неаккуратно с точки зрения пользователя, поэтому у кнопок на панелях инструментов нет границ, пока на них не будет наведен курсор мыши. В XUL есть тег <toolbar>, а в него для каждой команды можно разместить <toolbarbutton>. Если нужны примеры, взгляните на окно классического браузера.

    Тег <toolbarbutton> может использоваться и вне <toolbar>, они не прикованы друг к другу чугунной цепью. Они полностью независимы.

    Тег <toolbarbutton> - модификация тега <button>, у него такое же содержимое по умолчанию, но оно всегда идет после любого содержимого, предоставленного пользователем тега. В отличие от <button>, содержимое по умолчанию присутствует всегда.

    На рисунке 4.7 показано использование атрибутов checked и disabled вместе с <toolbarbutton>.

    Альтернативные представления <toolbarbutton> в теме Classic

    Рис. 4.7.  Альтернативные представления <toolbarbutton> в теме Classic

    XML-атрибуты toolbarmode и buttonstyle специально созданы для классического браузера. Они используются в его скинах (таблицах стилей) и недоступны глобально. Если атрибуту toolbarmode присвоить значение small, кнопки навигации браузера уменьшатся в размере. Если присвоить значение pictures атрибуту buttonstyle, то та часть содержимого по умолчанию, которая содержит <label>, будет скрыта; если присвоить значение text, скроется та часть, которая содержит <image>.

    В классическом браузере <toolbarbutton> используется для элементов всех возможных панелей инструментов, в том числе закладок на личной панели. Такие закладки - первый пример сложности, вводимой при чрезмерном использовании таблиц стилей: закладка сама по себе не выглядит как кнопка, она выглядит как гиперссылка в HTML. Другой пример творческого подхода к использованию стилей - тема Modern. В ней у элементов <toolbarbutton> границы кнопок убираются вообще. Если по имени <toolbarbutton> можно понять, что этот тег имеет какое-то отношение к кнопке, то по внешнему виду сориентироваться уже нельзя.

    Суть <toolbarbutton> в следующем: это точно такой же тег, что и <button>, но визуально он больше подходит для панели инструментов, его содержимое не заключается в <hbox> и для него добавлена собственная поддержка контекстных меню. Обычно такие меню появляются, когда мы щелкаем по какому-либо элементу интерфейса правой кнопкой мыши. Теги <toolbarbutton> могут содержать и собственные меню. Только для кнопок браузера "Вперед" и "Назад" специальный код внутри Mozilla гарантирует, что их нажатие и правой и левой кнопкой мыши приведет к открытию их меню.

    4.3.1.3 Тег <autorepeatbutton>

    Это кнопка, чье действие выполняется несколько раз. От нее самой мало пользы, но это важная составляющая при создании других, более сложных элементов графического интерфейса. Она основывается на теге <button>, но у нее нет содержимого по умолчанию и особых XML-атрибутов.

    Если пользователь наведет на такую кнопку указатель мыши, 20 раз в секунду начнет выполняться событие oncommand. На такие события могут реагировать соответствующие обработчики. Все другие события аналогичны событиям для любого тега, определенного пользователем.

    <autorepeatbutton> используется для создания тега <arrowscrollbox>, где такая кнопка нужна, чтобы реализовать непрерывную прокрутку. Кроме того, эта кнопка используется в выпадающих меню, когда они настолько длинные, что все элементы за раз не могут быть отображены. При удерживании кнопки <arrowscrollbox> нажатой, соответствующий блок прокручивается. Этот тег подробнее обсуждается в главе 8, "Навигация".

    Если <autorepeatbutton> появляется как часть большего тега, тогда его содержимое - одно только изображение, предоставляемое таблицей стилей. Изображение соответствует направлению прокрутки. При каждом запуске события <autorepeatbutton> выполняется поиск родительского тега, чье содержимое можно прокручивать, и для него выполняются необходимые для прокрутки действия.

    Кнопка <autorepeatbutton> интересна потому, что она еще несамостоятельна. Если она появляется вне тега <arrowscrollbox>, она будет работать некорректно. Если родительский тег несоответствующего типа, <autorepeatbutton> сделает то, что от нее требуется, но при этом накидает кучу ошибок в консоль JavaScript, что неприятно. Единственный способ избавиться от этих сообщений и сделать <autorepeatbutton> более независимой - отредактировать ее XBL-определение в chrome. Такие изменения могут предоставляться любым приложением Mozilla.

    4.3.1.4 Тег <thumb>

    Тег <thumb> - это тег <button>, единственным содержимым которого является тег <gripper>. <gripper> - тег, определенный пользователем. Тег <thumb> используется для реализации ползунка, появляющегося в центре полосы прокрутки.

    <thumb> интересен потому, что он отображается как графический элемент операционной системы. Комбинация <thumb>, <gripper> и расширений стилей Mozilla (см. раздел "Альтернатива: таблицы стилей" этой главы) позволяют <thumb> легко отображать ползунок, использующийся стандартной графической оболочкой ОС, а не ползунок Mozilla.

    <thumb> может выполнять часть своих функций вне полосы прокрутки, но он не создавался как общая desktop-specific кнопка. Он не отображает текст или другое содержимое, у него есть только внешние границы и текстура кнопки. Это простой пример создания кнопок, выглядящих как стандартные кнопки графической оболочки ОС. Стили <thumb>, выполняющие эту работу, можно найти в файле chrome xul.css, в toolkit.jar.

    4.3.1.5 Тег <scrollbarbutton>

    <scrollbarbutton> - это тег, предоставляющий кнопки для каждого конца полосы прокрутки. В XUL полосы прокруток реализуются с помощью тега <scrollbar>. Если вместо него применяется <nativescrollbar>, тогда не используются и теги <scrollbarbutton>. Стрелка на <scrollbarbutton> предоставляется таблицей стилей.

    <scrollbarbutton> - это измененный тег <button>, и в нем можно задействовать XML-атрибуты <button>. Кроме того, этот тег поддерживает атрибут type. Его значением могут быть increment и decrement, и он преследует две цели. Во-первых, он используется для выбора из таблицы стилей нужной пиктограммы, а во-вторых, он определяет, в какую сторону будет совершаться прокрутка. Increment означает прокрутку в прямом направлении, а decrement - в обратном.

    Тег <scrollbarbutton> похож на <autorepeatbutton> тем, что он работает надлежащим образом только внутри какого-либо объемлющего тега. Отличие заключается в том, что <scrollbarbutton> реализован без XBL-кода, так что автору приложения нечего редактировать, чтобы упростить использование этого тега. Но данный тег хотя бы не генерирует сообщений об ошибках.

    В целом, все части, составляющие XUL-тег <scrollbar>, довольно тесно связаны. Сами по себе <thumb>, <scrollbarbutton> и <slider> работают не очень. Так что лучше оставить их внутри <scrollbar>.

    4.3.2. Варианты кнопок

    Теги <button> и <toolbarbutton> могут отображать кнопки, размещая свое содержимое тремя разными способами. То, какое из них будет использоваться, зависит от атрибута type. Этот атрибут может отсутствовать (по умолчанию) или принимать одно из следующих значений:

    menu menu-button radio checkbox
    

    Примеры присваивания этих значений показаны на рисунке 4.8.

    <button> с разными значениями атрибута type.

    Рис. 4.8.  <button> с разными значениями атрибута type.

    Первые два значения, menu и menu-button меняют внешний вид кнопки так, что она поддерживает такое содержимое, как меню. Оно состоит из единственного тега <menupopup> и его потомков. Меню описываются в главе 7, "Формы и меню". Маленькие треугольнички на рисунке изображаются тегами <dropmarker>, они представляют собой лишь тег <image> с особыми стилями. Вспомним, что тег <button> заключает свое содержимое в <hbox>. Если это кнопка типа menu, тогда тег <dropmarker> оказывается внутри такого <hbox> и становится частью кнопки, на которую можно нажать. Если это кнопка типа menu-button, <dropmarker> оказывается вне <hbox>. В этом случае кнопка и <dropmarker> нажимаются по отдельности. Так или иначе, нажав на <dropmarker>, вы откроете содержащееся в кнопке меню, <menupopup>. Отдельный стиль гарантирует, что кнопка и треугольник для раскрытия меню остаются выровненными по горизонтали, даже когда последний находится вне <hbox> кнопки. Вне контекста выпадающего меню <dropmarker> никак не отображается.

    Два других типа кнопок, radio и checkbox, меняют отклик кнопки на нажатие. При их использовании кнопка копирует поведение тегов <radio> и <checkbox>, также описанных в главе 7, "Формы и меню".

    В случае переключателя (radio) нажатие на кнопку приведет к тому, что она сменит стиль и будет выглядеть нажатой. Все дальнейшие нажатия ничего не изменят. Если у кнопки есть атрибут group, нажатие на нее повлияет и на все остальные кнопки с таким же значением атрибута group. При нажатии на какую-либо кнопку из этой группы, все остальные будут выглядеть ненажатыми. Если потом нажать на какую-нибудь другую кнопку из этой группы, первая вернется в обычное состояние.

    В случае флажка (<checkbox>) каждое нажатие на кнопку меняет ее состояние с нажатого на обычное или наоборот. Эти нажатия никак не влияют на другие кнопки.

    К тегу <button> и разным его вариантам можно обращаться из JavaScript, как и к любому XML-тегу. У всех этих вариаций есть свойства объекта type, group, open и checked, доступные из JavaScript. Эти свойства соответствуют атрибутам <button> с тем же именем. Свойство open указывает, открыто ли сейчас меню <menupopup>.

    4.3.3. Grippys

    Grippys - маленькие, второстепенные элементы управления, появляющиеся на других или рядом с другими, более крупными и важными элементами управления. Их цель - дать пользователю возможность контроля над внешним видом основного элемента управления, например, как при изменении внешнего вида циферблата часов при прокручивании ручки справа. Самые известные примеры grippys - углы и края окон, хотя сами по себе grippys не так очевидны. Когда указатель мыши оказывается поверх этих grippys на краях и в углах окон, его значок меняется, и grippy можно перетаскивать, удерживая кнопку мыши нажатой, и менять размеры окна.

    Хотя grippys часто внешне похожи на кнопки, возможность перемещать или менять вид других графических элементов отличает их от обычных кнопок. Ползунок полосы прокрутки чем-то похож на grippy за исключением того, что он меняется сам, а не меняет полосу прокрутки. XUL-тег <dropmarker> тоже чем-то похож на grippy, хотя он тоже никак не меняет тег, к которому относится.

    В Mozilla и XUL есть несколько разных типов grippys. Вот их полный список: <grippy>, <toolbargrippy>, <resizer> и <gripper>.

    4.3.3.1. Тег <grippy>

    Чтобы увидеть grippy в действии, откройте Боковую панель Mozilla, выбрав в окне Навигатора View | Show/Hide.. | Sidebar. Здесь <grippy> - небольшая вертикальная полоска на узкой границе с правой стороны Боковой панели.

    Тег <grippy> используется внутри тега <splitter> - тонкого разделителя, который похож на видимый разделитель между двумя элементами содержимого с изменяемыми размерами. При перетаскивании <splitter> содержимое с одной его стороны сжимается, а с другой - расширяется. <splitter> дает пользователю возможность определять, какую часть окна может занимать какое-либо содержимое. Этот тег обсуждается в главе 8, "Навигация".

    Тег <grippy> очень прост. У него нет никаких особых атрибутов или содержимого. Его внешний вид полностью определяется стилями. Он помещается в центре тега <splitter>, чтобы напомнить пользователю, что тут есть что перетаскивать. Любая часть <splitter>, а не только <grippy>, может использоваться как точка, за которую можно перетаскивать разделитель. Использование тега <grippy> действительно тривиально:

    <splitter><grippy/><splitter>
    

    Единственное особое предназначение <grippy> - использование собственных обработчиков событий. Таким образом щелчки мышью могут собираться для <splitter>, который обычно "распознает" только перетаскивание. Такие одиночные щелчки могут скрывать разделитель, перемещать его на какое-то заранее определенное место, например, до упора влево или в середину, или клонировать его так, чтобы появлялись дополнительные разделители.

    В реализации тега <grippy> почти нет каких-либо особенностей. Единственная его необычная функция: для тега <splitter> <grippy> представляется как содержимое, поэтому иногда разделитель меняет атрибуты размещения своего grippy, если меняется сам. <grippy> - не определенный пользователем тег, так как его имя известно и используется в реализации платформы.

    4.3.3.2. Тег <toolbargrippy>

    Тег <toolbargrippy> применяется для сворачивания панели инструментов в маленькую пиктограмму так, чтобы она занимала меньше места. Для этого панель инструментов должна быть создана с помощью XUL-тега <toolbar>, заключенного в <toolbox>. У такой панели инструментов слева будет маленькая кнопка - <toolbargrippy>. На рисунке 4.9 показаны примеры использования таких grippys.

    Теги <toolbargrippy> для свернутых и развернутых панелей инструментов.

    Рис. 4.9.  Теги <toolbargrippy> для свернутых и развернутых панелей инструментов.

    Тег <toolbargrippy> - предмет жарких споров. В Mozilla 1.0.2 он существует, а в версии 1.2.1 был убран. В версии 1.3 его вернули, и он до сих пор используется. Аргументы за <toolbargrippy> примерно такие: он уже знаком пользователям Netscape; это уникальное нововведение; его сложно эмулировать в Internet Explorer. А вот аргументы против: он необычен и путает пользователей; он не позволяет фиксировать панели инструментов; он происходит от конкретной графической среды (OpenLook от Sun) и должен использоваться только там.

    Следующие замечания относятся только к тем версиям Mozilla, которые поддерживают <toolbargrippy>.

    Как и в случае <grippy>, сам по себе <toolbargrippy> не особенно полезен. Он представляет собой тег <image> с небольшими дополнениями. <toolbargrippy> создается автоматически тегом <toolbar> и никогда не указывается автором XUL-документа вручную. Значки на элементе grippy не происходят от какого-либо элемента управления из собственной графической среды ОС, это просто изображения, которые получились похожими на элементы управления графической среды OpenLook.

    У <toolbargrippy> нет особых атрибутов или собственного содержимого, но у тега <toolbar>, в котором он находится, есть один особый атрибут. <grippytooltiptext> предоставляет текст всплывающей подсказки для grippy, если панель инструментов свернута. Эта подсказка позволяет идентифицировать, какая панель скрывается за горизонтальным grippy.

    Поведение <toolbargrippy> полностью реализовано с помощью JavaScript и XBL-определения <toolbar>. При щелчке на grippy он сам и панель инструментов скрываются. Вместо этого появляется новый, горизонтальный grippy с другими стилями, его содержимое создается автоматически, затем этот grippy добавляется в XUL-документ. Все это делается с помощью скриптов, которые позволяют создавать новое содержимое с помощью интерфейсов DOM 1, описываемых в следующей главе. Когда появляется горизонтальный grippy, он представляет собой новое содержимое. Если щелкнуть по этому новому grippy, запускается обратный процесс. Горизонтальный grippy хранится внутри особого блока <hbox> тега <toolbox>. Этот <hbox> пуст и невидим, пока к нему не добавляются горизонтальные grippys.

    4.3.3.3. Тег <resizer>

    Тег <resizer> используется для изменения размеров текущего окна. Пользователь может щелкнуть по содержимому тега <resizer> и перетаскивать его, увеличивая или уменьшая размеры соответствующего окна. Изменяется целое окно, независимо от того, где находится содержимое тега <resizer>. Если поместить <resizer> среди другого содержимого окна, он никак не повлияет на размещение элементов.

    Существует два способа менять размеры окна приложения, и только в одном из них используется <resizer>.

    Один способ изменить размеры окна - отправить окну сообщения от менеджера окон графической среды. Это делается при перетаскивании мышью графических элементов вокруг окна. Так отправляется инструкция менеджеру окон, а не приложению. Менеджер окон может самостоятельно изменить границы окна, не сообщая ничего приложению. Известный пример - менеджер окон twm для X11, у которого есть параметр "каркас" (wire frame). Когда пользователь хочет изменить окно с помощью графических элементов менеджера окон twm, содержимое окна приложения застывает, а на экране появляется каркас окна (несколько прямоугольников). Пользователь перемещает и растягивает этот каркас так, как ему нужно, а затем отпускает кнопку мыши. Приложение получает сообщение о том, что ему нужно изменить размеры окна, чтобы они соответствовали измененному каркасу; содержимое окна также размещается так, чтобы заполнить окно с новыми размерами. В этом случае приложению нужно заново рассчитывать размещение только один раз. Более сложные менеджеры окон, например Sawfish для GNOME, могут заставлять приложение менять размеры окна несколько раз, пока пользователь не отпустит кнопку мыши. В любом случае это способ изменения размеров окна извне, когда приложение получает инструкции "снаружи".

    Во втором способе используется тег <resizer>. В этом случае приложение получает необработанные события мыши от графической среды, а не специальные инструкции для изменения окна. Приложение (Mozilla) само "догадывается" о том, что данные движения мыши подразумевают изменение размеров окна. Приложение напрямую или косвенно сообщает менеджеру окон об изменении размеров своего окна. У приложения по- прежнему есть выбор между изменением размещения содержимого несколько раз во время уменьшения или увеличения окна или один раз, когда будет известен окончательный размер. При использовании описанного способа изменение размеров окна инициируется приложением, а не менеджером окон. Если менеджер окон отсутствует, как, например, в случае маленькой встроенной системы вроде телеприставки или карманного компьютера, то это единственный способ изменить размеры окна.

    Тег <resizer> приводит к непрерывному, а не однократному пересчету размещения содержимого. Размещение видимого содержимого обновляется настолько быстро, насколько это возможно при уменьшении или увеличении окна.

    Как <resizer> влияет на границы окна, зависит от значения его особого атрибута dir. Использование dir совместно с <resizer> отличается от использования dir как обычного базового атрибута блочного размещения. В случае <resizer> этот атрибут определяет направление, в котором окно будет расширяться или сужаться, и может принимать одно из следующих значений:

    top left right bottom topleft topright bottomleft bottomright
    

    Значение по умолчанию - topleft. Первые четыре значения позволяют окну менять размер только в одном направлении, при этом противоположный край окна фиксируется. Оставшиеся четыре значения позволяют перемещать угол окна диагонально по направлению от противоположного угла (или к нему), который также фиксируется. Поверхностный просмотр исходных текстов Mozilla открывает существование атрибутов direction и resizedirection. Они работают не как dir и не делают ничего особенно важного, они просто хранят данные.

    У тега <resizer> нет содержимого и внешнего вида по умолчанию. Если он должен быть видимым, для него нужно указать конкретные стили и содержимое. В Mozilla вплоть до версии 1.2.1 стили и содержимое по умолчанию для <resizer> отсутствуют, так что его нельзя использовать без простейшей предварительной подготовки. В более поздних версиях он появляется в правом нижнем углу окна.

    4.3.3.4. Тег <gripper>

    Тег <gripper> - единственное содержимое <thumb>, которое, в свою очередь, должно быть содержимым <scrollbar>. Это пользовательский тег без содержимого, атрибутов и особого значения, и в его использовании как самостоятельного тега нет никакой нужды. Его имя "gripper" - всего лишь жаргонный синоним слова "grippy".

    4.3.4. Метки и <label>

    Как описывалось в главе 3, "Статическое содержимое", тег <label> позволяет добавлять обычное текстовое содержимое, но он нужен не только для этого. <label> также предоставляет содержимое другим тегам, помогает пользователю при вводе и предоставляет информацию, необходимую для людей с ограниченными возможностями. Аспекты навигации и accessibility обсуждаются в главе 7, "Формы и меню". Здесь мы будем смотреть на <label> как на вспомогательный элемент кнопок.

    У <label> есть две полезные особенности. Они могут предоставлять кнопкам содержимое и самостоятельно действовать как кнопка. Предоставление содержимого происходит так же, как и с любыми другими содержательными тегами. Вот простейший пример:

    <button><label>Press Me</label></button>
    

    Есть и альтернативная запись этого примера. Многие XUL-теги поддерживают атрибут label. В случае кнопки этот атрибут задает содержимое видимой кнопки. Перепишем предыдущий пример с использованием данного атрибута:

    <button label="Press Me"/>
    

    Разница между атрибутами label и value неочевидна. На данном этапе достаточно сказать, что визуально они выглядят одинаково, но у label есть некоторые особенности. Одна из них - возможность имитировать кнопку.

    Если label используется вместе с тегами <checkbox> или <radio> (которые обсуждаются в главе 6, "События"), тогда текст метки появляется рядом с элементом управления тега и может быть нажат, как если бы он был кнопкой. В некоторых графических средах пользователю дается подсказка при наведении на метку указателя мыши или если кнопка получает фокус, но иначе текст никак не выделяется. Так пользователю легче работать с элементом управления: он может щелкнуть как по самому элементу, так и по соответствующему тексту.

    Освоить работу с label сложно, потому что у него много разных вариантов использования, он применим не ко всем тегам. Он может предоставлять содержимое многим тегам, но <checkbox> и <radio> - единственные практические примеры использования текста <label> как кнопки.

    4.3.5. Остатки

    XUL-часть Mozilla достаточно нова, и на подготовку версии 1.0 потребовалось время. В ней все еще есть пробелы и уязвимые места. Есть еще несколько других тегов кнопок, едва упоминавшихся при обсуждении XUL. Эти теги могут быть причиной бесконечной путаницы, если не знать, что они собой представляют, не говоря уже о том, сколько придется играть в детектива, чтобы определить их текущий статус. Несколько наиболее непонятных тегов перечислены ниже.

    • <menubutton>, не аналог <button type="menu-button">. Это заброшенный эксперимент комбинирования кнопок и меню. Лучше забыть о нем и вместо него использовать атрибут type.
    • <titledbutton> был ранней попыткой комбинирования изображений и текста в кнопке, пока обычный <button> не достиг своего текущего состояния. Забудьте о нем и пользуйтесь <button>.
    • <spinner> - попытка создать элемент управления, который иногда называется счетчиком. Такой элемент управления состоит из поля с текстом и двумя маленькими кнопками с одной стороны. Эти кнопки находятся друг поверх друга, одна - стрелка вверх, другая - вниз. С их помощью пользователь может прокручивать последовательности значений, появляющиеся в текстовом поле при каждом нажатии. Пользователь может как ввести желаемое значение вручную, так и дойти до него с помощью кнопок. <spinner> еще не закончен и не готов к работе.
    • <spinbuttons> - дальнейшая попытка развития счетчиков, но состоит только из пары кнопок без текстового поля. У нее есть полное XBL-определение, но информация о стилях, в том числе об изображениях, отсутствует, как и в <resizer>. В лучшем случае это отправная точка для создания полнофункционального тега счетчика.
    • <slider> - последний тег, который вносит свой вклад в создание полос прокруток. Это полоса, на которой можно щелкать мышью и по которой перемещается ползунок <thumb>. <slider> тесно связан с тегом <scrollbar> и может привести к аварийному завершению работы классического браузера, если использовать его отдельно. Любыми способами избегайте встречи с ним.

    Этот список завершает возможности независимых кнопок в XUL Mozilla.

    Многие более сложные XUL-теги Mozilla также содержат элементы, похожие на кнопки. В таких случаях бессмысленно пытаться отдельно рассматривать эти кнопки. Теги вроде <tabbox>, <listbox> и <tree> подробно рассматриваются в разделах, посвященных им.

    Кроме всего прочего, кнопки - прекрасный повод подумать о проблемах интеграции с графической средой. Будет ли ваше приложение Mozilla органично сочетаться с другими приложениями, которые пользователь запускает на своем компьютере? Прежде всего, ваши кнопки должны соответствовать кнопкам этих приложений. Как этого добиться, показано ниже.

    4.4. Темы и скины

    Темы и скины меняют внешний вид программы. Как бы мы ее ни называли: темой, скином, профилем или маской - тема обычно состоит из информации о настройке, а не целых программ. Примените тему к кнопке, и ее внешний вид изменится.

    Ранние системы тем были не более чем настройками цвета, которые мог менять пользователь. Примерами таких систем могут служить настройки внешнего вида в Windows 9x/Me в разделе Display панели управления и файлы ресурсов X11.

    За ранними системами тем идут механизмы тем - особые части библиотеки графических элементов. Когда библиотеке нужно нарисовать кнопку, она обращается к механизму тем, который предоставляет графическую информацию, соответствующую текущей теме. Текущая тема определяется из настроек. Обычно такие темы создаются энтузиастами и выкладываются для свободной загрузки. Windows XP, Mac OS 10, GNOME 2.0 - примеры графических сред, поддерживающих механизмы тем, причем каждая по умолчанию предоставляет по крайней мере две темы на выбор.

    Для тем, основанных на механизмах тем, не очень важно, какие функции выполняет конкретное приложение, так как обычно внешний вид и функциональность разделяются. С точки зрения программиста, такие темы - украшательство, а не что-то полезное. Это одна точка зрения. Графический дизайн говорит нам о том, что окружающий мир, богатый пиктограммами, полон практических инструкций и указаний. Пример тому - знаки "Стоп". С этой точки зрения, хорошая тема критически важна для создания приложения, пользоваться которым было бы легко.

    Самые современные системы тем предоставляют больше возможностей, чем простой выбор декоративных элементов. Такие системы, например интерпретатор Lisp в менеджере окон Sawfish или система скинов SkinScript, использующаяся в Banshee Screamer, могут полностью перенастраивать пользовательский интерфейс приложения, а не только менять цвета и текстуры его визуальных элементов.

    Темы используются во многих программных продуктах, например, в WinAmp и Mozilla. Даже сотовые телефоны поддерживают темы, например, предоставляя возможности выбора звонка. На сайте http://themes.freshmeat.net/ перечислены темы для самых разных программ, поддерживающих темы, в том числе для Mozilla.

    Параллельно с вопросом о темах идут вопросы локализации: адаптации содержимого к данному языку или платформе. В Mozilla механизм локализации работает почти так же, как механизм тем. Он обсуждался в главе 3, "Статическое содержимое".

    4.4.1. Темы Mozilla

    Темы и скины Mozilla - две разные вещи. Тема Mozilla - это дизайнерская концепция с небольшой программной поддержкой. Темы также можно использовать для придания узнаваемого вида платформе Mozilla, для создания определенного образа или повышения производительности. Очевидные примеры - темы Mozilla Classic и Modern.

    Систему тем внутри Mozilla можно грубо сравнить с механизмом тем. Она предназначена для изменения только вида содержимого, а не самого содержимого. В крайних случаях ее можно приспособить и для изменения содержимого. Система тем Mozilla очень сильно зависит от поддержки таблиц стилей CSS 2 внутри Mozilla и опирается на несколько простых принципов:

    • темы Mozilla применяются только к XUL. За исключением полос прокруток, они не применяются к HTML. Собственные темы графических сред, тем не менее, применяются и к HTML, и к XUL. Они обсуждаются отдельно;
    • существует текущая тема с уникальным именем. Mozilla хранит это имя даже после завершения работы;
    • имя текущей темы, записанное в нижнем регистре, также является именем каталога в chrome. Темы Mozilla хранятся в chrome;
    • чтобы тема была полнофункциональной, она должна быть разработана для каждого расширения в chrome и для специального расширения с именем "global". messenger - пример имени расширения. Это имя используется для классического клиента почты и конференций;
    • информация о теме из расширения global используется для всех остальных расширений. Это договоренность, а не требование;
    • вся информация о темах должна быть специально включена в документы приложений. Никакая информация о темах автоматически не добавляется;
    • Mozilla автоматически меняет URL, относящиеся к темам, чтобы они содержали имя текущей темы. Это позволяет документам использовать текущую тему, не зная ее имени.

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

    Текущую тему можно менять. В классическом браузере можно выбрать View | Apply Theme для смены текущей темы и загрузки новых. Чтобы применить новую тему, нужно перезапустить браузер. Темы также можно установить, щелкнув по обычной гиперссылке - в этом случае будет задействована система XPInstall, описанная в главе 17, "Система распространения и установки - XPInstall". Так как темы хранятся в chrome как обычные файлы, и так как установка с XPInstall - общий и гибкий процесс, мало что может помешать вам нарушить правила использования тем. Чтобы быстро достичь результата и избавиться от проблем с поддержкой в будущем, имеет смысл создавать темы стандартным способом.

    Темы, созданные для классического браузера, необязательно будут работать с браузером Netscape 7.x или браузером Mozilla. Простые темы будут работать везде, но при использовании в одном браузере тем, специально созданных для другого браузера, вероятно, могут возникать ошибки. Многие авторы тем сейчас в первую очередь добавляют поддержку браузера Mozilla, а не классического браузера. Следовательно, темы не всегда переносимы.

    Можно нарисовать тему на бумаге или в графическом редакторе, но чтобы она стала действительно рабочей, ее нужно реализовать. А это предполагает создание скинов.

    4.4.2. Скины Mozilla

    Скин Mozilla - это набор файлов, реализующих тему для одного приложения, установленного в chrome, или для глобального расширения, которое используется во всех частях платформы.

    Скин может содержать файлы любых типов, но самое большое значение имеют таблицы стилей и изображения. Каждый скин строится вокруг таблицы стилей, которая меняет внешний вид XUL-документа. Если вы пользуетесь разными синтаксическими трюками CSS 2 вроде @import и url(), то ваши таблицы стилей могут включать другие таблицы стилей и изображения. Вместе эти элементы составляют внешний вид приложения. Это основная причина, почему XUL-документы не должны содержать встроенные стили. При хорошем проектировании скины могут использоваться несколько раз, и не надо каждый раз изобретать велосипед.

    В главе 1, "Основные концепции", была кратко описана структура каталога chrome Mozilla. Это корневой каталог для скинов, содержащий информацию о темах для всех расширений Mozilla. Чтобы создать скин, следует установить свои файлы внутрь этого каталога. Чтобы воспользоваться скином, нужно задать URL, указывающий на данный каталог. В использовании URL как раз и заключается особая поддержка тем Mozilla. Приведем пример.

    Предположим, у расширения chrome Mozilla под названием tool есть файл скина, который называется dialogs/warnings.css. Этот файл содержит все стили для соответствующего ему файла с содержимым dialogs/warnings.xul. Программист может включить этот скин в файл dialogs/warnings.xul таким образом:

    <?xml-stylesheet href="chrome://tool/skin/dialogs/warnings.css" 
    type="text/css"?>
    

    Здесь tool - имя расширения. Тут нет ничего интересного, касающегося скинов - просто жесткое включение. В этом примере URL для файла скина должен быть таким:

    chrome://tool/skin/dialogs/warnings.css
    

    Предположим, что текущая тема платформы - Modern, ей соответствует каталог с именем modern. Mozilla автоматически преобразует предыдущий URL в следующий путь относительно каталога установки:

    chrome/tool/skin/modern/dialogs/warnings.css
    

    После этого преобразования было добавлено имя темы (modern), а имя расширения (tool) было перемещено дальше. У этого каталога также есть URL:

    resource:/chrome/tool/skin/modern/dialogs/warnings.css
    

    URL-схема resource: указывает на корневой каталог установки платформы.

    Если же текущей темой окажется Classic, преобразованный путь к каталогу будет выглядеть так:

    chrome/tool/skin/classic/dialogs/warnings.css
    

    Это значит, что автор приложения должен предоставить файлы скина для каждой темы, которая может быть установлена для платформы. Это дело очень трудоемкое, к тому же иногда просто невозможно предсказать, какие темы могут быть установлены у пользователя. Самый простой путь обойти это требование - использовать глобальный скин для текущей темы. Этот глобальный скин может быть включен с помощью второго тега <?xml-stylesheet?> с таким URL:

    chrome://global/skin/
    

    У этого URL отсутствует конечное имя файла с расширением .css. При таком условии Mozilla будет запрашивать файл с именем по умолчанию - global.css, как в том случае, когда по умолчанию с сайта загружается index.html. Преобразованное имя каталога в этом примере будет одним из следующих:

    chrome/global/skin/modern/global.css 
    chrome/global/skin/classic/global.css
    

    Так как все ответственные дизайнеры тем включают в свои темы global.css, с использованием этого скина проблема поддержки неизвестных тем исчезает. Автору приложения нужно добавлять только особые скины для нестандартных функций своего приложения.

    Создание набора скинов для темы - нетривиальная задача. Учитывать человеческое восприятие сложно, но и процесс создания функциональных стилей и изображений также непрост. На то есть две причины. Во-первых, ваш глобальный скин должен быть достаточно гибким, чтобы не создавать проблем "всем" приложениям, которые захотят использовать данный скин. Это проблема переносимости. Во-вторых, чтобы ваша тема была полезной, нужно создать скины для известных приложений в Mozilla: Навигатора, Компоновщика, почтового клиента, адресной книги, настроек и т.д. Это тоже очень сложно, так как приложений много и выполнение такой задачи требует близкого знакомства классов, идентификаторов и структур содержимого в этих приложениях. Чтобы получить необходимые знания, нужно интенсивно изучать или приложения (с помощью Инспектора DOM), или скины тем Modern и Classic. Создание скинов для новых тем - обычно дело бескорыстное, но может быть и предложением какого-нибудь маркетолога.

    При создании или использовании скинов полезно придерживаться следующих правил:

    1. Глобальный скин должен включаться перед другими, более специализированными скинами.
    2. Глобального скина достаточно для большинства целей.
    3. Если создается специализированный скин, пусть в нем содержится инструкция @import, в которой указан глобальный скин, чтобы в XUL-файле нужно было ссылаться только на один файл таблицы стилей.
    4. Не следует менять глобальный скин, если вы не ответственны за всю тему целиком.

    Каталоги скинов могут содержать файлы любого типа. JavaScript-, XUL-, HTML- или DTD-файлы - все это может находиться в скине. Всегда есть уникальные условия, когда это может иметь большое значение, и такая возможность изредка используется в классическом браузере, но в целом ее следует избегать. Если вы будете пользоваться ею, вы просто переместите не зависящее от темы содержимое к зависящим от нее скинам, что умножает затраты на разработку и поддержку на количество тем, которые предстоит поддерживать. Этой возможностью пользоваться не рекомендуется.

    Скины не будут работать, если они просто скопированы в каталог chrome. В разделе "Практика" этой главы будет описано, как быстро, но не очень аккуратно поместить скин (или любой другой файл chrome) в нужное место.

    4.4.3. Иерархия таблиц стилей

    В XUL-приложение скины должны добавляться вручную, но это еще не все. Mozilla автоматически включает большое число таблиц стилей CSS 2. Рассказ о темах и скинах Mozilla не может быть завершен без обсуждения этих особых таблиц.

    Стандарт CSS 2 предоставляет три структурные особенности, которые можно использовать для организации иерархии таблицы стилей. Mozilla пользуется всеми тремя. Эти особенности не зависят от структуры документа, для которого создаются стили.

    Сама очевидная структурная особенность в CSS 2 - поддержка каскадных и наследуемых стилей. Подробности можно узнать в разделе 6 стандарта CSS 2. Стили можно применять и обобщенно и специально, как показано в листинге 4.3.

    * { color: lightgreen; } text { color: green; } text.keyword { 
    color: darkgreen; } #byline { color: black; }
    
    Листинг 4.3. Иерархия селекторов для постепенно темнеющего цвета

    В этом примере все теги светло-зеленые; теги <text> зеленые, теги <text class="keyword"> темно-зеленые, а единственный тег с id="byline" черный. Если первые стили поместить в общие css-файлы, а последние - в более специализированные, тогда независимо от порядка включения будут применены все эти стили. Пример: Mozilla предоставляет очень общие таблицы стилей с именами xul.css и html.css. Первый включает в себя следующее правило:

    * { -moz-user-focus: ignore; display: -moz-box; }
    

    Это правило заставляет все XUL-теги, независимо от того, определены они пользователем или нет, вести себя как блоки.

    Второй способ, предоставляемый CSS - упорядочивание. Если для одного селектора и свойства существуют два стиля, применяется только последний. В этом случае порядок применения таблиц стилей становится важен. Хотя ответственность за это можно возложить на Mozilla, обычно не стоит использовать эту особенность, так как по определению стилям положено быть правилами. Смысл системы правил в том, чтобы они все применялись одновременно, а это не так, если одно правило может переписать предыдущее.

    Наконец, чтобы разорвать связи между идентичными правилами стилей, можно использовать модификатор CSS 2 !important. Mozilla поддерживает понятие веса из CSS 2, которое реализуется двухбайтовым значением (от 0 до 65535). Если правило помечено как !important, вес увеличивается на 32768. В Инспекторе DOM Mozilla, когда в левой панели Document выбран узел со стилями, а в правой панели Object показываются правила CSS (CSS Style Rules), столбец Weight показывает веса разных стилей, применяемых к выбранному узлу.

    В таблице 4.1 показаны все источники правил стилей, которые могут быть применены к XUL- и HTML-документам. Самые общие источники показаны вверху. У особых файлов xul.css и html.css. самый низкий вес - 0.

    Таблица 4.1. Источники правил стилей для XUL и HTML

    Цель правил стиляПредоставляется ли темамиXUL-источникHTML-источник
    Реализовать свойства стилейНетВстроен в Mozilla, код на C/C++Встроен в Mozilla, код на C/C++
    Основные правила, которые применяются всегдаНетxul.css, с URL chrome://global/content/xul.csshtml.css, forms.css и quirks.css с URL вроде resource:///res/html.css
    Поддержка темы для стандартных элементов управления XULДаСкины в расширении global для XBL-элементов управления (например, chrome://global/skin/button.css)Нет
    Глобальная поддержка темы, использующаяся во всех расширениях chromeДаglobal.css с URLchrome://global/skin/Нет
    Специальная поддержка темы в одном или нескольких расширениях chromeДаСкины, размещенные по всему chrome, не находящиеся в расширении globalНет
    Встроенные стилиНетСледует избегать; находятся в xul-файлахНаходятся в html-файлах
    Пользовательские настройкиНетНетНастройки в Edit | Preferences | Appearance
    Пользовательские стилиНетchrome/userChrome.css в каталоге профиля пользователяchrome/userContent.css в каталоге профиля пользователя

    4.4.4. Собственные темы графических оболочек

    Система тем Mozilla не работает для любых других приложений, не основанных на Mozilla. Если все приложения в данной графической среде должны выглядеть и реагировать одинаково, значит, должна использоваться какая-то общая для них система тем. Распространенное решение этой проблемы - собственная система тем графической среды.

    Некоторые части содержимого, которое отображает Mozilla, можно сделать соответствующими собственной теме графической оболочки. При этом накладываются следующие ограничения:

    • версия Mozilla должна быть 1.2.1 или более поздняя;
    • графическая среда должна быть предоставляемой Windows XP, Mac OS 10.2 или иметь поддержку GTK 1.2;
    • информация системной темы графической среды применяется к элементам HTML-форм;
    • информация системной темы графической среды применяется к XUL-тегам, которые ведут себя как элементы управления;
    • системные темы работают для XUL, только если текущая тема Mozilla - Classic;
    • системные темы могут работать и с другими темами Mozilla, но только если те созданы с применением методик, использующихся в теме Classic.

    Собственные темы графической среды реализуются очень просто. Расширение CSS 2 в Mozilla -moz-appearance включает и отключает поддержку тем графической среды для отдельного тега. Если значение этого расширения none, тогда поддержка тем графической среды не используется. Если же значение ключевое, тогда этот ключ определяет, какой элемент графической среды будет использоваться для элемента управления Mozilla. Затем система тем графической среды попробует нарисовать (отобразить) нужный элемент управления вместо обычного содержимого Mozilla.

    Существует более 60 ключевых значений для этого расширения стилей. У большей их части имена совпадают с именами XUL-тегов, для которых они применяются, так что для кнопки, например, используется:

    -moz-appearance: button
    

    Возможно, но не рекомендуется (да и бессмысленно) отображать с помощью -moz-appearance меню как кнопку. Самый лучший способ продолжить изучение этих особенностей - начать со скинов темы Classic как руководства. Полный список ключевых слов можно найти в массиве kAppearanceKTable в файле исходного текста Mozilla content/shared/src/nsCSSProps.cpp.

    В тему Classic включены стили, соответствующие элементам управления Netscape Navigator 4, но они не играют роли, так как используется расширение -moz-appearance. Если -moz-appearance опять задать значение none, снова будут использоваться старые знакомые стили. Чтобы отключить поддержку системных тем, не нарушая работу существующих тем, нужно добавить следующую строчку в соответствующий глобальный css-файл, например, в xul.css или userChrome.css:

    * { -moz-appearance : none ! important; }
    

    В следующем разделе мы увидим, как работают системные темы.

    4.4.5. Пробы тем

    На рисунке 4.10 показано просто окно Mozilla с различными сочетаниями тем. Отображаются три разных XML-страницы. Первые две написаны на XUL, последняя - на HTML. Два XUL-документа отличаются друг от друга только в поддержке таблиц стилей.

    Комбинации системных тем и тем Mozilla


    Рис. 4.10.  Комбинации системных тем и тем Mozilla

    Версия "Без скинов" не включает таблицы стилей вообще, поэтому текущая тема Mozilla не дает ей ничего. Версия "Глобальный скин" содержит глобальный скин текущей темы, чего достаточно для полной поддержки темы. "HTML-страница" показывает, чем отличается использование информации о темах в HTML.

    На всех снимках окон меньше всего меняется тема Modern классической Mozilla, так как в ней почти не используются стили -moz-appearance. Похожим образом HTML-страницам предоставляются стандартные параметры стилей, даже при частом использовании -moz-appearance, как в теме Classic, или когда отсутствует тема, которая могла бы изменить поведение по умолчанию.

    4.4.6. GTK и ресурсы X-Windows

    UNIX-версии Mozilla используют графическую библиотеку GTK, которая, в свою очередь, задействует систему X-Windows. Очень часто приложения для X-Windows оформляются на основе так называемых Xresources, чьи базовые копии в UNIX обычно находятся в /usr/lib/X11/app-defaults. Сразу возникает вопрос, может ли Mozilla оформляться, как и остальные клиенты X11? Ответ: нет, так как библиотека GTK не поддерживает эти ресурсы X11.

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

    Менеджер окон в UNIX может использовать библиотеку GTK, а может и не использовать. В последнем случае для создания стилей этого менеджера можно редактировать Xresources. Примеры менеджеров окон, для которых это справедливо: twm и fvwm2. Но менеджеры окон никак не влияют на содержимое окон.

    4.5. Альтернатива: таблицы стилей

    Вся информация о стилях CSS 2 доступна для использования кнопками и в скинах.

    Предложенный в CSS 3 стиль font-family: button, устанавливающий шрифт, соответствующий шрифту для <button>, можно применить так:

    font-family: -moz-button;
    

    Свойство -moz-appearance, которое отвечает за включение поддержки системных тем, может принимать следующие значения для тегов кнопок, описанных в этой главе:

    button resizer scrollbarbutton_down scrollbarbutton_left 
    scrollbarbutton_right scrollbarbutton_up 
    scrollbargripper_horizontal scrollbargripper_vertical 
    scrollbarthumb_horizontal scrollbarthumb_vertical toolbarbutton 
    toolbargripper
    

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

    4.6. Практика: кнопки и темы для NoteTaker

    В предыдущих двух главах мы добавили в наше приложение NoteTaker структуру размещения элементов интерфейса и основное текстовое содержимое. В этой главе мы добавим кнопки. Наш план таков:

    • сделать кнопки для операций "Сохранить" и "Отмена";
    • временно сделать кнопки для операций "Редактировать" и "Ключевые слова". Далее мы научимся работать с вкладками и у нас для этих элементов управления будут особые кнопки;
    • включить поддержку тем.

    XUL-файл, описывающий окно приложения, над которым мы работаем - единственный файл, в который нам нужно внести существенные изменения. Необходимая правка для добавления кнопок очень проста, как видно из листинга 4.4.

    <!-- change this: --> 
    <text value="Cancel"/>
     <spacer flex="1"/>
     <text value="Save"/>
    <!-- to this: -->
     <button label="Cancel"/>
     <spacer flex="1"/>
     <button label="Save"/>
    <!-- and change this: -->
     <text value="Edit"/>
     <text value="Keywords"/>
    <!-- to this: -->
     <toolbarbutton label="Edit"/>
     <toolbarbutton label="Keywords"/>
    
    Листинг 4.4. Изменения в NoteTaker для превращения текста в кнопки

    После сохранения изменений окно диалога будет похоже на снимок из рисунка 4.11. Кнопка "Ключевые слова" подсвечена, так как во время снимка над ней был указатель мыши.

    NoteTaker с кнопками

    Рис. 4.11.  NoteTaker с кнопками

    Сейчас внешний вид кнопок еще не очень впечатляет. Кроме того, их немного портят границы блоков, которые мы добавили для наглядности во второй главе, "Верстка XUL". Чтобы добавить поддержку тем, нам нужно избавиться от стилей, которые мы временно вставляли в течение предыдущих лекций, и включить глобальный скин текущей темы.

    Глядя на рисунок 4.11, мы хотим избавиться от всех использованных нами стилей текста и, возможно, от некоторых границ блоков. Мы оставим несколько границ, просто чтобы помнить о том, что нам еще нужно сделать. Самая сложная и важная часть работы - найти соответствующие элементы управления, но мы пока знаем только о кнопках. Так что пока отложим замену всех блоков на элементы управления и просто убедимся, что у этих блоков с границами есть атрибут class="temporary", и изменим соответствующее правило стиля для отображения границ. Включения таблицы стилей в XUL-файле изменятся с

    <?xml-stylesheet href="boxes.css" type="text/css"?>
    

    на

    <?xml-stylesheet href="chrome://global/skin/" type="text/css"?> 
    <?xml-stylesheet href="boxes.css" type="text/css"?>
    

    На рисунке 4.12 показан результат этой работы при отображении сначала в теме Classic, а затем в теме Modern.

    NoteTaker с поддержкой тем: темы Classic и Modern

    Рис. 4.12.  NoteTaker с поддержкой тем: темы Classic и Modern

    Из рисунка 4.12 понятно, что <button>, <toolbarbutton> и <groupbox> принимают стандартный внешний вид, основанный на данных темах. Шрифты для текста также изменились.

    Если этот XUL-файл установить в chrome, таблица стилей boxes.css должна находиться с ним в одном каталоге. Этого достаточно для тестирования, но не идеально, если мы хотим полноценно поддерживать темы.

    Чтобы полностью поддерживать темы, требуется изменить следующую строчку в XUL-файле:

    <?xml-stylesheet href="boxes.css" type="text/css"?>
    

    на

    <?xml-stylesheet href="chrome://notetaker/skin/boxes.css" type="text/css"?>
    

    После этого мы переместим файл boxes.css в chrome вот сюда:

    chrome/notetaker/skin/modern/boxes.css
    

    Наконец, нам нужно зарегистрировать этот скин в реестре chrome, как мы регистрировали имя расширения в главе 1, "Основные концепции", и (возможно) файлы локализации в главе 2, "Проектирование с XUL". Это опять подразумевает создание стандартного файла contents.rdf, на этот раз в каталоге skin. В листинге 4.5 приведен текст необходимого RDF.

    <?xml version="1.0"?>
    <RDF
      xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
      xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
      <Seq about="urn:mozilla:skin:root">
        <li resource="urn:mozilla:skin:modern/1.0" />
      </Seq>
      <Description about="urn:mozilla:skin:modern/1.0"> 
        <chrome:packages>
          <Seq about="urn:mozilla:skin:modern/1.0:packages"> 
          <li resource="urn:mozilla:skin:modern/1.0:notetaker"/>
          </Seq>
        </chrome:packages>
      </Description>
    </RDF>
    
    Листинг 4.5. contents.rdf, необходимый для регистрации скина в chrome

    Опять же, чтобы понять, что весь этот RDF значит, придется заглянуть в главы 11-17. Если мы уверены, что скин уже существует (а мы уверены в этом относительно Modern и Classic), атрибуты тега <Description> с префиксом chrome: можно опустить. Что мы здесь и сделали. В первой части файла утверждается, что существует тема modern; во второй, большей, говорится о том, что у расширения NoteTaker есть зависящая от темы информация для данной темы.

    Чтобы все заработало, нужно сделать точную копию этого файла и заменить названия скинов (здесь "modern/1.0") и названия расширения (здесь "notetaker") на то, с чем вы работаете. Название "modern/1.0" включает номер версии, который объявляется в виде записей реестра приложений, описанного в главе 17, "Система распространения и установки - XPInstall". Здесь это всего лишь строчка, которую нам нужно правильно написать. Чтобы узнать ее правильное написание, следует заглянуть в файл contents.rdf в других расширениях, использующих эту тему.

    Наконец, нам нужно обновить файл installed-chrome.txt, чтобы платформа знала о появлении нового скина. Поэтому мы добавим в этот файл следующую строчку, сохраним его, и перезапустим платформу:

    skin,install,url,resource:/chrome/notetaker/skin/modern/
    

    Если мы не скопируем boxes.css и contents.rdf в аналогичное место для скина Classic, нашему приложению будут недоступны стили, которые мы вынесли отдельно.

    Во время тестирования, если только вы не работаете над собственно скином, проще всего хранить все css-файлы в каталоге content и перемещать таблицы стилей в каталог skin только тогда, когда нужно демонстрировать работу приложения.

    Теперь окно NoteTaker начинает походить на окно приложения, а не на какой-нибудь набросок. Мы пока не можем добавлять другие элементы управления по двум причинам: во-первых, наши знания об элементах управления XUL еще ограничены, а во-вторых, мы еще не определились, с какими данными должны иметь дело эти элементы управления.

    Если бы это была книга о проектировании баз данных, дальше последовало бы длинное обсуждение схем и типов. Схема бы обсуждалась с пользователями, о ней бы спорили, наконец, она приняла бы окончательный вид, и для каждого заполнителя в нашем приложении был бы выбран соответствующий тип. Но наша книга не о проектировании баз данных, так что мы пропустим этот шаг. Так как с обычными кнопками не связаны данные (они несут в большей степени функциональную нагрузку, а не информационную), здесь нам в любом случае не нужно проводить никакого анализа данных. Если бы у нас были кнопки-флажки, это было бы совсем другое дело.

    4.7. Отладка: обнаружение ошибок в работе кнопок и скинов

    Для создания темы вам может понадобиться более глубокое понимание того, как кнопки (или любые другие элементы управления) работают со стилями. Таблица 4.1 помогает понять структуру системы стилей, но это очень общий пример. Существует возможность отслеживать самую важную информацию о стилях для элемента управления XUL напрямую. Вот как это делается для тега <button>. Эту же методику можно применить и ко многим другим тегам.

    Прежде всего, нужно взглянуть на файл xul.css. Его URL: chrome://global/content.css, но лучше всего найти его в файле toolkit.jar в chrome и скопировать оттуда. В этом файле находятся одно или несколько правил стилей для каждого XUL-тега. Нас интересует свойство стиля -moz-binding. Для тега <button> оно выглядит так:

    -moz-binding: 
    url("chrome://global/content/bindings/button.xml#button");}
    

    Этот URL указывает на XBL-файл, который также находится в toolkit.jar. Вам не нужно знать XBL, чтобы понимать информацию о стиле. Конечная часть этого URL, #button - имя XBL-связки. Совершенно случайно оно совпадает с именем тега, <button>, но очевидно, что это сделано всего лишь для удобства.

    Если скопировать из архива упомянутый файл button.xml, затем можно найти тег <binding> с атрибутом id="button". В этом теге будет заключаться тег <resources>, а в нем будет находиться тег <stylesheet>. Этот тег <stylesheet> определяет таблицу стилей для элемента управления <button>, и это скин. Его можно прочитать, открыв любой JAR-архив с именем темы, например, classic.jar или modern.jar, так как во всех хорошо написанных темах предоставляются эти стандартные скины.

    Второй сложный вопрос таков: отображаемая кнопка (или другой элемент управления) использует системную тему или нет? В сущности, это не особенно важно, если только вы не рассматриваете полосы прокрутки. У полос прокрутки есть отдельный тег <nativescrollbar>, который используется, когда весь элемент управления должен отображаться в соответствии с системной темой. Если вы действительно хотите знать, применяется ли тема графической среды к вашему элементу управления, проверьте значение свойства -moz-appearance в таблице стилей или с помощью JavaScript. Например, это правило стиля окрашивает в красный цвет все кнопки, использующие системные темы:

    button[-moz-appearance="button"] { background-color:red; }
    

    Этого не рекомендуется делать для общедоступных приложений, так как пользователь контролирует работу тем в браузере, и надеяться на мелкие детали структуры размещения - гарантированный способ создать приложение, чью работу легко нарушить. Если вам действительно нужен полный контроль над внешним видом элементов управления, лучше избегать поддержки тем и предоставлять полный набор таблиц стилей для своего приложения. Как показано на рисунке 4.11, это связано с другими опасностями.

    Чтобы определять проблемы скинов, нужно найти проблему с содержимым.

    Во-первых, попробуйте запустить приложение с явно указанными таблицами стилей, а не стилями. Так можно проверить, согласовано ли содержимое таблицы стилей с XUL-кодом. Если вместе они работают корректно, вероятнее всего, XUL-часть приложения в порядке. Проверьте исходный порядок включения скинов в XUL-файлы. Глобальный скин должен идти первым; затем следуют все скины, специфичные для приложения; последними должны идти особые таблицы стилей, не связанные со скинами. Если и в случае явно указанных таблиц стилей работа некорректна, нужно убедиться с помощью Инспектора DOM, что вы все правильно делаете со стилями, идентификаторами и классами.

    Если кажется, что все в порядке, вероятнее всего, проблема в содержимом файла contents.rdf. Здесь очень легко допустить синтаксические ошибки. Простой способ убедиться, что этот файл корректно читается - проверить содержимое файла chrome.rdf в корневом каталоге chrome.

    Платформа автоматически создает этот файл при каждом просмотре содержимого chrome. Если комбинация скина и расширения (или комбинация из файлов локализации и расширения) не появляется ни в одном из списков этого файла, ваши файлы contents.rdf не могут быть прочитаны или содержат синтаксические ошибки, или их структура неверна. Проверьте их.

    Другая часть этой проблемы - файл installed-chrome.txt, чрезвычайно разборчивый в синтаксисе. После всех имен каталогов в конце строки должна идти наклонная черта, все упоминания файлов локализации должны включать код языка, все записи о скинах должны включть имя скина, а пути в chrome должны начинаться с resource: или jar:.

    4.8. Итоги

    Язык XUL в Mozilla богат разными элементами управления, и тег <button> - простейший из них. Так как понятие кнопки широко распространено, существует множество разных ее вариантов, которые следует принять во внимание. <button> и <toolbarbutton> соответствуют большинству требований. Хотя возможности кнопки делают ее уникальной, для пользователей очень важен и внешний вид. Кнопка должна и выглядеть, и реагировать как кнопка.

    Внешний вид напрямую связан с темами. Основой для тем в Mozilla является технология таблиц стилей CSS 2 плюс несколько хитростей с изменениями URL. Темы применяются к каждому окну XUL-приложения, и каждое окно использует один или несколько скинов данной темы. Скин - это всего лишь набор документов, определяющих стили, которые следуют концепциям дизайна темы плюс несколько связанных со стилями файлов.

    Как приложения могут поддерживать темы через включение таблиц стилей, так и темы поддерживают приложения, реализуя скины для стандартных элементов управления, расширений и целей стилей. Создание этих стандартных скинов - задача дизайнера темы.

    Один из аспектов системы таблиц стилей, который снова возвращает нас к кнопкам и элементам управления - расширение -moz-appearance. Это расширение позволяет XUL-тегу отображаться в соответствии с правилами системной темы, то есть текущей темы графической среды. Благодаря атрибуту -moz-appearance система стилей Mozilla становится частично прозрачной для системных тем. Эта система работает только для тех XUL-тегов, которые совпадают с системными элементами управления. Эта поддержка реализована в теме Classic, но может быть и в любой другой теме.

    Кнопки - лишь первые из многих XUL-тегов для элементов управления в Mozilla. Перед изучением остальных тегов необходимо понять, как заставить тег <button> что-нибудь делать. Для этого нам понадобятся скрипты. Скрипты и язык JavaScript описываются в следующей главе.


    об авторе

    Администрация сайта не несет ответственности за содержание и соблюдение копирайта на материалы,
    найденные в свободном доступе на просторах интернета без указания авторских прав на них.
    Документация предоставляется, размещается и публикуется пользователями сайта с максимально известной информацией об источнике.
    Если Вы являетесь правообладателем представленных статей, и не хотите их здесь видеть - напишите нам, и мы с радостью их удалим с сайта





    Сайт создан в системе uCoz