IDEA-139555 diff: show 'go to next file' popup near selected change or cursor

This commit is contained in:
Aleksey Pivovarov
2015-04-23 19:57:52 +03:00
parent 897263ad70
commit 4cbda94bf7
5 changed files with 103 additions and 21 deletions
@@ -34,6 +34,7 @@ import com.intellij.diff.util.DiffUserDataKeys;
import com.intellij.diff.util.DiffUserDataKeysEx;
import com.intellij.diff.util.DiffUserDataKeysEx.ScrollToPolicy;
import com.intellij.diff.util.DiffUtil;
import com.intellij.diff.util.LineRange;
import com.intellij.ide.DataManager;
import com.intellij.ide.impl.DataManagerImpl;
import com.intellij.openapi.Disposable;
@@ -41,6 +42,7 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
@@ -668,7 +670,7 @@ public abstract class DiffRequestProcessor implements Disposable {
if (!isNavigationEnabled() || !hasNextChange() || !getSettings().isGoToNextFileOnNextDifference()) return;
if (myIterationState != IterationState.NEXT) {
notifyMessage(e.getData(DiffDataKeys.CURRENT_EDITOR), true);
notifyMessage(e, true);
myIterationState = IterationState.NEXT;
return;
}
@@ -717,7 +719,7 @@ public abstract class DiffRequestProcessor implements Disposable {
if (!isNavigationEnabled() || !hasPrevChange() || !getSettings().isGoToNextFileOnNextDifference()) return;
if (myIterationState != IterationState.PREV) {
notifyMessage(e.getData(DiffDataKeys.CURRENT_EDITOR), false);
notifyMessage(e, false);
myIterationState = IterationState.PREV;
return;
}
@@ -726,32 +728,54 @@ public abstract class DiffRequestProcessor implements Disposable {
}
}
private void notifyMessage(@Nullable Editor editor, boolean next) {
private void notifyMessage(@NotNull AnActionEvent e, boolean next) {
Editor editor = e.getData(DiffDataKeys.CURRENT_EDITOR);
// TODO: provide "change" word in chain UserData - for tests/etc
String message = next ? "Press again to go to the next file" : "Press again to go to the previous file";
final LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(message));
Point point = new Point(myContentPanel.getWidth() / 2, next ? myContentPanel.getHeight() - JBUI.scale(40) : JBUI.scale(40));
final HintHint hintHint = new HintHint(myContentPanel, point)
.setPreferredPosition(next ? Balloon.Position.above : Balloon.Position.below)
.setAwtTooltip(true)
.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD))
.setTextBg(HintUtil.INFORMATION_COLOR)
.setShowImmediately(true);
if (editor == null) {
final Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
final HintHint hintHint = createNotifyHint(myContentPanel, point, next);
hint.show(myContentPanel, point.x, point.y, owner instanceof JComponent ? (JComponent)owner : null, hintHint);
}
else {
Point editorPoint = SwingUtilities.convertPoint(myContentPanel, point, editor.getComponent());
int x = SwingUtilities.convertPoint(myContentPanel, point, editor.getComponent()).x;
JComponent header = editor.getHeaderComponent();
int shift = editor.getScrollingModel().getVerticalScrollOffset() - (header != null ? header.getHeight() : 0);
LogicalPosition position;
LineRange changeRange = e.getData(DiffDataKeys.CURRENT_CHANGE_RANGE);
if (changeRange == null) {
position = new LogicalPosition(editor.getCaretModel().getLogicalPosition().line + (next ? 1 : 0), 0);
}
else {
position = new LogicalPosition(next ? changeRange.end : changeRange.start, 0);
}
int y = editor.logicalPositionToXY(position).y - shift;
Point editorPoint = new Point(x, y);
final HintHint hintHint = createNotifyHint(editor.getComponent(), editorPoint, !next);
HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, editorPoint, HintManager.HIDE_BY_ANY_KEY |
HintManager.HIDE_BY_TEXT_CHANGE |
HintManager.HIDE_BY_SCROLLING, 0, false, hintHint);
}
}
@NotNull
private static HintHint createNotifyHint(@NotNull JComponent component, @NotNull Point point, boolean above) {
return new HintHint(component, point)
.setPreferredPosition(above ? Balloon.Position.above : Balloon.Position.below)
.setAwtTooltip(true)
.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD))
.setTextBg(HintUtil.INFORMATION_COLOR)
.setShowImmediately(true);
}
// Iterate requests
protected class MyNextChangeAction extends NextChangeAction {
@@ -566,6 +566,18 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
return getOpenFileDescriptor(myEditor.getCaretModel().getOffset());
}
@CalledInAwt
@Nullable
protected OnesideDiffChange getCurrentChange() {
if (myChangedBlockData == null) return null;
int caretLine = myEditor.getCaretModel().getLogicalPosition().line;
for (OnesideDiffChange change : myChangedBlockData.getDiffChanges()) {
if (DiffUtil.isSelectedByLine(caretLine, change.getLine1(), change.getLine2())) return change;
}
return null;
}
@Nullable
protected OpenFileDescriptor getOpenFileDescriptor(int offset) {
assert myActualContent1 != null || myActualContent2 != null;
@@ -806,9 +818,13 @@ public class OnesideDiffViewer extends TextDiffViewerBase {
else if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) {
return myEditor;
}
else {
return super.getData(dataId);
else if (DiffDataKeys.CURRENT_CHANGE_RANGE.is(dataId)) {
OnesideDiffChange change = getCurrentChange();
if (change != null) {
return new LineRange(change.getLine1(), change.getLine2());
}
}
return super.getData(dataId);
}
private class MyStatusPanel extends StatusPanel {
@@ -27,12 +27,9 @@ import com.intellij.diff.requests.DiffRequest;
import com.intellij.diff.tools.util.*;
import com.intellij.diff.tools.util.base.HighlightPolicy;
import com.intellij.diff.tools.util.twoside.TwosideTextDiffViewer;
import com.intellij.diff.util.DiffDividerDrawUtil;
import com.intellij.diff.util.DiffDrawUtil;
import com.intellij.diff.util.*;
import com.intellij.diff.util.DiffUserDataKeysEx.ScrollToPolicy;
import com.intellij.diff.util.DiffUtil;
import com.intellij.diff.util.DiffUtil.DocumentData;
import com.intellij.diff.util.Side;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeEventQueue;
import com.intellij.openapi.Disposable;
@@ -501,6 +498,23 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
return affectedChanges;
}
@Nullable
@CalledInAwt
private SimpleDiffChange getSelectedChange(@NotNull Side side) {
EditorEx editor = side.select(myEditor1, myEditor2);
if (editor == null) return null;
int caretLine = editor.getCaretModel().getLogicalPosition().line;
for (SimpleDiffChange change : myDiffChanges) {
int line1 = change.getStartLine(side);
int line2 = change.getEndLine(side);
if (DiffUtil.isSelectedByLine(caretLine, line1, line2)) return change;
}
return null;
}
//
// Actions
//
@@ -820,9 +834,13 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer {
if (DiffDataKeys.PREV_NEXT_DIFFERENCE_ITERABLE.is(dataId)) {
return myPrevNextDifferenceIterable;
}
else {
return super.getData(dataId);
else if (DiffDataKeys.CURRENT_CHANGE_RANGE.is(dataId)) {
SimpleDiffChange change = getSelectedChange(getCurrentSide());
if (change != null) {
return new LineRange(change.getStartLine(getCurrentSide()), change.getEndLine(getCurrentSide()));
}
}
return super.getData(dataId);
}
private class MySyncScrollable extends BaseSyncScrollable {
@@ -392,6 +392,22 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
// Misc
//
@Nullable
@CalledInAwt
private SimpleThreesideDiffChange getSelectedChange(@NotNull ThreeSide side) {
EditorEx editor = side.select(myEditors);
int caretLine = editor.getCaretModel().getLogicalPosition().line;
for (SimpleThreesideDiffChange change : myDiffChanges) {
int line1 = change.getStartLine(side);
int line2 = change.getEndLine(side);
if (DiffUtil.isSelectedByLine(caretLine, line1, line2)) return change;
}
return null;
}
@SuppressWarnings("MethodOverridesStaticMethodOfSuperclass")
public static boolean canShowRequest(@NotNull DiffContext context, @NotNull DiffRequest request) {
return ThreesideTextDiffViewer.canShowRequest(context, request);
@@ -505,9 +521,14 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewer {
if (DiffDataKeys.PREV_NEXT_DIFFERENCE_ITERABLE.is(dataId)) {
return myPrevNextDifferenceIterable;
}
else {
return super.getData(dataId);
else if (DiffDataKeys.CURRENT_CHANGE_RANGE.is(dataId)) {
SimpleThreesideDiffChange change = getSelectedChange(getCurrentSide());
if (change != null) {
return new LineRange(change.getStartLine(getCurrentSide()), change.getEndLine(getCurrentSide()));
}
}
return super.getData(dataId);
}
private class MySyncScrollable extends BaseSyncScrollable {
@@ -19,6 +19,8 @@ import com.intellij.diff.DiffContext;
import com.intellij.diff.FrameDiffTool;
import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.requests.DiffRequest;
import com.intellij.diff.util.IntPair;
import com.intellij.diff.util.LineRange;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
@@ -26,6 +28,7 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
public interface DiffDataKeys {
DataKey<Editor> CURRENT_EDITOR = DataKey.create("diff_current_editor");
DataKey<DiffContent> CURRENT_CONTENT = DataKey.create("diff_current_content");
DataKey<LineRange> CURRENT_CHANGE_RANGE = DataKey.create("diff_current_change_range");
DataKey<DiffRequest> DIFF_REQUEST = DataKey.create("diff_request");
DataKey<DiffContext> DIFF_CONTEXT = DataKey.create("diff_context");