如何跨插件引用资源?

插件开发遇到的问题

如下图所示,在一个编辑器中,配置右键菜单,提供了icons/cut.png图标。 由于剪切操作为通用的操作,每一个编辑器都需要支持剪切操作,通过点击Browse…按钮,却只能选择本插件内的图片资源。如果每一个编辑器都需要支持这些通用操作,难道每一个插件项目中都必须有一套cut.png吗?

本篇文章就是为了解决这个问题。
在这里插入图片描述

问题的研究

在Eclipse中,平台本身对于图片资源有很多处理机制。对于跨插件方式,可以通过org.eclipse.ui.ISharedImages共享图片,这些图片创建后可以直到程序关闭才释放,一般用于通用的部分。在这个接口中,定义的一些图标,例如IMG_TOOL_CUT。这些图标,已经在类WorkbenchImages中,将这些图标声明。所以上图中,icon位置可以配置IMG_TOOL_CUT,在对应右键菜单处采用Eclipse平台的剪切图标。

除了Eclipse平台图标以外,我们可以自己定制吗?

于是尝试,通过在插件启动的时候,调用WorkbenchImages的public static void declareImage(String symbolicName,ImageDescriptor descriptor, boolean shared)方法,传入自定义字符串,例如_CUT,以及图标descriptor,在加载后,平台报出无法找到/_CUT图片路径。
所以这里就涉及到,扩展点之中配置的资源路径,是通过什么方式查找的?

该处扩展点中,图片资源的查找是通过AbstractUIPlugin类的public static ImageDescriptor imageDescriptorFromPlugin(String pluginId, String imageFilePath)方法查找的。当调用的时候,pluginId就是扩展点所处的插件的ID,
在这里插入图片描述

通过源码,可以看到图片加载顺序,首先是平台共享的图片资源,但是我们在对应的插件激活后调用declareImage,在图片查找之后,所以无法找到。

文件是通过FileLocator.find(url)查找,最后定位到图标。 所以,我们需要知道Eclipse平台的URL机制,该机制是在Eclipse平台启动后,内置的分析机制。

Eclipse平台的URL机制

转载自:https://blog.csdn.net/zhoujianboy/article/details/84129480

除常见的Http、FTP、FILE等协议之外,eclipse平台还支持多种扩展协议,甚至可以支持用户自定义协议。
Eclipse平台支持的协议,包括Plugin、Fragment、Meta、Config等,会在Eclipse runtime启动时候注册,可参见:

  1. org.eclipse.core.internal.runtime.Activator
  2. org.eclipse.core.internal.boot.PlatformURLHandler
  3. PlatformURLConnection
  4. URLConnection

从上述3)的继承实现上,可以看到,Eclipse对platform协议url的定位的支持情况如下:

platform:base/xxx, 相对于rcp根目录下的资源
platform:config/xxx, 相对于rcp的configuration目录下的资源
platform:fragment/foo.bar/xxx, 相对于foo.bar这个fragment下的资源
platform:meta/foo.bar/xxx, 相对于workspace/.metadata/.plugins/foo.bar目录下的资源
platform:plugin/foo.bar/xxx, 相对于foo.bar这个plugin下的资源
platform:resource/foo/xxx, 相对于workspace里foo工程下的资源, foo工程有可能在workspace目录之外.

也可以通过继承PlatformURLConnection类,定义自己的基于Platform的URL。

从根本上来说,这种便利性是由Java URLConnection 乃至关于URL的标准的可扩展性带来的,Eclipse平台只是有效地利用了这种可扩展性。类似的情况还有OSGI的Bundle协议和Java的Jar协议等。
在实际的插件开发中,常用以下方法给文件定位

1 在插件内定位:
Bundle bundle = MapEditorPlugin.getDefault().getBundle();
URL url = bundle.getEntry(“temp/xxx”);
这种方式表示 xxx 这个文件在本插件的temp目录下

2 在RCP的配置路径下:
URL url = new URL(“platform:config/xxx”);
Properties prop = new Properties() ;
prop.load(url.openStream());
这种方式表示xxx这个文件在你的rcp的工作目录下的configuration目录下

另外,应该善加利用Platform里的方法,如调用Platform.getConfigurationLocation()也可获得配置目录的Location,通过location可以getURL()。

以下变量也可用作提供的URL路径中的段:
n l nl nl-用于语言特定信息
o s os os-用于操作系统特定信息
w s ws ws-用于打开系统特定信息的窗口

例如,默认语言环境为en_CA的环境中的“platform:/plugin/org.eclipse.core.runtime/ n l nl nl/about.properties”的URL将返回与第一个位置about.properties对应的URL,其顺序如下:

plugin root/nl/en/CA/about.properties
fragment1 root/nl/en/CA/about.properties
fragment2 root/nl/en/CA/about.properties

plugin root/nl/en/about.properties
fragment1 root/nl/en/about.properties
fragment2 root/nl/en/about.properties

plugin root/about.properties
fragment1 root/about.properties
fragment2 root/about.properties

问题的解决

所以,上图中碰到的问题,可以通过下面方式解决。在icon中配置:

platform:plugin/图标所在其他插件ID/图标在其他插件中的位置

如果是在插件内的图标,则前面的” platform:plugin/图标所在其他插件ID/”可以省略掉。

测试后,问题解决了,右键菜单中对应项图标确实为配置的目标图片。

更多的思考

通过这种问题的解决,我们可以考虑到对于某一款基于Eclipse插件开发的程序,可以定义一个公共的资源插件。例如XXX.XXX.resource.ui项目。该项目中放置某一个整体模块或者整个软件系统的公共图标。其他插件扩展点中,可以采用上述配置方式。

当新扩展某一个子功能模块时,子功能可以引用核心系统的图片等资源,同时子功能模块维护自身特殊的图标。当某个插件未加载时,提供某个默认图标替代。而且URL字符串不会造成对某个插件的依赖。通过这种方式,既保证了资源文件的统一管理,也不会耦合。

如果在程序中,可以先通过org.eclipse.core.runtime.FileLocator.find(new java.net.URL(urlString)); 其中urlString可以采用”问题的解决”中的字符串。然后,通过ImageDescriptor.createFromURL(url)获取图标描述(其他资源获取方式也可以通过URL构建),进而获取图标。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值