diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java index 20d2f3f6b816..d38f8a947737 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/MarkupModelImpl.java @@ -144,9 +144,9 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx public void changeAttributesInBatch(@NotNull RangeHighlighterEx highlighter, @NotNull Consumer changeAttributesAction) { ApplicationManager.getApplication().assertIsDispatchThread(); - RangeHighlighterData.ChangeResult changed = ((RangeHighlighterImpl)highlighter).changeAttributesNoEvents(changeAttributesAction); - if (changed != RangeHighlighterData.ChangeResult.NOT_CHANGED) { - fireAttributesChanged(highlighter, changed == RangeHighlighterData.ChangeResult.RENDERERS_CHANGED); + RangeHighlighterImpl.ChangeResult changed = ((RangeHighlighterImpl)highlighter).changeAttributesNoEvents(changeAttributesAction); + if (changed != RangeHighlighterImpl.ChangeResult.NOT_CHANGED) { + fireAttributesChanged(highlighter, changed == RangeHighlighterImpl.ChangeResult.RENDERERS_CHANGED); } } @@ -213,7 +213,7 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx }); } - public void removeMarkupModelListener(@NotNull MarkupModelListener listener) { + void removeMarkupModelListener(@NotNull MarkupModelListener listener) { boolean success = myListeners.remove(listener); LOG.assertTrue(success); } diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java index 77dd53e653f4..09236fecc5b8 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/PersistentRangeHighlighterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +32,7 @@ import org.jetbrains.annotations.Nullable; * @author max */ class PersistentRangeHighlighterImpl extends RangeHighlighterImpl implements RangeHighlighterEx { + private int myLine; // for PersistentRangeHighlighterImpl only static PersistentRangeHighlighterImpl create(@NotNull MarkupModel model, int offset, int layer, @@ -51,7 +52,7 @@ class PersistentRangeHighlighterImpl extends RangeHighlighterImpl implements Ran @Nullable TextAttributes textAttributes) { super(model, startOffset, model.getDocument().getLineEndOffset(line), layer, target, textAttributes, false, false); - setLine(line); + myLine = line; } @Override @@ -66,33 +67,33 @@ class PersistentRangeHighlighterImpl extends RangeHighlighterImpl implements Ran if (!wasTranslatedViaDiff) { super.changedUpdateImpl(e); if (isValid()) { - setLine(getDocument().getLineNumber(getStartOffset())); + myLine = getDocument().getLineNumber(getStartOffset()); int endLine = getDocument().getLineNumber(getEndOffset()); - if (endLine != getLine()) { - setIntervalEnd(getDocument().getLineEndOffset(getLine())); + if (endLine != myLine) { + setIntervalEnd(getDocument().getLineEndOffset(myLine)); } } } if (isValid() && getTargetArea() == HighlighterTargetArea.LINES_IN_RANGE) { - setIntervalStart(DocumentUtil.getFirstNonSpaceCharOffset(getDocument(), getLine())); - setIntervalEnd(getDocument().getLineEndOffset(getLine())); + setIntervalStart(DocumentUtil.getFirstNonSpaceCharOffset(getDocument(), myLine)); + setIntervalEnd(getDocument().getLineEndOffset(myLine)); } } private boolean translatedViaDiff(DocumentEvent e, DocumentEventImpl event) { try { - setLine(event.translateLineViaDiff(getLine())); + myLine = event.translateLineViaDiff(myLine); } catch (FilesTooBigForDiffException ignored) { return false; } - if (getLine() < 0 || getLine() >= getDocument().getLineCount()) { + if (myLine < 0 || myLine >= getDocument().getLineCount()) { invalidate(e); } else { DocumentEx document = getDocument(); - setIntervalStart(document.getLineStartOffset(getLine())); - setIntervalEnd(document.getLineEndOffset(getLine())); + setIntervalStart(document.getLineStartOffset(myLine)); + setIntervalEnd(document.getLineEndOffset(myLine)); } return true; } @@ -101,16 +102,7 @@ class PersistentRangeHighlighterImpl extends RangeHighlighterImpl implements Ran public String toString() { return "PersistentRangeHighlighter" + (isGreedyToLeft() ? "[" : "(") + - (isValid() ? "valid" : "invalid") + "," + getStartOffset() + "," + getEndOffset() + " - " + getLine() + + (isValid() ? "valid" : "invalid") + "," + getStartOffset() + "," + getEndOffset() + " - " + myLine + (isGreedyToRight() ? "]" : ")"); } - - // delegates - private int getLine() { - return getData().myLine; - } - - private void setLine(int line) { - getData().myLine = line; - } } diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterData.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterData.java deleted file mode 100644 index b4b0bf9e7eee..000000000000 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterData.java +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.editor.impl; - -import com.intellij.codeInsight.daemon.GutterMark; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.ex.MarkupModelEx; -import com.intellij.openapi.editor.ex.RangeHighlighterEx; -import com.intellij.openapi.editor.markup.*; -import com.intellij.openapi.util.Comparing; -import com.intellij.util.Consumer; -import org.intellij.lang.annotations.MagicConstant; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.awt.*; - -/** - * User: cdr - */ -abstract class RangeHighlighterData { - private static final Color NULL_COLOR = new Color(0, 0, 0); - - private final MarkupModel myModel; - private TextAttributes myTextAttributes; - private LineMarkerRenderer myLineMarkerRenderer; - private Color myErrorStripeColor; - private Color myLineSeparatorColor; - private SeparatorPlacement mySeparatorPlacement; - private GutterIconRenderer myGutterIconRenderer; - private Object myErrorStripeTooltip; - private MarkupEditorFilter myFilter = MarkupEditorFilter.EMPTY; - private CustomHighlighterRenderer myCustomRenderer; - int myLine; // for PersistentRangeHighlighterImpl only - private LineSeparatorRenderer myLineSeparatorRenderer; - - private byte myFlags; - - RangeHighlighterData(@NotNull MarkupModel model, - @NotNull HighlighterTargetArea target, - TextAttributes textAttributes) { - myTextAttributes = textAttributes; - setFlag(TARGET_AREA_IS_EXACT_FLAG, target == HighlighterTargetArea.EXACT_RANGE); - myModel = model; - } - - private static final int AFTER_END_OF_LINE_FLAG = 0; - private static final int ERROR_STRIPE_IS_THIN_FLAG = 1; - private static final int TARGET_AREA_IS_EXACT_FLAG = 2; - private static final int IN_BATCH_CHANGE_FLAG = 3; - private static final int CHANGED_FLAG = 4; - private static final int RENDERERS_CHANGED_FLAG = 5; - @MagicConstant(intValues = {AFTER_END_OF_LINE_FLAG, ERROR_STRIPE_IS_THIN_FLAG, TARGET_AREA_IS_EXACT_FLAG, IN_BATCH_CHANGE_FLAG, CHANGED_FLAG, RENDERERS_CHANGED_FLAG}) - private @interface FlagConstant {} - - private boolean isFlagSet(@FlagConstant int flag) { - int state = myFlags >> flag; - return (state & 1) != 0; - } - - private void setFlag(@FlagConstant int flag, boolean value) { - assert flag < 8; - int state = value ? 1 : 0; - myFlags = (byte)(myFlags & ~(1 << flag) | state << flag); - } - - - @NotNull - public abstract RangeHighlighterEx getRangeHighlighter(); - - public TextAttributes getTextAttributes() { - return myTextAttributes; - } - - public void setTextAttributes(TextAttributes textAttributes) { - TextAttributes old = myTextAttributes; - myTextAttributes = textAttributes; - if (!Comparing.equal(old, textAttributes)) { - fireChanged(false); - } - } - - @NotNull - HighlighterTargetArea getTargetArea() { - return isFlagSet(TARGET_AREA_IS_EXACT_FLAG) ? HighlighterTargetArea.EXACT_RANGE : HighlighterTargetArea.LINES_IN_RANGE; - } - - LineMarkerRenderer getLineMarkerRenderer() { - return myLineMarkerRenderer; - } - - void setLineMarkerRenderer(LineMarkerRenderer renderer) { - LineMarkerRenderer old = myLineMarkerRenderer; - myLineMarkerRenderer = renderer; - if (!Comparing.equal(old, renderer)) { - fireChanged(true); - } - } - - CustomHighlighterRenderer getCustomRenderer() { - return myCustomRenderer; - } - - void setCustomRenderer(CustomHighlighterRenderer renderer) { - CustomHighlighterRenderer old = myCustomRenderer; - myCustomRenderer = renderer; - if (!Comparing.equal(old, renderer)) { - fireChanged(true); - } - } - - public GutterIconRenderer getGutterIconRenderer() { - return myGutterIconRenderer; - } - - public void setGutterIconRenderer(GutterIconRenderer renderer) { - GutterMark old = myGutterIconRenderer; - myGutterIconRenderer = renderer; - if (!Comparing.equal(old, renderer)) { - fireChanged(true); - } - } - - Color getErrorStripeMarkColor() { - if (myErrorStripeColor == NULL_COLOR) return null; - if (myErrorStripeColor != null) return myErrorStripeColor; - if (myTextAttributes != null) return myTextAttributes.getErrorStripeColor(); - return null; - } - - public void setErrorStripeMarkColor(Color color) { - if (color == null) color = NULL_COLOR; - Color old = myErrorStripeColor; - myErrorStripeColor = color; - if (!Comparing.equal(old, color)) { - fireChanged(false); - } - } - - public Object getErrorStripeTooltip() { - return myErrorStripeTooltip; - } - - public void setErrorStripeTooltip(Object tooltipObject) { - ApplicationManager.getApplication().assertIsDispatchThread(); - Object old = myErrorStripeTooltip; - myErrorStripeTooltip = tooltipObject; - if (!Comparing.equal(old, tooltipObject)) { - fireChanged(false); - } - } - - boolean isThinErrorStripeMark() { - return isFlagSet(ERROR_STRIPE_IS_THIN_FLAG); - } - - void setThinErrorStripeMark(boolean value) { - ApplicationManager.getApplication().assertIsDispatchThread(); - boolean old = isThinErrorStripeMark(); - setFlag(ERROR_STRIPE_IS_THIN_FLAG, value); - if (old != value) { - fireChanged(false); - } - } - - Color getLineSeparatorColor() { - return myLineSeparatorColor; - } - - void setLineSeparatorColor(Color color) { - Color old = myLineSeparatorColor; - myLineSeparatorColor = color; - if (!Comparing.equal(old, color)) { - fireChanged(false); - } - } - - SeparatorPlacement getLineSeparatorPlacement() { - return mySeparatorPlacement; - } - - void setLineSeparatorPlacement(@Nullable SeparatorPlacement placement) { - SeparatorPlacement old = mySeparatorPlacement; - mySeparatorPlacement = placement; - if (!Comparing.equal(old, placement)) { - fireChanged(false); - } - } - - void setEditorFilter(@NotNull MarkupEditorFilter filter) { - myFilter = filter; - fireChanged(false); - } - - @NotNull - MarkupEditorFilter getEditorFilter() { - return myFilter; - } - - public boolean isAfterEndOfLine() { - return isFlagSet(AFTER_END_OF_LINE_FLAG); - } - - void setAfterEndOfLine(boolean afterEndOfLine) { - boolean old = isAfterEndOfLine(); - setFlag(AFTER_END_OF_LINE_FLAG, afterEndOfLine); - if (old != afterEndOfLine) { - fireChanged(false); - } - } - - private void fireChanged(boolean renderersChanged) { - if (myModel instanceof MarkupModelEx) { - if (isFlagSet(IN_BATCH_CHANGE_FLAG)) { - setFlag(CHANGED_FLAG, true); - if (renderersChanged) { - setFlag(RENDERERS_CHANGED_FLAG, true); - } - } - else { - ((MarkupModelEx)myModel).fireAttributesChanged(getRangeHighlighter(), renderersChanged); - } - } - } - - int getAffectedAreaStartOffset() { - int startOffset = getRangeHighlighter().getStartOffset(); - switch (getTargetArea()) { - case EXACT_RANGE: - return startOffset; - case LINES_IN_RANGE: - Document document = myModel.getDocument(); - int textLength = document.getTextLength(); - if (startOffset >= textLength) return textLength; - return document.getLineStartOffset(document.getLineNumber(startOffset)); - default: - throw new IllegalStateException(getTargetArea().toString()); - } - } - - int getAffectedAreaEndOffset() { - int endOffset = getRangeHighlighter().getEndOffset(); - switch (getTargetArea()) { - case EXACT_RANGE: - return endOffset; - case LINES_IN_RANGE: - Document document = myModel.getDocument(); - int textLength = document.getTextLength(); - if (endOffset >= textLength) return endOffset; - return Math.min(textLength, document.getLineEndOffset(document.getLineNumber(endOffset)) + 1); - default: - throw new IllegalStateException(getTargetArea().toString()); - } - - } - - enum ChangeResult { NOT_CHANGED, MINOR_CHANGE, RENDERERS_CHANGED } - @NotNull - ChangeResult changeAttributesInBatch(@NotNull Consumer change) { - assert !isFlagSet(IN_BATCH_CHANGE_FLAG); - assert !isFlagSet(CHANGED_FLAG); - setFlag(IN_BATCH_CHANGE_FLAG, true); - setFlag(RENDERERS_CHANGED_FLAG, false); - ChangeResult result; - try { - change.consume(getRangeHighlighter()); - } - finally { - setFlag(IN_BATCH_CHANGE_FLAG, false); - boolean changed = isFlagSet(CHANGED_FLAG); - boolean renderersChanged = isFlagSet(RENDERERS_CHANGED_FLAG); - result = changed ? renderersChanged ? ChangeResult.RENDERERS_CHANGED : ChangeResult.MINOR_CHANGE : ChangeResult.NOT_CHANGED; - setFlag(CHANGED_FLAG, false); - setFlag(RENDERERS_CHANGED_FLAG, false); - } - return result; - } - - public MarkupModel getMarkupModel() { - return myModel; - } - - void setLineSeparatorRenderer(LineSeparatorRenderer renderer) { - LineSeparatorRenderer old = myLineSeparatorRenderer; - myLineSeparatorRenderer = renderer; - if (!Comparing.equal(old, renderer)) { - fireChanged(true); - } - } - - LineSeparatorRenderer getLineSeparatorRenderer() { - return myLineSeparatorRenderer; - } -} diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java index c59f28edd805..f1d86d7fa394 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java @@ -15,12 +15,18 @@ */ package com.intellij.openapi.editor.impl; +import com.intellij.codeInsight.daemon.GutterMark; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.ex.MarkupModelEx; import com.intellij.openapi.editor.ex.RangeHighlighterEx; import com.intellij.openapi.editor.markup.*; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Getter; +import com.intellij.util.BitUtil; import com.intellij.util.Consumer; +import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,7 +37,31 @@ import java.awt.*; * @author max */ class RangeHighlighterImpl extends RangeMarkerImpl implements RangeHighlighterEx, Getter { - private final RangeHighlighterData data; + private static final Color NULL_COLOR = new Color(0, 0, 0); + + private final MarkupModel myModel; + private TextAttributes myTextAttributes; + private LineMarkerRenderer myLineMarkerRenderer; + private Color myErrorStripeColor; + private Color myLineSeparatorColor; + private SeparatorPlacement mySeparatorPlacement; + private GutterIconRenderer myGutterIconRenderer; + private Object myErrorStripeTooltip; + private MarkupEditorFilter myFilter = MarkupEditorFilter.EMPTY; + private CustomHighlighterRenderer myCustomRenderer; + private LineSeparatorRenderer myLineSeparatorRenderer; + + private byte myFlags; + + private static final byte AFTER_END_OF_LINE_MASK = 1; + private static final byte ERROR_STRIPE_IS_THIN_MASK = 2; + private static final byte TARGET_AREA_IS_EXACT_MASK = 4; + private static final byte IN_BATCH_CHANGE_MASK = 8; + private static final byte CHANGED_MASK = 16; + private static final byte RENDERERS_CHANGED_MASK = 32; + + @MagicConstant(intValues = {AFTER_END_OF_LINE_MASK, ERROR_STRIPE_IS_THIN_MASK, TARGET_AREA_IS_EXACT_MASK, IN_BATCH_CHANGE_MASK, CHANGED_MASK, RENDERERS_CHANGED_MASK}) + private @interface FlagConstant {} RangeHighlighterImpl(@NotNull MarkupModel model, int start, @@ -42,33 +72,284 @@ class RangeHighlighterImpl extends RangeMarkerImpl implements RangeHighlighterEx boolean greedyToLeft, boolean greedyToRight) { super((DocumentEx)model.getDocument(), start, end,false); - - data = new RangeHighlighterData(model, target, textAttributes) { - @NotNull - @Override - public RangeHighlighterEx getRangeHighlighter() { - return RangeHighlighterImpl.this; - } - }; + myTextAttributes = textAttributes; + setFlag(TARGET_AREA_IS_EXACT_MASK, target == HighlighterTargetArea.EXACT_RANGE); + myModel = model; registerInTree(start, end, greedyToLeft, greedyToRight, layer); } - protected RangeHighlighterData getData() { - return data; + private boolean isFlagSet(@FlagConstant byte mask) { + return BitUtil.isSet(myFlags, mask); + } + + private void setFlag(@FlagConstant byte mask, boolean value) { + myFlags = BitUtil.set(myFlags, mask, value); + } + + + @Override + public TextAttributes getTextAttributes() { + return myTextAttributes; + } + + @Override + public void setTextAttributes(@NotNull TextAttributes textAttributes) { + TextAttributes old = myTextAttributes; + myTextAttributes = textAttributes; + if (!Comparing.equal(old, textAttributes)) { + fireChanged(false); + } + } + + @Override + @NotNull + public HighlighterTargetArea getTargetArea() { + return isFlagSet(TARGET_AREA_IS_EXACT_MASK) ? HighlighterTargetArea.EXACT_RANGE : HighlighterTargetArea.LINES_IN_RANGE; + } + + @Override + public LineMarkerRenderer getLineMarkerRenderer() { + return myLineMarkerRenderer; + } + + @Override + public void setLineMarkerRenderer(LineMarkerRenderer renderer) { + LineMarkerRenderer old = myLineMarkerRenderer; + myLineMarkerRenderer = renderer; + if (!Comparing.equal(old, renderer)) { + fireChanged(true); + } + } + + @Override + public CustomHighlighterRenderer getCustomRenderer() { + return myCustomRenderer; + } + + @Override + public void setCustomRenderer(CustomHighlighterRenderer renderer) { + CustomHighlighterRenderer old = myCustomRenderer; + myCustomRenderer = renderer; + if (!Comparing.equal(old, renderer)) { + fireChanged(true); + } + } + + @Override + public GutterIconRenderer getGutterIconRenderer() { + return myGutterIconRenderer; + } + + @Override + public void setGutterIconRenderer(GutterIconRenderer renderer) { + GutterMark old = myGutterIconRenderer; + myGutterIconRenderer = renderer; + if (!Comparing.equal(old, renderer)) { + fireChanged(true); + } + } + + @Override + public Color getErrorStripeMarkColor() { + if (myErrorStripeColor == NULL_COLOR) return null; + if (myErrorStripeColor != null) return myErrorStripeColor; + if (myTextAttributes != null) return myTextAttributes.getErrorStripeColor(); + return null; + } + + @Override + public void setErrorStripeMarkColor(Color color) { + if (color == null) color = NULL_COLOR; + Color old = myErrorStripeColor; + myErrorStripeColor = color; + if (!Comparing.equal(old, color)) { + fireChanged(false); + } + } + + @Override + public Object getErrorStripeTooltip() { + return myErrorStripeTooltip; + } + + @Override + public void setErrorStripeTooltip(Object tooltipObject) { + ApplicationManager.getApplication().assertIsDispatchThread(); + Object old = myErrorStripeTooltip; + myErrorStripeTooltip = tooltipObject; + if (!Comparing.equal(old, tooltipObject)) { + fireChanged(false); + } + } + + @Override + public boolean isThinErrorStripeMark() { + return isFlagSet(ERROR_STRIPE_IS_THIN_MASK); + } + + @Override + public void setThinErrorStripeMark(boolean value) { + ApplicationManager.getApplication().assertIsDispatchThread(); + boolean old = isThinErrorStripeMark(); + setFlag(ERROR_STRIPE_IS_THIN_MASK, value); + if (old != value) { + fireChanged(false); + } + } + + @Override + public Color getLineSeparatorColor() { + return myLineSeparatorColor; + } + + @Override + public void setLineSeparatorColor(Color color) { + Color old = myLineSeparatorColor; + myLineSeparatorColor = color; + if (!Comparing.equal(old, color)) { + fireChanged(false); + } + } + + @Override + public SeparatorPlacement getLineSeparatorPlacement() { + return mySeparatorPlacement; + } + + @Override + public void setLineSeparatorPlacement(@Nullable SeparatorPlacement placement) { + SeparatorPlacement old = mySeparatorPlacement; + mySeparatorPlacement = placement; + if (!Comparing.equal(old, placement)) { + fireChanged(false); + } + } + + @Override + public void setEditorFilter(@NotNull MarkupEditorFilter filter) { + myFilter = filter; + fireChanged(false); + } + + @Override + @NotNull + public MarkupEditorFilter getEditorFilter() { + return myFilter; + } + + @Override + public boolean isAfterEndOfLine() { + return isFlagSet(AFTER_END_OF_LINE_MASK); + } + + @Override + public void setAfterEndOfLine(boolean afterEndOfLine) { + boolean old = isAfterEndOfLine(); + setFlag(AFTER_END_OF_LINE_MASK, afterEndOfLine); + if (old != afterEndOfLine) { + fireChanged(false); + } + } + + private void fireChanged(boolean renderersChanged) { + if (myModel instanceof MarkupModelEx) { + if (isFlagSet(IN_BATCH_CHANGE_MASK)) { + setFlag(CHANGED_MASK, true); + if (renderersChanged) { + setFlag(RENDERERS_CHANGED_MASK, true); + } + } + else { + ((MarkupModelEx)myModel).fireAttributesChanged(this, renderersChanged); + } + } + } + + @Override + public int getAffectedAreaStartOffset() { + int startOffset = getStartOffset(); + switch (getTargetArea()) { + case EXACT_RANGE: + return startOffset; + case LINES_IN_RANGE: + Document document = myModel.getDocument(); + int textLength = document.getTextLength(); + if (startOffset >= textLength) return textLength; + return document.getLineStartOffset(document.getLineNumber(startOffset)); + default: + throw new IllegalStateException(getTargetArea().toString()); + } + } + + @Override + public int getAffectedAreaEndOffset() { + int endOffset = getEndOffset(); + switch (getTargetArea()) { + case EXACT_RANGE: + return endOffset; + case LINES_IN_RANGE: + Document document = myModel.getDocument(); + int textLength = document.getTextLength(); + if (endOffset >= textLength) return endOffset; + return Math.min(textLength, document.getLineEndOffset(document.getLineNumber(endOffset)) + 1); + default: + throw new IllegalStateException(getTargetArea().toString()); + } + + } + + enum ChangeResult { NOT_CHANGED, MINOR_CHANGE, RENDERERS_CHANGED } + @NotNull + ChangeResult changeAttributesNoEvents(@NotNull Consumer change) { + assert !isFlagSet(IN_BATCH_CHANGE_MASK); + assert !isFlagSet(CHANGED_MASK); + setFlag(IN_BATCH_CHANGE_MASK, true); + setFlag(RENDERERS_CHANGED_MASK, false); + ChangeResult result; + try { + change.consume(this); + } + finally { + setFlag(IN_BATCH_CHANGE_MASK, false); + boolean changed = isFlagSet(CHANGED_MASK); + boolean renderersChanged = isFlagSet(RENDERERS_CHANGED_MASK); + result = changed ? renderersChanged ? ChangeResult.RENDERERS_CHANGED : ChangeResult.MINOR_CHANGE : ChangeResult.NOT_CHANGED; + setFlag(CHANGED_MASK, false); + setFlag(RENDERERS_CHANGED_MASK, false); + } + return result; + } + + public MarkupModel getMarkupModel() { + return myModel; + } + + @Override + public void setLineSeparatorRenderer(LineSeparatorRenderer renderer) { + LineSeparatorRenderer old = myLineSeparatorRenderer; + myLineSeparatorRenderer = renderer; + if (!Comparing.equal(old, renderer)) { + fireChanged(true); + } + } + + @Override + public LineSeparatorRenderer getLineSeparatorRenderer() { + return myLineSeparatorRenderer; } @Override protected void registerInTree(int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { // we store highlighters in MarkupModel - ((MarkupModelEx)data.getMarkupModel()).addRangeHighlighter(this, start, end, greedyToLeft, greedyToRight, layer); + ((MarkupModelEx)getMarkupModel()).addRangeHighlighter(this, start, end, greedyToLeft, greedyToRight, layer); } @Override protected boolean unregisterInTree() { if (!isValid()) return false; // we store highlighters in MarkupModel - getData().getMarkupModel().removeHighlighter(this); + getMarkupModel().removeHighlighter(this); return true; } @@ -77,157 +358,14 @@ class RangeHighlighterImpl extends RangeMarkerImpl implements RangeHighlighterEx return this; } - // delegates - @Override - public TextAttributes getTextAttributes() { - return getData().getTextAttributes(); - } - - @Override - public void setTextAttributes(@NotNull TextAttributes textAttributes) { - getData().setTextAttributes(textAttributes); - } - - @NotNull - RangeHighlighterData.ChangeResult changeAttributesNoEvents(@NotNull Consumer change) { - return getData().changeAttributesInBatch(change); - } - @Override public int getLayer() { RangeHighlighterTree.RHNode node = (RangeHighlighterTree.RHNode)(Object)myNode; return node == null ? -1 : node.myLayer; } - @NotNull - @Override - public HighlighterTargetArea getTargetArea() { - return getData().getTargetArea(); - } - - @Override - public LineMarkerRenderer getLineMarkerRenderer() { - return getData().getLineMarkerRenderer(); - } - - @Override - public void setLineMarkerRenderer(LineMarkerRenderer renderer) { - getData().setLineMarkerRenderer(renderer); - } - - @Override - public CustomHighlighterRenderer getCustomRenderer() { - return getData().getCustomRenderer(); - } - - @Override - public void setCustomRenderer(CustomHighlighterRenderer renderer) { - getData().setCustomRenderer(renderer); - } - - @Override - public GutterIconRenderer getGutterIconRenderer() { - return getData().getGutterIconRenderer(); - } - - @Override - public void setGutterIconRenderer(GutterIconRenderer renderer) { - getData().setGutterIconRenderer(renderer); - } - - @Override - public Color getErrorStripeMarkColor() { - return getData().getErrorStripeMarkColor(); - } - - @Override - public void setErrorStripeMarkColor(Color color) { - getData().setErrorStripeMarkColor(color); - } - - @Override - public Object getErrorStripeTooltip() { - return getData().getErrorStripeTooltip(); - } - - @Override - public void setErrorStripeTooltip(Object tooltipObject) { - getData().setErrorStripeTooltip(tooltipObject); - } - - @Override - public boolean isThinErrorStripeMark() { - return getData().isThinErrorStripeMark(); - } - - @Override - public void setThinErrorStripeMark(boolean value) { - getData().setThinErrorStripeMark(value); - } - - @Override - public Color getLineSeparatorColor() { - return getData().getLineSeparatorColor(); - } - - @Override - public void setLineSeparatorColor(Color color) { - getData().setLineSeparatorColor(color); - } - - @Override - public void setLineSeparatorRenderer(LineSeparatorRenderer renderer) { - getData().setLineSeparatorRenderer(renderer); - } - - @Override - public LineSeparatorRenderer getLineSeparatorRenderer() { - return getData().getLineSeparatorRenderer(); - } - - @Override - public SeparatorPlacement getLineSeparatorPlacement() { - return getData().getLineSeparatorPlacement(); - } - - @Override - public void setLineSeparatorPlacement(@Nullable SeparatorPlacement placement) { - getData().setLineSeparatorPlacement(placement); - } - - @Override - public void setEditorFilter(@NotNull MarkupEditorFilter filter) { - getData().setEditorFilter(filter); - } - - @Override - @NotNull - public MarkupEditorFilter getEditorFilter() { - return getData().getEditorFilter(); - } - - @Override - public boolean isAfterEndOfLine() { - return getData().isAfterEndOfLine(); - } - - @Override - public void setAfterEndOfLine(boolean value) { - getData().setAfterEndOfLine(value); - } - - @Override - public int getAffectedAreaStartOffset() { - return getData().getAffectedAreaStartOffset(); - } - - @Override - public int getAffectedAreaEndOffset() { - return getData().getAffectedAreaEndOffset(); - } - @Override public String toString() { - return "RangeHighlighter: ("+getStartOffset()+","+getEndOffset()+"); layer:"+getLayer()+"; tooltip: "+getData().getErrorStripeTooltip(); + return "RangeHighlighter: ("+getStartOffset()+","+getEndOffset()+"); layer:"+getLayer()+"; tooltip: "+getErrorStripeTooltip(); } }