<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插件開發】基于WTP開發自定義的JSP編輯器(四):Strucutured Document分析視圖

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

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

            【WTP提供的Properteis視圖擴展】
            說明:Properteis視圖是Eclipse固有的,允許用戶通過相應的類型擴展機制來定制Properties視圖中的內容,涉及到的主要知識點包括:
            1、Eclipse的Adapter機制(IAdaptable、IAdapterFactory、AdapterManager),關于Eclipse中的類型適配擴展機制,博客中的另外一篇文章做了分析:
                【Eclipse插件開發】Eclipse中類型擴展機制分析
            2、Properties視圖相關的幾個重要接口:
                   org.eclipse.ui.views.properties.IPropertySource.class
                   org.eclipse.ui.views.properties.PropertySheetPage
                    ...
            3、WTP就是借助于Eclipse類型擴展機制,實現了對應的功能。我們看一下在WTP的StructuredTextEditor中的getAdapter方法中提供了擴展服務(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視圖的主要功能就是,根據用戶在編輯器中光標的位置,在Properties視圖中展示對應的標簽內容,并支持用戶編輯,例如:

         當前編輯器中,用戶光標位于jsp:directive.page標簽內,屬性視圖就列舉了對應的標簽內容,允許用戶編輯。

            【我們自己的Stuctured Document View】
              如果有一個視圖來將當前編輯器中的內容對應的IStrucuturedDocument以樹狀結構的方式展示出來,再提供一定的用戶交互,那對認清楚IStructuredDocument的本質是有作用的哈

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

                【效果預覽】

                    如上圖所示,雙擊視圖中的節點,編輯器中對應的內容被選中^_^。

                 【實現摘要(文章后面會附上完整代碼)】
                    1、創建插件工程wtp.stuctureddocument,創建視圖,不用多說,利用擴展點org.eclipse.ui.views,對應內容如下:        
     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為視圖對應的ViewPart實現,里面創建了一個tree viewer控件,并給其配置了對應的content provider和label provider,具體參加附件中的源碼。

                   2、利用workbench中的選擇服務(seleciton service)。前面需求中說過,我們要監聽光標在編輯器中的位置選擇,所以使用此服務,所以我們的StructuredDocumentView要實現org.eclipse.ui.ISelectionListener接口。
                    (PS:selection service是workbench的一個重要特性,也是我們常用的,Eclipse官方網站上有一篇專題文章,看看撒兩眼^_^)
        
                      注冊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     }
                    
                    實現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                 //注冊監聽器,便于同步刷新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      * 判斷當前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、如果當前選擇事件來自TextEditor類型的編輯器中(文本編輯器的共同超類),則去獲取編輯器對應的IDocument,如果是IStrucuturedDocument則判斷是否需要更新;如果不是,則不是我們的目標(例如如果打開的是java源碼編輯器,那對應的IDocument實現肯定不是WTP的IStrucuturedDocument了哈^_^)
                2、如果是IStrucuturedDocument,則確定是否需要更新(也就是判斷我們的Structured Document分析視圖中現有的input是否就是當前編輯器中內容對應的IStrucuturedDocument)。如果需要更新,則重新設置tree viewer輸入
                3、我們根據光標在編輯器中的位置信息(參加org.eclipse.jface.text.ITexSelection),首先利用IStructuredDocument.getRegionAtCharacterOffset(int)來定位對應的IStructuredDocumentRegion樹枝節點,然后在利用IStructuredDocumentRegion.getRegionAtCharacterOffset(int)來定位對應的ITextRegion樹葉節點,在我們視圖的樹狀控件中選中對應的樹葉節點。
                    回顧:對于IStructuredDocument來說,它的孩子就是IStructuredDoucmentRegion,并沒有提供對應的接口允許用戶直接去獲取特定offset對應的具體ITextRegion。再看一下前面用到的一幅圖吧:
                    

                    3、處理視圖中tree viewer雙擊,定位編輯器中對應內容
                        
     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區域
    20                     ((StructuredTextEditor)sourcePart).getTextViewer().setSelectedRange(selectionOffset, selectionLength);
    21                 }
    22                 else if (treePath.getSegmentCount() == 3) {
    23                     //選擇的是非container的ITextRegion,其父節點為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                     //處理編輯器選中,選中的是葉子節點的text region區域
    31                     ((StructuredTextEditor)sourcePart).getTextViewer().setSelectedRange(selectionOffset, selectionLength);
    32                 }
    33             }
    34         });
                    TreePath(org.eclipse.jface.viewers.TreePath)中的seg count信息其實確定了我們的雙擊的控件位于整個樹狀控件的位置,具體自己看吧^_^
                
                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實在前面handle selection的過程注冊的,再決定用一個新的IStructuredDocument作為tree viewer輸入的時候,同步注冊對應的監聽器。
                注意:我們這邊并沒有wtp自己的document listener,它自己都不建議使用了^_^

            5、處理編輯器關閉行為,利用workbench的part service特性。當對應的編輯器關閉時,視圖中的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          * 如果被關閉的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過程中緩存的,這邊就派上用場了啊,能夠判斷當前關閉的part是否就提供當前IStructuredDocument的text eidtor 了^_^
                注冊代碼再上面的init方法代碼中有,注冊了對應的selection listener和part listener
        

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

                最后強調一下,我們的這個插件工程需要依賴的插件列表為:
                 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


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

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

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

    評論

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

    不要只觀察規則的jsp內容對應的document是怎樣的
    也要看看不規則的(不符合jsp語法的)jsp內容對應的document是怎樣的

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

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

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

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

    IStructuredDocument structuredDocument = (IStructuredDocument)document; 這一句報錯啊,請問樓主Eclipse是哪個版本的呢?
    2015-01-21 15:18 | ddd
    主站蜘蛛池模板: 国产h视频在线观看网站免费| 一本大道一卡二大卡三卡免费| 1区2区3区产品乱码免费| 亚洲va无码专区国产乱码| 久久WWW免费人成—看片| 亚洲av再在线观看| 一区在线免费观看| 国产成人精品亚洲精品| 极品美女一级毛片免费| 国产成人亚洲精品影院| yellow视频免费在线观看| 国产亚洲精品久久久久秋霞| 美女无遮挡拍拍拍免费视频| 国产亚洲精品资源在线26u| 毛片在线播放免费观看| 一级毛片试看60分钟免费播放| 亚洲日韩精品无码专区网站| 国产日韩在线视频免费播放| 亚洲国产精品无码久久SM | 老司机亚洲精品影院| 伊人久久免费视频| va天堂va亚洲va影视中文字幕| 亚洲国产精华液2020| va亚洲va日韩不卡在线观看| 亚洲精品影院久久久久久| 99久久99这里只有免费费精品| 日本亚洲免费无线码 | 午夜成年女人毛片免费观看| 亚洲啪AV永久无码精品放毛片| 国产免费资源高清小视频在线观看| 色爽黄1000部免费软件下载| 精品国产综合成人亚洲区| 人与禽交免费网站视频| 国产V亚洲V天堂A无码| 成年人免费的视频| 猫咪免费观看人成网站在线| 亚洲国产成人私人影院| 在线观看国产情趣免费视频| a级毛片免费高清视频| 亚洲毛片免费视频| 亚洲成A人片在线观看中文|