PageRenderTime 62ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/netbeans-7.3/php.smarty/src/org/netbeans/modules/php/smarty/editor/coloring/EmbeddingHighlightsContainer.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 290 lines | 198 code | 33 blank | 59 comment | 48 complexity | cc8a6b4dabe9792620834f6e5b66340d MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
  5. *
  6. * The contents of this file are subject to the terms of either the GNU
  7. * General Public License Version 2 only ("GPL") or the Common
  8. * Development and Distribution License("CDDL") (collectively, the
  9. * "License"). You may not use this file except in compliance with the
  10. * License. You can obtain a copy of the License at
  11. * http://www.netbeans.org/cddl-gplv2.html
  12. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  13. * specific language governing permissions and limitations under the
  14. * License. When distributing the software, include this License Header
  15. * Notice in each file and include the License file at
  16. * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
  17. * particular file as subject to the "Classpath" exception as provided
  18. * by Sun in the GPL Version 2 section of the License file that
  19. * accompanied this code. If applicable, add the following below the
  20. * License Header, with the fields enclosed by brackets [] replaced by
  21. * your own identifying information:
  22. * "Portions Copyrighted [year] [name of copyright owner]"
  23. *
  24. * Contributor(s):
  25. *
  26. * The Original Software is NetBeans. The Initial Developer of the Original
  27. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
  28. * Microsystems, Inc. All Rights Reserved.
  29. *
  30. * If you wish your version of this file to be governed by only the CDDL
  31. * or only the GPL Version 2, indicate your decision by adding
  32. * "[Contributor] elects to include this software in this distribution
  33. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  34. * single choice of license, a recipient has the option to distribute
  35. * your version of this file under either the CDDL, the GPL Version 2 or
  36. * to extend the choice of license to its licensees as provided above.
  37. * However, if you add GPL Version 2 code and therefore, elected the GPL
  38. * Version 2 license, then the option applies only if the new code is
  39. * made subject to such option by the copyright holder.
  40. */
  41. package org.netbeans.modules.php.smarty.editor.coloring;
  42. import java.awt.Color;
  43. import java.util.List;
  44. import java.util.NoSuchElementException;
  45. import java.util.logging.Level;
  46. import java.util.logging.Logger;
  47. import javax.swing.text.AttributeSet;
  48. import javax.swing.text.BadLocationException;
  49. import javax.swing.text.Document;
  50. import javax.swing.text.SimpleAttributeSet;
  51. import javax.swing.text.StyleConstants;
  52. import org.netbeans.api.editor.mimelookup.MimeLookup;
  53. import org.netbeans.api.editor.settings.AttributesUtilities;
  54. import org.netbeans.api.editor.settings.FontColorSettings;
  55. import org.netbeans.api.lexer.Language;
  56. import org.netbeans.api.lexer.LanguagePath;
  57. import org.netbeans.api.lexer.TokenHierarchy;
  58. import org.netbeans.api.lexer.TokenHierarchyEvent;
  59. import org.netbeans.api.lexer.TokenHierarchyListener;
  60. import org.netbeans.api.lexer.TokenSequence;
  61. import org.netbeans.editor.BaseDocument;
  62. import org.netbeans.editor.Utilities;
  63. import org.netbeans.modules.php.smarty.editor.TplDataLoader;
  64. import org.netbeans.spi.editor.highlighting.HighlightsSequence;
  65. import org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer;
  66. import org.openide.util.WeakListeners;
  67. /**
  68. * Implementation of Highlighting SPI creating coloured background
  69. * for SMARTY templates.
  70. *
  71. * @author Martin Fousek
  72. * created according to EmbeddingHighlightsContainer
  73. */
  74. public class EmbeddingHighlightsContainer extends AbstractHighlightsContainer implements TokenHierarchyListener {
  75. private static final Logger LOG = Logger.getLogger(EmbeddingHighlightsContainer.class.getName());
  76. private static final String TPL_BACKGROUND_TOKEN_NAME = "smarty"; //NOI18N
  77. private static final String TPL_INNER_MIME_TYPE = "text/x-tpl-inner"; //NOI18N
  78. private final AttributeSet tplBackground;
  79. private final Document document;
  80. private TokenHierarchy<? extends Document> hierarchy = null;
  81. private long version = 0;
  82. EmbeddingHighlightsContainer(Document document) {
  83. this.document = document;
  84. //try load the background from tpl settings
  85. FontColorSettings fcs = MimeLookup.getLookup(TplDataLoader.MIME_TYPE).lookup(FontColorSettings.class);
  86. Color tplBG = null;
  87. if (fcs != null) {
  88. tplBG = getColoring(fcs, TPL_BACKGROUND_TOKEN_NAME);
  89. }
  90. tplBackground = tplBG == null ? SimpleAttributeSet.EMPTY : AttributesUtilities.createImmutable(
  91. StyleConstants.Background, tplBG, ATTR_EXTENDS_EOL, Boolean.TRUE);
  92. }
  93. @Override
  94. public HighlightsSequence getHighlights(int startOffset, int endOffset) {
  95. synchronized (this) {
  96. if (tplBackground != null) {
  97. if (hierarchy == null) {
  98. hierarchy = TokenHierarchy.get(document);
  99. if (hierarchy != null) {
  100. hierarchy.addTokenHierarchyListener(WeakListeners.create(TokenHierarchyListener.class, this, hierarchy));
  101. }
  102. }
  103. if (hierarchy != null) {
  104. return new Highlights(version, hierarchy, startOffset, endOffset);
  105. }
  106. }
  107. return HighlightsSequence.EMPTY;
  108. }
  109. }
  110. // ----------------------------------------------------------------------
  111. // TokenHierarchyListener implementation
  112. // ----------------------------------------------------------------------
  113. @Override
  114. public void tokenHierarchyChanged(TokenHierarchyEvent evt) {
  115. synchronized (this) {
  116. version++;
  117. }
  118. fireHighlightsChange(evt.affectedStartOffset(), evt.affectedEndOffset());
  119. }
  120. // ----------------------------------------------------------------------
  121. // Private implementation
  122. // ----------------------------------------------------------------------
  123. private static Color getColoring(FontColorSettings fcs, String tokenName) {
  124. AttributeSet as = fcs.getTokenFontColors(tokenName);
  125. if (as != null) {
  126. return (Color) as.getAttribute(StyleConstants.Background); //NOI18N
  127. }
  128. return null;
  129. }
  130. private class Highlights implements HighlightsSequence {
  131. private final long version;
  132. private final TokenHierarchy<? extends Document> scanner;
  133. private final int startOffsetBoundary;
  134. private final int endOffsetBoundary;
  135. private List<TokenSequence<?>> tokenSequenceList = null;
  136. private int startOffset;
  137. private int endOffset;
  138. private int realEndOffset;
  139. private AttributeSet attributeSet;
  140. private boolean finished = false;
  141. private Highlights(long version, TokenHierarchy<? extends Document> scanner, int startOffset, int endOffset) {
  142. this.version = version;
  143. this.scanner = scanner;
  144. this.startOffsetBoundary = startOffset;
  145. this.endOffsetBoundary = endOffset;
  146. }
  147. private boolean _moveNext() {
  148. if (tokenSequenceList == null) {
  149. // initialize
  150. this.startOffset = startOffsetBoundary;
  151. this.endOffset = startOffsetBoundary;
  152. this.realEndOffset = startOffsetBoundary;
  153. String mimeType = (String) document.getProperty ("mimeType"); //NOI18N
  154. Language<?> language = Language.find(mimeType);
  155. if (language != null) {
  156. //get html token sequence list
  157. LanguagePath topLevelLanguagePath = LanguagePath.get(language);
  158. tokenSequenceList = scanner.tokenSequenceList(topLevelLanguagePath, startOffsetBoundary, endOffsetBoundary);
  159. } else {
  160. LOG.log(Level.WARNING, "Language " + mimeType + " obtained from the document mimeType property cannot be found!"); //NOI18N
  161. }
  162. }
  163. if (tokenSequenceList != null) {
  164. for (TokenSequence tokenSequence : tokenSequenceList) {
  165. assert tokenSequence.language().mimeType().equals(TplDataLoader.MIME_TYPE);
  166. tokenSequence.move(realEndOffset);
  167. while (tokenSequence.moveNext() && tokenSequence.offset() < endOffsetBoundary) {
  168. TokenSequence eTokenSequence = tokenSequence.embedded();
  169. if (eTokenSequence == null || !eTokenSequence.moveNext()) {
  170. continue;
  171. }
  172. String embeddedMimeType = eTokenSequence.language().mimeType();
  173. if (TPL_INNER_MIME_TYPE.equals(embeddedMimeType)) {
  174. try {
  175. startOffset = eTokenSequence.offset();
  176. do {
  177. endOffset = eTokenSequence.offset() + eTokenSequence.token().length();
  178. } while (eTokenSequence.moveNext());
  179. realEndOffset = endOffset > realEndOffset ? endOffset : realEndOffset + 1;
  180. int startLO = Utilities.getLineOffset((BaseDocument) document, startOffset);
  181. int endLO = Utilities.getLineOffset((BaseDocument) document, endOffset);
  182. if (startLO != endLO) {
  183. //not just one line block - test boundaries
  184. if ((Utilities.getFirstNonWhiteBwd((BaseDocument) document, Utilities.getRowEnd((BaseDocument) document, startOffset)) + 1) == startOffset) {
  185. //just <script-style> tag on the first line -> move start to next line
  186. startOffset = Utilities.getRowStartFromLineOffset((BaseDocument) document, startLO + 1);
  187. }
  188. if (Utilities.getFirstNonWhiteFwd((BaseDocument) document, Utilities.getRowStartFromLineOffset((BaseDocument) document, endLO)) == endOffset) {
  189. //just </script-style> tag on the last line -> move block end to previous line end
  190. endOffset = Utilities.getRowStartFromLineOffset((BaseDocument) document, endLO);
  191. }
  192. }
  193. attributeSet = tplBackground;
  194. if (attributeSet != null) {
  195. return true;
  196. }
  197. } catch (BadLocationException ex) {
  198. LOG.log(Level.INFO, "An error occured when creating coloured background for TPL.", ex); //NOI18N
  199. }
  200. }
  201. }
  202. }
  203. }
  204. return false;
  205. }
  206. @Override
  207. public boolean moveNext() {
  208. synchronized (EmbeddingHighlightsContainer.this) {
  209. if (checkVersion()) {
  210. if (_moveNext()) {
  211. return true;
  212. }
  213. }
  214. }
  215. finished = true;
  216. return false;
  217. }
  218. @Override
  219. public int getStartOffset() {
  220. synchronized (EmbeddingHighlightsContainer.this) {
  221. if (finished) {
  222. throw new NoSuchElementException();
  223. } else {
  224. assert tokenSequenceList != null : "Sequence not initialized, call moveNext() first."; //NOI18N
  225. return startOffset;
  226. }
  227. }
  228. }
  229. @Override
  230. public int getEndOffset() {
  231. synchronized (EmbeddingHighlightsContainer.this) {
  232. if (finished) {
  233. throw new NoSuchElementException();
  234. } else {
  235. assert tokenSequenceList != null : "Sequence not initialized, call moveNext() first."; //NOI18N
  236. return endOffset;
  237. }
  238. }
  239. }
  240. @Override
  241. public AttributeSet getAttributes() {
  242. synchronized (EmbeddingHighlightsContainer.this) {
  243. if (finished) {
  244. throw new NoSuchElementException();
  245. } else {
  246. assert tokenSequenceList != null : "Sequence not initialized, call moveNext() first."; //NOI18N
  247. return attributeSet;
  248. }
  249. }
  250. }
  251. private boolean checkVersion() {
  252. synchronized(EmbeddingHighlightsContainer.this) {
  253. return this.version == EmbeddingHighlightsContainer.this.version;
  254. }
  255. }
  256. }
  257. }