<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
    數(shù)據(jù)加載中……

    【Eclipse插件開發(fā)】基于WTP開發(fā)自定義的JSP編輯器(四):Strucutured Document分析視圖

            在上一篇中,我們詳細(xì)闡述了WTP中最重要的數(shù)據(jù)模型之一IStructuredDocument(我們就稱之為WTP Document吧,和另外一個核心數(shù)據(jù)模型WTP Model----IStructuredModel對應(yīng)),本節(jié)中我們將自己開發(fā)一個工具來分析IStrucutredDocument。

            PS:千萬別著急,后面的文章會對WTP StructuredTextEditor進(jìn)行功能特征定制的,在真正定制之前一定要搞清楚WTP Document(IStructuredDocument)和WTP Model(IStructuredModel),連核心數(shù)據(jù)模型都不熟悉,后面談何定制^_^

            【W(wǎng)TP提供的Properteis視圖擴(kuò)展】
            說明:Properteis視圖是Eclipse固有的,允許用戶通過相應(yīng)的類型擴(kuò)展機(jī)制來定制Properties視圖中的內(nèi)容,涉及到的主要知識點(diǎn)包括:
            1、Eclipse的Adapter機(jī)制(IAdaptable、IAdapterFactory、AdapterManager),關(guān)于Eclipse中的類型適配擴(kuò)展機(jī)制,博客中的另外一篇文章做了分析:
                【Eclipse插件開發(fā)】Eclipse中類型擴(kuò)展機(jī)制分析
            2、Properties視圖相關(guān)的幾個重要接口:
                   org.eclipse.ui.views.properties.IPropertySource.class
                   org.eclipse.ui.views.properties.PropertySheetPage
                    ...
            3、WTP就是借助于Eclipse類型擴(kuò)展機(jī)制,實(shí)現(xiàn)了對應(yīng)的功能。我們看一下在WTP的StructuredTextEditor中的getAdapter方法中提供了擴(kuò)展服務(wù)(IWorkbenchPart本身就是聲明為IAdaptable):
                
     1 /*
     2      * (non-Javadoc)
     3      * 
     4      * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
     5      */
     6     public Object getAdapter(Class required) {
     7       //
     8       else if (IPropertySheetPage.class.equals(required) && isEditable()) {
     9             if (fPropertySheetPage == null || fPropertySheetPage.getControl() == null || fPropertySheetPage.getControl().isDisposed()) {
    10                 PropertySheetConfiguration cfg = createPropertySheetConfiguration();
    11                 if (cfg != null) {
    12                     ConfigurablePropertySheetPage propertySheetPage = new ConfigurablePropertySheetPage();
    13                     propertySheetPage.setConfiguration(cfg);
    14                     fPropertySheetPage = propertySheetPage;
    15                 }
    16             }
    17             result = fPropertySheetPage;
    18         }
    19          //.
    20 }
             ConfigurablePropertySheetPage^_^(org.eclipse.wst.sse.ui.internal.properties.ConfigurablePropertySheetPage)。

            WTP的properties視圖的主要功能就是,根據(jù)用戶在編輯器中光標(biāo)的位置,在Properties視圖中展示對應(yīng)的標(biāo)簽內(nèi)容,并支持用戶編輯,例如:

         當(dāng)前編輯器中,用戶光標(biāo)位于jsp:directive.page標(biāo)簽內(nèi),屬性視圖就列舉了對應(yīng)的標(biāo)簽內(nèi)容,允許用戶編輯。

            【我們自己的Stuctured Document View】
              如果有一個視圖來將當(dāng)前編輯器中的內(nèi)容對應(yīng)的IStrucuturedDocument以樹狀結(jié)構(gòu)的方式展示出來,再提供一定的用戶交互,那對認(rèn)清楚IStructuredDocument的本質(zhì)是有作用的哈

                【需求】
                1、提供一個Structured Document View視圖,以樹狀方式將當(dāng)前編輯器中的IStructuredDocument展示出來
                2、交互(編輯器 ---> Structured Document View視圖):
                       激活WTP JSP編輯器(或者是我們前面自己定制的編輯器),即時更新Structured Document View視圖
                       當(dāng)用戶光在編輯器中標(biāo)移動時,自動選中Structured Document View視圖中對應(yīng)的節(jié)點(diǎn)
                       當(dāng)編輯器中的內(nèi)容改變時,即時更新Structured Document View視圖
                       當(dāng)前激活編輯器關(guān)閉時,清空Structured Document View視圖內(nèi)容
                3、交互(Structured Document View視圖 ---> 編輯器)
                       雙擊視圖中樹狀控件中特定節(jié)點(diǎn),對應(yīng)內(nèi)容在編輯器中被選中
                4、顯示內(nèi)容:
                       對于IStructuredDocument,則顯示對應(yīng)的具體實(shí)現(xiàn)類(對應(yīng)于JSP類型則為JobSafeStructuredDocument)
                        對于IStrucutredDocumentRegion(ITextRegionCollection),則顯示實(shí)現(xiàn)類名稱、節(jié)點(diǎn)類型、位置范圍、文本等
                        對于葉子節(jié)點(diǎn)的ITextRegion,則顯示實(shí)現(xiàn)類名稱、節(jié)點(diǎn)類型、位置范圍(說明:相對于父ITextRegionCollection的相對位置,非對于整個文檔的相對位置?。。。?br />
                【效果預(yù)覽】

                    如上圖所示,雙擊視圖中的節(jié)點(diǎn),編輯器中對應(yīng)的內(nèi)容被選中^_^。

                 【實(shí)現(xiàn)摘要(文章后面會附上完整代碼)】
                    1、創(chuàng)建插件工程wtp.stuctureddocument,創(chuàng)建視圖,不用多說,利用擴(kuò)展點(diǎn)org.eclipse.ui.views,對應(yīng)內(nèi)容如下:        
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <?eclipse version="3.2"?>
     3 <plugin>
     4    <extension
     5          point="org.eclipse.ui.views">
     6       <category
     7             id="wtp.structureddocument.category"
     8             name="Structured Document分析"/>
     9       <view
    10             category="wtp.structureddocument.category"
    11             class="wtp.structureddocument.view.StructuredDocumentView"
    12             id="wtp.structureddocument.view"
    13             name="Structured Document分析"/>
    14    </extension>
    15 </plugin>
                    wtp.structureddocument.view.StructuredDocumentView為視圖對應(yīng)的ViewPart實(shí)現(xiàn),里面創(chuàng)建了一個tree viewer控件,并給其配置了對應(yīng)的content provider和label provider,具體參加附件中的源碼。

                   2、利用workbench中的選擇服務(wù)(seleciton service)。前面需求中說過,我們要監(jiān)聽光標(biāo)在編輯器中的位置選擇,所以使用此服務(wù),所以我們的StructuredDocumentView要實(shí)現(xiàn)org.eclipse.ui.ISelectionListener接口。
                    (PS:selection service是workbench的一個重要特性,也是我們常用的,Eclipse官方網(wǎng)站上有一篇專題文章,看看撒兩眼^_^)
        
                      注冊selection listener: 
    1 /* (non-Javadoc)
    2      * @see org.eclipse.ui.part.ViewPart#init(org.eclipse.ui.IViewSite)
    3      */
    4     public void init(IViewSite site) throws PartInitException {
    5         super.init(site);
    6         
    7         this.getSite().getPage().getWorkbenchWindow().getSelectionService().addPostSelectionListener(this);
    8         this.getSite().getPage().getWorkbenchWindow().getPartService().addPartListener(partListener);
    9     }
                    
                    實(shí)現(xiàn)selection事件處理:
     1 /* (non-Javadoc)
     2      * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
     3      */
     4     public void selectionChanged(IWorkbenchPart part, ISelection selection) {
     5         if (part instanceof TextEditor) {
     6             IEditorInput editorInput = ((TextEditor)part).getEditorInput();
     7             IDocument document = ((TextEditor)part).getDocumentProvider().getDocument(editorInput);
     8             
     9             if (!(document instanceof IStructuredDocument)) {
    10                 this.viewer.setInput(new Object[0]);
    11                 return ;
    12             }
    13         
    14             IStructuredDocument structuredDocument = (IStructuredDocument)document;
    15             
    16             if (this.needUpdateInput(document)) {
    17                 this.viewer.setInput(new Object[]{document});
    18                 this.viewer.expandAll();
    19                 this.viewer.collapseAll();
    20                 
    21                 //set source workbench part, will be used in part listener
    22                 this.sourcePart = part;
    23                 
    24                 //注冊監(jiān)聽器,便于同步刷新tree viewer
    25                 structuredDocument.addDocumentListener(documentListener);
    26             }
    27             
    28             if (selection instanceof ITextSelection) {
    29                 int offset = ((ITextSelection)selection).getOffset();
    30                 IStructuredDocumentRegion structuredDocumentRegion = structuredDocument.getRegionAtCharacterOffset(offset);
    31                 ITextRegion textRegion = structuredDocumentRegion.getRegionAtCharacterOffset(offset);
    32                 
    33                 this.viewer.collapseAll();
    34                 this.viewer.expandToLevel(structuredDocumentRegion, 2);
    35                 this.viewer.setSelection(new StructuredSelection(textRegion));
    36             }
    37         }
    38     }
                
     1 /**
     2      * 判斷當(dāng)前document和tree viewer中輸入的document是否一致
     3      * 
     4      * @param document
     5      * @return
     6      */
     7     private boolean needUpdateInput(IDocument document) {
     8         if (this.viewer.getInput() != null) {
     9             Object[] oldInput = (Object[])this.viewer.getInput();
    10             if (oldInput.length == 1)
    11                 return oldInput[0!= document;
    12         }
    13         
    14         return true;
    15     }

                看的出來,我們的selection處理邏輯如下:
                1、如果當(dāng)前選擇事件來自TextEditor類型的編輯器中(文本編輯器的共同超類),則去獲取編輯器對應(yīng)的IDocument,如果是IStrucuturedDocument則判斷是否需要更新;如果不是,則不是我們的目標(biāo)(例如如果打開的是java源碼編輯器,那對應(yīng)的IDocument實(shí)現(xiàn)肯定不是WTP的IStrucuturedDocument了哈^_^)
                2、如果是IStrucuturedDocument,則確定是否需要更新(也就是判斷我們的Structured Document分析視圖中現(xiàn)有的input是否就是當(dāng)前編輯器中內(nèi)容對應(yīng)的IStrucuturedDocument)。如果需要更新,則重新設(shè)置tree viewer輸入
                3、我們根據(jù)光標(biāo)在編輯器中的位置信息(參加org.eclipse.jface.text.ITexSelection),首先利用IStructuredDocument.getRegionAtCharacterOffset(int)來定位對應(yīng)的IStructuredDocumentRegion樹枝節(jié)點(diǎn),然后在利用IStructuredDocumentRegion.getRegionAtCharacterOffset(int)來定位對應(yīng)的ITextRegion樹葉節(jié)點(diǎn),在我們視圖的樹狀控件中選中對應(yīng)的樹葉節(jié)點(diǎn)。
                    回顧:對于IStructuredDocument來說,它的孩子就是IStructuredDoucmentRegion,并沒有提供對應(yīng)的接口允許用戶直接去獲取特定offset對應(yīng)的具體ITextRegion。再看一下前面用到的一幅圖吧:
                    

                    3、處理視圖中tree viewer雙擊,定位編輯器中對應(yīng)內(nèi)容。
                        
     1 this.viewer.addDoubleClickListener(new IDoubleClickListener() {
     2             public void doubleClick(DoubleClickEvent event) {
     3                 TreeSelection treeSelection = (TreeSelection)event.getSelection();
     4                 TreePath treePath = treeSelection.getPaths()[0];
     5                 
     6                 if (treePath.getSegmentCount() == 1) {
     7                     //選擇的是IStructuredDocument
     8                     IStructuredDocument structuredDocument = (IStructuredDocument)treeSelection.getFirstElement();
     9                     
    10                     //處理編輯器選中,選中整個文檔
    11                     ((StructuredTextEditor)sourcePart).getTextViewer().setSelectedRange(0, structuredDocument.getLength());
    12                 }
    13                 else if (treePath.getSegmentCount() == 2) {
    14                     //選擇的是IStructuredDocumentRegion
    15                     IStructuredDocumentRegion structuredDocumentRegion = (IStructuredDocumentRegion)treePath.getLastSegment();
    16                     int selectionOffset = structuredDocumentRegion.getStart();
    17                     int selectionLength = structuredDocumentRegion.getLength();
    18                     
    19                     //處理編輯器選中,選中structured document region區(qū)域
    20                     ((StructuredTextEditor)sourcePart).getTextViewer().setSelectedRange(selectionOffset, selectionLength);
    21                 }
    22                 else if (treePath.getSegmentCount() == 3) {
    23                     //選擇的是非container的ITextRegion,其父節(jié)點(diǎn)為IStructuredDocumentRegion
    24                     IStructuredDocumentRegion structuredDocumentRegion = (IStructuredDocumentRegion)treePath.getSegment(1);
    25                     ITextRegion textRegion = (ITextRegion)treePath.getLastSegment();
    26                     
    27                     int selectionOffset = structuredDocumentRegion.getStartOffset(textRegion);
    28                     int selectionLength = textRegion.getLength();
    29                     
    30                     //處理編輯器選中,選中的是葉子節(jié)點(diǎn)的text region區(qū)域
    31                     ((StructuredTextEditor)sourcePart).getTextViewer().setSelectedRange(selectionOffset, selectionLength);
    32                 }
    33             }
    34         });
                    TreePath(org.eclipse.jface.viewers.TreePath)中的seg count信息其實(shí)確定了我們的雙擊的控件位于整個樹狀控件的位置,具體自己看吧^_^
                
                4、利用IDocumentListener同步更新視圖。邏輯非常簡單,如下:          
    1 private class StructuredDocumentListener implements IDocumentListener {
    2         public void documentChanged(DocumentEvent event) {
    3             viewer.refresh();
    4         }
    5         
    6         public void documentAboutToBeChanged(DocumentEvent event) {
    7             // nothing to do
    8         }
    9     }
                我們的listener實(shí)在前面handle selection的過程注冊的,再決定用一個新的IStructuredDocument作為tree viewer輸入的時候,同步注冊對應(yīng)的監(jiān)聽器。
                注意:我們這邊并沒有wtp自己的document listener,它自己都不建議使用了^_^

            5、處理編輯器關(guān)閉行為,利用workbench的part service特性。當(dāng)對應(yīng)的編輯器關(guān)閉時,視圖中的tree viewer
     1 private class PartListener implements IPartListener {
     2         public void partActivated(IWorkbenchPart part) {
     3             // TODO Auto-generated method stub
     4             
     5         }
     6         
     7         public void partBroughtToTop(IWorkbenchPart part) {
     8             // TODO Auto-generated method stub
     9             
    10         }
    11         
    12         /* 
    13          * 如果被關(guān)閉的workbench part是提供document信息的source part,則情況tree viewer
    14          * 
    15          * @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
    16          */
    17         public void partClosed(IWorkbenchPart part) {
    18             if (sourcePart == part) {
    19                 sourcePart = null;
    20                 viewer.setInput(new Object[0]);
    21             }
    22         }
    23         
    24         public void partDeactivated(IWorkbenchPart part) {
    25             // TODO Auto-generated method stub
    26             
    27         }
    28         
    29         public void partOpened(IWorkbenchPart part) {
    30             // TODO Auto-generated method stub
    31         }
    32     }
                注意:上面代碼的source part是我們的handle selection過程中緩存的,這邊就派上用場了啊,能夠判斷當(dāng)前關(guān)閉的part是否就提供當(dāng)前IStructuredDocument的text eidtor 了^_^
                注冊代碼再上面的init方法代碼中有,注冊了對應(yīng)的selection listener和part listener
        

                上面基本上就是我們的視圖主類wtp.structureddocument.view.StructuredDocumentView的所有代碼了,我們開發(fā)這樣一個視圖也只用了200多行代碼...

                最后強(qiáng)調(diào)一下,我們的這個插件工程需要依賴的插件列表為:
                 org.eclipse.ui,
                 org.eclipse.core.runtime,
                 org.eclipse.core.resources,
                 org.eclipse.wst.sse.core,
                 org.eclipse.wst.xml.core,
                 org.eclipse.wst.sse.ui,
                 org.eclipse.jface.text,
                 org.eclipse.ui.workbench.texteditor


               【源碼下載】
                 源碼為實(shí)際工程以Export ---> Archive File方式導(dǎo)出的,下載鏈接:source.zip 。

    本博客中的所有文章、隨筆除了標(biāo)題中含有引用或者轉(zhuǎn)載字樣的,其他均為原創(chuàng)。轉(zhuǎn)載請注明出處,謝謝!

    posted on 2008-09-11 16:16 zhuxing 閱讀(3189) 評論(3)  編輯  收藏 所屬分類: Eclipse Plug-in & OSGI 、WTP(Web Tools Platform)

    評論

    # re: 【Eclipse插件開發(fā)】基于WTP開發(fā)自定義的JSP編輯器(四):Strucutured Document分析視圖  回復(fù)  更多評論   

    不要只觀察規(guī)則的jsp內(nèi)容對應(yīng)的document是怎樣的
    也要看看不規(guī)則的(不符合jsp語法的)jsp內(nèi)容對應(yīng)的document是怎樣的

    這很重要?。?!直接影響后面你定制的行為是否健壯?。?!
    2008-09-11 16:36 | zhuxing

    # re: 【Eclipse插件開發(fā)】基于WTP開發(fā)自定義的JSP編輯器(四):Strucutured Document分析視圖  回復(fù)  更多評論   

    明白,謝謝!
    2008-09-12 07:16 | srdrm

    # re: 【Eclipse插件開發(fā)】基于WTP開發(fā)自定義的JSP編輯器(四):Strucutured Document分析視圖[未登錄]  回復(fù)  更多評論   

    IStructuredDocument structuredDocument = (IStructuredDocument)document; 這一句報錯啊,請問樓主Eclipse是哪個版本的呢?
    2015-01-21 15:18 | ddd
    主站蜘蛛池模板: 99亚洲乱人伦aⅴ精品| 亚洲色精品VR一区区三区| 特级毛片免费观看视频| 成人片黄网站色大片免费| 亚洲国产日韩在线| 中文字幕无码播放免费| 亚洲欧洲国产经精品香蕉网| 久久久久高潮毛片免费全部播放| 亚洲av日韩综合一区在线观看| 青青青国产手机频在线免费观看| 亚洲AV无码欧洲AV无码网站| 久久国产免费一区| 亚洲日本香蕉视频| 无码中文在线二区免费| 人人狠狠综合久久亚洲| 亚洲精品国产综合久久一线| 亚洲免费一区二区| 久久狠狠高潮亚洲精品| 亚洲中文无码永久免费| 美景之屋4在线未删减免费| 亚洲精品无码永久在线观看| 在线毛片片免费观看| 亚洲色偷偷偷网站色偷一区| 成人性生交大片免费看无遮挡| 久久精品国产亚洲AV电影网| 亚洲色偷偷综合亚洲AV伊人| 特级无码毛片免费视频尤物| 亚洲中文字幕人成乱码| 免费一级毛片不卡不收费| 野花香在线视频免费观看大全| 亚洲第一页中文字幕| 又粗又硬又黄又爽的免费视频| 99久久成人国产精品免费 | 2022国内精品免费福利视频| 人人狠狠综合久久亚洲88| 日韩亚洲国产高清免费视频| 美女视频黄.免费网址| 亚洲激情在线观看| 国产伦一区二区三区免费 | 亚洲人成在线中文字幕| 成人伊人亚洲人综合网站222|