Показаны сообщения с ярлыком eclipse. Показать все сообщения
Показаны сообщения с ярлыком eclipse. Показать все сообщения

пятница, 27 марта 2009 г.

@author и Eclipse

Как правило достаёт постоянно исправлять в шаблоне кода значение тега JavaDoc - @author с невнятного имени учётной записи на что-то более понятное.
Решение элементарно и найдено первым-же запросм в google здесь.
Надо определять переменную user.name, что-то типа

eclipse -vmargs -Duser.name="Evgeny P. Florov"

вторник, 17 июня 2008 г.

TabbedPropertySheet vs PropertySheet

В Eclipse в настоящее время реализованы два механизма отображения свойств в PropertyView:
  • PropertySheet - "обычное" представление в виде двухколоночной таблицы "имя параметра" / редактор значения. Поддержка реализуется через наследования от IPropertySource (или с помощью адаптирования). Очень просто реализуется для простых свойств. Подробнее можно почитать здесь
  • TabbedPropertySheet - представление в виде закладок на которых размещаются созданные "вручную" секции с редакторами свойств. Реализуется относительно сложнее, зато результат более адаптирован задачам, то есть более подходит в случае реализации редакторов "сложных" свойств. Подробнее можно почитать здесь.
Однако основной вопрос для меня был: "как можно выбрать какую реализацию будет применять Eclipse для отображения свойств моего view". Оказалось всё просто. Необходимо перегрузить метод getAdapter для вашего view с тем , чтобы он адаптировал ваше view к IPropertySheet:

для PropertySheetPage

public Object getAdapter(Class adapter) {
if (adapter == IPropertySheetPage.class)
return new PropertySheetPage();
return super.getAdapter(adapter);
}

для TabbedPropertySheet
 
public Object getAdapter(Class adapter) {
if(adapter.equals(IPropertySheetPage.class))
return new TabbedPropertySheetPage(new ITabbedPropertySheetPageContributor(){
@Override
public String getContributorId() {
return "MyContributorID";
}
});
return super.getAdapter(adapter);
}


Все это также применимо к CommonNavigator. Для меня была не совсем очевидной сама возможность наследования от CommonNavigator. Но эксперимент показал, что всё нормально :)
Единственное надо не забыть указать именно свой класс-потомок CommonNavigator в объявлении расширения "org.eclipse.ui.views".

К сожалению не удалось обойтись без наследования. Так как определение фабрики/адаптера CommonNavigator к IProperySheePage не работает. Видимо из какого-то модуля аналогичный адаптер уже регистрируется.

четверг, 12 июня 2008 г.

Использование внешних библиотек plugin'ах Eclipse

Для того, чтобы использовать в plugin'ах классы из внешних библиотек их (jar'ы) придётся включать (физически) внутрь нашего plugin'а.
Разместив jar внутри какой-либо папки проекта plugin'а необходимо в редакторе манифеста на вкладке Runtime в блоке classpath добавить этот самый файл библиотеки.



Для того, чтобы не включать одни и те-же библиотеки в каждый plugin, можно их обернуть в специальный plugin, который в свою очередь экспортирует нужные пакеты для других plugin'ов. Для этого на той-же вкладке Runtime нужно добавить необходимые пакеты в поле Exported pakages




Необходимо отметить, что экспорт пакетов будет доступен только если plugin был сделан как java проект.

Bug при запуске Eclipse 3.4.0

При работе в Eclupse 3.4.0 (Ganimede RC4) обнаружился такой баг - попытка запустить среду на отладку (с целью отладить plug'in) запуск останавливается с ошибкой:

org.eclipse.swt.SWTError: XPCOM error -2147467262
at org.eclipse.swt.browser.Mozilla.error(Mozilla.java:1597)
at org.eclipse.swt.browser.Mozilla.setText(Mozilla.java:1820)
at org.eclipse.swt.browser.Browser.setText(Browser.java:733)
...

исследование вопроса привело сюда. Тут же указан обходной рецепт. Для меня он выглядел как указание в конфигурации отладки параметра:
-Dorg.eclipse.swt.browser.XULRunnerPath=/dev/null.

Что и помогло в итоге. Может и Вам поможет.

понедельник, 5 мая 2008 г.

Адаптеры Eclipse

Перевод статьи:
ECLIPSE ADAPTERS
A HANDS-ON, HAND-HOLDING EXPLANATION

Copyright © 2007 Jeffrey Ricker LLC
November 1, 2007
http://www.jeffreyricker.com

Из яблок в апельсины.


Когда вы создаёте plug-in'ы Eclipse - вы быстро сталкиваетесь лицом к лицу с адаптерами. Если вы не достаточно хорошо понимаете шаблон adapter, то адаптеры могут сбить вас с толку. Адаптеры Eclipse на самом деле очень просты. Я постараюсь сделать их ещё проще с помощью данной статьи.

Адаптеры работают по простой схеме: Получив некоторый адаптируемый объект А, дайте мне соотвествующий ему объект типа Б. Интерфейс адаптера Eclipse показан на листинге 1. Интерфейс возвращает объект который является экземляром указанного класса, который (экземпляр) ассоциирован с объектом или null, если такой ассоциированный объект не существует.

Листинг 1 интерфейс адаптера в Eclipse

package org.eclipse.core.runtime;
public interface IAdaptable {
public Object getAdapter(Class adapter);
}


Если я хочу перейти от яблок к апельсинам, то я должен сделать что-то похожее на Листинг 2. В данном случае IApple расширяет интерфейс IAdaptable.

Листинг 2 Адаптирование от яблок к апельсинам

IApple macintosh = new Macintosh();
IOrange orange = (IOrange) macintosh.getAdapter(IOrange.class);
if (orange==null)
log("No orange");
else
log("Created a "+ orange.getClass().getCanonicalName());


Одним из первичных применений адаптеров является разделение кода модели откода представлений (views) в шаблонах view-model-controller или view-model-presenter. Мы не хотим помещать информацию отображения (такую как иконки) в нашу модель яблока. Мы создаём отдельный класс для отображения яблока. Мы сделаем это с адаптерами как показано на Листенге 3.

Листинг 3. Использование адаптеров для отделения модели от представления

IApple apple = new Macintosh();
ILableProvider label = (ILabelProvider)apple.getAdapter(ILabelProvider.class);
String text = label.getText(apple);


Адаптеры позволяют нам преобразовывать объекты к другим видам (целям), о которые эти объекты могут ничего не знать. Например, объекты "яблоки" в Листинге 3 не должны знать что-либо о постащике ярлыков (label provider). Мы можем реализовать метод getAdapter() вручную для каждого объекта яблока, но это противоречит нашим целям. Вместо этого мы должны переложить адаптацию на платформу, как показано на Листинге 4.

Листинг 4 Адаптирование с помощью платформы

public abstract class Fruit implements IAdaptable{
public Object getAdapter(Class adapter){
return Platform.getAdapterManager().getAdapter(this, adapter);
}
}

Фабрики адаптеров


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

Листинг 5. Фабрика адаптеров яблок в апельсины

package com.jeffricker.fruit;
import org.eclipse.core.runtime.IAdapterFactory;
import com.jeffricker.fruit.apples.IApple;
import com.jeffricker.fruit.apples.Macintosh;
import com.jeffricker.fruit.oranges.IOrange;
import com.jeffricker.fruit.oranges.Mandarin;
/**
* Converts apples to oranges
* @author Ricker
*/
public class OrangeAdapterFactory implements IAdapterFactory {
public Object getAdapter(Object adaptableObject, Class adapterType) {
if (adapterType == IOrange.class) {
if (adaptableObject instanceof Macintosh) {
return new Mandarin();
}
}
return null;
}
public Class[] getAdapterList() {
return new Class[]{ IOrange.class };
}
}


Листинг 5 показывает фабрику адаптеров конвертирующих яблоки в апельсины. Фабрика позволяет поведение показанное на Листинге 2. Мы рассмотрим детально его поведение:
  • adaptableObject - объект, с которого мы начали - яблоко. adaptableObject - всегда экземпляр объекта;
  • adapterType - объект к которому мы адаптируем - апельсин. adapterType - всегда имеет тип class, а не экземпляр объекта.
  • Список адаптеров - это список типов классов к которым данная фабрика может адптировать объекты. В нашем случае - это только апельсины.
Мы должны регистрировать фабрику в платформе Eclipse для того, чтобы она была полезной. Листинг 6 показывает регистрационную запись из файла манифеста plug'in. Точка расширения- org.eclipse.core.runtime.adapters. Это то место, в котором я прошу быть максимально внимательным. adaptableType - это то, что из чего мы адаптируем. В нашем случае - яблоки.adapter - то во что мы адаптируем. В этом случае - апельсины.

Листинг 6 Регистрация фабрики адаптеров

<extension
point="org.eclipse.core.runtime.adapters">
<factory
adaptableType="com.jeffricker.fruit.apples.IApple"
class="com.jeffricker.fruit.OrangeAdapterFactory">;
<adapter
type="com.jeffricker.fruit.oranges.IOrange">
<⁄adapter>
<⁄factory>
<⁄extension>


Допускается несколько записей adapter на одну фабрику. Адаптеры перечисленные в точке расширения должны быть такими-же как те, которые предоставляются методом getAdapterList() в фабрике адаптера.
Если мы вместе посмотрим на листинг и проследим логику, то адаптеры станут понятнее.
1. Мы создаём экземпляр объекта Macintosh.

IApple macintosh = new Macintosh();

2. Мы просим Macintosh адаптироваться к IOrange

IOrange orange = (IOrange) macintosh.getAdapter(IOrange.class);

3. Объект Macintosh переадресует запрос платформе

public Object getAdapter(Class adapter){
return Platform.getAdapterManager().getAdapter(this, adapter);
}

4. Платформа находит в реестре подходящую фабрику адаптеров

<factory
adaptableType="com.jeffricker.fruit.apples.IApple"
class="com.jeffricker.fruit.OrangeAdapterFactory">
<adapter type="com.jeffricker.fruit.oranges.IOrange"⁄>
<⁄factory>

5. Платформа вызывает метод фабрики, передавая в него экземпляр объекта Macintosh и тип класса IOrange.
6. Фабрика адаптеров создаёт экземпляр объекта Mandarin

public Object getAdapter(Object adaptableObject, Class adapterType) {
if (adapterType == IOrange.class) {
if (adaptableObject instanceof Macintosh) {
return new Mandarin();
}
}
return null;
}

Точкой преткновения для меня является параметр adaptableType в точке расширения. В интерфейсе фабрики адаптеров на это нет указания. Это скрыто внутри логики метода getAdapter() фабрики. Его присутсвие в реестре становится понятным, когда вы начинаете думать об этом. Мы запрашиваем платформу найти адаптер для объекта Macintosh. Фабрики должны быть каким-либо способом привязаны к иерархии классов Macintosh. В нашем случае фабрика зарегистрирована с IApples. Рисунок 1 показывает взаимосвязи между объявлениями в реестре точки расширения и классом фабрики адаптера.


Рисунок 1. Взаимосвязи между фабрикой и точкой расширения

Пример поставщика представления


Адаптирование яблок к апельсинам безусловно глупый пример, но я расширил пример до чего-то более уместного. В Листинге 3 я показал адаптацию объекта яблока к ILabelProvider - интерфейсу, который используется компонентами JFace для отображения. Фабрика для этих целей показана на Листинге 7. Регистрация приведена в Листинге 8 и набросок поставщиков показан в листинге 9.
Если вы посмотрите классы поставщиков сгенерированные с помощью Eclipse Modeling Framework (EMF), то увидите, что концепция данного примера следует их логике.

Листинг 7. Фабрика поставщика фруктов для отображения фруктов в компонентах JFace

package com.jeffricker.fruit.provider;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import com.jeffricker.fruit.apples.IApple;
import com.jeffricker.fruit.oranges.IOrange;
public class FruitProviderAdapterFactory implements IAdapterFactory {
private AppleProvider appleProvider;
private OrangeProvider orangeProvider;
/** The supported types that we can adapt to */
private static final Class[] TYPES = {
FruitProvider.class, ILabelProvider.class, IContentProvider.class };
public Object getAdapter(Object adaptableObject, Class adapterType) {
if ((adapterType == FruitProvider.class)||
(adapterType == ILabelProvider.class)||
(adapterType == IContentProvider.class)){
if (adaptableObject instanceof IApple)
return getAppleProvider();
if (adaptableObject instanceof IOrange)
return getOrangeProvider();
}
return null;
}
public Class[] getAdapterList() {
return TYPES;
}
protected AppleProvider getAppleProvider(){
if (appleProvider == null)
appleProvider = new AppleProvider();
return appleProvider;
}
protected OrangeProvider getOrangeProvider(){
if (orangeProvider == null)
orangeProvider = new OrangeProvider();
return orangeProvider;
}


Листинг 8. Регистрация фабрики адаптера провайдера фруктов

<extension
point="org.eclipse.core.runtime.adapters">
<factory
adaptableType="com.jeffricker.fruit.IFruit"
class="com.jeffricker.fruit.provider.FruitProviderAdapterFactory">
<adapter
type="com.jeffricker.fruit.provider.FruitProvider">
<⁄adapter>
<adapter
type="org.eclipse.jface.viewers.IContentProvider">
<⁄adapter>
<adapter
type="org.eclipse.jface.viewers.ILabelProvider">
<⁄adapter>
<⁄factory>
<⁄extension>


Листинг 9. Классы поставщиков

package com.jeffricker.fruit.provider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
public abstract class FruitProvider implements
ILabelProvider, IContentProvider {
...
}
/**
* Provides the display of IApple objects
*/
public class AppleProvider extends FruitProvider{
public String getText(Object element){
...
}
public Image getIcon(Object element){
...
}
}
/**
* Provides the display of IOrange objects
*/
public class OrangeProvider extends FruitProvider {
...
}

Реальный пример


Eclipse Communication Framework (ECF) начинался как способ встраивания механизма сообщений в платформу Eclipse. Но в итоге он был расширен для реализации множества способов совместного использования данных в Eclipse Rich Client Platform (RCP).
ECF начинался с простого интерфейса называемого контейнер и использования шаблона Eclipse - IAdaptable для достижения кокретной функцинальности. Если мы будем использовать ECF для встроенного обмена сообщениями, то мы должны сфокусироваться на адаптации контейнера к presence и другим интерфейсам.
Листинг 10 показывает как создать ECF контейнер. Контейнер предоставляет основные виды обработки любых типов протоколов уровня сессий. Листинг 11 показывает как адаптировать контейнер к managing presence, основной особенности встроенного обмена сообщениями. Шаблон контейнер-адаптер отделяет протоколы уровня сессий от служб предоставляемых поверх этих протоколов.

Листинг 10. Создание ECF соединения

// make container instance
IContainer container = ContainerFactory.getDefault()
.createContainer("ecf.xmpp");
// make targetID
ID newID = IDFactory.getDefault()
.createID("ecf.xmpp","slewis@ecf1.osuosl.org");
// then connect to targetID with null authentication data
container.connect(targetID,null);


Листинг 11. Адаптирование контейнера к необходимой функциональности

IPresenceContainer presence = (IPresenceContainer)container
.getAdapter(IPresenceContainer.class);
if (presence != null) {
// The container DOES expose IPresenceContainer capabilities
} else {
// The container does NOT expose IPresenceContainer capabilities
}


Возможности широки. Например, мы можем создать собственный адаптер называемый IMarketDataContainer, который предоставляет потоковые рыночные данные. Мы можем создать его также как IPresenceContainer. Как показано в Листинге 12, различные поставщики рыночных данных могут иметь различные протоколы уровня сессий, например собственные закрытые протоколы, но шаблон контейнер-адаптер позволит нам включить всех их в Eclipse RCP одним и тем-же способом.

Листинг 12. Новые типы контейнеров для ECF

IContainer container = ContainerFactory.getDefault()
.createContainer("md.nyse");
ID newID = IDFactory.getDefault().createID("md.nyse","feed@jeffricker.com");
container.connect(targetID,null);
IMarketDataContainer marketData = (IMarketDataContainer)container
.getAdapter(IMarketDataContainer.class);


Шаблон адаптеров является мощным инструментом, который используется повсюду в платформе Eclipse. I hope with the hands-on, hand holding explanation in this article that you can now unleash that power in your own RCP applications.

воскресенье, 23 декабря 2007 г.

Eclipse.PlatformPluginDeveloperGuide.navigatorContent

Вольный перевод раздела руководства разаботчика plug-in'ов для Eclipse.
Выполнен - Флоров Евгений.
Будет пополняться постепенно.


...



suppressedExtensionId CDATA #REQUIRED
policy (InvokeOnlyIfSuppressedExtAlsoVisibleAndActive|InvokeAlwaysRegardlessOfSuppressedExt) "InvokeAlwaysRegardlessOfSuppressedExt">

В случае, если для данного элемента срабатывает как выражение triggerPoints у подавляемого расширения, так и у объявляемого расширения, то данное расширение будет вызвано, а подавленное им расширение - нет. Клиенты, которые указывают перекрываемый элемент должны также предоставлять поставщика содержания (content provider) реализующего org.eclipse.ui.navigator.IPipelinedTreeContentProvider, который предоставляет методы для перехвата (intercept) запросов на дочерние узлы (children), родительские узлы (parents), и непосредственые обновления представления (viewer).
  • suppressedExtensionId - Идентификатор подавляемого (если расширение в котором пределяется override видимо и активно) расширения.
  • policy - Политика - объявляет, как расширение должно вызываться со стороны движка/каркаса (framework). Если политика не указана, то используется значение по-умолчанию InvokeAlwaysRegardlessOfSuppressedExt. Доступны следующие политики:
    • InvokeOnlyIfSuppressedExtAlsoVisibleAndActive: Данный компонент является безусловно перекрывающим компонентом. За исключением того, когда подавленное им расширение видимо и доступно представлению, определяемому расширению не должна предоставляться возможность участвовать в процессе предоставления содержания. Если используется эта политика, данный компонент будет вызван только тогда, когда выражение triggerPoints для подавляемого расширения и выражение triggerPoints данного расширения доступны (срабатывают) для текущего элемента содержания. Поэтому, выражения triggerPoints и possibleChildren для данного расширения должны быть подмножеством соотвественно выражений triggerPoints и possibleChildren подавляемого им расширения. Другими словами, данная политика позволяет подавить (переопределить) предоставление провайдером suppressedExtensionId содержания для некоторого подмножества обрабатываемых им элементов.
    • InvokeAlwaysRegardlessOfSuppressedExt (default): Показывает, что данное расширение является первоклассным (first class) расширением; ему должна быть предоставлена возможность предоставлять содержание независимо от того активно-ли или видимо-ли для представления подавляемое расширение suppressedExtensionId. Таким образом, расширение является первоклассным и перекрывающим. Оно будет вызываться всегда, когда его выражение triggerPoints срабатывает. Когда подавляемое расширение и его выражение triggerPoints срабатывает, наше расширение будет вызвано вместо подавляемого расширения для данных элементов; подавленное расширение не получит возможность непосредственного участия в процессе.
...

понедельник, 3 декабря 2007 г.

Создание представлений на основе Common Navigator. Часть IV: Сборка объектов

Обзор

В предыдущем разделе, мы обсуждали как конфигурировать всплывающие меню для экземпляра Common Navigator. Как вы видели, Common Navigator может декларировать все его точки включения меню через точку расширения org.eclipse.ui.navigator.viewer и показывать все-ли привязки к точке расширения org.eclipse.ui.popupMenus должны быть учтены. Декларативная конфигурация меню предназначена для исключения программирования струткуры меню, и документирования структуры меню для потенциальных расширителей.

Мы также кратко говорили о двух способах, с помощью которых конфигураторы могут встроиться в меню:
  1. через org.eclipse.ui.popupMenus, который позволяет вам добавить меню через workbench;
  2. через org.eclipse.ui.navigator.navigatorContent, который специфичен для каркаса Common Navigator.
Мы рассмотрим ...popupMenus в данном разделе, и ...navigatorContent в следующем.

Как всегда, вы можете найти полные исходные тексты для этого примера в org.eclipse.ui.navigator.examples модуле из Eclipse CVS репозитория.

Добавление операции "Delete Property" с помощью org.eclipse.ui.popupMenus

Напоминаю, что для данной серии статей мы отображаем простую модель файла свойств.



Теперь мы добавим действие "Delete Property", которое позволяет пользователю выделить свойство из списка и удалить его.



Откройте редактор Plug-in Manifest двойным щелчком на файле plugin.xml в вашем проекте модуля. Если вы не не уверены в точ, что это означает, прочитайте еще раз раздел I данной серии.

На закладке Extensions, выберите Add... и затем org.eclipse.ui.popupMenus. Если вы не видете эту опции в списке, снимите метку с "Show only extension points from the required plugins". Если у вас org.eclipse.ui не добавлен в проект как модуль от которого зависит наш модуль, то сделайте это.

Теперь выберите элемент созданные в списке ("org.eclipse.ui.popupMenus"), нажмите правую кнопку и выберете "objectContribution". Затем, нажмите правую кнопку еще раз и выберите "action".



Любой objectContribution может объявить меню (поднемю расширения для всплывающего меню) и действия. Расширение довольно многословно для облегчения оптимизации загрузки модуля. Это означает, что расширение объявляет достаточно информации, для того, чтобы реальный класс (и следовательно модулю) не потребуется загружаться для отрисовки меню. Если пользователь не выбрал действие, то это означает, что модуль не был загружен.

На практике, расширение объявляет ярлыки меню, иконку меню, и контекстное окно для остальных типов. Расширение также объявляет путь панели меню (напоминаю, что мы описали значения для точек вставки в разделе III).

Используйте значения из следующей диаграммы для конфигурирования элементов действия. Вы можете ввести значения на странице Extensions, или перейти на закладку plugin.xml и заполнить его вручную.



Есть несколько вещей, которые мы должны обсудить здесь.

Первое - это objectClass, который объявляет, что именно нам интересно в ...PropertiesTreeData. Напоминаю, что мы уже определили простую модель объектов для представления name=value пар в файле свойств. Для удаления этих элементов, мы хотим, чтобы наши операции были доступны на экземпляре нашей модели.

Атрибут class указывает подкласс org.eclipse.ui.actions.ActionDelegate. Реализация DeletePropertyAction.run(IAction) имеет некоторый шаблон для robustness, но важная часть такова:



ActionDelegate объявляет метод selectionChanged(IAction, ISelection), который обновляется, когда меняется выбор в представлении. Мы перекрываем этот метод для запоминания выбора так, что когда приходит сообщение, что пользователь выбрал опцию меню мы знаем на каком элементе он кликнул.

Итого

Теперь вы должны чуствовать себя комфортно в экспериментах с добавлением большего числа действий во всплывающее меню, а так же при добавлении подменю. Убедитесь, что проверили элемент меню (accessible in the same way you found action earlier). Если вы используете закладку Extensions, все доступные атрибуты будут доступны вам и помните, что вы можете использовать правый щелчёк для создания подменю.

воскресенье, 2 декабря 2007 г.

Создание представлений на основе Common Navigator. Часть III: Конфигурирование меню

Автор оригинальной статьи : Michael D. Elder
Перевод: Евгений Флоров

В предыдущих разделах мы узнали как конструироватьCommon Navigator Framework (CNF) представление и базовое расшиерние для отображения файлов свойств. Теперь мы разберёмся с тем как конфигурировать меню для CNF представления и как добавить действия в наше представление для манипулирования его содержанием.

Обзор

Существует две основные возможности для добавления действий в Common Navigator Framework (CNF) представление:
  • Собрать действия используея org.eclipse.ui.popupMenus как objectContributions или viewerContributions. Точка расширения ...popupMenus позволит вам собрать индивидуальные делегаты действий через Eclipse Workbench. CNF представление может быть сконфигурировано с учётом условий (contributions) (это вариант по-умолчанию) или игнорируя их. В случае, когда Project Explorer contributed by Platform/UI, object and viewer contributions are honored. (Будет затронуто в разделе IV.)
  • Сборка действий используя org.eclipse.ui.navigator.navigatorContent как actionProvider'ы. Иногда, клиенты требуют больше программного управления тем, какие действия собраны в данное меню в конкретном контексте, а также какие retargetable действия сконфгурированы на основе текущего выбора (элемента).
Конфигурирование структуры меню

В Разделе I, мы определили элемент viewer нашего примера, и всплывающее меню там было кратко упомянуто.
Напоминаю, что есть два способа конфигурирования всплывающего меню. Первая возможность - это простое указание значения для popupMenuId элемента viewer в org.eclipse.ui.navigator.viewer. Вторая возможность - это выполнить более активную роль в конфигурировании точек включения (insertion points) поддержки меню.

Подсказка: Случай, когда указывается (определяется) и popupMenuId и элемент popupMenu - является ошибкой.

Если мы установили popupMenuId, мы должны иметь что-то похожее на это:



Идентификатор может быть использован расширителями (extenders) org.eclipse.ui.popupMenus для добавления viewerContributions особенностей к представлению, однако не требуются идентификаторы для objectContributions.

Когда указан только атрибут popupMenuId, набор по-умолчанию точек вставки автоматически конфигурируется во всплывающем меню. Это документируется в schema
reference для org.eclipse.ui.navigator.viewer, но продублировано здесь для удобства:

"group.new" separator="true"
"group.goto"
"group.open" separator="true"
"group.openWith"
"group.edit" separator="true"
"group.show" separator="true"
"group.reorganize"
"group.port" separator="true"
"group.generate" separator="true"
"group.search" separator="true"
"group.build" separator="true"
"additions" separator="true"
"group.properties" separator="true"

Эти значения могут быть использованы атрибутом menubarPath элементов в org.eclipse.ui.popupMenus.

Эти значения могут быть также использованы тогда, когда программно используются или ищутся элементы меню (смотри org.eclipse.jface.action.IContributionManager, конкретно insertAfter(), insertBefore(), и appendToGroup().

Все строковые константы ("group.*") описаны в org.eclipse.ui.navigator.ICommonMenuConstants и доступны для программного использования.

С другой стороны, мы можем определить элемент popupMenu как дочку для viewer, где затем мы можем определить наш mix точек включения. Запомните, что вы можете использовать закладку Extensions редактора Plug-in Manifest для создания элементов расширения из меню.



Для нашего примера, мы можем использовать такую же конфигурацию меню, как и в Project Explorer:



Каждый элемент insertionPoint показывает GroupMarker'у, что является доступным через IContributionMenu API. Везде, где атрибут separator устанавливается в "истина", меню отобразит горизонтальную линию. Меню в Eclipse достаточно разумны, чтобы отображать лии по-необходимости, так две линии расположенные вплотную отображаются как одна горизонтальная линия.

Также, необходимо принять во внимание атрибут allowsPlatformContributions="true" для элемента popupMenu. По-умолчанию, CNF представления учитывают сборки ..popupMenus. Установка данного атрибута в "ложь" ограничит меню только учётом Action Provider'ов.

Пример выше не делает что-либо фанастического, но в вашем CNF представлении, мы можете определить ваши точки включения меню ("group.example") где сделать их чуствительными для ваших сценариев. Рекомендуемым соглашением именования является "group.*", как верхняя точка включения, с исключением для специальных дополнительных групп.

Несколько комментариев на счет расширения или управления набором точек включения в меню CNF. Невозможно декларативно управлять или расширять набор точек включения для уже сконфигурированных представлений. Возможно программно добавить новые GroupMarker'ы или Separators через Action Provider'ов, но эта правктика должна использоваться аккуратно. Мы получим подробности о том как это может быть в разделе V, но на данный момент просто примите во внимание предупреждение о том, что эта практика должна применяться с осторожностью и только используя в своих интересах атрибут dependsOn элемента actionProvider , где значение показывает идентификатор Action Provider, который добавляет к меню дополнительные точки включения. Точки включения не должны программно удаляться, так как другие расширения могут зависить от них. Если ваше представление не использует конкретную точку включения, то вы можете пропустить ее, когда определяете ваш элемент popupElement.

четверг, 29 ноября 2007 г.

Создание представлений на основе Common Navigator. Часть II: Добавление содержания

Автор оригинальной статьи : Michael D. Elder
Перевод: Евгений Флоров

В данном разделе, мы выполним добавление простого расширения содержания в представление созданное в последнем примере. Для исключения возможности завязнуть в сложных провайдерах контента (content provider) и ярлыков (label provider), мы сконцентрируемся на файловой структуре с очень простой моделью, в этом случае - плоские старые *.properties файлы. По-завершению, наше расширение контента позволит нам раскрыть любой *.properties файл в Example viewer и отобразить данные файла в представлении.

Вы можете также загрузить полный пример в том виде, в котором он будет в конце данного раздела.

Во-первых, давайте посмотрим на что будет похоже расширение в plugin.xml файле. Если вы читали предыдущий раздел, вы знаете, что вы можете строить расширение (подобное последующему примеру) используя закладку Extensions в Plug-in Manifest Editor. Сначала путем выбора Add... на странице Extensions, выберите org.eclipse.ui.navigator.navigatorContent, затем в меню по правой кнопке выберите New > navigatorContent. Другой способ - это создание этого расширения в закладке plugin.xml того-же редактора. Оба варианта хороши, но первая возможность использует меню New из Extension Point Schema так, что вы увидете другие опции, которые довтупны в закладке plugin.xml.


Расширение объявляет расширение содержания с id - "org.eclipse.ui.examples.navigator.propertiesContent", с отображаемым именем "Properties File Contents". Имя - это текстовая строка используемая в закладке "Available Extensions" диалогах Filters. Мы разберемся с кодом для провайдеров содержимого и ярлыков позднее, а на данный момент запомните только, что каждый из них должен быть специфицирован; вы не можете описать только один или другой.

В итоге мы устанавливаем некоторые атрибуты для того, чтобы сказать каркасу как нам хотелось бы, чтобы наше расширение отображалось в представлении.
  • activeByDefault определяет должно ли расширение быть активным в конфигурации по-умолчанию (то есть в новом workspace).
  • icon определяет какая исонка должна быть использована, когда ссылаются на расширение в пользовательском интерфейсе
  • priority используется в нескольких различных случаях. Наиболее известным является определение относительного порядка элементов в представлении (высокоприоритетные элементы подымаются вверх представления, низкоприоритетные - опускаются вниз). В основном, вариантов "normal"или "high" должно быть достаточно для большинства расширений, показывая, что они должны смешиваться с ресурсными расширениями (когда приоритеты одинаковы, то для сортировки элементов используется алфавтная сортировка их ярлыков) или поместить их выше ресурсов под проектами.
Внутри каждого элемента, мы можем указать множество типов расширений, но до того, как расширить пример, мы должны описать каркасу - когда наше расширение должно быть вызвано. Мы должны описать когда мы можем предоставить дочерние, родительские узлы или ярлыки и иконки узлов дерева. Мы делаем это используя Eclipse Core Expressions. Пока я предложу вам обратиться к документации по org.eclipse.core.expressions для изучения подробностей об этом или вы можете использовать New > ...меню в закладке Extensions для простого создания их.

Для расширений содержания существует два важных выражения: triggerPoints и possibleChildren.

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



Выражение possibleChildren показывает для каких типов узлов дерева наше расширение может предоставить ярлыки или родителя. Для ваших сценариев, которые могут поддерживать связь с редактором, или setSelection() на представлении, данное выражение должно быть аккуратным и полным.



После того, как мы определили расширение, мы должны связать (bind) его к представлению с которым мы хотим это расширение ассоциировать. Данная спецификация показывает, что любое расширение которое соотвествует шаблону included является видимым любому представлению с указанным в элементе viewerId. Напоминаю, что мы видели это в предыдущем разделе.

Например, мы привяжем наше расширение содержания свойств (с id "org.eclipse.ui.examples.navigator.propertiesContent") к нашему Example View (с id "org.eclipse.ui.examples.navigator.view").



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

Во-первых нам нужна модель. Файл свойств имеет черезвычайно простую структуру и мы смоделируем это используя только один тип объекта модели, называемый PropertiesTreeData, который будет иметь три поля: name (имя свойства), значение (значение свойства), и container (файл содержащий модель свойств). Один из этих элементов модели будет создан для каждого свойства в *.properties файле.

В нашем примере, модель свойств будет загружена только когда она будет запрошена через поставщика содержания (content provider). Поставщик содержания используется каркасом для определения дочек каждого элемента в дереве, или для указанного элемента, определение их родителя (или родителей, так как их может быть потенциально больше чем один).

Поставщик содержания в нашем примере реализует implements org.eclipse.jface.viewers.ITreeContentProvider для предоставления информации о структуре дерева. Каркас Common Navigator также поддерживает реализации новых org.eclipse.jface.viewers.ITreePathContentProvider, но это уже выходит за рамки этого примера.

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

Теперь, мы сконцентрируемся на интеграционных методах представления, определенных в ITreeContentProvider.


ITreeContentProvider должен релизовать getElements(Object input), getChildren(Object parent), hasChildren(Object element) и getParent(Object element).

Метод getElements() запрашивается для элементов в корне представления. Многие реализации просто перенаправляют этот вызов в getChildren(), и это то, что мы сделаем.



getChildren() принимает объект (в нашем случае либо *.properties IFile либо экземпляр объекта нашей модели PropertiesTreeData так как мы описали это в нашем расширении.

В последующей реализации, мы выполняем проверку на то является ли переданный элемент экземпляром org.eclipse.core.resources.IFile и если да, то имеет ли файл расширение - *.properties. Если переданные элемент удовлетворяет этим условиям, то мы проверяем наш кэш загруженной модели или пытаемся загрузить модель, если она не кеширована. Метод updateModel() будет создавать объект PropertiesTreeData для каждого свойства и кэшировать то, что найдет в cachedModelMap. Загрузите полный текст исходного кода для того, чтобы посмотреть как реализован updateModel().



Метод hasChildren() оптимизирован для того, чтобы вернуть "истина" если он вызван с IFile с расширением *.properties. Другой альтернативой является ранняя загрузка содержимого для выполнения вычислений, но эта возможность привносит с собой дополнительные накладные расходы.

При вызове с элементом модели PropertiesTreeData - hasChildren() вернет "ложь", что означает, что наши элементы модели не могут иметь детей (свойства не могут иметь детей, но остальные модели могут).



Метод getParent() вернет IFile, который содержит элемент PropertiesTreeData или null если вызывается для любого другого элемента. Каркас Common Navigator продолжит опрос остальных расширений пока не обнаружится не нулевой родитель или пока все связанные расширения не будут опрошены. Запомните, что некоторое расширение может быть запрошено на предоставление родителя для некоторого элемента, если этот элемент соотвествует его выражению.



В конце концов, поставщик ярлыков (label provider) нашего расширения содержания скажет представлению как отобразить иконку и ярлык для наших элементов модели (PropertiesTreeData). Так как мы только начали изучение этих элементов, мы не должны беспокоиться о предоставлении иконок и ярлыков для любых других элементов. Другие расширения предоставят ярлыки и иконки для других элементов в дереве.

PropertiesLabelProvider реализует org.eclipse.jface.viewers.ILabelProvider и также org.eclipse.ui.navigator.IDescriptionProvider.

ILabelProvider является интерфейсом по-умолчанию требуемым JFace для предоставления ярлыков и иконок.

IDescriptionProvider специфичен для каркаса Common Navigator и используется для предоставления текста для стори состояния в левом нижнем углу окна Eclipse.

Методы требуемые ILabelProvider - это getText() и getImage(). Мы отобразим ярлык для наших элементов модели как строку "name= value"для свойства (быз кавычек). Для иконки, мы просто используем одну из доступных иконок предоставляемых Platform/UI.



Поставщик ярлыков будет запрашиваться для ярлыков, иконок, описаний для каждого элемента предоставленного непосредственно расширением или для любого элемента, который соответствует выражению для этого расширения. Если null возвращен для иконки или ярлыка, каркас продолжит работать с другими доступными расширениями основываясь на их выражениях и связывании представления. Если ваши расширения хотят не хотят использовать свою возможность предоставлять ярлык или иконку, они всегда должны возвращать null.

Финальный вид отображающий файлы свойств доступен в нашем Example View.

вторник, 27 ноября 2007 г.

Создание представлений на основе Common Navigator. Часть I: Определение представления

Автор оригинальной статьи : Michael D. Elder
Перевод: Евгений Флоров

Я начал принимать вопросы о Common Navigator в eclipse.platform newsgroup и сообщения из сообщества показывали, что недостаточно примеров. С целью помочь сообществу понять Common Navigator framework, я размещу некоторые примеры (в репозитории Eclipse по адресу dev.eclipse.org:/home/eclipse, куда вы можете зайти как "anonymous"; смотрите wiki для пояснений. Я буду документировать эти примеры в этом блоге. Возможно я вставлю созданную здесь документацию в Platform SDK, но я хочу организовать обсуждение, где потенциальные пользователи могли-бы высказать свое мнение максимально простым способом и непосредственно в первоисточник (то есть данный блог).

Детальная документация о точках расширения и API доступна в помощи платформы Eclipse (Help > Help Content) в разделе Platform Plug-in Developer's Guide > Reference > API Reference | Extension Points Reference.
К данной теме имеют отношения org.eclipse.ui.navigator.viewer и org.eclipse.ui.navigator.navigatorContent, а также пакет org.eclipse.ui.navigator. Если вам потребуются дополнительные детали по каким-либо моментам данного документа, пожалуйста воспользуйтесь этими ссылками.

Итак, с чего начнем? Во-первых мы должны сконфигурировать плюгин, который будет содержать представление (view), а именно добавить в его зависимости
org.eclipse.ui.navigator. Затем мы определим view part используя точку расширения org.eclipse.ui.views и укажем класс org.eclipse.ui.navigator.CommonNavigator как нашу реализацию view part, который обеспечит окружение (cradle) для нашего представления. Затем мы определим расширение org.eclipse.ui.navigator.viewer для конфигурирования представления как Common Navigator. В заключение, мы можем определить расширение org.eclipse.ui.navigator.navigatorContent вместе с связываниями (bindings) (org.eclipse.ui.navigator.viewer/viewerContentBinding) для того, чтобы ассоциировать расширения с нашим представлением.

Вы не должны использовать org.eclipse.ui.navigator.CommonNavigator как framework в своих целях; вместо этого вы можете вставлять свой контент используя org.eclipse.ui.navigator.INavigatorContentService виртуально куда угодно - от диалогов до редакторов или определить ваш viewer и view part класс, но в этом примере, мы будем придерживаться основ.

Основная настройка.

Common Navigator Framework появился в Eclipse 3.2. Следовательно, вы должны иметь окружение обновленное до Eclipse 3.2. Тема этого документа не будет касаться вопросов настройки Eclipse для self-hosting разработки. I assume that you have Eclipse 3.2 setup and are either self-hosting against a target of your own choice or the default.

Перед тем, как мы будем делать что-нибудь, мы должны убедиться, что наш plugin сконфигурирован со всеми необходимыми зависимостями. Либо создайте новый Plugin (File> New> Project: Plug-in Development> Plug-in Project: Введите имя и примите все по-умолчанию), или откойте Редактор манифеста plugin'а (выберите "plugin.xml"файл в вашем представлении (Project Explorer, Package Explorer, Navigator, и т.д.) и двойным щелчком или правой кнопкой и выберите Open With> Plug-in Manifest Editor. На закладке Dependencies, нажмите Add... и начинайте печатать org.eclipse.ui.navigator и выберете этот пункт, когда он подстветится или вы его увидите в списке.

Теперь выберите закладку Extensions редактора.

Определение view part

Для использования Common Navigator в вашем представлении, при его определении вы должны зарегистрировать реальный view part. Eclipse view parts определяются точкой расширения org.eclipse.ui.views. View part - контейнер для нашего представления; он имеет именованные закладки, место для меню представления (маленький треугольник в правом верхнем углу view part), и может содержать любой widget, который мы должны показать конечному пользователю. View parts не являются особенностью Common Navigators, мы просто используем их как окружение для хранения нашего представления.

Вы можете определить представлени через закладку Extensions путём выбора Add... и начиная печатать org.eclipse.ui.views до момента, когда вы его увидите в списке. Затем правый щелчёк на элементе, созданном под деревом "All Extensions" и имеющим имя org.eclipse.ui.views и выбрать New > view. Это приведет к созданию элемента в файле plugin.xml.

Когда вы выберете элемент view, то доступные для данного элемента атрибуты должны появиться как поля редактирования и widgets справа. Мы введём следующие значения (без кавычек):

id: "org.eclipse.ui.examples.navigator.view"
name: "Example View"
class: "org.eclipse.ui.navigator.CommonNavigator"
icon: "icons/filenav_nav.gif" (or your own)
allowMultiple: false

Теперь выберите закладку "plugin.xml" редактора. Вы должны увидеть что-нибудь похожее на это.



Вы можете создать категорию как на рисунке, но убедитесь, что указали категорию, с которой должен быть ассоциирован ваш viewer. Это делается определением атрибута "category". В противном случае, ваш viewer появится в категории Other в Show View dialog (Window > Show View > Other...).

Определение конфигурации viewer

Сразу мосле определения view part, нам необходимо определить конфигурацию расширений для нашего view part (org.eclipse.ui.navigator.viewer) которые скажут framework'у некоторые основные моменты, такие как то, что view part является Common Navigator, какая структура всплывающего меню должна быть, дополнительно к свойствам определяющим поведение viewer по-умолчанию.

Откройте опять закладку Extensions и нажмите Add...; когда появится диалог начинайте печатать org.eclipse.ui.navigator.viewer до тех пор, пока вы не увидите этот пункт в списке и выберите его. Клик правой кнопкой на новом элементе org.eclipse.ui.navigator.viewer в дереве "All Extensions" и выберите New > viewer. Этот элемент позволит нам ассоциировать абстрактный Common Navigator viewer с конкретным view part. Абстрактный viewer - это тот, с которым ассоциированы расширения, вне зависимости встроен он в view part или как-либо еще. Так для данного примера, мы будем использовать id, который использовали выше в нашем расширении org.eclipse.ui.views (org.eclipse.ui.examples.navigator.view"). Выберите элемент во view (который будет по-умолчанию обозначен name-of-you-plugin.viewer) и измените viewerId в поле редактирования, которое появится справа на "org.eclipse.ui.examples.navigator.view" без кавычек.

Некоторые комментарии о всплывающих меню.

Каркас Common Navigatorпредлгает два способа позволяющих viewer'ам адаптироватьэто меню.
  • Первый путь - это определение popupMenuId viewer'а для принятия разделителей и идентификаторов маркеров групп для меню. Значения по-умолчанию описаны в точке расширения org.eclipse.ui.navigator.viewer, но для удобства, повторены ниже.
  • С другой стороны, вы можете не определять popupMenuId и вместо этого указать элемент как дочерний для элемента. В этом случае, вы также можете определить ваши разделители и маркеры групп для ваших downstream клиентов.
Если вы предполагаете привязывать содержание или действия предоставляемые Платформой (Resource, Java(tm)), то рекомендуется использовать группировку по-умолчанию.

"group.new" separator="true"
"group.
goto"
"group.open" separator="true"
"group.openWith"
"group.edit" separator="true"
"group.show" separator="true"

"group.reorganize"

"group.port"
"group.generate" separator="true"
"group.search" separator="true"
"group.build" separator="true"
"additions" separator="true"
"group.properties" separator="true"

Некторые пояснения по поводу опций.
Элемент <> под элементом <> позволяет вам указывать строковые пары имя=значение. Существуют опции используемые базовым каркасом (описанные в разделе Примеры для org.eclipse.ui.navigator.viewer), но этот механизм может быть использован для ваших представлений или расширений для обеспечения дополнительного конфигурирования границ расширения представления. Обратитесь к org.eclipse.ui.navigator.INavigatorViewerDescriptor для ознакомления с API чтения свойст указанных в элементе. Вы можете получить описатель представления через org.eclipse.ui.navigator.INavigatorContentService представления Common Navigator viewer.

После того, как вы установили viewerId, вы можете выбрать закладку "plugin.xml" для просмотра определений следующих элементов.


После определения представления, нам необходимо добавить расширения содержания и привязать их к представлению. Я буду описывать этот процесс более детально в следующей части. Для примера мы просто привяжем содержание ресурсов по-умолчанию (определенные модулем org.eclipse.ui.navigator.resources) к нашему представлению.


Вернитесь обратно на закладку Extensions, нажмите правой кнопкой на расширении org.eclipse.ui.navigator.viewer и выберите New > viewerContentBinding. Выберите элемент viewerContentBinding и установите viewerId в то значение идентификатора, которое мы использовали для нашего представления ("org.eclipse.ui.navigator.examples.view").
Нажмите правой кнопкой на новом элементе viewerContentBinding и выберите New > includes. В завершение, нажмите правой кнопкой на новом элементе includes и выберите New > contentExtension. Для атрибута pattern в contentExtension мы укажем "org.eclipse.ui.navigator.resourceContent" без кавычек. Этот идентификатор используется модулем org.eclipse.ui.navigator.resources для идентификации расширения Resource.

На закладке "plugin.xml", мы должны иметь что-то похожее на вот это:

Теперь вы можете запустить верстак (workbench) - (Run... > New Eclipse Application) и посмотреть представление в работе. Мы пока не определили каких-либо действий для него, поэтому вам потребуется использовать либо Resource Navigator, либо Package Explorer для создания проекта, который вы хотите увидеть в представлении. Мы будем добавлять действия Resource и фильтры далее, но на данный момент, обратите внимание на поведение по-умолчанию ассоциированное с представлением: кнопки Collapse All, Link with Editor, Filters (вместе с закладкой Filters ("Available Filters") и Extensions ("Available Content")).

Для привязки фильтров ресурсов, нам необходимо добавить другой элемент contentExtension к нашему includes. Укажите "org.eclipse.ui.navigator.resources.filters.*" как идентификатор. Это подцепит все фильтры определенные org.eclipse.ui.navigator.resources. С другой стороны, вы можете выбрать отдельные фильтры, которые хотите видеть в plugin.xml этого модуля и указать идентификаторы.

Выберите Run... опять и проверьте, что вам теперь доступны несколько фильтров ресурсов в вашей закладке "Available Filters" диалога Filters.

Далее мы будем привязывать действия с ресурсами по-умолчанию. Для привязывания действий нам необходимо добавить viewerActionBinding в корень точки расширения. Нажмите правой кнопкой на org.eclipse.ui.navigator.viewer и выберите New > viewerActionBinding. Убедитесь в правильности viewerId и затем добавьте эелемент includes, который имеет элемент actionExtension. Для атрибута pattern укажите "org.eclipse.ui.navigator.resources.*". Теперь когда вы запустите верстак, вы по-умолчанию увидите New, Import, Export, и Refresh в пустом представлении, а также другие действия соотвествующие Resource Navigator при выделении элементов в представлении.

Ваш plugin.xml в этот момент должен выглядеть так:

"Откуда он знает все правельные идентификаторы? Это просто "магические числа для меня!" Для определения идертификаторов расширений содержания которые вы хотите привязать к вашему представлению, вы можете просмотреть файлы plugin.xml модулей определяющих расширения. Вы можете использовать представления Plug-ins для того, чтобы сделать это проще всего (Window > Show View > Other...: PDE > Plug-ins) или вы можете открыть plugin.xml файл для org.eclipse.ui.navigator.navigatorContent (используя опять представление Plug-ins) и закладку Extension Points, выберите navigatorContent. Затем нажмите Find References для обнаружения всех расширений в вашем workspace определяющих расширения содержания или действий, которые мы можете захотеть использовать в вашем представлении. Расширения содержания определяются элементом navigatorContent, так что используйте атрибут id расширений navigatorContent при привязывании когда вы определяете элементы contentExtension под viewerContentBindings для вышего представления. Расширения действий определяются элементом actionProvider, так, что используйте атрибут id расширений actionProvider при привязывании, когда определяете элементы actionExtension под viewerActionBindings для вашего представления. Имейте ввиду, что actionProvider который вложен в расширение navigatorContent привязывается автоматически, когда охватывающее его расширение содержания привязано к представлению.

Определение фильтров
Последнее, что мы сделаем сегодня - это определение фильтра для нашего представления используя Eclipse Core Expressions. Документация на каркас Core Expressions доступна с модулем org.eclipse.core.expressions. Мы используем проверки свойств (property testers) определенные org.eclipse.core.resources для проверки типа (вида) проекта, и скроем все проекты, которые не имеют этот тип проекта.

Итак, вернитесь на закладку Extensions редактора манифеста модуля, затем нажмите Add... и выберите org.eclipse.ui.navigator.navigatorContent. Затем добавьте новый элемент commonFilter в это расширение (также как до этого: правый щелчек на элементе org.eclipse.ui.navigator.navigatorContent, выбрать New > commonFilter). Измените предлагаемый id на "org.eclipse.ui.examples.navigator.filters.hideNonJavaProjects", и измените имя на "Hide non-Java projects". Вместо указания класса-реализации, мы только определим выражение в виде XML. Нажмите правой кнопкой на элементе commonFilter и выберите New > filterExpression. Здесь мы можем продолжить использование меню по правой кнопке для создания выражения, подобного следующему:

Вы также можете установить атрибут activeByDefault в выражении для определения будет ли фильтр активен в конфигурации по-умолчанию.

В завершение, нам необходимо определить contentExtension как чать нашего viewerContentBinding для данного представления. Убедитесь в использовании id нашего нового фильтра или общего шаблона (например "org.eclipse.ui.examples.navigator.filters.*") для привязывания этого фильтра и всех будущих фильтров, которые мы (или наши подчиненные сушности) определим как соотвествующие этому id. Ваш итоговый plugin.xml должен выглядеть похожим на следующее:


Теперь запустите верстак последний раз. Создайте несколько Simple проектов и несколько Java проектов. Когда фильтр "Hide non-Java Projects" включен, Simple проекты должны пропадать из представления.