打开editor的接口讨论
【打开editor的接口讨论】
先来看一下workbench吧,workbench从静态划分应该大致如下:
从结构图我们大致就可以猜测出来,workbench page作为一个IWorkbenchPart(无论是eidtor part还是view part)的容器,肯定会接受workbench page的管理。看了一下,IWorkbenchPage接口定义中确实提供给了如下打开编辑器的操作:
【IWokbenchPage提供的接口】
2
3 public IEditorPart openEdito(IEditorInput input, String editorId)throws PartInitException;
4
5 public IEditorPart openEdito(IEditorInput input, String editorId, boolean activate) throws PartInitException;
6
7 public IEditorPart openEditor(final IEditorInput input, final String editorId, final boolean activate, final int matchFlags)throws PartInitException;
8 }
那到这边,可能很多人已经知道了怎么调用这些接口了:
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().openEditor(...)
(说明:PlatformUI可以看作是整个eclipse ui框架的门面类,当然最核心的作用就是让用户获取到workbench。Eclipse中存在的其他一些门面类如:ResourcesPlugin、Platform、JavaCore、JavaUI等)
我们再仔细看一下IWorkbenchPage对应的实现类(org.eclipse.ui.internal.WorkbenchPage)中的以上接口的实现代码,真正在管理Editor的是一个叫做EditorManager的东东(同理,view part对应的管理器角色类是叫做ViewFactory的东东)。 这里的EditorManager和View Factory是workbench实现中非常精华的部分,看一下里面的实现就会很大程度上理解workbench所谓懒加载、懒初始化是如何实现的了,如何实现part 复用的...等等 。
上图就用来说明workbench是如何来管理各种part的,其中descriptor角色的核心作用是延迟加载扩展(延迟加载用户通过editors或者views提供的扩展),reference角色的核心作用是用来延迟初时化具体的part(例如避免过早的创建对应的control等等)。再说下去有点偏离主题了,这部分,以后有时间再写
【IDE工具类提供的接口】
上面IWorkbenchPage提供接口都需要用户准备两样东西:一是创建IEditorInput实例,二是指定editor id。有些用户可能不想干这两件事情,所以在工具类org.eclipse.ui.ide.IDE中提供了其他的接口:
2
3 public static IEditorPart openEditor(IWorkbenchPage page, IFile input, boolean activate) throws PartInitException { }
4
5 public static IEditorPart openEditor(IWorkbenchPage page, IFile input, boolean activate, boolean determineContentType) { }
6
7 public static IEditorPart openEditor(IWorkbenchPage page, IFile input, String editorId) throws PartInitException { }
8
9 public static IEditorPart openEditor(IWorkbenchPage page, IFile input, String editorId, boolean activate) throws PartInitException { }
10
11
上面5个接口操作中, 对于上面的三个操作,Eclipse会自动为你准备IEditorInput实例,并动态绑定合适的编辑器类型。对于下面的两个操作,Eclipse会为你自动准备IEditorInput实例,但是需要用户自己指定editor id。
接下来我们看两个问题,一是如何创建IEditorInput实例的;而是如何动态计算对应的editor id的。
【有关FileEditorInput】
在IDE工具类中提供的5个接受IFile对象的openEditor接口中,在对应的实现中都是默认构造了一个FileEditorInput(org.eclipse.ui.part.FileEditorInput)实例,这个实例也是org.eclipse.ui.IFileEditorInput接口的默认实现类(注意:Eclipse中很多地方都使用这种Interface/Default Impl的方式,Interface会暴露,Default Impl则根据情况选择是否暴露,一般是如果Interface希望用户来扩展继承,则会暴露对应的Default Impl,如果Interface不希望用户来扩展继承,例如IResource系列接口,则一般会将Default Impl丢如对应的internal包中)。
我们看一下org.eclipse.ui.part.FileEditorInput中是如何实现IEditorInput.exists()接口的:
2 private IFile file;
3
4 public boolean exists() {
5 return file.exists();
6 }
7 }
我们看到内部的实现是持有了IFile句柄,如果IFile代表的资源没有存在于工作区之内,那么就会返回false。(疑问:如果我们打开工作区外部的文件呢???显然,FileEditorInput并不合适,稍后看...)
【动态计算editor id】
下面,我们再来看一下IDE类是如何计算所谓的默认eidtor id的。追踪实现,我们看到了IDE.getDefaultEditor
2 // Try file specific editor.
3 IEditorRegistry editorReg = PlatformUI.getWorkbench()
4 .getEditorRegistry();
5 try {
6 String editorID = file.getPersistentProperty(EDITOR_KEY);
7 if (editorID != null) {
8 IEditorDescriptor desc = editorReg.findEditor(editorID);
9 if (desc != null) {
10 return desc;
11 }
12 }
13 } catch (CoreException e) {
14 // do nothing
15 }
16
17 IContentType contentType = null;
18 if (determineContentType) {
19 contentType = getContentType(file);
20 }
21 // Try lookup with filename
22 return editorReg.getDefaultEditor(file.getName(), contentType);
23 }
上面的代码大致赶了如下两件事情:
1、如果对应的资源设定了一个特定的持久化属性EDITOR_KEY,则会使用EDITOR_KEY属性值所代表的编辑器(说明:有关Eclipse资源的属性支持,请参阅其他文档)。那如果一个资源不在工作区之内,又如何设定EDITOR_KEY属性呢??? (~_~确实没法设定)
2、查找对应的content type,用户通过org.eclipse.core.runtime.contentTypes扩展点来注册自定义的内容类型,在内容类型中会指定对应的文件扩展名和默认编码,例如JDT中注册了如下内容类型(摘自org.eclipse.jdt.core/plugin.xml):
<!-- Extension: Java Content Types -->
<!-- =================================================================================== -->
<extension point="org.eclipse.core.runtime.contentTypes">
<!-- declares a content type for Java Properties files -->
<content-type id="javaProperties" name="%javaPropertiesName"
base-type="org.eclipse.core.runtime.text"
priority="high"
file-extensions="properties"
default-charset="ISO-8859-1"/>
<!-- Associates .classpath to the XML content type -->
<file-association
content-type="org.eclipse.core.runtime.xml"
file-names=".classpath"/>
<!-- declares a content type for Java Source files -->
<content-type id="javaSource" name="%javaSourceName"
base-type="org.eclipse.core.runtime.text"
priority="high"
file-extensions="java"/>
<!-- declares a content type for Java class files -->
<content-type id="javaClass" name="%javaClassName"
priority="high"
file-extensions="class">
<describer
class="org.eclipse.core.runtime.content.BinarySignatureDescriber">
<parameter name="signature" value="CA, FE, BA, BE"/>
</describer>
</content-type>
<!-- declares a content type for JAR manifest files -->
<content-type id="JARManifest" name="%jarManifestName"
base-type="org.eclipse.core.runtime.text"
priority="high"
file-names="MANIFEST.MF"
default-charset="UTF-8"/>
</extension>
那如果我们在注册编辑器的时候和对应的content type绑定,这不就联系起来了吗~_~。那我们看一下java源码编辑器扩展描述(摘自org.eclipse.jdt.ui/plugin.xml):
name="%JavaEditor.label"
default="true"
icon="$nl$/icons/full/obj16/jcu_obj.gif"
contributorClass="org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditorActionContributor"
class="org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor"
symbolicFontName="org.eclipse.jdt.ui.editors.textfont"
id="org.eclipse.jdt.ui.CompilationUnitEditor">
<contentTypeBinding
contentTypeId="org.eclipse.jdt.core.javaSource"
/>
</editor>
我们看到上面的xml中有contentTypeBinding元素,里面指定了绑定java源码content type。
那如果我们在注册编辑器的时候,没有绑定对应的content type呢?Eclipse允许你配置,往下看:
我想看到这边对eclipse如何动态计算一个文件对应的editor应该是明白了吧,再回顾一下吧:
1、查看资源本身是否有EIDTOR_ID持久属性(注意:一、只有工作区中存在的资源才允许设置持久属性;二、资源属性知识针对特定资源,不会影响同类型资源,即你对工作区中特定的.java文件设定了EIDTOR_ID持久属性,并不会影响工作区中其他.java文件资源的编辑器绑定操作)
2、查找对应的content type,然后查找对应的editor扩展或者查找Eclipse中的Content Types和File Associations配置
3、如果都找不到,则直接给一个默认的编辑器。例如,我们经常碰到是"org.eclipse.ui.DefaultTextEditor"
【IDE工具类提供的接口 VS IWorkbenchPage提供的接口】
看一下以上提到的各个角色之间的调用关系图吧:
【使用Eclipse提供的打开editor的接口】
还是那句话,需求决定一切。我们看一下打开编辑器的需求:
1、打开工作区中工程内的文件资源
2、打开工作区.metadata目录中的文件资源
3、打开工作区外部的文件资源
【说明】Eclipse工作区实际上是有数据区和元数据区两个区域组成的,示意如下:
对于Eclipse来说,.metadata目录下存放的是插件运行时的关键状态数据,不建议用户再工作区实例运行期间做相应修改,为此eclipse干了两件事情:1、运行期间会自动在.metadata目录下产生一个进程锁定的.lock文件;2、Eclipse不允许用户通过IResource系列接口直接访问或修改.meatadata目录下的资源
【打开工作区工程内的资源】
假设工作区中有测试工程TestProject,工程下有文本文件java_file.txt。对应创建代码如下:
2 //创建工程
3 IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("TestProject");
4 if (!project.exists())
5 project.create(null);
6 if (!project.isOpen())
7 project.open(null);
8
9 //创建文件
10 IFile java_file = project.getFile(new Path("/java_file.txt"));
11 InputStream inputStreamJava = new ByteArrayInputStream("class MyType{}".getBytes());
12 if (!java_file.exists())
13 java_file.create(inputStreamJava, false, null);
14 } catch (CoreException e) {
15 IStatus status = new Status(IStatus.ERROR, "myplugin", 101, "创建资源失败", e);
16 Activator.getDefault().getLog().log(status);
17 }
打开方式一:Eclipse默认计算对应的editor id,会用default text editor打开
2 IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
3 IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("TestProject");
4
5 IFile java_file = project.getFile(new Path("/java_file.txt"));
6 IDE.openEditor(page, java_file);
7 } catch (CoreException e) {
8 IStatus status = new Status(IStatus.ERROR, "myplugin", 102, "打开工作区内文件出错", e);
9 Activator.getDefault().getLog().log(status);
10 }
打开方式二:指定java源码编辑器打开,会用java源码编辑器打开
2 IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
3 IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("TestProject");
4
5 IFile java_file = project.getFile(new Path("/java_file.txt"));
6 IDE.openEditor(page, java_file, "org.eclipse.jdt.ui.CompilationUnitEditor");
7 } catch (CoreException e) {
8 IStatus status = new Status(IStatus.ERROR, "myplugin", 102, "打开工作区内文件出错", e);
9 Activator.getDefault().getLog().log(status);
10 }
打开方式三:设定editor id属性,该文件以后默认都用此editor id打开
2 IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
3 IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("TestProject");
4
5 IFile java_file = project.getFile(new Path("/java_file.txt"));
6 java_file.setPersistentProperty(IDE.EDITOR_KEY, "org.eclipse.jdt.ui.CompilationUnitEditor");
7 IDE.openEditor(page, java_file);
8 } catch (CoreException e) {
9 IStatus status = new Status(IStatus.ERROR, "myplugin", 102, "打开工作区内文件出错", e);
10 Activator.getDefault().getLog().log(status);
11 }
说明:对于工作区工程内的资源,可以有两种方式:一是local的,那就是物理存在与工程之内;二是link进入的。打开编辑器的时候,不需要做区分。
【打开工作区外部的资源】
说明:既存在于工作区外部,同时又没有被link进工程。
在Eclipse中有个功能,就是File->Open File,可以打开一个外部文件。那我们看一下它是怎么实现的。我们只需要打开对应的对话框,然后挂起主线程,就可以找到对应的action了(挂起线程可以帮我们很方便的调试很多类型的问题,以后细说~_~):
分析一下OpenExternalFileAction的实现,我们发现它自己构建了一个editor input
打开editor的接口讨论相关推荐
- salesforce 和微信的集成(一)通过SFDC Site打开微信开发接口
本文代码参照柳峰的代码.十分感谢. 开始在做微信集成的时候,是采用微信+阿里云服务器+SFDC这种模式进行的.在阿里云上部署java程序实现和微信服务器的沟通,在通过SFDC的对外API实现和java ...
- IDEA打开父类的接口方法快捷键
有两个类,分别为A类是接口.B类为A的实现类. 如果想在B类里的某个方法,打开A类 可以鼠标右键点击这个方法名,按下键盘:Ctrl+U,就可以跳转到A类接口的该方法上面. 转载于:https://ww ...
- 小程序体验版本接口是http协议,打开不调用接口
工作中遇到的问题: 小程序体验版本打开后显示空白 只有点击"打开调试模式"再次打开才能显示正常 原因: 因为体验版本的接口协议是http,但小程序只认https,所以不会去调接口: ...
- 无法打开计算机 eploxre 接口未知,绝地求生辅助发卡网Win7系统打开计算机属性提示“此项目的属性未知”解决方案...
windows7系统查看QQ好友ip地址的方法[图文] 最近有用户反映Win7系统打开电脑属性提示"这个项目属性未知".Win7系统为什么打不开电脑属性?Win7系统可以打开电脑属 ...
- 解散了地图接口讨论群
因为自己长期没有空来管理,造成群里面除了几个专职发广告的人之外,没有什么活跃的用户,今天索性就关闭了这个2006年建的群,在解散时候或者是解散前对大家造成的困扰请谅解.. 另外,我近期会将自己的 ht ...
- Eclipse插件打开编辑器
今天终于可以闲一天,想来想去就乱写点东西吧,说不定对有些新人有点帮助呢-_- 用Eclipse API的方式来打开编辑器,可能对任何一个插件开发者都不是很陌生的操作了.但是,还是建议你忍着看一下,全当 ...
- 工作271:打开弹出框调用当前页面接口
<template><div><button-dialog@open="open"ref="dialog"width=" ...
- 在Nature都点赞的大会上,马斯克被「脑机接口之父」炮轰了:他说的话,我一个字都不认同...
金磊 杨净 发自 凹非寺 量子位 报道 | 公众号 QbitAI 如何评价马斯克的脑机接口? 「不会有永生.不会有心灵感应」. 「是错误的说法,更像是营销手段」. 给出如此犀利评价的不是别人,正是脑 ...
- 没有required_springboot-使用OpenAPI之后我再也没有写过接口文档
一 前言 这篇文章主要是带大家入门下如何使用OpenAPI, 笔者在github上找到对应得swagger项目都没找到javase得人门文章,看了下是基于JAX-RS,吐血了: 二 什么是 OpenA ...
最新文章
- spring28: aspectJ--基于xml
- 滴滴基于 Flink 的实时数仓建设实践
- 神经网络前向引擎内存复用技术(基于caffe)
- python的变量名必须以什么开头_python以下划线开头的变量名含义
- 迅雷前CEO陈磊涉嫌职务侵占罪已被立案侦查,股价周四下跌超7%
- UI控件之UITextField
- long 雪花算法_Snowflake 雪花算法
- 使用Magoshare for Mac无法打开恢复的文件或扫描后找不到丢失的文件怎么办?
- 文本数据挖掘之文本信息抽取
- Centos启动默认打开网络
- 用户画像第四章(企业级360°用户画像_标签开发_挖掘标签_用户购物性别模型-USG)
- 并不对劲的bzoj1095:p2056:[ZJOI2007]捉迷藏
- gcs服务 oracle,gcs resource
- 软件设计师经典视频教程
- 汇编与接口技术期末复习笔记(1)—— 汇编部分
- Hbase中RowKey的设计原则和热点问题
- 微软官方原版win7(64位/32位)旗舰版系统下载
- 职场人的购物清单出炉,来看看大家买了什么?
- 拉格朗日插值法python实现
- 【蓝桥杯选拔赛真题25】python输出指定数据 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析
热门文章
- 习题6-2 使用函数求特殊a串数列和 (20 分)
- 操作系统 系统开销比率_操作系统中的最高响应比率下一个(HRRN)调度
- 平院实训门禁系统导入
- Python---冒泡排序、选择排序
- php的create_function、function_exists判断函数是否存在
- php 命令链模式,设计模式之------命令链模式
- kafka数据不丢失不重复_超高速底层系统数据复制,安全精准不丢失
- 用户关系表 存储_列式存储系列(一)CStore
- 初中文化能学编程吗_网页编程课程来了,确定不来pick一下!!!|科创辅学进行时...
- 168.167Excle表列整数字符和字符整数的互相转化