Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Фреймворк Jitsi

Глава 10 из книги "Архитектура приложений с открытым исходным кодом", том 1.

Оригинал: "Jitsi", глава 10 из 1 тома книги "The Architecture of Open Source Applications"
Автор: Emil Ivov
Перевод: Н.Ромоданов

10.6. Сервис пользовательского интерфейса

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

Первое, что приходит на ум, это - плагины. Плагинам в Jitsi часто нужно иметь возможность взаимодействовать с пользователем. Это означает, что они должны открывать, закрывать, перемещать или добавлять компоненты в существующие окна и панели в интерфейсе пользователя. Это то место, где в игру вступает наш сервис UIService. Он позволяет управлять основным окном в Jitsi, а также тем, как наши иконки будут позволять пользователям управлять приложением из dock-меню в Mac OS X или из области уведомлений в Windows.

Кроме простого использования списка контактов, плагины также могут выполнять дополнительные действия. Хорошим примером такого плагина является плагин, реализующий в Jitsi поддержку шифрования чата (OTR). Нашей сборке OTR необходимо зарегистрировать несколько графических компонентов в различных частях пользовательского интерфейса. Она добавляет кнопку замка в окно чата и подраздел в меню всех контактов, которое открывается правой кнопкой мыши.

Хорошо то, что он может делать все это с помощью вызова нескольких метода. В активаторе OSGi для сборки OTR, т. е. в OtrActivator, содержатся следующие строки:

Hashtable<String, String> filter = new Hashtable<String, String>();

// Регистрируем элемент меню, открывающегося правой кнопкой.
filter(Container.CONTAINER_ID,
    Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU.getID());

bundleContext.registerService(PluginComponent.class.getName(),
    new OtrMetaContactMenu(Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU),
    filter);

// Регистрируем элемент меню панели меню окна чата.
filter.put(Container.CONTAINER_ID,
           Container.CONTAINER_CHAT_MENU_BAR.getID());

bundleContext.registerService(PluginComponent.class.getName(),
           new OtrMetaContactMenu(Container.CONTAINER_CHAT_MENU_BAR),
           filter);

Как вы можете видеть, добавление компонентов в наш графический интерфейс пользователя просто сводится к регистрации сервисов OSGi. С другой стороны, наша реализация UIService выполняет поиск собственной реализации интерфейса PluginComponent. Всякий раз, когда она обнаруживает, что была зарегистрирована новая реализация, она получает ссылку на нее и добавляет ее в контейнер, указанный в фильтре сервиса OSGi.

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

// Поиск компонентов плагина, зарегистрированных через контекст сборки OSGI.
ServiceReference[] serRefs = null;

String osgiFilter = "("
    + Container.CONTAINER_ID
    + "="+Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU.getID()+")";

serRefs = GuiActivator.bundleContext.getServiceReferences(
        PluginComponent.class.getName(),
        osgiFilter);
// Проходим по всем плагинам, которые найдем, и добавляем их в меню.
for (int i = 0; i < serRefs.length; i ++)
{
    PluginComponent component = (PluginComponent) GuiActivator
        .bundleContext.getService(serRefs[i]);

    component.setCurrentContact(metaContact);

    if (component.getComponent() == null)
        continue;

    this.add((Component)component.getComponent());
}

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


Продолжение статьи: Усвоенные уроки и Благодарности.