<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編輯器(六):IStructuredModel(DOM Document)分析視圖

            前面的幾節中,我們都已經完整的介紹過了WTP最核心的幾個數據模型:語法Document(IStructuredDocument)、語義Document(IDOMDocument、ICSSDocument)和WTP模型(IStructuredModel)。IStructuredModel在某種程度上可以看作是語義Document和語法Document的門面,三者關系再羅唆一下:
            
            前面在講完WTP 語法Document(IStructuredDocument)的時候,我們開發過一個Structured Document分析視圖,我想通過那個視圖可以加深對IStructuredDocument的理解。在本節中,我們在開發一個視圖,來分析一下WTP的語義Document(我們只分析最常用的IDOMDocument),希望也有類似的作用。

            PS:這兩個視圖其實可以作為一個工具來用,對于想修改或者定制WTP源碼(當然也包括基于WTP開發一些工具)的開發者可以做一個工具,當寫代碼分析IStructuredDocument(Text Region)和IDOMDocument(Indexed Region)遇到障礙的時候,這兩個視圖應該做為一個助手^_^。而且通過這兩個視圖內容顯示的比較,應該會明白為什么IStructuredDocument是語法Document,為什么IDOMDocument(ICSSDocument)是語義Document。

              開發本IStructuredModel(DOM Document)分析視圖很多地方和前面的Structured Document分析視圖類似,有不明白的地方(涉及到技術實現的地方),可以參考一下前面的第四節。

            【需求】
              和前面的Structured Document分析視圖需求比較類似,大致如下:
               1、提供一個Structured Model分析視圖,以樹狀方式將當前編輯器中的IDOMDocument展示出來
               2、交互(編輯器 ---> Structured Model分析視圖):
                    激活WTP JSP編輯器(或者是我們前面自己定制的編輯器),即時更新Structured Model分析視圖
                    當用戶光在編輯器中標移動時,自動選中Structured Model分析視圖中對應的節點
                    當編輯器中的內容改變時,即時更新Structured Model分析視圖
                    當前激活編輯器關閉時,清空Structured Model分析視圖內容
               3、交互(Structured Model分析視圖 ---> 編輯器)
                    雙擊視圖中樹狀控件中特定節點,對應內容在編輯器中被選中
                4、顯示內容:
                     因為每個節點都是IDOMNode,則分別顯示其實現類名稱、位置信息和文本內容
                    
              【效果預覽】
                
                上面顯示的效果是,雙擊視圖中對應的IDOMNode,對應的文本內容在編輯器中被選中。

                【實現摘要(文章后門會附上對應的源碼)】
                 1、創建插件工程wtp.stucturedmodel,創建視圖。視圖IViewPart對應實現類為StructuredModelView,這個和前面講過的Structured Document分析視圖類似,這邊就不細講了。
    public class StructuredModelView extends ViewPart implements ISelectionListener{
        
    private TreeViewer viewer;
        
    private ITreeContentProvider contentProvider;
        
    private ILabelProvider labelProvider;
            
            
    //
    }
              
                 2、利用workbench中的選擇服務(seleciton service)。前面需求中說過,我們要監聽光標在編輯器中的位置選擇,所以使用此服務,所以我們的StructuredModelView要實現org.eclipse.ui.ISelectionListener接口。
                    注冊、銷毀selection listener和前面開發Structured Document分析視圖是一樣的,在視圖實現類init方法中注冊,在dispose方法中銷毀。        
    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             //判斷是否是IStructuredDocument
    10             if (!(document instanceof IStructuredDocument)) {
    11                 this.viewer.setInput(new Object[0]);
    12                 return ;
    13             }
    14             
    15             //對于editor使用的IStructuredModel,是用IModelManager來管理的
    16             IModelManager modelManager = StructuredModelManager.getModelManager();
    17             IStructuredModel structuredModel = modelManager.getModelForRead((IStructuredDocument)document);
    18             if (structuredModel == null)
    19                 return ;
    20             
    21             //根據判斷是否需要更新tree vier輸入做不同處理
    22             if (this.needUpdateInput(structuredModel)) {
    23                 //減少old model的引用計數,并注銷對應的model listener
    24                 if (this.viewer.getInput() instanceof IStructuredModel) {
    25                     IStructuredModel oldStructuredModel = ((IStructuredModel)this.viewer.getInput());
    26                     
    27                     oldStructuredModel.removeModelStateListener(modelStateListener);
    28                     oldStructuredModel.releaseFromRead();
    29                 }
    30                 
    31                 //設置輸入,并注冊模型狀態監聽器
    32                 structuredModel.addModelStateListener(this.modelStateListener);
    36             }
    37             else {
    38                 //如果不需要此structuredModel作為輸入,則將此structuredModel的引用計數復原
    39                 structuredModel.releaseFromRead();
    40             }
    41             
    42             //根據編輯器中選擇定位到model tree viewer中相應節點
    43             if (selection instanceof ITextSelection)
    44             this.processTextSelection((ITextSelection)selection, structuredModel);
    45             
    46             this.sourcePart = part;
    47         }
    48     }
    49     
    50     /**
    51      * 判斷當前structuredModel和tree viewer中已有的structured model是否一致(判斷是否==,而非equals)
    52      * 
    53      * @param structuredModel
    54      * @return
    55      */
    56     private boolean needUpdateInput(IStructuredModel structuredModel) {
    57         if (this.viewer.getInput() != null)
    58             return this.viewer.getInput() != structuredModel;
    59         
    60         return true;
    61     }
                看的出來,我們的selection處理邏輯如下:
                1、如果當前選擇事件來自TextEditor類型的編輯器中(文本編輯器的共同超類),則去獲取編輯器對應的IDocument,如果是IStrucuturedDocument則判斷是否需要更新;如果不是,則不是我們的菜^_^
                2、利用WTP提供的模型管理器IModelManager(這個在下一節會詳細講,很重要^_^)獲取和以上IStructuredDocument對應的IStructuredModel(通過IStructuredModel,可以獲取到對應的語義Document--IDOMDocument,前面說過的^_^)。然后判斷是否需要刷新模型tree viewer,判斷的依據是看tree viewer中現有的input和本IStructuredModel是否一致。
                    PS:這邊有兩點需要注意:一是IModelStateListener的注冊;二是IModelManager的使用。

                3、處理text selection(參見org.eclipse.jface.text.ITexSelection),定位對應的dom node。大致過程為:首先判根據IStructuredModel.getIndexedRegion獲取對應的節點(注意這邊只能定位到對應的IDOMElement元素,并不能定到對應的IDOMAttr或者IDOMText);其次判斷光標是否位于節點的attribute中,如果是,則定位到dom attr(具體可以參見代碼)

             3、處理視圖中tree viewer雙擊,定位編輯器中對應內容
    this.viewer.addDoubleClickListener(new IDoubleClickListener() {
                    
    public void doubleClick(DoubleClickEvent event) {
                        TreeSelection selection 
    = (TreeSelection)event.getSelection();
                        
                        
    //樹上的每個節點都是indexed region
                        IndexedRegion indexedRegion = (IndexedRegion)selection.getFirstElement();
                        
                        
    //處理編輯器選中
                        int selectionOffset = indexedRegion.getStartOffset();
                        
    int length = indexedRegion.getEndOffset() - selectionOffset;
                        ((StructuredTextEditor)sourcePart).getTextViewer().setSelectedRange(selectionOffset, length);
                    }
                });
                上面我們根據tree viewer中選中的indexed region對應的坐標,直接通過ITextViewer.setSelectedRange(int offset, int length)接口來進行文本選中。(PS:WTP提供的StructuredText本身就是一種ISourceViewer,ISourceViewer本身又是一種ITextViewer^_^)

                4、利用IModelStateListener同步更新視圖。我們在上一節在介紹IStructuredModel的時候,提到過WTP提供了一個IModelStateListener來允許用戶監聽IStructuredModel的狀態變化,IStructuredModel本身又作為一個target,接受用戶注冊IModelStateListener實現。我們的IModelStateListener實現非常簡單,只在目標IStructuredModel變化了之后,刷新視圖中的tree viewer
                
    private class ModelStateListener implements IModelStateListener {
         
    /* (non-Javadoc)
             * @see org.eclipse.wst.sse.core.internal.provisional.IModelStateListener#modelChanged(org.eclipse.wst.sse.core.internal.provisional.IStructuredModel)
             
    */
            
    public void modelChanged(IStructuredModel model) {
                viewer.refresh();
            }

           
    //只覆寫了該方法,其他方法代碼省略
    }

                5、處理編輯器關閉行為,利用workbench的part service特性。當關聯編輯器關閉時,削減目標IStructuredModel的引用計數,并注銷之前注冊的IModelStateListener,清空視圖中的tree viewer。    
    private class PartListener implements IPartListener {
            
    public void partActivated(IWorkbenchPart part) {
                
    // TODO Auto-generated method stub
                
            }
            
            
    public void partBroughtToTop(IWorkbenchPart part) {
                
    // TODO Auto-generated method stub
                
            }
            
            
    /* 
             * 如果被關閉的workbench part是提供structured model信息的source part,則:
             * 1、削減該structured model的引用計數(因為已經不再引用)
             * 2、注銷之前注冊的IModelStateListener
             * 3、清空tree viewer
             * 
             * @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
             
    */
            
    public void partClosed(IWorkbenchPart part) {
                
    //削減引用計數,并注銷對應的model listener
                if (part == StructuredModelView.this) {
                    
    if (viewer.getInput() instanceof IStructuredModel) {
                        IStructuredModel structuredModel 
    = ((IStructuredModel)viewer.getInput());
                        structuredModel.releaseFromRead();
                        
                        structuredModel.removeModelStateListener(modelStateListener);
                    }
                }
                
                
    //update model tree viewer
                if (sourcePart == part) {
                    sourcePart 
    = null;
                    viewer.setInput(
    null);
                }
            }
            
            
    public void partDeactivated(IWorkbenchPart part) {
                
    // TODO Auto-generated method stub
                
            }
            
            
    public void partOpened(IWorkbenchPart part) {
                
    // TODO Auto-generated method stub
            }
        }


                6、tree viewer對應的content provider實現。(其實和我們遍歷一個普通的xml dom document很類似)    
    public class ModelTreeContentProvider implements ITreeContentProvider {

        
    /* 
         * IStructuredModel分為兩種:IDOMModel和ICSSModel,對應的document實現分別為IDOMDocument和ICSSDocument。
         * 我們只分析IDOMModel(IDOMDocument)的情況,對于ICSSModel(ICSSDocument)的分析留給大家吧^_^
         * 
         * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
         
    */
        
    public Object[] getChildren(Object parentElement) {
            
    if (parentElement == null)
                
    return new Object[0];
            
            
    //如果是IDOMModel,則獲取對應的IDOMDocument
            if (parentElement instanceof IDOMModel) {
                IDOMDocument domDocument 
    = ((IDOMModel)parentElement).getDocument();
                
    return new Object[]{domDocument};
            }
            
            
    //對于遵守xml dom規范的node,則按照xml node的結構來遍歷
            if (parentElement instanceof IDOMNode) {
                List children 
    = new ArrayList();
                
                NamedNodeMap attributes 
    = ((IDOMNode)parentElement).getAttributes();
                
    if (attributes != null) {
                    
    for (int i = 0; i < attributes.getLength(); i++) {
                        children.add(attributes.item(i));
                    }
                }
                
                NodeList childNodes 
    = ((IDOMNode)parentElement).getChildNodes();
                
    for (int i = 0; i < childNodes.getLength(); i++) {
                    children.add(childNodes.item(i));
                }
                
                
    return children.toArray();
            }
            
            
    return new Object[0];
        }
         
    //其他方法省略
    }

                

                以上基本上就是本視圖的主要代碼了,開發這個視圖代碼基本上也是300行左右。

                本插件工程需要依賴的插件列表為:
                 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方式導出的,下載鏈接:Structured Model(Dom Document)分析視圖源碼

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

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

    評論

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

    HOHO,真棒!

    什么時候講到 EDITOR 啊~~
    2008-09-18 10:08 | srdrm

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

    大俠,代碼還是前一節的啊,和前面的有重復,能不能換一下撒?謝謝啊!
    2008-10-15 20:33 | 飛揚的麥子

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

    代碼搞混了^_^ 不好意思!
    已經更新了
    2008-10-16 11:20 | zhuxing
    主站蜘蛛池模板: 国产尤物在线视精品在亚洲| 亚洲制服丝袜第一页| 一级看片免费视频| 亚洲?v无码国产在丝袜线观看| 亚洲乱色熟女一区二区三区蜜臀| 成年人性生活免费视频| 亚洲欧美成人av在线观看| 岛国大片免费在线观看| 国产精品久久久久久亚洲小说| 免费在线黄色网址| 精选影视免费在线 | 久久精品亚洲一区二区| 91视频免费网址| 亚洲videos| 免费久久精品国产片香蕉| 亚洲精品视频免费观看| 亚洲爆乳无码一区二区三区| 99久热只有精品视频免费看 | 国产精品亚洲专区无码WEB| 亚洲精品99久久久久中文字幕| 国产精品永久免费| 亚洲综合色丁香麻豆| 成人免费网站在线观看| 激情婷婷成人亚洲综合| 亚洲国产一成人久久精品| 在线免费观看国产| 国产精品亚洲一区二区无码| 亚洲中文久久精品无码ww16| 99re在线精品视频免费| 亚洲人成色4444在线观看| 亚洲一级黄色视频| 亚洲毛片免费观看| 色爽黄1000部免费软件下载| 亚洲国产香蕉碰碰人人| 青青青国产免费一夜七次郎| 福利免费在线观看| 亚洲色最新高清av网站| 国产综合亚洲专区在线| 91免费资源网站入口| 中文字幕免费在线看电影大全 | 91精品国产亚洲爽啪在线观看|