diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/ex/InjectedAwareEditorRepaintStrategy.java b/platform/lang-impl/src/com/intellij/openapi/editor/ex/InjectedAwareEditorRepaintStrategy.java
new file mode 100644
index 000000000000..7943c243e182
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/ex/InjectedAwareEditorRepaintStrategy.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2011 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.ex;
+
+import com.intellij.injected.editor.DocumentWindow;
+import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.editor.impl.EditorRepaintStrategy;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * This strategy handles the situation when typing is performed inside parsed injected text. Usually editor's highlighter
+ * doesn't know anything about injected context internals and sees it just as a single big token (e.g. MXML files may contain
+ * Flash code inside CDATA comment and the highlighter (based on XML lexer) considers the whole Flash code block to be just
+ * a CDATA token).
+ *
+ * So, every time user types at injected context, highlighter receives document change event and asks editor to repaint
+ * affected token. That is rather heavy operation if performed frequently for the large text range. That's why current
+ * strategy handles such requests to the whole injected context repaint and skips them.
+ *
+ * It's assumed that corresponding repainting is performed during editor's markup model updates triggered by injected
+ * context processing.
+ *
+ * @author Denis Zhdanov
+ * @since 6/17/11 11:16 AM
+ */
+public class InjectedAwareEditorRepaintStrategy implements EditorRepaintStrategy {
+
+ @Override
+ public TextRange adjustHighlighterRegion(@NotNull EditorEx editor, int startOffset, int endOffset) {
+ return isInjectedContext(editor, startOffset, endOffset) ? null : new TextRange(startOffset, endOffset);
+ }
+
+ private static boolean isInjectedContext(@NotNull EditorEx editor, int startOffset, int endOffset) {
+ final Project project = editor.getProject();
+ if (project == null) {
+ return false;
+ }
+ final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
+ final PsiFile psiFile = documentManager.getCachedPsiFile(editor.getDocument());
+ if (psiFile == null) {
+ return false;
+ }
+
+ final List injectedDocuments = InjectedLanguageUtil.getCachedInjectedDocuments(psiFile);
+ for (DocumentWindow injectedDocument : injectedDocuments) {
+ for (RangeMarker rangeMarker : injectedDocument.getHostRanges()) {
+ if (Math.max(rangeMarker.getStartOffset(), startOffset) <= Math.min(rangeMarker.getEndOffset(), endOffset)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
index 47e01bbe9a9d..d1505e61a566 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
@@ -54,6 +54,7 @@ import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
import com.intellij.openapi.editor.impl.softwrap.SoftWrapDrawingType;
import com.intellij.openapi.editor.impl.softwrap.SoftWrapHelper;
import com.intellij.openapi.editor.markup.*;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
import com.intellij.openapi.ide.CopyPasteManager;
@@ -1312,22 +1313,33 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return line * getLineHeight();
}
- public void repaint(int startOffset, int endOffset) {
+ public void repaint(final int startOffset, final int endOffset) {
if (!isShowing() || myScrollPane == null || myDocument.isInBulkUpdate()) {
return;
}
+ int startOffsetToUse = startOffset;
+ int endOffsetToUse = endOffset;
assertIsDispatchThread();
- if (endOffset > myDocument.getTextLength()) {
- endOffset = myDocument.getTextLength();
+ if (endOffsetToUse > myDocument.getTextLength()) {
+ endOffsetToUse = myDocument.getTextLength();
+ }
+
+ for (EditorRepaintStrategy repaintStrategy : Extensions.getExtensions(EditorRepaintStrategy.EP_NAME)) {
+ final TextRange range = repaintStrategy.adjustHighlighterRegion(this, startOffsetToUse, endOffsetToUse);
+ if (range == null) {
+ return;
+ }
+ startOffsetToUse = range.getStartOffset();
+ endOffsetToUse = range.getEndOffset();
}
// We do repaint in case of equal offsets because there is a possible case that there is a soft wrap at the same offset and
// it does occupy particular amount of visual space that may be necessary to repaint.
- if (startOffset <= endOffset) {
- int startLine = myDocument.getLineNumber(startOffset);
- int endLine = myDocument.getLineNumber(endOffset);
+ if (startOffsetToUse <= endOffsetToUse) {
+ int startLine = myDocument.getLineNumber(startOffsetToUse);
+ int endLine = myDocument.getLineNumber(endOffsetToUse);
repaintLines(startLine, endLine);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorRepaintStrategy.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorRepaintStrategy.java
new file mode 100644
index 000000000000..315c7816525f
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorRepaintStrategy.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2011 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.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Defines contract for the strategy that may adjust/control editor's repainting.
+ *
+ * @author Denis Zhdanov
+ * @since 6/17/11 11:04 AM
+ */
+public interface EditorRepaintStrategy {
+
+ ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.editorRepaintStrategy");
+
+ /**
+ * Asks current strategy to adjust (if necessary) target document region repaint request received from the given editor's highlighter.
+ *
+ * @param editor target editor
+ * @param startOffset start offset of the document text range requested to be repainted (inclusive)
+ * @param endOffset end offset of the document text range requested to be repainted (exclusive)
+ * @return actual text range to repaint (if any); null as an indication that no further processing
+ * for the current repaint request should be performed
+ */
+ @Nullable
+ TextRange adjustHighlighterRegion(@NotNull EditorEx editor, int startOffset, int endOffset);
+}
diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml
index f85f02ac8314..55b6c572d603 100644
--- a/platform/platform-resources/src/META-INF/LangExtensions.xml
+++ b/platform/platform-resources/src/META-INF/LangExtensions.xml
@@ -456,6 +456,7 @@
+
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
index 4b18ededa4d6..7905c54ba756 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
@@ -112,6 +112,8 @@
+
+