<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Live a simple life

    沉默(zhu_xing@live.cn)
    隨筆 - 48, 文章 - 0, 評論 - 132, 引用 - 0
    數據加載中……

    【Eclipse插件開發】打開編輯器


            今天終于可以閑一天,想來想去就亂寫點東西吧,說不定對有些新人有點幫助呢~_~
            用Eclipse API的方式來打開編輯器,可能對任何一個插件開發者都不是很陌生的操作了。但是,還是建議你忍著看一下,全當是復習吧~_~。
           
            【打開editor的接口討論】
            先來看一下workbench吧,workbench從靜態劃分應該大致如下:
           
                從結構圖我們大致就可以猜測出來,workbench page作為一個IWorkbenchPart(無論是eidtor part還是view part)的容器,肯定會接受workbench page的管理??戳艘幌?,IWorkbenchPage接口定義中確實提供給了如下打開編輯器的操作:

                 【IWokbenchPage提供的接口】
    1 public interface IWorkbenchPage extends IPartService, ISelectionService,ICompatibleWorkbenchPage {
    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中提供了其他的接口:
                
     1 public static IEditorPart openEditor(IWorkbenchPage page, IFile input) throws PartInitException { }
     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()接口的:
    1 public class FileEditorInput implements IFileEditorInput,IPathEditorInput,IPersistableElement {
    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
              
     1  public static IEditorDescriptor getDefaultEditor(IFile file, boolean determineContentType) {
     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):
    <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。對應創建代碼如下:
                
     1 try {
     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, falsenull);
    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打開 
     1 try {
     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源碼編輯器打開
     1 try {
     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打開
     1 try {
     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


    本博客中的所有文章、隨筆除了標題中含有引用或者轉載字樣的,其他均為原創。轉載請注明出處,謝謝!

    posted on 2008-08-27 14:54 zhuxing 閱讀(14819) 評論(7)  編輯  收藏 所屬分類: Eclipse Plug-in & OSGI

    評論

    # re: 【Eclipse插件開發】打開編輯器  回復  更多評論   

    我說Eclipse怎么能記住文件最后使用的編輯器,原來是有這個EDITOR_KEY屬性。

    講的很明白,能不能稍微將將EditorSite?
    2008-08-28 10:27 | Always BaNg.

    # re: 【Eclipse插件開發】打開編輯器  回復  更多評論   

    將得很細致。
    可是我不明白,如果我不想用默認的IFileEditorInput的話,如何使用別的IEditorInput的子類的??或者使用我自己定義的Input的類?
    zhoucheng1985@vip.qq.com
    2009-03-06 16:36 | zhoucheng

    # re: 【Eclipse插件開發】打開編輯器  回復  更多評論   

    非常感謝,我找這個東西找了兩天,終于找到了!很有用,繼續關注!
    2009-11-03 14:17 | MeJustMe

    # re: 【Eclipse插件開發】打開編輯器  回復  更多評論   

    文中 IDE.openEditor(page, java_file); 的IDE類是怎么來的,謝謝
    2011-10-09 10:15 | usur

    # re: 【Eclipse插件開發】打開編輯器  回復  更多評論   

    @MeJustMe
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    @usur
    做的真爛,這頁面

    # re: 【Eclipse插件開發】打開編輯器  回復  更多評論   

    為什么寫到打開工作區外的文件,后面就沒有了啊,我現在正是在想怎么打開工作區外面的文件,希望補全啊
    2013-07-12 09:53 | baker

    # re: 【Eclipse插件開發】打開編輯器[未登錄]  回復  更多評論   

    Cannot determine URI for 這個錯誤是什么原因啊
    2014-12-05 10:18 | xw
    主站蜘蛛池模板: 色噜噜的亚洲男人的天堂| 亚洲一区中文字幕在线电影网| 亚洲日韩精品无码专区加勒比☆ | 中文字幕亚洲综合久久| www成人免费视频| 亚洲午夜日韩高清一区| 又粗又长又爽又长黄免费视频 | 亚洲理论片在线中文字幕| 91精品啪在线观看国产线免费| 亚洲尹人香蕉网在线视颅| 免费91最新地址永久入口 | 成人无码视频97免费| 国产亚洲真人做受在线观看| 中文在线免费看视频| 亚洲成AV人片在| 十八禁无码免费网站| 亚洲欧洲日韩综合| 日韩免费视频一区| 日韩毛片在线免费观看| 亚洲午夜福利AV一区二区无码| 久久99免费视频| 亚洲乱码一二三四区国产| 日韩毛片免费在线观看| j8又粗又长又硬又爽免费视频| 亚洲成A人片在线观看无码不卡| 一级毛片免费观看| 亚洲精品无码人妻无码| 一区国严二区亚洲三区| 久久国产精品成人免费| 亚洲人成网网址在线看| 免费国产成人高清视频网站| 中文字幕免费视频精品一| 亚洲黄色在线观看视频| 四虎成人免费观看在线网址| 一级毛片免费播放试看60分钟| 亚洲成AV人在线观看天堂无码| 国产v精品成人免费视频400条| 国产偷国产偷亚洲高清在线| 亚洲AV无码专区国产乱码电影 | 区三区激情福利综合中文字幕在线一区亚洲视频1 | 亚洲精品亚洲人成在线观看|