CodeFoldingManager converted to service

GitOrigin-RevId: 511fec1be0ccd3f6ccb9a5030ee994f96b9178ac
This commit is contained in:
Dmitry Jemerov
2019-10-04 13:16:44 +00:00
committed by intellij-monorepo-bot
parent c661506070
commit 69c67340be
6 changed files with 132 additions and 110 deletions
@@ -1,8 +1,7 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.folding;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.FoldRegion;
@@ -14,7 +13,7 @@ import org.jetbrains.annotations.Nullable;
public abstract class CodeFoldingManager {
public static CodeFoldingManager getInstance(Project project) {
return project.getComponent(CodeFoldingManager.class);
return ServiceManager.getService(project, CodeFoldingManager.class);
}
public abstract void updateFoldRegions(@NotNull Editor editor);
@@ -3,40 +3,29 @@ package com.intellij.codeInsight.folding.impl;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.folding.CodeFoldingManager;
import com.intellij.codeInsight.hint.EditorFragmentComponent;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.EditorMouseEvent;
import com.intellij.openapi.editor.event.EditorMouseEventArea;
import com.intellij.openapi.editor.event.EditorMouseMotionListener;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.ex.FoldingModelEx;
import com.intellij.openapi.fileEditor.impl.text.CodeFoldingState;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.UnfairTextRange;
import com.intellij.openapi.util.UserDataHolderEx;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.ui.LightweightHint;
import com.intellij.util.containers.WeakList;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.List;
public class CodeFoldingManagerImpl extends CodeFoldingManager implements ProjectComponent, Disposable {
public class CodeFoldingManagerImpl extends CodeFoldingManager implements Disposable {
private final Project myProject;
private final Collection<Document> myDocumentsWithFoldingInfo = new WeakList<>();
@@ -44,7 +33,7 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec
private final Key<DocumentFoldingInfo> myFoldingInfoInDocumentKey = Key.create("FOLDING_INFO_IN_DOCUMENT_KEY");
private static final Key<Boolean> FOLDING_STATE_KEY = Key.create("FOLDING_STATE_KEY");
CodeFoldingManagerImpl(Project project) {
public CodeFoldingManagerImpl(Project project) {
myProject = project;
}
@@ -57,90 +46,6 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec
}
}
@Override
public void projectOpened() {
final EditorMouseMotionListener myMouseMotionListener = new EditorMouseMotionListener() {
LightweightHint myCurrentHint;
FoldRegion myCurrentFold;
@Override
public void mouseMoved(@NotNull EditorMouseEvent e) {
if (myProject.isDisposed()) return;
LightweightHint hint = null;
try {
HintManager hintManager = HintManager.getInstance();
if (hintManager != null && hintManager.hasShownHintsThatWillHideByOtherHint(false)) {
return;
}
if (e.getArea() != EditorMouseEventArea.FOLDING_OUTLINE_AREA) return;
Editor editor = e.getEditor();
if (PsiDocumentManager.getInstance(myProject).isUncommited(editor.getDocument())) return;
MouseEvent mouseEvent = e.getMouseEvent();
FoldRegion fold = ((EditorEx)editor).getGutterComponentEx().findFoldingAnchorAt(mouseEvent.getX(), mouseEvent.getY());
if (fold == null || !fold.isValid()) return;
if (fold == myCurrentFold && myCurrentHint != null) {
hint = myCurrentHint;
return;
}
TextRange psiElementRange = EditorFoldingInfo.get(editor).getPsiElementRange(fold);
if (psiElementRange == null) return;
int textOffset = psiElementRange.getStartOffset();
// There is a possible case that target PSI element's offset is less than fold region offset (e.g. complete method is
// returned as PSI element for fold region that corresponds to java method code block). We don't want to show any hint
// if start of the current fold region is displayed.
Point foldStartXY = editor.visualPositionToXY(editor.offsetToVisualPosition(Math.max(textOffset, fold.getStartOffset())));
Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
if (visibleArea.y > foldStartXY.y) {
if (myCurrentHint != null) {
myCurrentHint.hide();
myCurrentHint = null;
}
// We want to show a hint with the top fold region content that is above the current viewport position.
// However, there is a possible case that complete region has a big height and only a little bottom part
// is shown at the moment. We can't just show hint with the whole top content because it would hide actual
// editor content, hence, we show max(2; available visual lines number) instead.
// P.S. '2' is used here in assumption that many java methods have javadocs which first line is just '/**'.
// So, it's not too useful to show only it even when available vertical space is not big enough.
int availableVisualLines = EditorFragmentComponent.getAvailableVisualLinesAboveEditor(editor);
int startVisualLine = editor.offsetToVisualPosition(textOffset).line;
int desiredEndVisualLine = Math.max(0, editor.xyToVisualPosition(new Point(0, visibleArea.y)).line - 1);
int endVisualLine = startVisualLine + availableVisualLines;
if (endVisualLine > desiredEndVisualLine) {
endVisualLine = desiredEndVisualLine;
}
// Show only the non-displayed top part of the target fold region
int endOffset = editor.logicalPositionToOffset(editor.visualToLogicalPosition(new VisualPosition(endVisualLine, 0)));
TextRange textRange = new UnfairTextRange(textOffset, endOffset);
hint = EditorFragmentComponent.showEditorFragmentHint(editor, textRange, true, true);
myCurrentFold = fold;
myCurrentHint = hint;
}
}
finally {
if (hint == null) {
if (myCurrentHint != null) {
myCurrentHint.hide();
myCurrentHint = null;
}
myCurrentFold = null;
}
}
}
};
StartupManager.getInstance(myProject).registerPostStartupActivity(
(DumbAwareRunnable)() -> EditorFactory.getInstance().getEventMulticaster().addEditorMouseMotionListener(myMouseMotionListener, myProject));
}
@Override
public void releaseFoldings(@NotNull Editor editor) {
ApplicationManager.getApplication().assertIsDispatchThread();
@@ -0,0 +1,104 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.folding.impl;
import com.intellij.codeInsight.hint.EditorFragmentComponent;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.openapi.editor.event.EditorMouseEvent;
import com.intellij.openapi.editor.event.EditorMouseEventArea;
import com.intellij.openapi.editor.event.EditorMouseMotionListener;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.UnfairTextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.ui.LightweightHint;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.event.MouseEvent;
class FoldingHintMouseMotionListener implements EditorMouseMotionListener {
private final Project myProject;
LightweightHint myCurrentHint;
FoldRegion myCurrentFold;
FoldingHintMouseMotionListener(Project project) {
myProject = project;
}
@Override
public void mouseMoved(@NotNull EditorMouseEvent e) {
if (myProject.isDisposed()) return;
LightweightHint hint = null;
try {
HintManager hintManager = HintManager.getInstance();
if (hintManager != null && hintManager.hasShownHintsThatWillHideByOtherHint(false)) {
return;
}
if (e.getArea() != EditorMouseEventArea.FOLDING_OUTLINE_AREA) return;
Editor editor = e.getEditor();
if (PsiDocumentManager.getInstance(myProject).isUncommited(editor.getDocument())) return;
MouseEvent mouseEvent = e.getMouseEvent();
FoldRegion fold = ((EditorEx)editor).getGutterComponentEx().findFoldingAnchorAt(mouseEvent.getX(), mouseEvent.getY());
if (fold == null || !fold.isValid()) return;
if (fold == myCurrentFold && myCurrentHint != null) {
hint = myCurrentHint;
return;
}
TextRange psiElementRange = EditorFoldingInfo.get(editor).getPsiElementRange(fold);
if (psiElementRange == null) return;
int textOffset = psiElementRange.getStartOffset();
// There is a possible case that target PSI element's offset is less than fold region offset (e.g. complete method is
// returned as PSI element for fold region that corresponds to java method code block). We don't want to show any hint
// if start of the current fold region is displayed.
Point foldStartXY = editor.visualPositionToXY(editor.offsetToVisualPosition(Math.max(textOffset, fold.getStartOffset())));
Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
if (visibleArea.y > foldStartXY.y) {
if (myCurrentHint != null) {
myCurrentHint.hide();
myCurrentHint = null;
}
// We want to show a hint with the top fold region content that is above the current viewport position.
// However, there is a possible case that complete region has a big height and only a little bottom part
// is shown at the moment. We can't just show hint with the whole top content because it would hide actual
// editor content, hence, we show max(2; available visual lines number) instead.
// P.S. '2' is used here in assumption that many java methods have javadocs which first line is just '/**'.
// So, it's not too useful to show only it even when available vertical space is not big enough.
int availableVisualLines = EditorFragmentComponent.getAvailableVisualLinesAboveEditor(editor);
int startVisualLine = editor.offsetToVisualPosition(textOffset).line;
int desiredEndVisualLine = Math.max(0, editor.xyToVisualPosition(new Point(0, visibleArea.y)).line - 1);
int endVisualLine = startVisualLine + availableVisualLines;
if (endVisualLine > desiredEndVisualLine) {
endVisualLine = desiredEndVisualLine;
}
// Show only the non-displayed top part of the target fold region
int endOffset = editor.logicalPositionToOffset(editor.visualToLogicalPosition(new VisualPosition(endVisualLine, 0)));
TextRange textRange = new UnfairTextRange(textOffset, endOffset);
hint = EditorFragmentComponent.showEditorFragmentHint(editor, textRange, true, true);
myCurrentFold = fold;
myCurrentHint = hint;
}
}
finally {
if (hint == null) {
if (myCurrentHint != null) {
myCurrentHint.hide();
myCurrentHint = null;
}
myCurrentFold = null;
}
}
}
}
@@ -0,0 +1,16 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.folding.impl;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
import org.jetbrains.annotations.NotNull;
public class FoldingHintPostStartupActivity implements StartupActivity.DumbAware {
@Override
public void runActivity(@NotNull Project project) {
EditorFactory.getInstance().getEventMulticaster().addEditorMouseMotionListener(
new FoldingHintMouseMotionListener(project), project);
}
}
@@ -122,6 +122,9 @@
<applicationService serviceInterface="com.intellij.codeInsight.folding.CodeFoldingSettings"
serviceImplementation="com.intellij.codeInsight.folding.CodeFoldingSettingsImpl"/>
<postStartupActivity implementation="com.intellij.codeInsight.folding.impl.FoldingHintPostStartupActivity"/>
<projectService serviceInterface="com.intellij.codeInsight.folding.CodeFoldingManager"
serviceImplementation="com.intellij.codeInsight.folding.impl.CodeFoldingManagerImpl"/>
<applicationService serviceInterface="com.intellij.psi.statistics.StatisticsManager"
serviceImplementation="com.intellij.psi.statistics.impl.StatisticsManagerImpl"/>
@@ -29,11 +29,6 @@
<implementation-class>com.intellij.execution.impl.ProjectRunConfigurationInitializer</implementation-class>
</component>
<component>
<interface-class>com.intellij.codeInsight.folding.CodeFoldingManager</interface-class>
<implementation-class>com.intellij.codeInsight.folding.impl.CodeFoldingManagerImpl</implementation-class>
</component>
<component>
<interface-class>com.intellij.openapi.fileEditor.FileEditorManager</interface-class>
<implementation-class>com.intellij.openapi.fileEditor.impl.PsiAwareFileEditorManagerImpl</implementation-class>