mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
diff: carefully keep editor scroll/caret position
This commit is contained in:
+10
-15
@@ -31,6 +31,7 @@ import com.intellij.openapi.util.diff.tools.ErrorDiffTool;
|
||||
import com.intellij.openapi.util.diff.tools.external.ExternalDiffTool;
|
||||
import com.intellij.openapi.util.diff.tools.util.DiffDataKeys;
|
||||
import com.intellij.openapi.util.diff.tools.util.DiffUserDataKeys;
|
||||
import com.intellij.openapi.util.diff.tools.util.DiffUserDataKeys.ScrollToPolicy;
|
||||
import com.intellij.openapi.util.diff.tools.util.PrevNextDifferenceIterable;
|
||||
import com.intellij.openapi.util.diff.tools.util.SoftHardCacheMap;
|
||||
import com.intellij.openapi.util.diff.util.DiffUtil;
|
||||
@@ -47,9 +48,6 @@ import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.openapi.util.diff.tools.util.DiffUserDataKeys.ScrollToPolicy.FIRST_CHANGE;
|
||||
import static com.intellij.openapi.util.diff.tools.util.DiffUserDataKeys.ScrollToPolicy.LAST_CHANGE;
|
||||
|
||||
public abstract class CacheDiffRequestChainProcessor implements Disposable {
|
||||
private static final Logger LOG = Logger.getInstance(CacheDiffRequestChainProcessor.class);
|
||||
|
||||
@@ -138,15 +136,17 @@ public abstract class CacheDiffRequestChainProcessor implements Disposable {
|
||||
//
|
||||
|
||||
public void updateRequest() {
|
||||
updateRequest(false);
|
||||
updateRequest(false, null);
|
||||
}
|
||||
|
||||
public void updateRequest(boolean force) {
|
||||
public void updateRequest(boolean force, @Nullable ScrollToPolicy scrollToChangePolicy) {
|
||||
boolean hadFocus = isFocused();
|
||||
|
||||
DiffRequest request = loadRequest();
|
||||
if (!force && request == myActiveRequest) return;
|
||||
|
||||
request.putUserData(DiffUserDataKeys.SCROLL_TO_CHANGE, scrollToChangePolicy);
|
||||
|
||||
myState.destroy();
|
||||
myToolbarStatusPanel.setContent(null);
|
||||
myToolbarPanel.setContent(null);
|
||||
@@ -371,15 +371,15 @@ public abstract class CacheDiffRequestChainProcessor implements Disposable {
|
||||
}
|
||||
|
||||
if (myIterationState != IterationState.NEXT) {
|
||||
if (iterable != null) iterable.notify("Press again to go to the next file"); // TODO: provide "change" word in chain UserData - for tests/etc
|
||||
// TODO: provide "change" word in chain UserData - for tests/etc
|
||||
if (iterable != null) iterable.notify("Press again to go to the next file");
|
||||
myIterationState = IterationState.NEXT;
|
||||
return;
|
||||
}
|
||||
|
||||
myIterationState = IterationState.NONE;
|
||||
myRequestChain.setIndex(myRequestChain.getIndex() + 1);
|
||||
myContext.putUserData(DiffUserDataKeys.SCROLL_TO_CHANGE, FIRST_CHANGE);
|
||||
updateRequest();
|
||||
updateRequest(false, ScrollToPolicy.FIRST_CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,8 +421,7 @@ public abstract class CacheDiffRequestChainProcessor implements Disposable {
|
||||
|
||||
myIterationState = IterationState.NONE;
|
||||
myRequestChain.setIndex(myRequestChain.getIndex() - 1);
|
||||
myContext.putUserData(DiffUserDataKeys.SCROLL_TO_CHANGE, LAST_CHANGE);
|
||||
updateRequest();
|
||||
updateRequest(false, ScrollToPolicy.LAST_CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,7 +446,6 @@ public abstract class CacheDiffRequestChainProcessor implements Disposable {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
myRequestChain.setIndex(myRequestChain.getIndex() + 1);
|
||||
myContext.putUserData(DiffUserDataKeys.SCROLL_TO_CHANGE, null);
|
||||
updateRequest();
|
||||
}
|
||||
}
|
||||
@@ -471,7 +469,6 @@ public abstract class CacheDiffRequestChainProcessor implements Disposable {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
myRequestChain.setIndex(myRequestChain.getIndex() - 1);
|
||||
myContext.putUserData(DiffUserDataKeys.SCROLL_TO_CHANGE, null);
|
||||
updateRequest();
|
||||
}
|
||||
}
|
||||
@@ -483,7 +480,6 @@ public abstract class CacheDiffRequestChainProcessor implements Disposable {
|
||||
public void consume(Integer index) {
|
||||
if (index >= 0 && index != myRequestChain.getIndex()) {
|
||||
myRequestChain.setIndex(index);
|
||||
myContext.putUserData(DiffUserDataKeys.SCROLL_TO_CHANGE, null);
|
||||
updateRequest();
|
||||
}
|
||||
}
|
||||
@@ -578,8 +574,7 @@ public abstract class CacheDiffRequestChainProcessor implements Disposable {
|
||||
}
|
||||
myToolOrder.add(index, myDiffTool);
|
||||
|
||||
myContext.putUserData(DiffUserDataKeys.SCROLL_TO_CHANGE, null);
|
||||
updateRequest(true);
|
||||
updateRequest(true, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+133
-48
@@ -10,10 +10,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.diff.DiffBundle;
|
||||
import com.intellij.openapi.diff.DiffNavigationContext;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
@@ -25,6 +22,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.diff.actions.BufferedLineIterator;
|
||||
import com.intellij.openapi.util.diff.actions.NavigationContextChecker;
|
||||
@@ -43,7 +41,6 @@ import com.intellij.openapi.util.diff.tools.util.DiffDataKeys;
|
||||
import com.intellij.openapi.util.diff.tools.util.DiffUserDataKeys;
|
||||
import com.intellij.openapi.util.diff.tools.util.DiffUserDataKeys.ScrollToPolicy;
|
||||
import com.intellij.openapi.util.diff.tools.util.PrevNextDifferenceIterable;
|
||||
import com.intellij.openapi.util.diff.tools.util.ScrollToLineHelper;
|
||||
import com.intellij.openapi.util.diff.tools.util.base.HighlightPolicy;
|
||||
import com.intellij.openapi.util.diff.tools.util.base.TextDiffViewerBase;
|
||||
import com.intellij.openapi.util.diff.util.CalledInAwt;
|
||||
@@ -135,13 +132,11 @@ class OnesideDiffViewer extends TextDiffViewerBase {
|
||||
Side side = myContext.getUserData(DiffUserDataKeys.PREFERRED_FOCUS_SIDE);
|
||||
if (side != null) myMasterSide = side;
|
||||
|
||||
myScrollToLineHelper.processContext(myContext, myRequest);
|
||||
myScrollToLineHelper.processContext();
|
||||
}
|
||||
|
||||
private void updateContextHints() {
|
||||
int onesideLine = DiffUtil.getLineToScroll(myEditor);
|
||||
Pair<Side, Integer> pair = transferLineFromOneside(onesideLine);
|
||||
myRequest.putUserData(DiffUserDataKeys.SCROLL_TO_LINE, pair);
|
||||
myScrollToLineHelper.updateContext();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -368,7 +363,7 @@ class OnesideDiffViewer extends TextDiffViewerBase {
|
||||
myChangedBlockData = new ChangedBlockData(diffChanges, convertor, invertedConvertor, diffSeparators);
|
||||
|
||||
// TODO: remember current in current caret position position on rediff rather than positon in combined file
|
||||
myScrollToLineHelper.scrollOnRediff();
|
||||
myScrollToLineHelper.onRediff();
|
||||
|
||||
myStatusPanel.update();
|
||||
myPanel.setGoodContent();
|
||||
@@ -387,40 +382,46 @@ class OnesideDiffViewer extends TextDiffViewerBase {
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
private Pair<Side, Integer> transferLineFromOneside(int line) {
|
||||
if (myChangedBlockData == null) return Pair.create(myMasterSide, line);
|
||||
private Pair<int[], Side> transferLineFromOneside(int line) {
|
||||
int[] lines = new int[2];
|
||||
|
||||
if (myChangedBlockData == null) {
|
||||
lines[0] = myActualContent1 != null ? line : 0;
|
||||
lines[1] = myActualContent2 != null ? line : 0;
|
||||
return Pair.create(lines, myMasterSide);
|
||||
}
|
||||
|
||||
LineNumberConvertor lineConvertor = myChangedBlockData.getLineNumberConvertor();
|
||||
TIntFunction convertor1 = lineConvertor.getConvertor1();
|
||||
TIntFunction convertor2 = lineConvertor.getConvertor2();
|
||||
|
||||
int line1 = convertor1.execute(line);
|
||||
int line2 = convertor2.execute(line);
|
||||
lines[0] = convertor1.execute(line);
|
||||
lines[1] = convertor2.execute(line);
|
||||
|
||||
if (line1 == -1 && line2 == -1) {
|
||||
line1 = convertor1.execute(line - 1);
|
||||
line2 = convertor2.execute(line - 1);
|
||||
if (line1 != -1) line1++;
|
||||
if (line2 != -1) line2++;
|
||||
if (lines[0] == -1 && lines[1] == -1) {
|
||||
lines[0] = convertor1.execute(line - 1);
|
||||
lines[1] = convertor2.execute(line - 1);
|
||||
if (lines[0] != -1) lines[0]++;
|
||||
if (lines[1] != -1) lines[1]++;
|
||||
}
|
||||
if (line1 == -1 && line2 == -1) {
|
||||
line1 = convertor1.execute(line + 1);
|
||||
line2 = convertor2.execute(line + 1);
|
||||
if (line1 > 0) line1--;
|
||||
if (line2 > 0) line2--;
|
||||
if (lines[0] == -1 && lines[1] == -1) {
|
||||
lines[0] = convertor1.execute(line + 1);
|
||||
lines[1] = convertor2.execute(line + 1);
|
||||
if (lines[0] > 0) lines[0]--;
|
||||
if (lines[1] > 0) lines[1]--;
|
||||
}
|
||||
|
||||
if (line1 == -1 && line2 == -1) {
|
||||
return Pair.create(myMasterSide, line);
|
||||
if (lines[0] == -1 && lines[1] == -1) {
|
||||
return Pair.create(lines, myMasterSide);
|
||||
}
|
||||
if (line1 == -1) {
|
||||
return Pair.create(Side.RIGHT, line2);
|
||||
if (lines[0] == -1) {
|
||||
return Pair.create(lines, Side.RIGHT);
|
||||
}
|
||||
if (line2 == -1) {
|
||||
return Pair.create(Side.LEFT, line1);
|
||||
if (lines[1] == -1) {
|
||||
return Pair.create(lines, Side.LEFT);
|
||||
}
|
||||
|
||||
return myMasterSide.isLeft() ? Pair.create(Side.LEFT, line1) : Pair.create(Side.RIGHT, line2);
|
||||
return Pair.create(lines, myMasterSide);
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
@@ -529,12 +530,12 @@ class OnesideDiffViewer extends TextDiffViewerBase {
|
||||
if (descriptor != null) return descriptor;
|
||||
}
|
||||
else {
|
||||
Pair<Side, Integer> pair = transferLineFromOneside(myEditor.offsetToLogicalPosition(offset).line);
|
||||
Pair<int[], Side> pair = transferLineFromOneside(myEditor.offsetToLogicalPosition(offset).line);
|
||||
OpenFileDescriptor descriptor1 = myActualContent1.getOpenFileDescriptor(offset);
|
||||
OpenFileDescriptor descriptor2 = myActualContent2.getOpenFileDescriptor(offset);
|
||||
if (descriptor1 == null) return descriptor2;
|
||||
if (descriptor2 == null) return descriptor1;
|
||||
return pair.first.select(descriptor1, descriptor2);
|
||||
pair.second.select(descriptor1, descriptor2);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -934,28 +935,91 @@ class OnesideDiffViewer extends TextDiffViewerBase {
|
||||
}
|
||||
}
|
||||
|
||||
private class MyScrollToLineHelper extends ScrollToLineHelper {
|
||||
public void scrollOnRediff() {
|
||||
if (myShouldScroll && myScrollToChange != null) if (doScrollToChange(myScrollToChange)) onSuccessfulScroll();
|
||||
if (myShouldScroll && myScrollToLine != null) if (doScrollToLine(myScrollToLine)) onSuccessfulScroll();
|
||||
if (myShouldScroll && myNavigationContext != null) if (doScrollToContext(myNavigationContext)) onSuccessfulScroll();
|
||||
if (myShouldScroll) doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
|
||||
onSuccessfulScroll();
|
||||
private class MyScrollToLineHelper {
|
||||
protected boolean myShouldScroll = true;
|
||||
|
||||
@Nullable private ScrollToPolicy myScrollToChange;
|
||||
@Nullable private EditorPosition myEditorPosition;
|
||||
@Nullable private LogicalPosition[] myCaretPosition;
|
||||
@Nullable private DiffNavigationContext myNavigationContext;
|
||||
|
||||
public void processContext() {
|
||||
myScrollToChange = myRequest.getUserData(DiffUserDataKeys.SCROLL_TO_CHANGE);
|
||||
myEditorPosition = myRequest.getUserData(EditorPosition.KEY);
|
||||
myCaretPosition = myRequest.getUserData(DiffUserDataKeys.EDITORS_CARET_POSITION);
|
||||
myNavigationContext = myRequest.getUserData(DiffUserDataKeys.NAVIGATION_CONTEXT);
|
||||
}
|
||||
|
||||
private boolean doScrollToLine(@NotNull Pair<Side, Integer> scrollToLine) {
|
||||
int onesideLine = transferLineToOneside(scrollToLine.first, scrollToLine.second);
|
||||
DiffUtil.scrollToLine(myEditor, onesideLine);
|
||||
public void updateContext() {
|
||||
LogicalPosition position = myEditor.getCaretModel().getLogicalPosition();
|
||||
Pair<int[], Side> pair = transferLineFromOneside(position.line);
|
||||
LogicalPosition[] carets = new LogicalPosition[2];
|
||||
carets[0] = getPosition(pair.first[0], position.column);
|
||||
carets[1] = getPosition(pair.first[1], position.column);
|
||||
|
||||
EditorPosition editorsPosition = new EditorPosition(carets, getPoint(myEditor));
|
||||
|
||||
myRequest.putUserData(DiffUserDataKeys.SCROLL_TO_CHANGE, null);
|
||||
myRequest.putUserData(EditorPosition.KEY, editorsPosition);
|
||||
myRequest.putUserData(DiffUserDataKeys.EDITORS_CARET_POSITION, carets);
|
||||
myRequest.putUserData(DiffUserDataKeys.NAVIGATION_CONTEXT, null);
|
||||
}
|
||||
|
||||
public void onRediff() {
|
||||
if (myShouldScroll && myScrollToChange != null) {
|
||||
myShouldScroll = !doScrollToChange(myScrollToChange);
|
||||
}
|
||||
if (myShouldScroll && myNavigationContext != null) {
|
||||
myShouldScroll = !doScrollToContext(myNavigationContext);
|
||||
}
|
||||
if (myShouldScroll && myCaretPosition != null && myCaretPosition.length == 2) {
|
||||
if (myEditorPosition != null && myEditorPosition.isSame(myCaretPosition)) {
|
||||
scrollToPoint(myEditor, myEditorPosition.myPoint);
|
||||
}
|
||||
else {
|
||||
doScrollToLine(myMasterSide, myMasterSide.selectN(myCaretPosition));
|
||||
}
|
||||
}
|
||||
if (myShouldScroll) {
|
||||
doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
|
||||
}
|
||||
myShouldScroll = false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private LogicalPosition getPosition(int line, int column) {
|
||||
if (line == -1) return new LogicalPosition(0, 0);
|
||||
return new LogicalPosition(line, column);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Point getPoint(@Nullable Editor editor) {
|
||||
if (editor == null) return new Point(0, 0);
|
||||
ScrollingModel model = editor.getScrollingModel();
|
||||
return new Point(model.getHorizontalScrollOffset(), model.getVerticalScrollOffset());
|
||||
}
|
||||
|
||||
private void scrollToPoint(@Nullable Editor editor, @NotNull Point point) {
|
||||
if (editor == null) return;
|
||||
editor.getScrollingModel().disableAnimation();
|
||||
editor.getScrollingModel().scrollHorizontally(point.x);
|
||||
editor.getScrollingModel().scrollVertically(point.y);
|
||||
editor.getScrollingModel().enableAnimation();
|
||||
}
|
||||
|
||||
private boolean doScrollToLine(@NotNull Side side, @NotNull LogicalPosition position) {
|
||||
int onesideLine = transferLineToOneside(side, position.line);
|
||||
DiffUtil.scrollEditor(myEditor, onesideLine, position.column);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean doScrollToChange(@NotNull ScrollToPolicy scrollToPolicy) {
|
||||
private boolean doScrollToChange(@NotNull ScrollToPolicy scrollToChangePolicy) {
|
||||
if (myChangedBlockData == null) return false;
|
||||
List<OnesideDiffChange> changes = myChangedBlockData.getDiffChanges();
|
||||
if (changes.isEmpty()) return false;
|
||||
|
||||
OnesideDiffChange targetChange;
|
||||
switch (scrollToPolicy) {
|
||||
switch (scrollToChangePolicy) {
|
||||
case FIRST_CHANGE:
|
||||
targetChange = changes.get(0);
|
||||
break;
|
||||
@@ -963,10 +1027,10 @@ class OnesideDiffViewer extends TextDiffViewerBase {
|
||||
targetChange = changes.get(changes.size() - 1);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(scrollToPolicy.name());
|
||||
throw new IllegalArgumentException(scrollToChangePolicy.name());
|
||||
}
|
||||
|
||||
DiffUtil.scrollToLine(myEditor, targetChange.getLine1());
|
||||
DiffUtil.scrollEditor(myEditor, targetChange.getLine1());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -986,7 +1050,28 @@ class OnesideDiffViewer extends TextDiffViewerBase {
|
||||
}
|
||||
if (line == -1) return false;
|
||||
|
||||
return doScrollToLine(Pair.create(Side.RIGHT, line));
|
||||
return doScrollToLine(Side.RIGHT, new LogicalPosition(line, 0));
|
||||
}
|
||||
}
|
||||
|
||||
private static class EditorPosition {
|
||||
public static final Key<EditorPosition> KEY = Key.create("Diff.OnesideEditorPosition");
|
||||
|
||||
@NotNull public final LogicalPosition[] myCaretPosition;
|
||||
@NotNull public final Point myPoint;
|
||||
|
||||
public EditorPosition(@NotNull LogicalPosition[] caretPosition, @NotNull Point point) {
|
||||
myCaretPosition = caretPosition;
|
||||
myPoint = point;
|
||||
}
|
||||
|
||||
public boolean isSame(@Nullable LogicalPosition[] caretPosition) {
|
||||
// TODO: allow small fluctuations ?
|
||||
if (caretPosition == null) return true;
|
||||
if (caretPosition.length != 2) return false;
|
||||
if (!caretPosition[0].equals(myCaretPosition[0])) return false;
|
||||
if (!caretPosition[1].equals(myCaretPosition[1])) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -345,7 +345,7 @@ class SimpleDiffViewer extends TwosideTextDiffViewer {
|
||||
|
||||
EditorEx editor = getCurrentEditor();
|
||||
int line = getCurrentSide().getStartLine(targetChange.getFragment());
|
||||
DiffUtil.scrollToLine(editor, line);
|
||||
DiffUtil.scrollEditor(editor, line);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -366,7 +366,8 @@ class SimpleDiffViewer extends TwosideTextDiffViewer {
|
||||
}
|
||||
if (line == -1) return false;
|
||||
|
||||
return doScrollToLine(Pair.create(Side.RIGHT, line));
|
||||
scrollToLine(Side.RIGHT, line);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
+5
-9
@@ -3,23 +3,22 @@ package com.intellij.openapi.util.diff.tools.util;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.diff.DiffNavigationContext;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.diff.util.Side;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
public interface DiffUserDataKeys {
|
||||
/*
|
||||
* Scroll priority: SCROLL_TO_CHANGE > SCROLL_TO_LINE > NAVIGATION_CONTEXT > DEFAULT(FIRST_CHANGE)
|
||||
*/
|
||||
|
||||
//
|
||||
// DiffRequest
|
||||
//
|
||||
|
||||
Key<Pair<Side, Integer>> SCROLL_TO_LINE = Key.create("Diff.ScrollToLine");
|
||||
enum ScrollToPolicy {FIRST_CHANGE, LAST_CHANGE}
|
||||
|
||||
Key<ScrollToPolicy> SCROLL_TO_CHANGE = Key.create("Diff.ScrollToChange");
|
||||
Key<LogicalPosition[]> EDITORS_CARET_POSITION = Key.create("Diff.EditorsCaretPosition");
|
||||
Key<DiffNavigationContext> NAVIGATION_CONTEXT = Key.create("Diff.NavigationContext");
|
||||
|
||||
Key<String> HELP_ID = Key.create("Diff.HelpId");
|
||||
@@ -31,9 +30,6 @@ public interface DiffUserDataKeys {
|
||||
|
||||
Key<Side> PREFERRED_FOCUS_SIDE = Key.create("Diff.PreferredFocusSide");
|
||||
|
||||
Key<ScrollToPolicy> SCROLL_TO_CHANGE = Key.create("Diff.ScrollSoChange");
|
||||
enum ScrollToPolicy {FIRST_CHANGE, LAST_CHANGE}
|
||||
|
||||
//
|
||||
// DiffChain
|
||||
//
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
package com.intellij.openapi.util.diff.tools.util;
|
||||
|
||||
import com.intellij.openapi.diff.DiffNavigationContext;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.diff.api.FrameDiffTool.DiffContext;
|
||||
import com.intellij.openapi.util.diff.requests.DiffRequest;
|
||||
import com.intellij.openapi.util.diff.tools.util.DiffUserDataKeys.ScrollToPolicy;
|
||||
import com.intellij.openapi.util.diff.util.Side;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ScrollToLineHelper {
|
||||
protected boolean myShouldScroll = true;
|
||||
|
||||
@Nullable protected ScrollToPolicy myScrollToChange;
|
||||
@Nullable protected Pair<Side, Integer> myScrollToLine;
|
||||
@Nullable protected DiffNavigationContext myNavigationContext;
|
||||
|
||||
public void processContext(@NotNull DiffContext context, @NotNull DiffRequest request) {
|
||||
myScrollToChange = context.getUserData(DiffUserDataKeys.SCROLL_TO_CHANGE);
|
||||
myScrollToLine = request.getUserData(DiffUserDataKeys.SCROLL_TO_LINE);
|
||||
myNavigationContext = request.getUserData(DiffUserDataKeys.NAVIGATION_CONTEXT);
|
||||
}
|
||||
|
||||
public void onSuccessfulScroll() {
|
||||
myShouldScroll = false;
|
||||
|
||||
myScrollToChange = null;
|
||||
myScrollToLine = null;
|
||||
myNavigationContext = null;
|
||||
}
|
||||
}
|
||||
+110
-33
@@ -3,16 +3,13 @@ package com.intellij.openapi.util.diff.tools.util.twoside;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.diff.DiffNavigationContext;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.event.VisibleAreaEvent;
|
||||
import com.intellij.openapi.editor.event.VisibleAreaListener;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.diff.actions.impl.FocusOppositePaneAction;
|
||||
import com.intellij.openapi.util.diff.actions.impl.OpenInEditorWithMouseAction;
|
||||
import com.intellij.openapi.util.diff.api.FrameDiffTool.DiffContext;
|
||||
@@ -23,7 +20,6 @@ import com.intellij.openapi.util.diff.requests.ContentDiffRequest;
|
||||
import com.intellij.openapi.util.diff.requests.DiffRequest;
|
||||
import com.intellij.openapi.util.diff.tools.util.DiffUserDataKeys;
|
||||
import com.intellij.openapi.util.diff.tools.util.DiffUserDataKeys.ScrollToPolicy;
|
||||
import com.intellij.openapi.util.diff.tools.util.ScrollToLineHelper;
|
||||
import com.intellij.openapi.util.diff.tools.util.SyncScrollSupport;
|
||||
import com.intellij.openapi.util.diff.tools.util.base.TextDiffViewerBase;
|
||||
import com.intellij.openapi.util.diff.util.CalledInAwt;
|
||||
@@ -122,8 +118,8 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
|
||||
if (side != null) myCurrentSide = side;
|
||||
}
|
||||
|
||||
myScrollToLineHelper.processContext(myContext, myRequest);
|
||||
myScrollToLineHelper.scrollOnInit();
|
||||
myScrollToLineHelper.processContext();
|
||||
myScrollToLineHelper.onInit();
|
||||
}
|
||||
|
||||
private void updateContextHints() {
|
||||
@@ -131,9 +127,7 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
|
||||
myContext.putUserData(DiffUserDataKeys.PREFERRED_FOCUS_SIDE, myCurrentSide);
|
||||
}
|
||||
|
||||
Side side = getCurrentSide();
|
||||
int line = DiffUtil.getLineToScroll(getCurrentEditor());
|
||||
myRequest.putUserData(DiffUserDataKeys.SCROLL_TO_LINE, Pair.create(side, line));
|
||||
myScrollToLineHelper.updateContext();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -166,7 +160,7 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
|
||||
|
||||
@CalledInAwt
|
||||
protected void scrollOnRediff() {
|
||||
myScrollToLineHelper.scrollOnRediff();
|
||||
myScrollToLineHelper.onRediff();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -273,21 +267,15 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
|
||||
//
|
||||
|
||||
@CalledInAwt
|
||||
protected boolean doScrollToLine(@NotNull Pair<Side, Integer> scrollToLine) {
|
||||
Side side = scrollToLine.first;
|
||||
Integer line = scrollToLine.second;
|
||||
|
||||
protected void scrollToLine(@NotNull Side side, int line) {
|
||||
Editor editor = side.select(myEditor1, myEditor2);
|
||||
if (editor != null && line != -1) {
|
||||
DiffUtil.scrollToLine(editor, line);
|
||||
myCurrentSide = side;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (editor == null) return;
|
||||
DiffUtil.scrollEditor(editor, line);
|
||||
myCurrentSide = side;
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
protected boolean doScrollToChange(@NotNull ScrollToPolicy scrollToPolicy) {
|
||||
protected boolean doScrollToChange(@NotNull ScrollToPolicy scrollToChangePolicy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -409,19 +397,108 @@ public abstract class TwosideTextDiffViewer extends TextDiffViewerBase {
|
||||
}
|
||||
}
|
||||
|
||||
private class MyScrollToLineHelper extends ScrollToLineHelper {
|
||||
public void scrollOnInit() {
|
||||
if (myShouldScroll && myScrollToLine != null && myScrollToChange == null) if (doScrollToLine(myScrollToLine)) onSuccessfulScroll();
|
||||
private class MyScrollToLineHelper {
|
||||
protected boolean myShouldScroll = true;
|
||||
|
||||
@Nullable private ScrollToPolicy myScrollToChange;
|
||||
@Nullable private EditorsPosition myEditorsPosition;
|
||||
@Nullable private LogicalPosition[] myCaretPosition;
|
||||
@Nullable private DiffNavigationContext myNavigationContext;
|
||||
|
||||
public void processContext() {
|
||||
myScrollToChange = myRequest.getUserData(DiffUserDataKeys.SCROLL_TO_CHANGE);
|
||||
myEditorsPosition = myRequest.getUserData(EditorsPosition.KEY);
|
||||
myCaretPosition = myRequest.getUserData(DiffUserDataKeys.EDITORS_CARET_POSITION);
|
||||
myNavigationContext = myRequest.getUserData(DiffUserDataKeys.NAVIGATION_CONTEXT);
|
||||
}
|
||||
|
||||
public void scrollOnRediff() {
|
||||
EditorEx editor = getCurrentEditor();
|
||||
if (editor.getCaretModel().getOffset() != 0 || editor.getScrollingModel().getVerticalScrollOffset() != 0) return;
|
||||
public void updateContext() {
|
||||
LogicalPosition[] carets = new LogicalPosition[2];
|
||||
carets[0] = getPosition(myEditor1);
|
||||
carets[1] = getPosition(myEditor2);
|
||||
|
||||
if (myShouldScroll && myScrollToChange != null) if (doScrollToChange(myScrollToChange)) onSuccessfulScroll();
|
||||
if (myShouldScroll && myNavigationContext != null) if (doScrollToContext(myNavigationContext)) onSuccessfulScroll();
|
||||
if (myShouldScroll) doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
|
||||
onSuccessfulScroll();
|
||||
EditorsPosition editorsPosition = new EditorsPosition(carets, getPoint(myEditor1), getPoint(myEditor2));
|
||||
|
||||
myRequest.putUserData(DiffUserDataKeys.SCROLL_TO_CHANGE, null);
|
||||
myRequest.putUserData(EditorsPosition.KEY, editorsPosition);
|
||||
myRequest.putUserData(DiffUserDataKeys.EDITORS_CARET_POSITION, carets);
|
||||
myRequest.putUserData(DiffUserDataKeys.NAVIGATION_CONTEXT, null);
|
||||
}
|
||||
|
||||
public void onInit() {
|
||||
if (!myShouldScroll) return;
|
||||
if (myScrollToChange != null) return;
|
||||
if (myNavigationContext != null) return;
|
||||
|
||||
if (myCaretPosition != null && myCaretPosition.length == 2) {
|
||||
if (myEditor1 != null) myEditor1.getCaretModel().moveToLogicalPosition(myCaretPosition[0]);
|
||||
if (myEditor2 != null) myEditor2.getCaretModel().moveToLogicalPosition(myCaretPosition[1]);
|
||||
|
||||
if (myEditorsPosition != null && myEditorsPosition.isSame(myCaretPosition)) {
|
||||
scrollToPoint(myEditor1, myEditorsPosition.myPoint1);
|
||||
scrollToPoint(myEditor2, myEditorsPosition.myPoint2);
|
||||
}
|
||||
else {
|
||||
getCurrentEditor().getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
|
||||
}
|
||||
myShouldScroll = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void onRediff() {
|
||||
if (myShouldScroll && myScrollToChange != null) {
|
||||
myShouldScroll = !doScrollToChange(myScrollToChange);
|
||||
}
|
||||
if (myShouldScroll && myNavigationContext != null) {
|
||||
myShouldScroll = !doScrollToContext(myNavigationContext);
|
||||
}
|
||||
if (myShouldScroll) {
|
||||
doScrollToChange(ScrollToPolicy.FIRST_CHANGE);
|
||||
}
|
||||
myShouldScroll = false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private LogicalPosition getPosition(@Nullable Editor editor) {
|
||||
return editor != null ? editor.getCaretModel().getLogicalPosition() : new LogicalPosition(0, 0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Point getPoint(@Nullable Editor editor) {
|
||||
if (editor == null) return new Point(0, 0);
|
||||
ScrollingModel model = editor.getScrollingModel();
|
||||
return new Point(model.getHorizontalScrollOffset(), model.getVerticalScrollOffset());
|
||||
}
|
||||
|
||||
private void scrollToPoint(@Nullable Editor editor, @NotNull Point point) {
|
||||
if (editor == null) return;
|
||||
editor.getScrollingModel().disableAnimation();
|
||||
editor.getScrollingModel().scrollHorizontally(point.x);
|
||||
editor.getScrollingModel().scrollVertically(point.y);
|
||||
editor.getScrollingModel().enableAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
private static class EditorsPosition {
|
||||
public static final Key<EditorsPosition> KEY = Key.create("Diff.EditorsPosition");
|
||||
|
||||
@NotNull public final LogicalPosition[] myCaretPosition;
|
||||
@NotNull public final Point myPoint1;
|
||||
@NotNull public final Point myPoint2;
|
||||
|
||||
public EditorsPosition(@NotNull LogicalPosition[] caretPosition, @NotNull Point point1, @NotNull Point point2) {
|
||||
myCaretPosition = caretPosition;
|
||||
myPoint1 = point1;
|
||||
myPoint2 = point2;
|
||||
}
|
||||
|
||||
public boolean isSame(@Nullable LogicalPosition[] caretPosition) {
|
||||
// TODO: allow small fluctuations ?
|
||||
if (caretPosition == null) return true;
|
||||
if (caretPosition.length != 2) return false;
|
||||
if (!caretPosition[0].equals(myCaretPosition[0])) return false;
|
||||
if (!caretPosition[1].equals(myCaretPosition[1])) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,10 +146,18 @@ public class DiffUtil {
|
||||
editor.reinitSettings();
|
||||
}
|
||||
|
||||
public static void scrollToLine(@Nullable final Editor editor, int line) {
|
||||
public static void scrollEditor(@Nullable final Editor editor, int line) {
|
||||
scrollEditor(editor, line, 0);
|
||||
}
|
||||
|
||||
public static void scrollEditor(@Nullable final Editor editor, int line, int column) {
|
||||
scrollEditor(editor, new LogicalPosition(line, column));
|
||||
}
|
||||
|
||||
public static void scrollEditor(@Nullable final Editor editor, @NotNull LogicalPosition position) {
|
||||
if (editor == null) return;
|
||||
editor.getCaretModel().removeSecondaryCarets();
|
||||
editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(line, 0));
|
||||
editor.getCaretModel().moveToLogicalPosition(position);
|
||||
ScrollingModel scrollingModel = editor.getScrollingModel();
|
||||
scrollingModel.disableAnimation();
|
||||
scrollingModel.scrollToCaret(ScrollType.CENTER);
|
||||
@@ -164,11 +172,6 @@ public class DiffUtil {
|
||||
scrollingModel.scrollToCaret(ScrollType.CENTER);
|
||||
}
|
||||
|
||||
public static int getLineToScroll(@NotNull Editor editor) {
|
||||
// TODO: scroll to visible area, not caret
|
||||
return editor.getCaretModel().getLogicalPosition().line;
|
||||
}
|
||||
|
||||
//
|
||||
// UI
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user