В последнем совете мы увидели, что обработчик может быть объявлен отдельно от команды. Это позволяет использовать несколько объявлений обработчиков для одной и той же команды. Мы также можем настроить, когда обработчик активен и видим, через сам plugin.xml. Обработчик, который не имеет ни одного из этих условий, называется «обработчиком по умолчанию». Когда никакой другой обработчик не связан с командой в определенном контексте, обработчик по умолчанию будет обработчиком, который будет выполнен. Помните, что в любой момент времени с командой может быть связан только один обработчик. Давайте посмотрим, как конкретный обработчик выбран для данного контекста.
Обработчик может быть указан с условием activeWhen с использованием языка выражений. Скажем, для нашей команды у нас есть два разных обработчика. Один должен быть активным, если текущим выбором является IFile, а другой должен быть активным, если текущим выбором является IFolder. Выражение для них будет выглядеть так:
<handler
class="com.eclipse_tips.commads.SomeCommandHandler1"
commandId="com.eclipse-tips.commands.someCommand">
<activeWhen>
<with
variable="selection">
<iterate
operator="or">
<instanceof
value="org.eclipse.core.resources.IFile">
</instanceof>
</iterate>
</with>
</activeWhen>
</handler>
<handler
class="com.eclipse_tips.commads.SomeCommandHandler2"
commandId="com.eclipse-tips.commands.someCommand">
<activeWhen>
<with
variable="selection">
<iterate
operator="or">
<instanceof
value="org.eclipse.core.resources.IFolder">
</instanceof>
</iterate>
</with>
</activeWhen>
</handler>
Я сохраню объяснение языка выражений для отдельной подсказки, но пока короткая однострочная desc: первый обработчик будет включен, когда ток выбора содержит хотя бы один IFile, а второй обработчик будет включен, когда выбор содержит хотя бы один IFolder. Это поднимает до двух вопросов.
1) Что, если выбор — это просто IP-проект?
В этом случае, поскольку ни один из обработчиков не подходит, команда отключена. Это где обработчик по умолчанию, если вы его предоставили, будет связан с командой (и команда будет включена).
2) Что если в выборке содержатся как IFile, так и IFolder?
Теперь оба обработчика одинаково квалифицированы для обработки команды. Но поскольку среда не может выбрать один случайным образом, команда просто отключена. Даже если вы предоставили обработчик по умолчанию, он не будет связан с командой, потому что два других обработчика более специфичны, чем заданный по умолчанию.
Как определяется «специфичность» обработчика? Это зависит от условий, которые вы задаете в выражении activeWhen. Порядок определяется в классе ISources. Вы можете просмотреть весь набор, чтобы увидеть наиболее часто используемые из них, порядок от наименее специфического к наиболее специфическому выглядит следующим образом:
- Активный контекст (activeContexts)
- Наборы активных действий (activeActionSets)
- Active Shell (activeShell)
- Окно Active Workbench (activeWorkbenchWindow)
- Идентификатор активного редактора (activeEditorId)
- Идентификатор активной части (activePartId)
- Текущий выбор (выделение)
Если обработчик имеет activeWhen, определенный с активным контекстом, а другой с текущим выбором, будет выбран второй, так как выбор более специфичен, чем активный контекст. ActiveWhen для всех обработчиков оценивается и выбирается тот, который возвращает true для наиболее конкретного условия. Когда два обработчика возвращают значение true для доступного наиболее конкретного условия (например, для выбора, имеющего IFile и IFolder в нашем случае), никакой обработчик не будет связан с командой.
Все это делается даже без загрузки вашего обработчика в память. Даже без загрузки вашего плагина!
В предыдущем совете мы видели, как выбирается обработчик с выражением activeWhen, когда объявляется более одного обработчика. Теперь предположим, что выбран обработчик, независимо от того, включена команда или нет, определяется выражением enabledWhen.
В нашем предыдущем примере мы видели обработчик, который активен, когда выборка хотя бы содержит один IFile. Теперь давайте хотим включить его только тогда, когда общее количество выборок равно 2. Мы можем указать его как:
<handler
class="com.eclipse_tips.commads.SomeCommandHandler1"
commandId="com.eclipse-tips.commands.someCommand">
<activeWhen>
<with
variable="selection">
<iterate
operator="or">
<instanceof
value="org.eclipse.core.resources.IFile">
</instanceof>
</iterate>
</with>
</activeWhen>
<enabledWhen>
<with
variable="selection">
<count
value="2">
</count>
</with>
</enabledWhen>
</handler>
Таким образом, обработчик будет активным и связанным с командой, если выборка содержит хотя бы один IFile. Тем не менее команда будет включена только в том случае, если выделение содержит ровно 2 элемента. activeWhen и enabledWhen похожи — в зависимости от языка выражений и отложенной загрузки плагина до выполнения команды. Но есть небольшая разница — ваш обработчик может быть загружен, если выражение enabledWhen возвращает true и ваш плагин уже загружен. Алгоритм включения работает следующим образом:
- Не включено, если указано, плагин не загружен — команда включена
- Не указано, если указано, но плагин загружен — обратитесь к handler.isEnabled () и соответственно установите команду
- enableWhen указано, возвращает false, команда отключена (независимо от того, загружен плагин или нет)
- enableWhen указано, возвращает true, плагин не загружен — команда включена
- enableWhen указано, возвращает true, плагин загружен — обратитесь к handler.isEnabled () и установите команду соответственно
До сих пор мы видели команды, обработчики и их включения. Но как насчет обобщения команды? Это можно сделать, добавив параметры для команды. И это будет следующий совет в этой серии.