Опубликован: 10.12.2007 | Уровень: специалист | Доступ: платный
Лекция 9:

Команды

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.

Очевидно, второй пример сложнее первого, но есть серьезные основания считать этот подход лучшим.

Дмитрий Гуменюк
Дмитрий Гуменюк
Россия, Звенигород
Konstantin Grishko
Konstantin Grishko
Россия, Москва, Московский финансово-промышленный университет "Синергия", Москва