今天终于可以闲一天,想来想去就乱写点东西吧,说不定对有些新人有点帮助呢~_~

用Eclipse API的方式来打开编辑器,可能对任何一个插件开发者都不是很陌生的操作了。但是,还是建议你忍着看一下,全当是复习吧~_~。
       
        【打开editor的接口讨论】
        先来看一下workbench吧,workbench从静态划分应该大致如下:
       
            从结构图我们大致就可以猜测出来,workbench page作为一个IWorkbenchPart(无论是eidtor part还是view part)的容器,肯定会接受workbench page的管理。看了一下,IWorkbenchPage接口定义中确实提供给了如下打开编辑器的操作:

【IWokbenchPage提供的接口】

 public interface IWorkbenchPage extends IPartService, ISelectionService,ICompatibleWorkbenchPage {

      public IEditorPart openEdito(IEditorInput input, String editorId)throws PartInitException;

      public IEditorPart openEdito(IEditorInput input, String editorId, boolean activate) throws PartInitException;

      public IEditorPart openEditor(final IEditorInput input, final String editorId, final boolean activate, final int matchFlags)throws PartInitException;
}

那到这边,可能很多人已经知道了怎么调用这些接口了:
           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中提供了其他的接口:

  public static IEditorPart openEditor(IWorkbenchPage page, IFile input) throws PartInitException { }

  public static IEditorPart openEditor(IWorkbenchPage page, IFile input, boolean activate) throws PartInitException {  }

  public static IEditorPart openEditor(IWorkbenchPage page, IFile input, boolean activate, boolean determineContentType) { }

  public static IEditorPart openEditor(IWorkbenchPage page, IFile input, String editorId) throws PartInitException {  }

  public static IEditorPart openEditor(IWorkbenchPage page, IFile input, String editorId, boolean activate) throws PartInitException {  }
 

上面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()接口的:

 public class FileEditorInput implements IFileEditorInput,IPathEditorInput,IPersistableElement {
private IFile file; public boolean exists() {
return file.exists();
}
}

我们看到内部的实现是持有了IFile句柄,如果IFile代表的资源没有存在于工作区之内,那么就会返回false。(疑问:如果我们打开工作区外部的文件呢???显然,FileEditorInput并不合适,稍后看...)
        
        【动态计算editor id】
         下面,我们再来看一下IDE类是如何计算所谓的默认eidtor id的。追踪实现,我们看到了IDE.getDefaultEditor

   public static IEditorDescriptor getDefaultEditor(IFile file, boolean determineContentType) {
// Try file specific editor.
IEditorRegistry editorReg = PlatformUI.getWorkbench()
.getEditorRegistry();
try {
String editorID = file.getPersistentProperty(EDITOR_KEY);
if (editorID != null) {
IEditorDescriptor desc = editorReg.findEditor(editorID);
if (desc != null) {
return desc;
}
}
} catch (CoreException e) {
// do nothing
} IContentType contentType = null;
if (determineContentType) {
contentType = getContentType(file);
}
// Try lookup with filename
return editorReg.getDefaultEditor(file.getName(), contentType);
}

上面的代码大致赶了如下两件事情:
            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):

    <editor
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。对应创建代码如下:

      try {
//创建工程
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("TestProject");
if (!project.exists())
project.create(null);
if (!project.isOpen())
project.open(null); //创建文件
IFile java_file = project.getFile(new Path("/java_file.txt"));
InputStream inputStreamJava = new ByteArrayInputStream("class MyType{}".getBytes());
if (!java_file.exists())
java_file.create(inputStreamJava, false, null);
} catch (CoreException e) {
IStatus status = new Status(IStatus.ERROR, "myplugin", 101, "创建资源失败", e);
Activator.getDefault().getLog().log(status);
}


        
        打开方式一:Eclipse默认计算对应的editor id,会用default text editor打开

       try {
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("TestProject"); IFile java_file = project.getFile(new Path("/java_file.txt"));
IDE.openEditor(page, java_file);
} catch (CoreException e) {
IStatus status = new Status(IStatus.ERROR, "myplugin", , "打开工作区内文件出错", e);
Activator.getDefault().getLog().log(status);
}

打开方式二:指定java源码编辑器打开,会用java源码编辑器打开

      try {
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("TestProject"); IFile java_file = project.getFile(new Path("/java_file.txt"));
IDE.openEditor(page, java_file, "org.eclipse.jdt.ui.CompilationUnitEditor");
} catch (CoreException e) {
IStatus status = new Status(IStatus.ERROR, "myplugin", , "打开工作区内文件出错", e);
Activator.getDefault().getLog().log(status);
}

打开方式三:设定editor id属性,该文件以后默认都用此editor id打开

     try {
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("TestProject"); IFile java_file = project.getFile(new Path("/java_file.txt"));
java_file.setPersistentProperty(IDE.EDITOR_KEY, "org.eclipse.jdt.ui.CompilationUnitEditor");
IDE.openEditor(page, java_file);
} catch (CoreException e) {
IStatus status = new Status(IStatus.ERROR, "myplugin", , "打开工作区内文件出错", e);
Activator.getDefault().getLog().log(status);
}

说明:对于工作区工程内的资源,可以有两种方式:一是local的,那就是物理存在与工程之内;二是link进入的。打开编辑器的时候,不需要做区分。

【打开工作区外部的资源】
        说明:既存在于工作区外部,同时又没有被link进工程。
        
        在Eclipse中有个功能,就是File->Open File,可以打开一个外部文件。那我们看一下它是怎么实现的。我们只需要打开对应的对话框,然后挂起主线程,就可以找到对应的action了(挂起线程可以帮我们很方便的调试很多类型的问题,以后细说~_~):
                      

分析一下OpenExternalFileAction的实现,我们发现它自己构建了一个editor input

Eclipse插件打开编辑器的更多相关文章

  1. Eclipse插件(导出UML图,打开文件资源管理器插件,静态代码分析工具PMD,在eclipse上安装插件)

    目录 能够导出UML图的Eclipse插件 打开文件资源管理器插件 Java静态代码分析工具PMD 如何在eclipse上安装插件 JProfiler性能分析工具 从更新站点安装EclEmma 能够导 ...

  2. freemarker编辑器eclipse插件

    freemarker编辑器eclipse插件 支持语法高亮,语法校验,代码提示的工具 freemarker  IDE(JBoss): http://download.jboss.org/jbossto ...

  3. 在Eclipse打开css文件时,会自动调用文本编辑器打开,而不是在Eclipse中打开

    问题描述 在Eclipse中打开css文件时候,如下图,使用系统自带的文本编辑器打开 解决方案 点击Window下的Preference,找到File Associations,然后点击Add,将cs ...

  4. 关于Eclipse插件之IWorkbench IWorkbenchWindow IWorkbenchPage |WorkbenchPart......等的总结

    1..IWorkbench: workbench是eclipse用户界面中最底层的对象,它建立在Display之上,包含一个或多个IWorkbenchWindow,用于向终端用户呈现信息 当你的wor ...

  5. Eclipse插件基础篇一

    名词翻译 有一些名词在翻译的过程中可能会出现歧义,在这里统一一下. アーキテクチャ=architecture=架构 プラットフォーム=platform=平台 コンポーネント=component=组件 ...

  6. Sencha EXTJS6的 Eclipse 插件安装指南

    Sencha EXTJS的 Eclipse 插件安装指南 (翻译:苏生米沿) 本文地址:http://blog.csdn.net/sushengmiyan/article/details/52566 ...

  7. 用 Eclipse 插件提高代码质量

    如果能在构建代码前发现代码中潜在的问题会怎么样呢?很有趣的是,Eclipse 插件中就有这样的工具,比如 JDepend 和 CheckStyle,它们能帮您在软件问题暴露前发现这些问题.在 让开发自 ...

  8. Eclipse 插件集合

    以下是我整理的自己开发过程中的常用Eclipse插件,按字母排序: (1)    AmaterasUML        介绍:Eclipse的UML插件,支持UML活动图,class图,sequenc ...

  9. 2.eclipse 插件安装烦死人(1)

    嫌公司用的eclipse不爽,准备自己弄一个,diy的,没想到装插得烦死人. 诱惑人的“常用插件”: (1)    AmaterasUML        介绍:Eclipse的UML插件,支持UML活 ...

随机推荐

  1. ~/.ssh/目录找不到解决方法

    执行 cd ~/.ssh发现.ssh目录找不到 原因是因为没有用root用户ssh登录过,执行一下ssh操作就会自动生成了

  2. Cross-Stage-Partial-Connections

  3. java web 下载文件 response.setHeader()的用法 (转载)

    response.setHeader()的用法 response.setHeader()下载中文文件名乱码问题 收藏 1. HTTP消息头 (1)通用信息头 即能用于请求消息中,也能用于响应信息中,但 ...

  4. 花式求解 LeetCode 279题-Perfect Squares

    原文地址 https://www.jianshu.com/p/2925f4d7511b 迫于就业的压力,不得不先放下 iOS 开发的学习,开始走上漫漫刷题路. 今天我想聊聊 LeetCode 上的第2 ...

  5. 一网打尽 Java 并发模型

    本篇文章我们来探讨一下并发设计模型. 可以使用不同的并发模型来实现并发系统,并发模型说的是系统中的线程如何协作完成并发任务.不同的并发模型以不同的方式拆分任务,线程可以以不同的方式进行通信和协作. 并 ...

  6. idea的热加载与热部署

    一:热加载与热部署     热部署的意思就是不用手动重启环境,修改类后,项目会自动重启.但是如果项目比较大,重启也需要耗时十几秒左右.     热加载意为不需要重新启动,修改了什么文件就重新加载什么文 ...

  7. python库安装失败的解决方法

    安装python库 在https://www.lfd.uci.edu/~gohlke/pythonlibs 中,搜索对应库名称 选取对应版本下载 在cmd窗口中,用命令 pip install+文件路 ...

  8. 拼接html不显示layui进度条解决方法

    最新有个新需求,要异步拼接html并渲染数据,并且我这边是用layui的flow.load(流加载)渲染多个进度条.按官网给出的 element.progress('demo', n+'%'); 就是 ...

  9. 关于Java的对象,锁和对象的内存布局、访问定位

    1. 对象的创建和分配 创建对象(如克隆.反序列化)通常仅仅一个new关键字,但在虚拟机中,对象的创建的过程需要如下步骤: 类加载检查 先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并 ...

  10. 第3章 Hive数据类型

    第3章 Hive数据类型 3.1 基本数据类型 对于Hive的String类型相当于数据库的varchar类型,该类型是一个可变的字符串,不过它不能声明其中最多能存储多少个字符,理论上它可以存储2GB ...