RCP开发中如何配置enabledWhen实现弹出菜单按需禁用?
实现RCP弹出菜单按需禁用的解决方案
针对你提到的场景——当UI选中项对应的扩展没有assist-provider属性时禁用弹出菜单,核心思路是通过自定义PropertyTester结合enabledWhen表达式来实现条件判断,具体步骤如下:
1. 编写自定义PropertyTester类
因为默认的RCP表达式无法直接访问扩展点的属性,我们需要自己实现一个属性测试器,用来检查选中项对应的扩展是否包含assist-provider属性。
package com.aaa.bbb.core.assist; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.Platform; import org.eclipse.core.expressions.PropertyTester; public class AssistProviderPropertyTester extends PropertyTester { // 自定义属性名 private static final String PROPERTY_HAS_ASSIST_PROVIDER = "hasAssistProvider"; // 替换成com.ccc.ddd.validator项目中目标扩展点的实际ID private static final String VALIDATOR_EXTENSION_POINT_ID = "com.ccc.ddd.validator.yourTargetExtensionPoint"; // 你要检查的属性名 private static final String ATTR_ASSIST_PROVIDER = "assist-provider"; @Override public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { // 只处理我们定义的属性 if (!PROPERTY_HAS_ASSIST_PROVIDER.equals(property)) { return false; } // 第一步:从选中项中获取对应的扩展ID // 这里需要根据你的UI实现调整,比如选中项是你的自定义模型对象,里面存了扩展ID String extensionId = getExtensionIdFromSelection(receiver); if (extensionId == null) { return false; } // 第二步:从扩展注册表中找到对应的扩展 IExtensionRegistry registry = Platform.getExtensionRegistry(); IExtension targetExtension = registry.getExtension(VALIDATOR_EXTENSION_POINT_ID, extensionId); if (targetExtension == null) { return false; } // 第三步:检查扩展是否包含assist-provider属性 for (IConfigurationElement element : targetExtension.getConfigurationElements()) { // 根据你的扩展点结构调整,比如属性是在根元素还是子元素上 String assistProviderValue = element.getAttribute(ATTR_ASSIST_PROVIDER); if (assistProviderValue != null && !assistProviderValue.isBlank()) { return true; } } // 没有找到属性,返回false(禁用菜单) return false; } // 示例方法:根据选中对象获取扩展ID,你需要根据实际UI场景实现 private String getExtensionIdFromSelection(Object receiver) { // 比如如果选中项是你的自定义模型类 if (receiver instanceof YourSelectionModel) { return ((YourSelectionModel) receiver).getExtensionId(); } // 如果你是通过IStructuredSelection获取选中项,也可以在这里处理 // 比如: // if (receiver instanceof IStructuredSelection) { // Object selectedObj = ((IStructuredSelection) receiver).getFirstElement(); // if (selectedObj instanceof YourSelectionModel) { // return ((YourSelectionModel) selectedObj).getExtensionId(); // } // } return null; } }
2. 在core项目中注册PropertyTester
打开com.aaa.bbb.core项目的plugin.xml,添加org.eclipse.core.expressions.propertyTesters扩展,注册我们的测试器:
<extension point="org.eclipse.core.expressions.propertyTesters"> <propertyTester class="com.aaa.bbb.core.assist.AssistProviderPropertyTester" id="com.aaa.bbb.core.assistProviderPropertyTester" namespace="com.aaa.bbb.core" properties="hasAssistProvider" type="com.yourpackage.YourSelectionModel"> <!-- 替换成选中项的实际类型全限定名 --> </propertyTester> </extension>
3. 在目标扩展点中配置enabledWhen条件
回到com.aaa.bbb.core.command.assistValidationResult扩展点,给你的弹出菜单/命令添加enabledWhen表达式,使用我们自定义的属性:
<extension point="com.aaa.bbb.core.command.assistValidationResult"> <!-- 你的菜单或命令定义 --> <command id="com.aaa.bbb.core.assistValidationCommand" name="Assist Validation"> <enabledWhen> <!-- 当hasAssistProvider为true时启用菜单,否则禁用 --> <test property="com.aaa.bbb.core.hasAssistProvider" value="true"/> </enabledWhen> </command> </extension>
关键注意事项
- 替换占位符:记得把代码和XML中的占位符(比如扩展点ID、选中项类型)换成你的实际项目值。
- 依赖配置:确保com.aaa.bbb.core项目在
plugin.xml的Require-Bundle中添加了对com.ccc.ddd.validator项目的依赖,或者至少依赖了包含目标扩展点定义的插件。 - 选中项适配:
getExtensionIdFromSelection方法需要根据你的UI组件实际情况调整,核心是能从选中对象中拿到对应的扩展ID,这样才能定位到com.ccc.ddd.validator中的具体扩展。 - enabledWhen vs activeWhen:你选的
enabledWhen完全正确,它控制菜单的可用状态(灰显禁用),而activeWhen是控制菜单是否显示,符合你“菜单始终显示,仅按需禁用”的需求。
内容的提问来源于stack exchange,提问作者user13746660
相关产品推荐
相关产品推荐

