diff: carefully keep editor scroll/caret position

This commit is contained in:
Aleksey Pivovarov
2015-02-03 19:47:02 +03:00
parent aece5ce950
commit 80f04188ca
7 changed files with 271 additions and 146 deletions
@@ -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);
}
}
}
@@ -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;
}
}
}
@@ -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;
}
//
@@ -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
//
@@ -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;
}
}
@@ -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
//