Россия, Звенигород |
Команды
9.1. Команды и Mozilla
Система команд Mozilla - одна из менее очевидных сторон платформы, и, но в то же время она мощная и гибкая. Она позволяет программисту думать о функциональности приложения как о наборе сообщений. Каждое сообщение - или команда, или о команде. При правильном применении система команд действует как точка интеграции и организации функций приложения. Использование команд в собственно классической Mozilla организовано неплохо, но часть ее также похоронена под грузом другого кода.
Система команд Mozilla спроектирована для поддержки сложных приложений. Простым приложениям команды не нужны; они могут обойтись и простыми обработчиками событий. Для сложных приложений целью Mozilla было предоставить систему, в которой:
- элементы пользовательского интерфейса могут пользоваться одной командой, даже если они находятся в разных файлах с исходными текстами;
- у команд может быть собственное состояние, которое можно менять и о котором можно сообщать;
- команды и элементы управления могут добавляться и меняться независимо;
- могли бы разобраться все типы программистов, а не только авторы приложений;
- существовала бы осмысленная реакция по умолчанию;
- простые случаи использования поддерживались бы простым синтаксисом;
- повторно использовалась система событий DOM, где это возможно.
Найти команду в Mozilla очень легко. Простые операции вроде сохранения файла, добавления закладки, выбора содержимого, выделения полужирным шрифтом, прокрутки страницы или отмены - все это команды.
Обнаружить команду в терминах исходного кода не так легко. Самый очевидный признак команды - простая строка, чье имя - имя команды. Такие имена могут определяться платформой или программистом приложения. К сожалению, остальная часть инфраструктуры команд довольно сильно разбросана по платформе. Части системы команд есть в XUL, JavaScript, XPCOM, существующих файлах chrome и внутренностях платформы.
9.1.1. Hello, World
Простой пример использования системы команд приведен в листинге 9.1.
<?xml version="1.0"?> <!DOCTYPE window> <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <command id="hello" oncommand="alert('hello, world');"/> <button label="Say It" command="hello"/> </window>Листинг 9.1. Пример "hello, world", реализованный как команда Mozilla
Тег <command> реализует команду, в данном случае простой обработчик событий, который вызывает alert(). Тег <button> идентифицирует эту команду по имени. Когда мы нажимаем кнопку, генерируется событие DOM 2 специального типа command, и идентифицированная команда захватывает это событие и запускается. Результатом будет появление окошка alert().
Команды не всегда столь просты, и не всегда основаны на обработке события. Если реализовать эту команду на JavaScript, эффект, вызываемый кодом листинга 9.2, будет тот же, что и в листинге 9.1.
<?xml version="1.0"?> <!DOCTYPE window> <window xmlns= "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script> var control = { supportsCommand : function (cmd) { return true; }, doCommand : function (cmd) { alert(cmd + ", world"); }, isCommandEnabled : function (cmd) { return true; }, onEvent : function (event_name) {} }; window.controllers.appendController(control); function execute(cmd) { var disp = document.commandDispatcher var cont = disp.getControllerForCommand(cmd); cont.doCommand(cmd); } </script> <button label="Say It" onclick="execute('hello')"/> </window>Листинг 9.2. Пример hello, world, реализованный как команда на JavaScript.
Этот код описывает объект control, реализующий команду; фактически, данный объект может реализовать несколько команд. Команда реализована в методе doCommand(). Затем объект нужно встроить в инфраструктуру команд платформы. Он будет вызываться каждый раз, когда потребуется выполнить данную команду. И, наконец, команда может быть вызвана в любом месте документа XUL с помощью функции execute(). В данном случае удобно использовать обработчик onclick.
Очевидно, второй пример сложнее первого, но есть серьезные основания считать этот подход лучшим.