lst: extract LST popup logic to separate class

This commit is contained in:
Aleksey Pivovarov
2016-04-13 18:07:59 +03:00
committed by Aleksey Pivovarov
parent 688d0fa063
commit 9ef2903168
2 changed files with 365 additions and 293 deletions
@@ -0,0 +1,303 @@
/*
* Copyright 2000-2016 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.vcs.ex;
import com.intellij.codeInsight.hint.EditorFragmentComponent;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.diff.comparison.ByWord;
import com.intellij.diff.comparison.ComparisonPolicy;
import com.intellij.diff.fragments.DiffFragment;
import com.intellij.diff.util.DiffDrawUtil;
import com.intellij.diff.util.DiffUtil;
import com.intellij.diff.util.TextDiffType;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.util.BackgroundTaskUtil;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.HintHint;
import com.intellij.ui.HintListener;
import com.intellij.ui.LightweightHint;
import com.intellij.util.Function;
import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
import static com.intellij.diff.util.DiffUtil.getDiffType;
import static com.intellij.diff.util.DiffUtil.getLineCount;
public abstract class LineStatusMarkerPopup {
@NotNull public final LineStatusTracker myTracker;
@NotNull public final Editor myEditor;
@NotNull public final Range myRange;
public LineStatusMarkerPopup(@NotNull LineStatusTracker tracker, @NotNull Editor editor, @NotNull Range range) {
myTracker = tracker;
myEditor = editor;
myRange = range;
}
@NotNull
protected abstract ActionToolbar buildToolbar(@Nullable Point mousePosition, @NotNull Disposable parentDisposable);
@NotNull
protected FileType getFileType() {
return PlainTextFileType.INSTANCE;
}
protected boolean isShowInnerDifferences() {
return false;
}
public void scrollAndShow() {
if (!myTracker.isValid()) return;
final Document document = myTracker.getDocument();
int line = Math.min(myRange.getType() == Range.DELETED ? myRange.getLine2() : myRange.getLine2() - 1, getLineCount(document) - 1);
final int lastOffset = document.getLineStartOffset(line);
myEditor.getCaretModel().moveToOffset(lastOffset);
myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
showAfterScroll();
}
public void showAfterScroll() {
myEditor.getScrollingModel().runActionOnScrollingFinished(new Runnable() {
public void run() {
showHintAt(null);
}
});
}
public void showHint(@NotNull MouseEvent e) {
final JComponent comp = (JComponent)e.getComponent(); // shall be EditorGutterComponent, cast is safe.
final JLayeredPane layeredPane = comp.getRootPane().getLayeredPane();
final Point point = SwingUtilities.convertPoint(comp, ((EditorEx)myEditor).getGutterComponentEx().getWidth(), e.getY(), layeredPane);
showHintAt(point);
e.consume();
}
public void showHintAt(@Nullable Point mousePosition) {
if (!myTracker.isValid()) return;
final Disposable disposable = Disposer.newDisposable();
FileType fileType = getFileType();
List<DiffFragment> wordDiff = computeWordDiff();
installMasterEditorHighlighters(wordDiff, disposable);
JComponent editorComponent = createEditorComponent(fileType, wordDiff);
ActionToolbar toolbar = buildToolbar(mousePosition, disposable);
toolbar.updateActionsImmediately(); // we need valid ActionToolbar.getPreferredSize() to calc size of popup
toolbar.setReservePlaceAutoPopupIcon(false);
PopupPanel popupPanel = new PopupPanel(myEditor, toolbar, editorComponent);
LightweightHint hint = new LightweightHint(popupPanel);
HintListener closeListener = new HintListener() {
public void hintHidden(final EventObject event) {
Disposer.dispose(disposable);
}
};
hint.addHintListener(closeListener);
int line = myEditor.getCaretModel().getLogicalPosition().line;
Point point = HintManagerImpl.getHintPosition(hint, myEditor, new LogicalPosition(line, 0), HintManager.UNDER);
if (mousePosition != null) { // show right after the nearest line
int lineHeight = myEditor.getLineHeight();
int delta = (point.y - mousePosition.y) % lineHeight;
if (delta < 0) delta += lineHeight;
point.y = mousePosition.y + delta;
}
point.x -= popupPanel.getEditorTextOffset(); // align main editor with the one in popup
int flags = HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING;
HintManagerImpl.getInstanceImpl().showEditorHint(hint, myEditor, point, flags, -1, false, new HintHint(myEditor, point));
if (!hint.isVisible()) {
closeListener.hintHidden(null);
}
}
@Nullable
private List<DiffFragment> computeWordDiff() {
if (!isShowInnerDifferences()) return null;
if (myRange.getType() != Range.MODIFIED) return null;
final CharSequence vcsContent = myTracker.getVcsContent(myRange);
final CharSequence currentContent = myTracker.getCurrentContent(myRange);
return BackgroundTaskUtil.tryComputeFast(new Function<ProgressIndicator, List<DiffFragment>>() {
@Override
public List<DiffFragment> fun(ProgressIndicator indicator) {
return ByWord.compare(vcsContent, currentContent, ComparisonPolicy.DEFAULT, indicator);
}
}, Registry.intValue("diff.status.tracker.byword.delay"));
}
private void installMasterEditorHighlighters(@Nullable List<DiffFragment> wordDiff, @NotNull Disposable parentDisposable) {
if (wordDiff == null) return;
final List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
int currentStartShift = myTracker.getCurrentTextRange(myRange).getStartOffset();
for (DiffFragment fragment : wordDiff) {
int currentStart = currentStartShift + fragment.getStartOffset2();
int currentEnd = currentStartShift + fragment.getEndOffset2();
TextDiffType type = getDiffType(fragment);
highlighters.addAll(DiffDrawUtil.createInlineHighlighter(myEditor, currentStart, currentEnd, type));
}
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
for (RangeHighlighter highlighter : highlighters) {
highlighter.dispose();
}
}
});
}
@Nullable
private EditorFragmentComponent createEditorComponent(@Nullable FileType fileType, @Nullable List<DiffFragment> wordDiff) {
if (myRange.getType() == Range.INSERTED) return null;
EditorEx uEditor = (EditorEx)EditorFactory.getInstance().createViewer(myTracker.getVcsDocument(), myTracker.getProject());
uEditor.setColorsScheme(myEditor.getColorsScheme());
DiffUtil.setEditorCodeStyle(myTracker.getProject(), uEditor, fileType);
EditorHighlighterFactory highlighterFactory = EditorHighlighterFactory.getInstance();
uEditor.setHighlighter(highlighterFactory.createEditorHighlighter(myTracker.getProject(), getFileName(myTracker.getDocument())));
if (wordDiff != null) {
int vcsStartShift = myTracker.getVcsTextRange(myRange).getStartOffset();
for (DiffFragment fragment : wordDiff) {
int vcsStart = vcsStartShift + fragment.getStartOffset1();
int vcsEnd = vcsStartShift + fragment.getEndOffset1();
TextDiffType type = getDiffType(fragment);
DiffDrawUtil.createInlineHighlighter(uEditor, vcsStart, vcsEnd, type);
}
}
EditorFragmentComponent fragmentComponent =
EditorFragmentComponent.createEditorFragmentComponent(uEditor, myRange.getVcsLine1(), myRange.getVcsLine2(), false, false);
EditorFactory.getInstance().releaseEditor(uEditor);
return fragmentComponent;
}
private static String getFileName(@NotNull Document document) {
final VirtualFile file = FileDocumentManager.getInstance().getFile(document);
if (file == null) return "";
return file.getName();
}
private static class PopupPanel extends JPanel {
@Nullable private final JComponent myEditorComponent;
public PopupPanel(@NotNull final Editor editor,
@NotNull ActionToolbar toolbar,
@Nullable JComponent editorComponent) {
super(new BorderLayout());
setOpaque(false);
myEditorComponent = editorComponent;
boolean isEditorVisible = myEditorComponent != null;
Color background = ((EditorEx)editor).getBackgroundColor();
Color borderColor = editor.getColorsScheme().getColor(EditorColors.SELECTED_TEARLINE_COLOR);
JComponent toolbarComponent = toolbar.getComponent();
toolbarComponent.setBackground(background);
toolbarComponent.setBorder(null);
JComponent toolbarPanel = JBUI.Panels.simplePanel(toolbarComponent);
toolbarPanel.setBackground(background);
Border outsideToolbarBorder = JBUI.Borders.customLine(borderColor, 1, 1, isEditorVisible ? 0 : 1, 1);
Border insideToolbarBorder = JBUI.Borders.empty(1, 5, 1, 5);
toolbarPanel.setBorder(BorderFactory.createCompoundBorder(outsideToolbarBorder, insideToolbarBorder));
if (myEditorComponent != null) {
// default border of EditorFragmentComponent is replaced here with our own.
Border outsideEditorBorder = JBUI.Borders.customLine(borderColor, 1);
Border insideEditorBorder = JBUI.Borders.empty(2);
myEditorComponent.setBorder(BorderFactory.createCompoundBorder(outsideEditorBorder, insideEditorBorder));
}
// 'empty space' to the right of toolbar
JPanel emptyPanel = new JPanel();
emptyPanel.setOpaque(false);
emptyPanel.setPreferredSize(new Dimension());
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.setOpaque(false);
topPanel.add(toolbarPanel, BorderLayout.WEST);
topPanel.add(emptyPanel, BorderLayout.CENTER);
add(topPanel, BorderLayout.NORTH);
if (myEditorComponent != null) add(myEditorComponent, BorderLayout.CENTER);
// transfer clicks into editor
MouseAdapter listener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
transferEvent(e, editor);
}
@Override
public void mouseClicked(MouseEvent e) {
transferEvent(e, editor);
}
public void mouseReleased(MouseEvent e) {
transferEvent(e, editor);
}
};
emptyPanel.addMouseListener(listener);
}
private static void transferEvent(MouseEvent e, Editor editor) {
editor.getContentComponent().dispatchEvent(SwingUtilities.convertMouseEvent(e.getComponent(), e, editor.getContentComponent()));
}
public int getEditorTextOffset() {
return 3; // myEditorComponent.getInsets().left
}
}
}
@@ -15,265 +15,107 @@
*/
package com.intellij.openapi.vcs.ex;
import com.intellij.codeInsight.hint.EditorFragmentComponent;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.diff.comparison.ByWord;
import com.intellij.diff.comparison.ComparisonPolicy;
import com.intellij.diff.fragments.DiffFragment;
import com.intellij.diff.util.DiffDrawUtil;
import com.intellij.diff.util.DiffUtil;
import com.intellij.diff.util.TextDiffType;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.markup.LineMarkerRenderer;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.util.BackgroundTaskUtil;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vcs.VcsApplicationSettings;
import com.intellij.openapi.vcs.actions.ShowNextChangeMarkerAction;
import com.intellij.openapi.vcs.actions.ShowPrevChangeMarkerAction;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.HintHint;
import com.intellij.ui.HintListener;
import com.intellij.ui.LightweightHint;
import com.intellij.util.Function;
import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
import static com.intellij.diff.util.DiffUtil.getDiffType;
import static com.intellij.diff.util.DiffUtil.getLineCount;
public class LineStatusTrackerDrawing {
private LineStatusTrackerDrawing() {
}
public static LineMarkerRenderer createRenderer(final Range range, final LineStatusTracker tracker) {
return new LineStatusMarkerRenderer(range) {
public void doAction(final Editor editor, final MouseEvent e) {
e.consume();
final JComponent comp = (JComponent)e.getComponent(); // shall be EditorGutterComponent, cast is safe.
final JLayeredPane layeredPane = comp.getRootPane().getLayeredPane();
final Point point = SwingUtilities.convertPoint(comp, ((EditorEx)editor).getGutterComponentEx().getWidth(), e.getY(), layeredPane);
showActiveHint(range, editor, tracker, point);
public void doAction(Editor editor, MouseEvent e) {
new MyLineStatusMarkerPopup(tracker, editor, range).showHint(e);
}
};
}
public static void showActiveHint(@NotNull Range range,
@NotNull Editor editor,
@NotNull LineStatusTracker tracker,
@Nullable Point mousePosition) {
if (!tracker.isValid()) return;
final Disposable disposable = Disposer.newDisposable();
List<DiffFragment> wordDiff = computeWordDiff(range, tracker);
installEditorHighlighters(range, editor, tracker, wordDiff, disposable);
JComponent editorComponent = createEditorComponent(range, editor, tracker, wordDiff);
ActionToolbar toolbar = buildToolbar(range, editor, tracker, mousePosition, disposable);
toolbar.updateActionsImmediately(); // we need valid ActionToolbar.getPreferredSize() to calc size of popup
toolbar.setReservePlaceAutoPopupIcon(false);
PopupPanel popupPanel = new PopupPanel(editor, toolbar, editorComponent);
LightweightHint hint = new LightweightHint(popupPanel);
HintListener closeListener = new HintListener() {
public void hintHidden(final EventObject event) {
Disposer.dispose(disposable);
}
};
hint.addHintListener(closeListener);
int line = editor.getCaretModel().getLogicalPosition().line;
Point point = HintManagerImpl.getHintPosition(hint, editor, new LogicalPosition(line, 0), HintManager.UNDER);
if (mousePosition != null) { // show right after the nearest line
int lineHeight = editor.getLineHeight();
int delta = (point.y - mousePosition.y) % lineHeight;
if (delta < 0) delta += lineHeight;
point.y = mousePosition.y + delta;
}
point.x -= popupPanel.getEditorTextOffset(); // align main editor with the one in popup
int flags = HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING;
HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, point, flags, -1, false, new HintHint(editor, point));
if (!hint.isVisible()) {
closeListener.hintHidden(null);
}
public static void moveToRange(Range range, Editor editor, LineStatusTracker tracker) {
new MyLineStatusMarkerPopup(tracker, editor, range).scrollAndShow();
}
@Nullable
private static List<DiffFragment> computeWordDiff(@NotNull Range range, @NotNull LineStatusTracker tracker) {
if (!VcsApplicationSettings.getInstance().SHOW_LST_WORD_DIFFERENCES) return null;
if (range.getType() != Range.MODIFIED) return null;
final CharSequence vcsContent = tracker.getVcsContent(range);
final CharSequence currentContent = tracker.getCurrentContent(range);
return BackgroundTaskUtil.tryComputeFast(new Function<ProgressIndicator, List<DiffFragment>>() {
@Override
public List<DiffFragment> fun(ProgressIndicator indicator) {
return ByWord.compare(vcsContent, currentContent, ComparisonPolicy.DEFAULT, indicator);
}
}, Registry.intValue("diff.status.tracker.byword.delay"));
public static void showHint(Range range, Editor editor, LineStatusTracker tracker) {
new MyLineStatusMarkerPopup(tracker, editor, range).showAfterScroll();
}
@NotNull
private static ActionToolbar buildToolbar(@NotNull Range range,
@NotNull Editor editor,
@NotNull LineStatusTracker tracker,
@Nullable Point mousePosition,
@NotNull Disposable parentDisposable) {
final DefaultActionGroup group = new DefaultActionGroup();
private static class MyLineStatusMarkerPopup extends LineStatusMarkerPopup {
@NotNull private final LineStatusTracker myTracker;
final ShowPrevChangeMarkerAction localShowPrevAction = new ShowPrevChangeMarkerAction(tracker.getPrevRange(range), tracker, editor);
final ShowNextChangeMarkerAction localShowNextAction = new ShowNextChangeMarkerAction(tracker.getNextRange(range), tracker, editor);
final RollbackLineStatusRangeAction rollback = new RollbackLineStatusRangeAction(tracker, range, editor);
final ShowLineStatusRangeDiffAction showDiff = new ShowLineStatusRangeDiffAction(tracker, range, editor);
final CopyLineStatusRangeAction copyRange = new CopyLineStatusRangeAction(tracker, range);
final ToggleByWordDiffAction toggleWordDiff = new ToggleByWordDiffAction(range, editor, tracker, mousePosition);
group.add(localShowPrevAction);
group.add(localShowNextAction);
group.add(rollback);
group.add(showDiff);
group.add(copyRange);
group.add(toggleWordDiff);
JComponent editorComponent = editor.getComponent();
EmptyAction.setupAction(localShowPrevAction, "VcsShowPrevChangeMarker", editorComponent);
EmptyAction.setupAction(localShowNextAction, "VcsShowNextChangeMarker", editorComponent);
EmptyAction.setupAction(rollback, IdeActions.SELECTED_CHANGES_ROLLBACK, editorComponent);
EmptyAction.setupAction(showDiff, "ChangesView.Diff", editorComponent);
EmptyAction.setupAction(copyRange, IdeActions.ACTION_COPY, editorComponent);
final List<AnAction> actionList = ActionUtil.getActions(editorComponent);
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
actionList.remove(localShowPrevAction);
actionList.remove(localShowNextAction);
actionList.remove(rollback);
actionList.remove(showDiff);
actionList.remove(copyRange);
}
});
return ActionManager.getInstance().createActionToolbar(ActionPlaces.FILEHISTORY_VIEW_TOOLBAR, group, true);
}
private static void installEditorHighlighters(@NotNull Range range,
@NotNull Editor editor,
@NotNull LineStatusTracker tracker,
@Nullable List<DiffFragment> wordDiff,
@NotNull Disposable parentDisposable) {
if (wordDiff == null) return;
final List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
int currentStartShift = tracker.getCurrentTextRange(range).getStartOffset();
for (DiffFragment fragment : wordDiff) {
int currentStart = currentStartShift + fragment.getStartOffset2();
int currentEnd = currentStartShift + fragment.getEndOffset2();
TextDiffType type = getDiffType(fragment);
highlighters.addAll(DiffDrawUtil.createInlineHighlighter(editor, currentStart, currentEnd, type));
public MyLineStatusMarkerPopup(@NotNull LineStatusTracker tracker,
@NotNull Editor editor,
@NotNull Range range) {
super(tracker, editor, range);
myTracker = tracker;
}
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
for (RangeHighlighter highlighter : highlighters) {
highlighter.dispose();
@Override
protected boolean isShowInnerDifferences() {
return VcsApplicationSettings.getInstance().SHOW_LST_WORD_DIFFERENCES;
}
@NotNull
@Override
protected ActionToolbar buildToolbar(@Nullable Point mousePosition, @NotNull Disposable parentDisposable) {
final DefaultActionGroup group = new DefaultActionGroup();
final ShowPrevChangeMarkerAction localShowPrevAction = new ShowPrevChangeMarkerAction(myTracker.getPrevRange(myRange), myTracker, myEditor);
final ShowNextChangeMarkerAction localShowNextAction = new ShowNextChangeMarkerAction(myTracker.getNextRange(myRange), myTracker, myEditor);
final RollbackLineStatusRangeAction rollback = new RollbackLineStatusRangeAction(myTracker, myRange, myEditor);
final ShowLineStatusRangeDiffAction showDiff = new ShowLineStatusRangeDiffAction(myTracker, myRange, myEditor);
final CopyLineStatusRangeAction copyRange = new CopyLineStatusRangeAction(myTracker, myRange);
final ToggleByWordDiffAction toggleWordDiff = new ToggleByWordDiffAction(myRange, myEditor, myTracker, mousePosition);
group.add(localShowPrevAction);
group.add(localShowNextAction);
group.add(rollback);
group.add(showDiff);
group.add(copyRange);
group.add(toggleWordDiff);
JComponent editorComponent = myEditor.getComponent();
EmptyAction.setupAction(localShowPrevAction, "VcsShowPrevChangeMarker", editorComponent);
EmptyAction.setupAction(localShowNextAction, "VcsShowNextChangeMarker", editorComponent);
EmptyAction.setupAction(rollback, IdeActions.SELECTED_CHANGES_ROLLBACK, editorComponent);
EmptyAction.setupAction(showDiff, "ChangesView.Diff", editorComponent);
EmptyAction.setupAction(copyRange, IdeActions.ACTION_COPY, editorComponent);
final List<AnAction> actionList = ActionUtil.getActions(editorComponent);
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
actionList.remove(localShowPrevAction);
actionList.remove(localShowNextAction);
actionList.remove(rollback);
actionList.remove(showDiff);
actionList.remove(copyRange);
}
}
});
}
});
@Nullable
private static JComponent createEditorComponent(@NotNull Range range,
@NotNull Editor editor,
@NotNull LineStatusTracker tracker,
@Nullable List<DiffFragment> wordDiff) {
if (range.getType() == Range.INSERTED) return null;
DocumentEx doc = (DocumentEx)tracker.getVcsDocument();
EditorEx uEditor = (EditorEx)EditorFactory.getInstance().createViewer(doc, tracker.getProject());
uEditor.setColorsScheme(editor.getColorsScheme());
FileType fileType = tracker.getVirtualFile().getFileType();
DiffUtil.setEditorCodeStyle(tracker.getProject(), uEditor, fileType);
EditorHighlighterFactory highlighterFactory = EditorHighlighterFactory.getInstance();
EditorHighlighter highlighter = highlighterFactory.createEditorHighlighter(tracker.getProject(), getFileName(tracker.getDocument()));
uEditor.setHighlighter(highlighter);
if (wordDiff != null) {
int vcsStartShift = tracker.getVcsTextRange(range).getStartOffset();
for (DiffFragment fragment : wordDiff) {
int vcsStart = vcsStartShift + fragment.getStartOffset1();
int vcsEnd = vcsStartShift + fragment.getEndOffset1();
TextDiffType type = getDiffType(fragment);
DiffDrawUtil.createInlineHighlighter(uEditor, vcsStart, vcsEnd, type);
}
return ActionManager.getInstance().createActionToolbar(ActionPlaces.FILEHISTORY_VIEW_TOOLBAR, group, true);
}
JComponent fragmentComponent =
EditorFragmentComponent.createEditorFragmentComponent(uEditor, range.getVcsLine1(), range.getVcsLine2(), false, false);
EditorFactory.getInstance().releaseEditor(uEditor);
return fragmentComponent;
}
private static String getFileName(final Document document) {
final VirtualFile file = FileDocumentManager.getInstance().getFile(document);
if (file == null) return "";
return file.getName();
}
public static void moveToRange(final Range range, final Editor editor, final LineStatusTracker tracker) {
if (!tracker.isValid()) return;
final Document document = tracker.getDocument();
int line = Math.min(range.getType() == Range.DELETED ? range.getLine2() : range.getLine2() - 1, getLineCount(document) - 1);
final int lastOffset = document.getLineStartOffset(line);
editor.getCaretModel().moveToOffset(lastOffset);
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
showHint(range, editor, tracker);
}
public static void showHint(final Range range, final Editor editor, final LineStatusTracker tracker) {
editor.getScrollingModel().runActionOnScrollingFinished(new Runnable() {
public void run() {
showActiveHint(range, editor, tracker, null);
}
});
@NotNull
@Override
protected FileType getFileType() {
return myTracker.getVirtualFile().getFileType();
}
}
private static class ToggleByWordDiffAction extends ToggleAction implements DumbAware {
@@ -301,80 +143,7 @@ public class LineStatusTrackerDrawing {
@Override
public void setSelected(AnActionEvent e, boolean state) {
VcsApplicationSettings.getInstance().SHOW_LST_WORD_DIFFERENCES = state;
showActiveHint(myRange, myEditor, myTracker, myMousePosition);
}
}
private static class PopupPanel extends JPanel {
@Nullable private final JComponent myEditorComponent;
public PopupPanel(@NotNull final Editor editor,
@NotNull ActionToolbar toolbar,
@Nullable JComponent editorComponent) {
super(new BorderLayout());
setOpaque(false);
myEditorComponent = editorComponent;
boolean isEditorVisible = myEditorComponent != null;
Color background = ((EditorEx)editor).getBackgroundColor();
Color borderColor = editor.getColorsScheme().getColor(EditorColors.SELECTED_TEARLINE_COLOR);
JComponent toolbarComponent = toolbar.getComponent();
toolbarComponent.setBackground(background);
toolbarComponent.setBorder(null);
JComponent toolbarPanel = JBUI.Panels.simplePanel(toolbarComponent);
toolbarPanel.setBackground(background);
Border outsideToolbarBorder = JBUI.Borders.customLine(borderColor, 1, 1, isEditorVisible ? 0 : 1, 1);
Border insideToolbarBorder = JBUI.Borders.empty(1, 5, 1, 5);
toolbarPanel.setBorder(BorderFactory.createCompoundBorder(outsideToolbarBorder, insideToolbarBorder));
if (myEditorComponent != null) {
// default border of EditorFragmentComponent is replaced here with our own.
Border outsideEditorBorder = JBUI.Borders.customLine(borderColor, 1);
Border insideEditorBorder = JBUI.Borders.empty(2);
myEditorComponent.setBorder(BorderFactory.createCompoundBorder(outsideEditorBorder, insideEditorBorder));
}
// 'empty space' to the right of toolbar
JPanel emptyPanel = new JPanel();
emptyPanel.setOpaque(false);
emptyPanel.setPreferredSize(new Dimension());
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.setOpaque(false);
topPanel.add(toolbarPanel, BorderLayout.WEST);
topPanel.add(emptyPanel, BorderLayout.CENTER);
add(topPanel, BorderLayout.NORTH);
if (myEditorComponent != null) add(myEditorComponent, BorderLayout.CENTER);
// transfer clicks into editor
MouseAdapter listener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
transferEvent(e, editor);
}
@Override
public void mouseClicked(MouseEvent e) {
transferEvent(e, editor);
}
public void mouseReleased(MouseEvent e) {
transferEvent(e, editor);
}
};
emptyPanel.addMouseListener(listener);
}
private static void transferEvent(MouseEvent e, Editor editor) {
editor.getContentComponent().dispatchEvent(SwingUtilities.convertMouseEvent(e.getComponent(), e, editor.getContentComponent()));
}
public int getEditorTextOffset() {
return 3; // myEditorComponent.getInsets().left
new MyLineStatusMarkerPopup(myTracker, myEditor, myRange).showHintAt(myMousePosition);
}
}
}