mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:19:59 +07:00
228 lines
7.5 KiB
Java
228 lines
7.5 KiB
Java
package com.intellij.openapi.diff.impl;
|
|
|
|
import com.intellij.openapi.Disposeable;
|
|
import com.intellij.openapi.diff.DiffContent;
|
|
import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
|
|
import com.intellij.openapi.diff.impl.util.LabeledEditor;
|
|
import com.intellij.openapi.diff.impl.util.SyncScrollSupport;
|
|
import com.intellij.openapi.editor.Editor;
|
|
import com.intellij.openapi.editor.colors.EditorColors;
|
|
import com.intellij.openapi.editor.event.EditorMouseAdapter;
|
|
import com.intellij.openapi.editor.event.EditorMouseEvent;
|
|
import com.intellij.openapi.editor.event.EditorMouseEventArea;
|
|
import com.intellij.openapi.editor.event.EditorMouseMotionAdapter;
|
|
import com.intellij.openapi.editor.ex.EditorEx;
|
|
import com.intellij.openapi.editor.ex.EditorHighlighter;
|
|
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
|
import com.intellij.openapi.project.Project;
|
|
import com.intellij.util.IJSwingUtilities;
|
|
|
|
import javax.swing.*;
|
|
import java.awt.*;
|
|
import java.awt.event.FocusAdapter;
|
|
import java.awt.event.FocusEvent;
|
|
|
|
public class DiffSideView {
|
|
private final JComponent MOCK_COMPONENT = new JPanel();
|
|
{
|
|
MOCK_COMPONENT.setFocusable(true);
|
|
}
|
|
|
|
private static final DiffHighliterFactory DUMMY_HIGHLIGHTER_FACTORY = new DiffHighliterFactoryImpl(null, null);
|
|
private final LabeledEditor myPanel = new LabeledEditor();
|
|
|
|
private final DiffSidesContainer myContainer;
|
|
private final CurrentLineMarker myLineMarker = new CurrentLineMarker();
|
|
|
|
private DiffHighliterFactory myHighlighterFactory = DUMMY_HIGHLIGHTER_FACTORY;
|
|
private EditorSource myEditorSource = EditorSource.NULL;
|
|
private boolean myIsMaster = false;
|
|
private String myTitle;
|
|
|
|
public DiffSideView(String title, DiffSidesContainer container) {
|
|
myTitle = title;
|
|
myContainer = container;
|
|
insertComponent(MOCK_COMPONENT);
|
|
}
|
|
|
|
public JComponent getComponent() {
|
|
return myPanel;
|
|
}
|
|
|
|
public void setEditorSource(EditorSource source) {
|
|
MyState state = new MyState();
|
|
myEditorSource = source;
|
|
myLineMarker.attach(myEditorSource);
|
|
Editor editor = myEditorSource.getEditor();
|
|
if (editor == null) {
|
|
insertComponent(MOCK_COMPONENT);
|
|
return;
|
|
}
|
|
editor.getScrollingModel().scrollHorizontally(0);
|
|
insertComponent(editor.getComponent());
|
|
applyHighlighter();
|
|
setMouseListeners(source);
|
|
MyEditorFocusListener.install(this);
|
|
|
|
state.restore();
|
|
}
|
|
|
|
private void insertComponent(JComponent component) {
|
|
myPanel.setComponent(component, myTitle);
|
|
}
|
|
|
|
public void setHighlighterFactory(DiffHighliterFactory highlighterFactory) {
|
|
myHighlighterFactory = highlighterFactory;
|
|
applyHighlighter();
|
|
}
|
|
|
|
private void applyHighlighter() {
|
|
EditorEx editor = myEditorSource.getEditor();
|
|
if (editor == null) return;
|
|
EditorHighlighter highlighter = myHighlighterFactory.createHighlighter();
|
|
if (highlighter != null) editor.setHighlighter(highlighter);
|
|
editor.getColorsScheme().setColor(EditorColors.CARET_ROW_COLOR, null);
|
|
}
|
|
|
|
public void setTitle(String title) {
|
|
myTitle = title;
|
|
Editor editor = getEditor();
|
|
if (editor == null) return;
|
|
boolean readonly = editor.isViewer() || !editor.getDocument().isWritable();
|
|
myPanel.updateTitle(myTitle, readonly);
|
|
}
|
|
|
|
private void setMouseListeners(EditorSource source) {
|
|
DiffContent content = source.getContent();
|
|
MouseLineNumberListener.install(content, source, myContainer);
|
|
}
|
|
|
|
public void beSlave() {
|
|
myIsMaster = false;
|
|
myLineMarker.hide();
|
|
}
|
|
|
|
private static class MouseLineNumberListener {
|
|
private static final Cursor HAND__CURSOR = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
|
|
private final Editor myEditor;
|
|
private final DiffSidesContainer myContainer;
|
|
private final DiffContent myContent;
|
|
private final Project myProject;
|
|
|
|
private final EditorMouseAdapter myMouseListener = new EditorMouseAdapter() {
|
|
public void mouseReleased(EditorMouseEvent e) {
|
|
if (!isInMyArea(e)) return;
|
|
OpenFileDescriptor descriptor = getOpenFileDescriptor(e);
|
|
if (descriptor == null) return;
|
|
myContainer.showSource(descriptor);
|
|
}
|
|
};
|
|
|
|
private OpenFileDescriptor getOpenFileDescriptor(EditorMouseEvent e) {
|
|
int offset = myEditor.logicalPositionToOffset(myEditor.xyToLogicalPosition(e.getMouseEvent().getPoint()));
|
|
return myContent.getOpenFileDescriptor(offset);
|
|
}
|
|
|
|
private boolean isInMyArea(EditorMouseEvent e) {
|
|
return e.getArea() == EditorMouseEventArea.LINE_NUMBERS_AREA;
|
|
}
|
|
|
|
private final EditorMouseMotionAdapter myMouseMotionListener = new EditorMouseMotionAdapter() {
|
|
public void mouseMoved(EditorMouseEvent e) {
|
|
if (!isInMyArea(e)) return;
|
|
Cursor cursor = getOpenFileDescriptor(e) != null ? HAND__CURSOR : Cursor.getDefaultCursor();
|
|
e.getMouseEvent().getComponent().setCursor(cursor);
|
|
myEditor.getContentComponent().setCursor(cursor);
|
|
}
|
|
};
|
|
|
|
public MouseLineNumberListener(DiffContent content, Editor editor, DiffSidesContainer container, Project project) {
|
|
myEditor = editor;
|
|
myContainer = container;
|
|
myContent = content;
|
|
myProject = project;
|
|
}
|
|
|
|
public static void install(DiffContent content, EditorSource source, DiffSidesContainer container) {
|
|
final Editor editor = source.getEditor();
|
|
Project project = container.getProject();
|
|
if (project == null) return;
|
|
final MouseLineNumberListener listener = new MouseLineNumberListener(content, editor, container, project);
|
|
editor.addEditorMouseListener(listener.myMouseListener);
|
|
editor.addEditorMouseMotionListener(listener.myMouseMotionListener);
|
|
source.addDisposable(new Disposeable() {
|
|
public void dispose() {
|
|
editor.removeEditorMouseListener(listener.myMouseListener);
|
|
editor.removeEditorMouseMotionListener(listener.myMouseMotionListener);
|
|
}
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
private static class MyEditorFocusListener extends FocusAdapter {
|
|
private final DiffSideView mySideView;
|
|
|
|
private MyEditorFocusListener(DiffSideView sideView) {
|
|
mySideView = sideView;
|
|
}
|
|
|
|
public void focusGained(FocusEvent e) {
|
|
mySideView.becomeMaster();
|
|
}
|
|
|
|
public static MyEditorFocusListener install(DiffSideView sideView) {
|
|
final MyEditorFocusListener listener = new MyEditorFocusListener(sideView);
|
|
final JComponent focusableComponent = sideView.getFocusableComponent();
|
|
focusableComponent.addFocusListener(listener);
|
|
sideView.myEditorSource.addDisposable(new Disposeable() {
|
|
public void dispose() {
|
|
focusableComponent.removeFocusListener(listener);
|
|
}
|
|
});
|
|
return listener;
|
|
}
|
|
}
|
|
|
|
public JComponent getFocusableComponent() {
|
|
Editor editor = getEditor();
|
|
return editor != null ? editor.getContentComponent() : MOCK_COMPONENT;
|
|
}
|
|
|
|
public void becomeMaster() {
|
|
if (myIsMaster) return;
|
|
myIsMaster = true;
|
|
myContainer.setCurrentSide(this);
|
|
beMaster();
|
|
}
|
|
|
|
private void beMaster() {
|
|
myLineMarker.set();
|
|
}
|
|
|
|
public void scrollToFirstDiff(int logicalLine) {
|
|
Editor editor = myEditorSource.getEditor();
|
|
SyncScrollSupport.scrollEditor(editor, logicalLine);
|
|
}
|
|
|
|
public Editor getEditor() {
|
|
return myEditorSource.getEditor();
|
|
}
|
|
|
|
public FragmentSide getSide() {
|
|
return myEditorSource.getSide();
|
|
}
|
|
|
|
private class MyState {
|
|
private final boolean isFocused;
|
|
public MyState() {
|
|
isFocused = IJSwingUtilities.hasFocus(getFocusableComponent());
|
|
}
|
|
|
|
public void restore() {
|
|
if (isFocused) getFocusableComponent().requestFocus();
|
|
if (myIsMaster) beMaster();
|
|
}
|
|
}
|
|
}
|