最后一步就是實現(xiàn)各種功能
語法高亮
首先我們要實現(xiàn)的是語法高亮.如下圖所示:
從本質(zhì)上來說,語法高亮就是給分割后的Token指定相應(yīng)的顯示屬性,在語法高亮的處理機制里面也需要用到Token, Scanner和Rule這些東西.通過復(fù)寫SourceViewerConfiguration的getPresentationReconciler()方法來給指定的內(nèi)容類型添加語法高亮的特性:
- public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer)
- {
- PresentationReconciler reconciler = new PresentationReconciler();
- DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getXMLTagScanner());
- reconciler.setDamager(dr, XMLPartitionScanner.XML_TAG);
- reconciler.setRepairer(dr, XMLPartitionScanner.XML_TAG);
- dr = new DefaultDamagerRepairer(getXMLScanner());
- reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
- reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
- ...
- return reconciler;
- }
在上面的代碼中有一個IPresentationReconciler實例,他是用來監(jiān)聽底層的IDocument實例的變動,一個內(nèi)容類型會跟一個IPresentationDamager和IPresentationRepairer實例相關(guān)聯(lián),當(dāng)編輯文檔時,將會給受影響的文檔區(qū)域?qū)?yīng)內(nèi)容類型的IPresentationDamager實例發(fā)送消息,接著IPresentationDamager會返回一個IRegion實例,并將這些信息傳遞給IPresentationRepairer實例,該實例會對發(fā)生改變的區(qū)域重新設(shè)置顯示屬性.
上述過程聽起來可能比較復(fù)雜,不過萬幸的是我們并不需要自己去實現(xiàn)這些東西, JFace提供了一個DefaultDamagerRepairer來處理IPresentationDamager和IPresentationRepairer要做的事情,同時還提供了一個PresentationReconciler類用來將二者關(guān)聯(lián)起來,而我們要做的就是告訴編輯器在使用給定的內(nèi)容類型對文檔進行分割之后的結(jié)構(gòu)是怎樣的,以及每一種文檔類型的顯示屬性
DefaultDamagerRepairer的構(gòu)造器需要一個ITokenScanner 參數(shù),該接口跟分割Token Scanner非常類似,兩種Scanner得到的Token都是IToken的一種實現(xiàn),不同之處在于Token粒度不同,分割Token Scanner得到的Token是一個具有某種內(nèi)容類型的文檔區(qū)域,而使用語法高亮Scanner得到的Token是一段具有相同文本格式的字符串序列,顯然后者的粒度更細
這里我們拿XMLTagScanner來說,該Scanner主要針對XML_TAG內(nèi)容類型, 因此它得到的Token表示的是位于XML標(biāo)識符之間的文本內(nèi)容
- public class XMLTagScanner extends RuleBasedScanner
- {
- public XMLTagScanner(ColorManager manager)
- {
- Color color = manager.getColor(IXMLColorConstants.STRING);
- TextAttribute textAttribute = new TextAttribute(color);
- IToken string = new Token(textAttribute);
- IRule[] rules = new IRule[3];
- // Add rule for double quotes
- rules[0] = new SingleLineRule("\"", "\"", string, '\\');
- // Add a rule for single quotes
- rules[1] = new SingleLineRule("'", "'", string, '\\');
- // Add generic whitespace rule.
- rules[2] = new WhitespaceRule(new XMLWhitespaceDetector());
- setRules(rules);
- }
- }
XMLTagScanner繼承了RuleBasedScanner,因此和我們在RuleBasedPartitionScanner中看到的一樣,它也是使用某種規(guī)則處理機制來識別Token的
這里我們定義了三個規(guī)則:一個用于匹配雙引號中的字符,一個用于匹配單引號中的字符,還有一個則用來匹配空格
為了給XML的標(biāo)簽名顯示為藍色,我們使用以下的代碼,即給Token設(shè)置一個默認的顏色值:
- protected XMLTagScanner getXMLTagScanner()
- {
- if (tagScanner == null)
- {
- tagScanner = new XMLTagScanner(colorManager);
- Color color = colorManager.getColor(IXMLColorConstants.TAG);
- TextAttribute textAttribute = new TextAttribute(color);
- Token token = new Token(textAttribute);
- tagScanner.setDefaultReturnToken(token);
- }
- return tagScanner;
- }
內(nèi)容格式化
格式化就是通過使用縮進和空格使文檔結(jié)構(gòu)化,從而更具有可讀性, 格式化處理包括兩個步驟:
第一步,為即將格式化的內(nèi)容定義格式化策略,這些策略可以是全局性的,也可以是針對某個分割區(qū)域的.通過IFormattingStrategy接口來實現(xiàn).
第二步,通過SourceViewerConfiguration實現(xiàn)類給ISourceViewer添加這些策略
格式化也會使用到分割處理,這讓我們再一次體會到了掌握以及正確使用文檔分割的重要性.下面我們就以最簡單的TextFormattingStrategy來進行說明,該格式化策略用于處理嵌套在XML元素中的文本內(nèi)容
- public class TextFormattingStrategy extends DefaultFormattingStrategy
- {
- private static final String lineSeparator = System.getProperty("line.separator");
- public String format(String content,
- boolean isLineStart,
- String indentation,
- int[] positions)
- {
- if (indentation.length() == 0)
- return content;
- return lineSeparator + content.trim() + lineSeparator + indentation;
- }
- }
這里我們通過繼承DefaultFormattingStrategy并復(fù)寫format方法來實現(xiàn), 其具體做法是對文本內(nèi)容進行trim處理,然后在文本前后加上換行符
上面的介紹可能太簡單,在我們的實現(xiàn)類XMLFormattingStrategy中包含了更復(fù)雜的格式化處理代碼,這里我們對其細節(jié)不再一一展開,有興趣的讀者可以自己去加以體會,可以說格式化處理是一項非常有挑戰(zhàn)性的活兒,因為它還涉及到對選擇的文本進行智能識別的處理,這個需要反復(fù)的實驗才能得到理想的結(jié)果
通過重載SourceViewerConfiguration.getContentFormatter()方法可以非常容易的將格式化操作添加到編輯器中
- public IContentFormatter getContentFormatter(ISourceViewer sourceViewer)
- {
- ContentFormatter formatter = new ContentFormatter();
- XMLFormattingStrategy formattingStrategy = new XMLFormattingStrategy();
- DefaultFormattingStrategy defaultStrategy = new DefaultFormattingStrategy();
- TextFormattingStrategy textStrategy = new TextFormattingStrategy();
- DocTypeFormattingStrategy doctypeStrategy = new DocTypeFormattingStrategy();
- PIFormattingStrategy piStrategy = new PIFormattingStrategy();
- formatter.setFormattingStrategy(defaultStrategy, IDocument.DEFAULT_CONTENT_TYPE);
- formatter.setFormattingStrategy(textStrategy, XMLPartitionScanner.XML_TEXT);
- formatter.setFormattingStrategy(doctypeStrategy, XMLPartitionScanner.XML_DOCTYPE);
- formatter.setFormattingStrategy(piStrategy, XMLPartitionScanner.XML_PI);
- formatter.setFormattingStrategy(textStrategy, XMLPartitionScanner.XML_CDATA);
- formatter.setFormattingStrategy(formattingStrategy, XMLPartitionScanner.XML_START_TAG);
- formatter.setFormattingStrategy(formattingStrategy, XMLPartitionScanner.XML_END_TAG);
- return formatter;
- }
上述代碼首選創(chuàng)建了一個formatter,然后通過formatter的setFormattingStrategy()方法給我們的每一個內(nèi)容類型指定一個個格式化策略即可.
安徽新華電腦學(xué)校專業(yè)職業(yè)規(guī)劃師為你提供更多幫助【在線咨詢】