CITKIT.ru - свободные мысли о свободном софте
Деловая газета CitCity.ru Библиотека CITForum.ru Форумы Курилка
Каталог софта Движение Open Source Дискуссионный клуб Дистрибутивы Окружение Приложения Заметки Разное
23.10.2017

Последние комментарии

ОСТОРОЖНО: ВИНДОФИЛИЯ! (2250)
24 December, 22:53
Kubuntu Feisty (15)
24 December, 18:42
Один на один с Windows XP (3758)
24 December, 11:46

Каталог софта

Статьи

Дискуссионный клуб
Linux в школе
Open Source и деньги
Open Source и жизнь
Windows vs Linux
Копирайт
Кто такие анонимусы
Лицензии
Нетбуки
Нужен ли русский Linux?
Пользователи
Дистрибутивы
Идеология
Выбор дистрибутива
Archlinux & CRUX
Debian
Fedora
Gentoo
LFS
LiveCD
Mandriva
OpenSolaris
Slackware
Zenwalk
Другие линуксы
BSD
MINIX
Движение Open Source
История
Классика жанра
Окружение
shell
Библиотеки UI
Графические среды
Шрифты
Приложения
Безопасность
Управление пакетами
Разное
Linuxformat. Колонки Алексея Федорчука
Заметки
Блогометки
Файловые системы
Заметки о ядре

Приложения

XUL приложения

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

Конечно, это касается только расширений относительно высокого уровня - тех, для создания которых достаточно функциональности платформы и XUL/XBL/JavaScript. Именно эти технологии мы и рассмотрим.

XUL

XUL - аббревиатура от XML User Interface Language, XML-язык описания пользовательского интерфейса. XUL используется во всех основных продуктах семейства Mozilla. Особенности этого языка определяют легкость работы с ним:

  • это XML, следовательно, если вы знакомы с основами XML, вы знакомы с основами XUL; XML-синтаксис понятен и прост; для этих же целей XML используется и в Qt, и в GTK, и в Avalon, что доказывает эффективность применения XML в разработке пользовательских интерфейсов;
  • в распоряжении разработчика находится большой набор уже готовых элементов управления, при этом создавать свои элементы управления очень можно как на основе стандартых, так и с нуля, все равно это будет несложно (впрочем, это уже более заслуга XBL, и об этом ниже);
  • при создании интерфейса не нужно думать о том, как приложение будет выглядеть в какой-либо ОС, об этом за вас уже подумали; при использовании стандартных элементов управления можно также не беспокоиться о том, как интерфейс будет выглядеть с разными темами;
  • правильно спроектированный интерфейс легко локализуем.

Рассмотрим пример XUL-файла:

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
<?xml-stylesheet href="chrome://helloworld/skin/hello.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://helloworld/locale/hello.dtd">
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&title.label;">
    <vbox align="center">
        <description flex="1" class="bound"/>
        <button label="&close.label;" oncommand="close();"/>
    </vbox>
</window>

Разберем его построчно.

  1. Стандартное объявление XML-файла.
  2. Загрузка таблицы стилей. Мы загружаем глобальную таблицу стилей, которая определяет внешний вид и поведение основных элементов управления. Это объявление не будет меняться, даже если пользователь установит собственную тему.
  3. Загрузка таблицы стилей. Эта таблица стилей может и отсутствовать, однако порой нужно как-то изменить вид или поведение элементов управления, кроме того, XBL-привязки подключаются через CSS.
  4. Указание DTD с сущностями. Сущности используются для того, чтобы можно было локализовать приложение, не трогая разметки интерфейса. В зависимости от выбранного языка пользователя будет загружаться нужный DTD-файл. Если расширение не содержит локализации на нужный язык, используется язык по умолчанию, то есть американский английский. Вот так может выглядеть наш DTD-файл:
    <!ENTITY title.label "Hello World">
    <!ENTITY close.label "Close">
  5. Корневой элемент XUL-документа с указанием пространства имен и заголовком. Наиболее часто, помимо window, используются dialog и wizard. Обратите внимание, что в заголовке вместо текста указана XML-сущность.
  6. Элемент vbox. Практически все элементы графического интерфейса основываются на модели блоков, более того большинство на самом деле являются box-ами с расширенной функциональностью. vbox выстраивает свое содержимое вертикально, hbox - горизонтально, однако это всего лишь синонимы для элемента box с разными значениями атрибута orient.
  7. Элемент description может содержать как другие элементы, так и обычный текст. Значение атрибута flex означает, что элемент может занимать больше места, чем это ему необходимо - растягиваться до внутренних границ родительского элемента. Атрибут class имеет тот же смысл, что и в HTML, в данном случае мы сами придумали название класса (это нам понадобится позже).
  8. Элемент, означающий простую кнопку. Кнопок на самом деле великое множество - переключатели, флажки и т.д.; кнопки могут содержать изображения. Все, как в HTML! Атрибут label содержит надпись на кнопке, а атрибут oncommand задает обработчик события command - нажатия на кнопку. Так как это стандартная функция, нам не нужно было импортировать файл с ее телом.

Такой файл представляет собой простейшее самостоятельно окно.

Снимок простейшего окна
Рис. 1. Снимок простейшего окна

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

<?xml version="1.0"?>
<!DOCTYPE overlay SYSTEM "chrome://helloworld/locale/overlay.dtd">
<overlay id="helloworld-overlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <script src="overlay.js"/>
    <menupopup id="menu_HelpPopup">
        <menuitem id="helloworld-hello" label="&helloworld;"
        oncommand="HelloWorld.onMenuItemCommand(event);"/>
    </menupopup>
</overlay>

Разберем его построчно.

  1. Уже знакомое нам объявление DTD-файла для разрешения сущностей.
  2. Начало фрагмента, содержащего изменения интерфейса с указанием пространства имен и идентификатор оверлея.
  3. Загрузка сценария с обработчиком (и вообще с нужными нам функциями).
  4. Следующие две строчки означают, что изменению подвергнется меню с идентификатором menu_HelpPopup: мы добавим еще один пункт меню, при выборе которого будет вызван указанный обработчик.

Добавление пункта меню с помощью оверлея
Рис. 2. Добавление пункта меню с помощью оверлея

Для того чтобы оверлеи действительно заработали, их нужно зарегистрировать в chrome [1].

JavaScript

XUL определяет внешний вид приложения, но оно должно еще и что-то делать. Логика приложений/расширений пишется на JavaScript (хотя на самом деле можно пользоваться не только им, но интерпретатор JavaScript является частью Gecko - ядра, и это проще всего). Это достаточно простой и популярный язык, а веб-разработчикам его и вовсе не нужно будет осваивать специально. Документация по JavaScript доступна как на сайте Mozilla, так и на многих других сайтах. Это стандартизованный язык (см. набор стандартов ECMAScript).

Вот как может выглядеть файл, импортируемый нами в оверлее выше:

var HelloWorld = {
    onLoad: function() {
        // initialization code
        this.initialized = true;
    },
    onMenuItemCommand: function() {
        window.open("chrome://helloworld/content/hello.xul", "", "chrome");
    }
};
window.addEventListener("load", function(e) { HelloWorld.onLoad(e); }, false);
  1. onLoad: мы определяем объект HelloWorld, при загрузке которого выполняется инициализация.
  2. onMenuItemCommand: обработчик события выбора пункта меню открывает новое окно (в нашем случае это будет самое первое окно с кнопкой).
  3. Подписываемся на оповещение о загрузке окна для выполнения кода инициализации.

При написании сценариев для расширений нужно помнить, что имена функций должны быть уникальными, либо нужно прямо указывать, для какого именно объекта вызывается функция. Причина в том, как определяется область видимости.

Во-первых, есть традицонное определение области видимости переменных - локальные и глобальные. Во-вторых, простой набор инструкций, заключенных в фигурные скобки ({}) не создает отдельной области видимости. В-третьих, допустимо использование переменных, объявленных хоть где-нибудь в данном блоке кода, например, следующий код не вызовет исключения:

function f() {
    alert(x); // значение "undefined"
    var x = 1;
    alert(x); // значение "1"
}

Наконец, есть понятие цепочек областей видимости. Цепочка представляет собой упорядоченный список объектов. При вызове функции интерпретатор просматривает все объекты по порядку вплоть до глобального объекта (например, window) и как только находит подходящую функцию, вызывает ее. Таким образом можно пользоваться функциями, определенными в других объектах.

Кроме того, в JavaScript поддерживаются замыкания (closures), а в конструкторах для создания наследования используются прототипы, а не классы. С недавних пор в сценариях можно использовать текст в UTF-8.

XBL

XUL позволяет как определять новые элементы, отсутствующие в стандартном наборе (см. архив toolkit.jar в каталоге chrome/), так и переопределять внешний вид, содержимое и поведение стандартных. Для этого используется XBL, XML Binding Language.

Вернемся к самом первому XUL-файлу. Напомню, что там были такие строчки:

<?xml-stylesheet href="chrome://helloworld/skin/hello.css" type="text/css"?>
...
<description flex="1" class="bound"/>

Обе они нужны нам в данном случае только для того, чтобы переопределить элемент description, то есть создать новую XBL-привязку.

Обычно элемент description используется примерно так:

<description>
    Здесь может быть текст.
    <box>Или другие элементы.</box>
</description>

Мы создадим новый класс (bound) таких элементов, который будет содержать изображение. У нас может получиться такой XBL-файл:

<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <binding id="bound">
        <content>
            <xul:hbox>
                <xul:image
                src="chrome://helloworld/skin/penguin_group.gif"/>
            </xul:hbox>
        </content>
    </binding>
</bindings>

Разберем его.

  1. Корневой элемент у этого файла - bindings. Один файл может содержать несколько привязок (binding).
  2. У каждой привзяки должен быть уникальный в этом файле идентификатор.
  3. Элемент content определяет, что на самом деле будет показываться. В нашем случае это изображение.

Подключаются привязки в CSS-файлах. Нам нужно будет написать:

description.bound {
    -moz-binding: url('chrome://helloworld/skin/hello.xml#bound');
}

Кроме того, у элемента binding могут быть следующие потомки:

  • resources - для подключения дополнительных стилей и изображений;
  • implementation - для определения методов, которые можно будет вызывать для создаваемого (изменяемого) элемента управления, и свойств;
  • handlers - для определения обработчиков событий.

Также у binding есть примечательные атрибуты:

  • extends указывает, что привязка расширяет функциональность другого элемента, который используется как базовый;
  • inherits определяет, будет ли привязка использовать стили, связанные с переопределяемым элементом изначально.

Сборка и установка расширений

Теперь нужно собрать расширение в единое целое. Для начала расположим наши файлы в правильном порядке:

chrome/
	helloworld.jar <- ZIP-архив
		content/
			hello.xul
		    	overlay.js
			overlay.xul
		locale/
			en-US/
				hello.dtd
				overlay.dtd
		skin/
			hello.css
		hello.xml
		penguin_group.gif
chome.manifest
install.rdf

Каталоги content, locale и skin могут называться и по-другому, но принято называть их именно так. Они содержат неизменную часть приложения, файлы локализации и файлы внешнего вида соответственно. Расширение также может содержать только content - просто расширять функциональность, - только locale - пакет локализации - или только skin - тема. helloworld.jar - обычный ZIP-архив.

Из chrome.manifest основное приложение сможет узнать, какие именно части содержит регистрируемое расширение. Нам нужно зарегистрировать все, включая один оверлей:

content  helloworld  jar:chrome/helloworld.jar!/content/
locale   helloworld  en-US        jar:chrome/helloworld.jar!/locale/en-US/
skin     helloworld  classic/1.0  jar:chrome/helloworld.jar!/skin/
overlay  chrome://browser/content/browser.xul  chrome://helloworld/content/overlay.xul

Файл install.rdf нужен для регистрации в менеджере расширений. В нашем случае он может быть таким:

<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
    <Description about="urn:mozilla:install-manifest">
        <em:id>helloworld@mozilla.doslash.org</em:id>
        <em:name>Hello World (Firefox 1.5 edition)</em:name>
        <em:version>1.0.1</em:version>
        <em:description>Modified classic first extension from MozillaZine KB</em:description>
        <em:creator>Nickolay Ponomarev</em:creator>
        <em:contributor>Put your name here</em:contributor>
        <em:targetApplication>
        <!-- Firefox -->
            <Description>
                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                <em:minVersion>1.5</em:minVersion>
                <em:maxVersion>1.5.0.*</em:maxVersion>
            </Description>
        </em:targetApplication>
    </Description>
</RDF>

Теперь все содержимое каталога кладем в ZIP-архив с именем helloworld.xpi. Все!

Менеджер расширений с новым расширением
Рис. 3. Менеджер расширений с новым расширением

О чем не было сказано (самое интересное)

XulRunner

На самом деле на XUL можно писать не только расширения к Firefox, Thunderbird, Seamonkey и т. д., на XUL можно писать и полноценные приложения. С 2005 г. разработчики mozilla.org предлагают пользоваться также Xulrunner, который позволяет это делать. При этом:

  • такое приложение запускается в отдельном процессе;
  • совершенно не зависит от Firefox/Thunderbird/..., поэтому они могут быть даже не установлены.

Есть и минусы, например, вам придется включать в свой дистрибутив сам Xulrunner, а значит, объем дистрибутива станет примерно на 13 Мб больше.

XUL и веб

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

Также существует проект по интеграции XUL и JSF.

RDF (и datasources вообще) и шаблоны

При создании некоторых приложений сложно заранее узнать, какое именно количество данных придется отображать (например, вы пишете клиент к базе данных). В этом случае можно использовать XUL-шаблоны: вы просто указываете, какие данные будут получены, как их отображать и откуда из брать. В будущем, возможно, шаблоны будут заменены на XSLT-преобразования. RDF (Resource Description Framework) - XML-формат, который используется для хранения различных данных. К сожалению, на данный момент такие источники данных - единственные, которые разработчики могут использовать сразу же. Однако уже сейчас доступно расширение mozStorage для работы с SQLite.

О защите

Расширения можно подписывать. В Firefox (начиная с версии 1.5) можно осуществлять безопасный доступ из XUL-приложений к незащищенному содержимому - веб-страницам, тогда можно быть уверенным, что нужные функции не будут замещены сценариями с веб-страницы.

XPCOM

XPCOM - Cross-platform Component Object Model. Как только вам перестанет хватать стандартной функциональности платформы (скажем, вы хотите реализовать поддержку нового протокола), вам придется искать или писать самостоятельно нужный XPCOM-компонент. Это уже более низкий уровень разработки, который потребует от вас знания C++, но и здесь нет ничего сложного, тем более что на сайте mozilla.org достаточно документации. Создав такой компонент, вы можете легко получить нужную функциональность в обычном JavaScript-сценарии.

Инструменты разработки

  • XulDev, среда разработки
  • EclipseXUL, модуль для среды разработки Eclipse
  • XulUnit, платформа для тестирования XUL-приложений
  • Venkman, отладчик JavaScript
  • DOM Inspector, инструмент для просмотра дерева DOM любых веб-документов или XUL-приложений
  • Поддерживаемые платформы

    • Linux
    • Windows
    • MacOS X
    • FreeBSD
    • Solaris
    • OS/2
    • Любая другая, на которой вы сможете собрать Mozilla

    Да, если вы вдруг думаете, что на XUL можно писать только расширения, вы ошибаетесь. На XUL уже написаны: несколько браузеров, почтовый клиент, HTML-редактор, календарь, IRC-клиент, Jabber-клиент, отладчик JavaScript и полноценная среда разработки - Komodo.

    Дополнительная информация

    Англоязычные ресурсы:

    Русскоязычные ресурсы:

    Файлы, использующиеся в тексте:

    Примечания

    [1] Возможное происхождение термина chrome.

    From Jargon File (4.3.1, 29 Jun 2001) [jargon]:
    
      chrome n. [from automotive slang via wargaming] Showy features added to
         attract users but contributing little or nothing to the power of a
         system. "The 3D icons in Motif are just chrome, but they certainly are
         _pretty_ chrome!" Distinguished from {bells and whistles} by the fact
         that the latter are usually added to gratify developers' own desires for
         featurefulness. Often used as a term of contempt.
    




    Новости:

    Все новости на CitCity.ru

    Компании месяца

     
    Последние комментарии
    Почему школам следует использовать только свободные программы (101)
    20 Декабрь, 14:51
    ОСТОРОЖНО: ВИНДОФИЛИЯ! (2250)

    24 Декабрь, 22:53
    Linux в школе: мифы про школу и информатику (334)
    24 Декабрь, 22:43
    Kubuntu Feisty (15)
    24 Декабрь, 18:42
    Software is like sex: it's better when it's free.
    ©Linus Torvalds