<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編輯器(十二):定制自動編輯策略(Auto Edit Strategy)

                JFace Text Framework框架的一個重要的功能特征就是自動編輯策略,它允許用戶對輸入的內容(準確的說應該是即將來臨的Document修改^_^)做即時編輯,然后又會透明的將用戶的修改付諸于實現(即應用到當前文檔)。在本節,我們將在前兩節有關TLD Content Model的基礎上開發一個自動編輯策略。

            【JFace Text Framework 自動編輯策略原理介紹】

             【JDT Java源碼編輯器自動編輯策略演示】
              我們每個使用Eclipse JDT進行Java編程的開發者都會對JDT中Java源碼編輯器的自動編輯策略印象深刻,它給編碼人員帶來了很大的方便。舉例如下:
         
                如上圖所示,我們在編寫一個新的函數,圖中黑色豎線“|”就是光標所在處,當我們按下回車鍵的時候,效果變為如下:
         
                    如上圖所示,當我們輸入回車鍵之后,JDT Java源碼編輯器自動幫我們矯正了內容(text)和位置(offset):原來的輸入內容應該是“\r\n”,JDT Java源碼編輯器自動幫我們矯正為“\r\n\t\t\r\n\t}”;根據“\r\n”內容推算,輸入后光標位置應該位于28行的起始處,JDT Java源碼編輯器自動幫我們矯正為離28行其實處兩個“\t”的距離。

                【自動編輯流程和主要角色】
                                    
                    上圖就演示了自動編輯過程:
                    1、用戶編輯,鍵盤事件
                    2、根據鍵盤事件,對事件信息進行分析,拼裝到名為DocumentCommand的數據結構中,該數據結構中包含了用戶的輸入內容(text)、光標位置(offset)等信息,例如,上面JDT的例子中用戶的輸入內容為“\r\n”。這一步JFace Text Framework幫用戶解決了
                    3、調用自動編輯策略,對應DocumentCommand中數據進行自定義矯正,例如,JDT Java源碼編輯器的自動編輯策略將輸入內容矯正為“\r\n\t\t\r\n\t}”。用戶自己負責,JDT Java源碼編輯器在這邊干活了,提供了自己的IAutoEditStrategy^_^
                    4、將用戶矯正后的DocumentCommand應用到對應編輯器(說白了,就是轉化為一個Document replace動作執行)。這一步JFace Text Framework幫用戶解決了
                    
                    我們可以看到,JFace Text Framework已經替我們干了大部分活,我們需要關心的是如下兩個角色:    
                    org.eclipse.jface.text.DocumentCommand:數據載體,封裝了一個文本變化(text modification)的信息,例如輸入內容(text)、光標位置(offset)、長度(length)等等。我們要做的恰恰就是在我們自己的自動編輯策略中對DocumentCommand中的內容做矯正,然后JFace Text Framework會自動幫我們應用到目標IDocument中。
                    org.eclipse.jface.text.IAutoEditStrategy:自動編輯編輯策略,根據不同應用場景對DocumentCommand中的信息做不同的矯正。我們看一下其接口定義就知道了:
    package org.eclipse.jface.text;


    /**
     * An auto edit strategy can adapt changes that will be applied to
     * a text viewer's document. The strategy is informed by the text viewer
     * about each upcoming change in form of a document command. By manipulating
     * this document command, the strategy can influence in which way the text
     * viewer's document is changed. Clients may implement this interface.
     *
     * 
    @since 2.1
     
    */
    public interface IAutoEditStrategy {

        
    /**
         * Allows the strategy to manipulate the document command.
         *
         * 
    @param document the document that will be changed
         * 
    @param command the document command describing the change
         
    */
        
    void customizeDocumentCommand(IDocument document, DocumentCommand command);
    }
                
                【配置IAutoEditStrategy到SourceViewer】
                
    上面我們已經講了自動編輯的流程和主要角色,可以大家都有個疑問:IAutoEditStrategy到底是如何被自動調用的?IAutoEditStrategy實現需要被配置到對應的SourceViewerConfiguration中,并和對應的內容類型(很多時候也可以理解為分區類型)綁定。JFace Text Framework會在初始化編輯器實例的時候讀取用戶的配置,然后根據不同的內容類型去查找對應的自動編輯器策略。 
    package org.eclipse.jface.text.source;

    public class SourceViewerConfiguration {
        
    /**
         * Returns the auto edit strategies ready to be used with the given source viewer
         * when manipulating text of the given content type. For backward compatibility, this implementation always
         * returns an array containing the result of {
    @link #getAutoIndentStrategy(ISourceViewer, String)}.
         *
         * 
    @param sourceViewer the source viewer to be configured by this configuration
         * 
    @param contentType the content type for which the strategies are applicable
         * 
    @return the auto edit strategies or <code>null</code> if automatic editing is not to be enabled
         * 
    @since 3.1
         
    */
        
    public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, String contentType) {
            
    //
        }
    }
                
                附加說明:1、有關內容類型(分區類型)可以參考前面章節的內容; 2、原有的IAutoIndentStrategy接口Eclipse已經不推薦使用^_^

                【定制WTP StructuredTextEditor的自動編輯策略】
             
    【需求】
                    當用戶輸入標簽結束符“>”時,如果標簽在TLD中定義為不含有標簽體(即bodycontent屬性值為empty),則自動將用戶的輸入內容矯正為“/>”。
                    
                    【前提知識】
                      對WTP基本數據模型不很了解的可以參見一下前面的相關章節:
                      【Eclipse插件開發】基于WTP開發自定義的JSP編輯器(三) :WTP Structured Document     
                      【Eclipse插件開發】基于WTP開發自定義的JSP編輯器(五) :WTP Structured Model     
                      【Eclipse插件開發】基于WTP開發自定義的JSP編輯器(七):WTP數據模型總結和模型管理    
                      【Eclipse插件開發】基于WTP開發自定義的JSP編輯器(十):WTP TLD內容模型介紹     

                    【開發自定義的IAutoEditStrategy實現】    
    /**
     * 針對JSP_DIRECTIVE分區的自動編輯策略
     *
     * 
    @author zhuxing (mailto:zhu_xing@live.cn)
     
    */
    /*
     * 修改歷史
     * $Log$ 
     
    */
    public class JSPDirectivePartitionAutoEditStrategy implements IAutoEditStrategy {
        
        
    /* (non-Javadoc)
         * @see org.eclipse.jface.text.IAutoEditStrategy#customizeDocumentCommand(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.DocumentCommand)
         
    */
        
    public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
            String text 
    = command.text;
            
    if (!">".equals(text))
                
    return ;
            
            IStructuredDocument structuredDocument 
    = (IStructuredDocument)document;
            IStructuredDocumentRegion structuredDocumentRegion 
    = structuredDocument.getRegionAtCharacterOffset(command.offset);
            ITextRegion currentRegion 
    = structuredDocumentRegion.getRegionAtCharacterOffset(command.offset);
            
            
    int startOffset = structuredDocumentRegion.getStartOffset(currentRegion);
            
    int textLength = currentRegion.getTextLength();
            
            
    //執行前提條件:1、用戶正在標簽名區域編輯;2、用戶編輯位置位于標簽名末端
            if (currentRegion.getType() == DOMRegionContext.XML_TAG_NAME 
                    
    && command.offset >= startOffset +
     textLength) {
                
    if (!
    hasBody(structuredDocumentRegion))
                    command.text 
    = "/>"
    ;
            }
        }

        
    /**
         * 查詢對應的TLD內容模型,判斷該標簽在TLD中定義的時候是否含有標簽體
         * 
         * 
    @param structuredDocumentRegion
         * 
    @return
         
    */
        
    private boolean hasBody(IStructuredDocumentRegion structuredDocumentRegion) {
            
    //獲取標簽名稱
            IStructuredDocument structuredDocument = structuredDocumentRegion.getParentDocument();
            IStructuredModel structuredModel 
    = StructuredModelManager.getModelManager().getModelForRead(structuredDocument);
            IDOMElement domElement 
    = (IDOMElement)structuredModel.getIndexedRegion(structuredDocumentRegion.getStartOffset());
            String tagName 
    = domElement.getNodeName();
            
            
    /**
             * 1、獲取位置相關的TLD Document列表
             * 2、查找對應的TLD Element(Tag)定義
             * 3、判斷TLD Element(Tag)定義中定義的bodycontent屬性是否為“empty”
             
    */
            TLDCMDocumentManager manager 
    = TaglibController.getTLDCMDocumentManager(structuredDocument);
            List list 
    = manager.getCMDocumentTrackers(structuredDocumentRegion.getStartOffset());
            
    for (Iterator iter = list.iterator(); iter.hasNext();) {
                TaglibTracker tracker 
    = (TaglibTracker) iter.next();
                TLDDocument tlDocument 
    = (TLDDocument)tracker.getDocument();
                CMNode cmnode 
    = tlDocument.getElements().getNamedItem(tagName);
                
    if (cmnode == null)
                    
    continue ;
                
                String bodyType 
    = ((TLDElementDeclaration)cmnode).getBodycontent();
                
    if ("empty".equals(bodyType))
                    
    return false;
                
    return true;
            }
            
    return false;
        }
        
    }

                    基本流程如下:
                    1、執行條件判斷,我這邊假設用戶正在標簽名區域編輯(通過判斷編輯區域region的region type來判斷),并且編輯位置位于標簽名內容末端           
                    2、查詢和當前文檔中特定位置相關的WTP TLD內容模型,判斷該標簽在TLD文件中定義的時候是否聲明允許有標簽體
                    3、如果標簽在TLD中定義為不含有標簽體,則矯正為自動閉合,“>”--->“/>”

                    PS:有關語法Document、語義Doucment、WTP TLD Content Document等數據類型相關內容請參見前面的章節。

                【配置SourceViewerConfiguration】
                  將我們上面的開發的自動編輯策略配置到我們的SourceViewerConfiguration實現中:   
    /**
     * 自定義StructuredTextViewerConfiguration,基于WTP jst提供的StructuredTextViewerConfigurationJSP,
     * 后面會提供自定義的自動提示策略等擴展。
     *
     * 
    @author zhuxing (mailto:zhu_xing@live.cn)
     
    */
    /*
     * 修改歷史
     * $Log$ 
     
    */
    public class JSPStructuredTextViewerConfiguration extends
            StructuredTextViewerConfigurationJSP {
        
    /* 
         * 提供自定義的自動提示策略
         * 
         * @see org.eclipse.jst.jsp.ui.StructuredTextViewerConfigurationJSP#getContentAssistProcessors(org.eclipse.jface.text.source.ISourceViewer, java.lang.String)
         
    */
        
    protected IContentAssistProcessor[] getContentAssistProcessors(ISourceViewer sourceViewer, String partitionType) {
            
    //我們目前只自定義JSP標簽屬性值自動提示的情況,所以針對的分區類型為IJSPPartitions.JSP_DIRECTIVE
            if (partitionType == IJSPPartitions.JSP_DIRECTIVE) {
                
    return new IContentAssistProcessor[]{new CustomizedJSPContentAssistantProcessor(), new JSPContentAssistProcessor()};
            }
            
            
    return super.getContentAssistProcessors(sourceViewer, partitionType);
        }
        
        
    /* 
         * 提供自定義的自動編輯策略
         * 
         * @see org.eclipse.jst.jsp.ui.StructuredTextViewerConfigurationJSP#getAutoEditStrategies(org.eclipse.jface.text.source.ISourceViewer, java.lang.String)
         
    */
        
    public IAutoEditStrategy[] getAutoEditStrategies(ISourceViewer sourceViewer, String contentType) {
            
    //我們目前只自定義JSP標簽名有關的自動編輯策略,所以針對的分區類型為IJSPPartitions.JSP_DIRECTIVE
            if (contentType == IJSPPartitions.JSP_DIRECTIVE) {
                List
    <IAutoEditStrategy> strategies = new ArrayList<IAutoEditStrategy>();
                
                
    //WTP已配置的自動編輯策略
                IAutoEditStrategy[] existingStrategies = super.getAutoEditStrategies(sourceViewer, contentType);
                Collections.addAll(strategies, existingStrategies);
                
                
    //自定義的自動編輯策略
                IAutoEditStrategy customizedStrategies = new JSPDirectivePartitionAutoEditStrategy();
                strategies.add(customizedStrategies);
                
                
    return strategies.toArray(new IAutoEditStrategy[strategies.size()]);
            }
            
            
    return super.getAutoEditStrategies(sourceViewer, contentType);
        }
        
    }

                我們在我們自己的SourceViewerConfiguration實現JSPStructuredTextViewerConfiguration中覆寫了getAutoEditStrategies方法。由于我們只是演示定制標簽名輸入時候的自動編輯策略,所以針對的分區類型為IJSPPartitions.JSP_DIRECTIVE。

                【效果演示】

               
    如上圖所示,我們輸入了標簽名test1:test,而且光標位于標簽名文本內容之后,此時WTP的源碼校驗器給出了錯誤提示,說我們的標簽缺少對應的閉合符號。

               我們看一下test1:test標簽對應的TLD定義,定位為不允許有標簽體:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
    <taglib>
        
    <tlibversion>1.0</tlibversion>
        
    <jspversion>1.0</jspversion>
        
    <shortname>test1</shortname>
        
    <uri>http://www.tkk7.com/zhuxing/tags/test1</uri>
        
    <tag>
            
    <name>test</name>
            
    <tagclass>any</tagclass>
            
    <bodycontent>empty</bodycontent>
            <attribute>
                
    <name>scope</name>
                
    <required>true</required>
                
    <rtexprvalue>true</rtexprvalue>
            
    </attribute>
        
    </tag>
    </taglib>
               
                根據需求,當我們在圖中光標位置輸入“>”的時候,我們前面開發的自動編輯策略會自動將其矯正為合法的結束符“/>”,效果如下:

                
                對比如下,如果沒有應用自動編輯策略,則會得到如下源碼校驗錯誤:


            【后記】
                提醒:從需求上講,我們示例中開發的自動編輯策略其實是非常簡單的。但是將其放置到一個定制WTP StructuredTextEditor的場景中,就不可避免的和我們前面介紹的WTP基礎數據模型的知識打交道,在這里再次強調,前面介紹的WTP各種數據模型一定要熟練搞清楚,基礎中的基礎!!!

                 源碼為實際工程以Export ---> Archive File方式導出的,下載鏈接:WTP StructuredTextEditor自動編輯策略定制示例源碼

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

    posted on 2008-10-20 15:50 zhuxing 閱讀(3348) 評論(3)  編輯  收藏 所屬分類: Eclipse Plug-in & OSGIWTP(Web Tools Platform)

    評論

    # re: 【Eclipse插件開發】基于WTP開發自定義的JSP編輯器(十二):定制自動編輯策略(Auto Edit Strategy)  回復  更多評論   

    有個問題想請教一下,我想導入org.eclipse.wst.dtd.core這個插件,但是發現在RCP中無法加載該插件,我想是應該該插件一些依賴沒有加進來,那么我該怎么知道需要再添加那些插件作為依賴啊?
    2008-10-20 19:32 | 飛揚的麥子

    # re: 【Eclipse插件開發】基于WTP開發自定義的JSP編輯器(十二):定制自動編輯策略(Auto Edit Strategy)  回復  更多評論   

    1、首先確定是否是你說的缺少依賴的問題
    2、簡單的插件依賴關系缺少,結合編譯錯誤稍微看一下應該就可以解決了
    3、如果真的插件依賴關系比較復雜,可以借助Plug-in Dependencies視圖
    2008-10-21 09:39 | zhuxing

    # re: 【Eclipse插件開發】基于WTP開發自定義的JSP編輯器(十二):定制自動編輯策略(Auto Edit Strategy)  回復  更多評論   

    如果想實現驗證后對編輯器屬性文字進行相關顏色、字體樣式設置,應該怎么做呢?
    2013-08-29 10:38 | cat
    主站蜘蛛池模板: 精品无码免费专区毛片| 久久永久免费人妻精品| 天天干在线免费视频| 激情综合亚洲色婷婷五月| 人成午夜免费视频在线观看| 亚洲成a人片7777| 一个人看的www在线观看免费| 久久乐国产综合亚洲精品| 成年18网站免费视频网站| 久久综合亚洲色hezyo| 亚洲国产V高清在线观看| 99久久成人国产精品免费| 久久亚洲免费视频| 最近中文字幕完整版免费高清| 亚洲国产日韩在线人成下载| 成人A级毛片免费观看AV网站| 亚洲高清国产拍精品熟女| 亚洲国产精品狼友中文久久久 | 亚洲不卡中文字幕无码| 免费网站看av片| 久久精品国产亚洲av麻豆图片 | 亚洲熟女乱综合一区二区| 你是我的城池营垒免费观看完整版| 亚洲最大福利视频网站| 在线免费观看色片| h视频在线免费观看| 亚洲一卡2卡三卡4卡有限公司| 99久久免费国产精品特黄| 在线观看亚洲专区| 亚洲成av人在线视| 成年女人看片免费视频播放器| 立即播放免费毛片一级| 香蕉视频在线观看亚洲| 在线观看免费污视频| 中文字幕看片在线a免费| 亚洲国产精品综合一区在线| 免费国产小视频在线观看| 亚洲免费在线播放| 美女黄色免费网站| 亚洲天堂中文字幕在线观看| 国产国产人免费视频成69大陆 |