2 * Created by IntelliJ IDEA.
6 * To change template for new class use
7 * Code Style | Class Templates options (Tools | IDE Options).
9 package com
.intellij
.openapi
.editor
.impl
;
11 import com
.intellij
.openapi
.diagnostic
.Logger
;
12 import com
.intellij
.openapi
.editor
.Document
;
13 import com
.intellij
.openapi
.editor
.ex
.MarkupModelEx
;
14 import com
.intellij
.openapi
.editor
.impl
.event
.MarkupModelEvent
;
15 import com
.intellij
.openapi
.editor
.impl
.event
.MarkupModelListener
;
16 import com
.intellij
.openapi
.editor
.markup
.HighlighterTargetArea
;
17 import com
.intellij
.openapi
.editor
.markup
.RangeHighlighter
;
18 import com
.intellij
.openapi
.editor
.markup
.TextAttributes
;
19 import com
.intellij
.openapi
.util
.UserDataHolderBase
;
20 import com
.intellij
.openapi
.application
.ApplicationManager
;
21 import org
.jetbrains
.annotations
.NotNull
;
23 import java
.util
.ArrayList
;
24 import java
.util
.Collection
;
25 import java
.util
.List
;
27 public class MarkupModelImpl
extends UserDataHolderBase
implements MarkupModelEx
{
28 private static final Logger LOG
= Logger
.getInstance("#com.intellij.openapi.editor.impl.MarkupModelImpl");
29 private final DocumentImpl myDocument
;
31 private final HighlighterList myHighlighterList
;
32 private final Collection
<RangeHighlighter
> myHighlighters
= new ArrayList
<RangeHighlighter
>();
33 private RangeHighlighter
[] myCachedHighlighters
;
34 private final List
<MarkupModelListener
> myListeners
= new ArrayList
<MarkupModelListener
>();
35 private MarkupModelListener
[] myCachedListeners
;
37 MarkupModelImpl(DocumentImpl document
) {
38 myDocument
= document
;
39 myHighlighterList
= new HighlighterList(document
) {
41 protected void assertDispatchThread() {
42 MarkupModelImpl
.this.assertDispatchThread();
47 protected void assertDispatchThread() {
48 ApplicationManager
.getApplication().assertIsDispatchThread();
51 public void dispose() {
52 myHighlighterList
.dispose();
56 public RangeHighlighter
addLineHighlighter(int lineNumber
, int layer
, TextAttributes textAttributes
) {
57 if (lineNumber
>= getDocument().getLineCount() || lineNumber
< 0) {
58 throw new IndexOutOfBoundsException("lineNumber:" + lineNumber
+ ". Shold be in [0, " + (getDocument().getLineCount() - 1) + "]");
61 int offset
= getFirstNonspaceCharOffset(getDocument(), lineNumber
);
63 return addRangeHighlighter(offset
, offset
, layer
, textAttributes
, HighlighterTargetArea
.LINES_IN_RANGE
);
66 public RangeHighlighter
addPersistentLineHighlighter(int lineNumber
, int layer
, TextAttributes textAttributes
) {
67 if (lineNumber
>= getDocument().getLineCount() || lineNumber
< 0) return null;
69 int offset
= getFirstNonspaceCharOffset(getDocument(), lineNumber
);
71 return addRangeHighlighter(offset
, offset
, layer
, textAttributes
, HighlighterTargetArea
.LINES_IN_RANGE
, true);
74 static int getFirstNonspaceCharOffset(Document doc
, int lineNumber
) {
75 int lineStart
= doc
.getLineStartOffset(lineNumber
);
76 int lineEnd
= doc
.getLineEndOffset(lineNumber
);
77 CharSequence text
= doc
.getCharsSequence();
78 int offset
= lineStart
;
79 for (int i
= lineStart
; i
< lineEnd
; i
++) {
80 char c
= text
.charAt(i
);
81 if (c
!= ' ' && c
!= '\t') {
90 public RangeHighlighter
[] getAllHighlighters() {
91 if (myCachedHighlighters
== null) {
92 myCachedHighlighters
= myHighlighters
.toArray(new RangeHighlighter
[myHighlighters
.size()]);
94 return myCachedHighlighters
;
97 private RangeHighlighter
addRangeHighlighter(int startOffset
,
100 TextAttributes textAttributes
,
101 HighlighterTargetArea targetArea
,
102 boolean isPersistent
) {
103 RangeHighlighterImpl segmentHighlighter
= new RangeHighlighterImpl(this, startOffset
, endOffset
, layer
, targetArea
,
104 textAttributes
, isPersistent
);
105 myHighlighters
.add(segmentHighlighter
);
106 myCachedHighlighters
= null;
107 myHighlighterList
.addSegmentHighlighter(segmentHighlighter
);
108 fireSegmentHighlighterChanged(segmentHighlighter
);
109 return segmentHighlighter
;
114 public RangeHighlighter
addRangeHighlighter(int startOffset
,
117 TextAttributes textAttributes
,
118 @NotNull HighlighterTargetArea targetArea
) {
119 return addRangeHighlighter(startOffset
, endOffset
, layer
, textAttributes
, targetArea
, false);
122 public void removeHighlighter(RangeHighlighter segmentHighlighter
) {
123 boolean removed
= myHighlighters
.remove(segmentHighlighter
);
124 LOG
.assertTrue(removed
);
125 myCachedHighlighters
= null;
126 myHighlighterList
.removeSegmentHighlighter(segmentHighlighter
);
127 fireSegmentHighlighterChanged(segmentHighlighter
);
130 public void removeAllHighlighters() {
131 for (RangeHighlighter highlighter
: myHighlighters
) {
132 fireSegmentHighlighterChanged(highlighter
);
133 myHighlighterList
.removeSegmentHighlighter(highlighter
);
135 myHighlighters
.clear();
136 myCachedHighlighters
= null;
140 public Document
getDocument() {
144 public void addMarkupModelListener(MarkupModelListener listener
) {
145 myListeners
.add(listener
);
146 myCachedListeners
= null;
149 public void removeMarkupModelListener(MarkupModelListener listener
) {
150 boolean success
= myListeners
.remove(listener
);
151 LOG
.assertTrue(success
);
152 myCachedListeners
= null;
155 public void setRangeHighlighterAttributes(final RangeHighlighter highlighter
, final TextAttributes textAttributes
) {
156 ((RangeHighlighterImpl
)highlighter
).setTextAttributes(textAttributes
);
157 fireSegmentHighlighterChanged(highlighter
);
160 private MarkupModelListener
[] getCachedListeners() {
161 if (myCachedListeners
== null) {
162 myCachedListeners
= myListeners
.isEmpty() ? MarkupModelListener
.EMPTY_ARRAY
: myListeners
.toArray(new MarkupModelListener
[myListeners
.size()]);
164 return myCachedListeners
;
167 protected void fireSegmentHighlighterChanged(RangeHighlighter segmentHighlighter
) {
168 MarkupModelEvent event
= new MarkupModelEvent(this, segmentHighlighter
);
169 MarkupModelListener
[] listeners
= getCachedListeners();
170 for (MarkupModelListener listener
: listeners
) {
171 listener
.rangeHighlighterChanged(event
);
175 public HighlighterList
getHighlighterList() {
176 return myHighlighterList
;
179 public boolean containsHighlighter(RangeHighlighter highlighter
) {
180 return myHighlighters
.contains(highlighter
);